From 101dada7922c7ad98bf1c13b8dc1ffa352ddc35d Mon Sep 17 00:00:00 2001 From: Ulisses Ferreira Date: Fri, 4 Sep 2026 12:28:12 +0100 Subject: [PATCH 1/3] chore: drop Node 20, target ES2022, and build packages as ESM-only - Require Node.js ^22.14.0 || ^24 everywhere (engines, yarn constraints, CI matrix); Node 18 and 20 are EOL. - Bump the shared TypeScript target and lib from ES2020 to ES2022. - Replace the dual CommonJS/ESM ts-bridge build with an ESM-only build using tsc --build. Packages now ship dist/index.js and dist/index.d.ts; lodash is replaced with lodash-es. - Update the library template and yarn constraints accordingly. --- .github/workflows/lint-build-test.yml | 4 +- .yarnrc.yml | 1 - AGENTS.md | 4 +- docs/processes/adding-new-packages.md | 2 +- jest.config.packages.js | 6 ++ package.json | 2 +- packages/bitcoin-wallet-snap/package.json | 2 +- packages/snap-networks-utils/CHANGELOG.md | 3 + .../snap-networks-utils/jest.config.cjs | 15 +++++ packages/snap-networks-utils/package.json | 45 ++++---------- packages/snap-networks-utils/src/index.ts | 42 +++++++------ .../providers/assets/AssetsProvider.test.ts | 4 +- .../RemoteFeatureFlagsProvider.test.ts | 4 +- .../src/utils/async/async.test.ts | 2 +- .../src/utils/buildUrl/buildUrl.test.ts | 2 +- .../src/utils/buildUrl/buildUrl.ts | 7 ++- .../utils/dedupe/InFlightCoalescer.test.ts | 2 +- .../src/utils/errors/errors.test.ts | 8 +-- .../src/utils/errors/errors.ts | 6 +- .../src/utils/errors/index.ts | 12 ++-- .../src/utils/errors/trackError.test.ts | 8 +-- .../src/utils/errors/trackError.ts | 4 +- .../src/utils/logger/Logger.test.ts | 2 +- .../src/utils/logger/__mocks__/Logger.ts | 2 +- .../createOriginPermissions.test.ts | 2 +- .../originPermissions/validateOrigin.test.ts | 2 +- .../src/utils/safeMerge/safeMerge.test.ts | 2 +- .../src/utils/sanitize/sanitize.test.ts | 2 +- .../utils/serialization/serialization.test.ts | 2 +- .../src/utils/serialization/serialization.ts | 4 +- .../src/utils/urlStruct/urlStruct.test.ts | 2 +- .../src/utils/uuidStruct/uuidStruct.test.ts | 2 +- .../snap-networks-utils/tsconfig.build.json | 4 +- packages/solana-wallet-snap/package.json | 2 +- packages/stellar-wallet-snap/package.json | 2 +- packages/tron-wallet-snap/package.json | 2 +- .../library-template/jest.config.cjs | 0 .../library-template/package.json | 19 ++---- .../library-template/src/index.test.ts | 2 +- .../library-template/tsconfig.build.json | 4 +- tsconfig.base.json | 11 ++-- tsconfig.json | 2 +- tsconfig.packages.libs.build.json | 3 +- tsconfig.packages.snaps.json | 2 +- yarn.config.cjs | 51 +++++----------- yarn.lock | 60 ++++++++----------- 46 files changed, 171 insertions(+), 200 deletions(-) rename scripts/create-package/library-template/jest.config.js => packages/snap-networks-utils/jest.config.cjs (67%) rename packages/snap-networks-utils/jest.config.js => scripts/create-package/library-template/jest.config.cjs (100%) diff --git a/.github/workflows/lint-build-test.yml b/.github/workflows/lint-build-test.yml index c90912846..acffe6e83 100644 --- a/.github/workflows/lint-build-test.yml +++ b/.github/workflows/lint-build-test.yml @@ -89,7 +89,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x, 22.x, 24.x] + node-version: [22.x, 24.x] outputs: child-workspace-package-names: ${{ steps.workspace-package-names.outputs.child-workspace-package-names }} steps: @@ -213,7 +213,7 @@ jobs: needs: [prepare, build] strategy: matrix: - node-version: [20.x, 22.x] + node-version: [22.x, 24.x] package-name: ${{ fromJson(needs.prepare.outputs.child-workspace-package-names) }} steps: - name: Checkout and setup environment diff --git a/.yarnrc.yml b/.yarnrc.yml index 03ae30813..4c0e4f39a 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -27,7 +27,6 @@ npmPreapprovedPackages: - "@metamask/*" - "@metamask-previews/*" - "@lavamoat/*" - - "@ts-bridge/*" plugins: - path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs diff --git a/AGENTS.md b/AGENTS.md index a70dc7d1f..4201e9e57 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,12 +51,12 @@ The monorepo uses a hierarchical configuration approach for different tools. For - `tsconfig.packages.json` defines shared TypeScript settings for all packages. - Packages are either Snaps or non-Snaps: - `tsconfig.packages.snaps.json` defines shared TypeScript settings for all Snap packages. - - `tsconfig.packages.libs.build.json` defines shared declaration build settings for library packages, used by `ts-bridge`. + - `tsconfig.packages.libs.build.json` defines shared build settings for library packages, used by `tsc --build`. - `tsconfig.scripts.json` defines shared TypeScript settings for directories in `scripts/`. - The root `lint:tsc` script checks repository scripts with `tsconfig.json`, then checks each workspace package configuration directly. It does not build Snap bundles with `tsc`. - `packages/**/tsconfig.json` (and `scripts/create-package/library-template/tsconfig.json`) defines TypeScript settings for each package that are meant to be used by code editors and type checking. -- Library packages and the library template also have `tsconfig.build.json` files for `ts-bridge` declaration builds. Snap packages do not have build configs because `mm-snap` builds their bundles. +- Library packages and the library template also have `tsconfig.build.json` files for ESM-only `tsc` builds. Snap packages do not have build configs because `mm-snap` builds their bundles. - `scripts/create-package/tsconfig.json` customizes TypeScript settings for the `create-package` tool. #### Jest diff --git a/docs/processes/adding-new-packages.md b/docs/processes/adding-new-packages.md index d5b52b249..1b4137d4c 100644 --- a/docs/processes/adding-new-packages.md +++ b/docs/processes/adding-new-packages.md @@ -8,7 +8,7 @@ Manually creating a new monorepo package can be a tedious, even frustrating proc 1. Create a new package using `yarn create-package`. - You can specify the kind of package you want with the `--type` option. It defaults to `snap`: - `--type snap` creates a new Snap, whose bundle is built with `mm-snap`. - - `--type library` (or the `--type lib` shorthand) creates a new non-Snap package, whose declarations are built with `ts-bridge`. + - `--type library` (or the `--type lib` shorthand) creates a new non-Snap package, which is built as ESM-only with `tsc`. - Use the `--help` flag for usage information. - Once this is done, you can find a package with your chosen name in `/packages`. 2. Make sure your license is correct. diff --git a/jest.config.packages.js b/jest.config.packages.js index e7fbc4ab2..d24ae01da 100644 --- a/jest.config.packages.js +++ b/jest.config.packages.js @@ -90,6 +90,12 @@ module.exports = { // so in that case use their published versions '/../../node_modules/@metamask/$1', ], + // Source code uses `lodash-es` (ESM-only), but tests are compiled to + // CommonJS, where `lodash` is used instead. + '^lodash-es$': 'lodash', + // Sources use explicit `.js` extensions (required for Node16 ESM + // resolution), which Jest must map back to the `.ts` files. + '^(\\.{1,2}/.*)\\.js$': '$1', }, // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader diff --git a/package.json b/package.json index d11c76d81..509bd36e1 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "ws@7.4.6": "^7.5.10" }, "engines": { - "node": ">=20" + "node": "^22.14.0 || ^24" }, "packageManager": "yarn@4.17.1", "lavamoat": { diff --git a/packages/bitcoin-wallet-snap/package.json b/packages/bitcoin-wallet-snap/package.json index 76370babb..e7abec7fa 100644 --- a/packages/bitcoin-wallet-snap/package.json +++ b/packages/bitcoin-wallet-snap/package.json @@ -74,6 +74,6 @@ "wif": "^5.0.0" }, "engines": { - "node": ">=20" + "node": "^22.14.0 || ^24" } } diff --git a/packages/snap-networks-utils/CHANGELOG.md b/packages/snap-networks-utils/CHANGELOG.md index 57c5a84b9..63f888142 100644 --- a/packages/snap-networks-utils/CHANGELOG.md +++ b/packages/snap-networks-utils/CHANGELOG.md @@ -31,6 +31,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Require Node.js `^22.14.0 || ^24`; Node.js 20 and below are no longer supported ([#273](https://github.com/MetaMask/internal-snaps/pull/273)) +- Compile with TypeScript `target` and `lib` of `ES2022` ([#273](https://github.com/MetaMask/internal-snaps/pull/273)) +- Replace the dual CommonJS/ESM build with an ESM-only build, using `tsc` instead of `ts-bridge`. The package now ships `dist/index.js` and `dist/index.d.ts`; CommonJS consumers need Node.js 22+'s `require(esm)` support or a bundler ([#273](https://github.com/MetaMask/internal-snaps/pull/273)) - **BREAKING** Replace the logger utilities with a configurable `Logger` class that requires a log level and supports level filtering, per-instance prefixes, and method decorators. ([#136](https://github.com/MetaMask/internal-snaps/pull/136)) - Bump `@metamask/utils` from `^11.9.0` to `^11.11.9` ([#161](https://github.com/MetaMask/internal-snaps/pull/161)) - **BREAKING** Bump `@metamask/snaps-sdk` from `^11.2.0` to `^12.0.1` ([#214](https://github.com/MetaMask/internal-snaps/pull/214)) diff --git a/scripts/create-package/library-template/jest.config.js b/packages/snap-networks-utils/jest.config.cjs similarity index 67% rename from scripts/create-package/library-template/jest.config.js rename to packages/snap-networks-utils/jest.config.cjs index f198bc8f9..4edbb9d5d 100644 --- a/scripts/create-package/library-template/jest.config.js +++ b/packages/snap-networks-utils/jest.config.cjs @@ -14,6 +14,21 @@ module.exports = merge(baseConfig, { // The display name when running multiple projects displayName, + // This package is an ES module (`"type": "module"`), but tests are run in + // CommonJS mode, so force `ts-jest` to compile to CommonJS regardless of + // the package type. + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + tsconfig: { + module: 'CommonJS', + moduleResolution: 'node10', + }, + }, + ], + }, + coveragePathIgnorePatterns: [ ...(baseConfig.coveragePathIgnorePatterns ?? []), '.*/__mocks__/', diff --git a/packages/snap-networks-utils/package.json b/packages/snap-networks-utils/package.json index 5fc829e8a..2a7694e3f 100644 --- a/packages/snap-networks-utils/package.json +++ b/packages/snap-networks-utils/package.json @@ -18,39 +18,20 @@ "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" }, "./dedupe": { - "import": { - "types": "./dist/utils/dedupe/InFlightCoalescer.d.mts", - "default": "./dist/utils/dedupe/InFlightCoalescer.mjs" - }, - "require": { - "types": "./dist/utils/dedupe/InFlightCoalescer.d.cts", - "default": "./dist/utils/dedupe/InFlightCoalescer.cjs" - } + "types": "./dist/utils/dedupe/InFlightCoalescer.d.ts", + "default": "./dist/utils/dedupe/InFlightCoalescer.js" }, "./logger": { - "import": { - "types": "./dist/utils/logger/Logger.d.mts", - "default": "./dist/utils/logger/Logger.mjs" - }, - "require": { - "types": "./dist/utils/logger/Logger.d.cts", - "default": "./dist/utils/logger/Logger.cjs" - } + "types": "./dist/utils/logger/Logger.d.ts", + "default": "./dist/utils/logger/Logger.js" }, "./package.json": "./package.json" }, @@ -59,8 +40,8 @@ "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 --build --verbose tsconfig.build.json", + "build:clean": "tsc --build --clean tsconfig.build.json && rimraf ./dist", "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/snap-networks-utils", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/snap-networks-utils", @@ -77,16 +58,16 @@ "@metamask/superstruct": "^3.4.1", "@metamask/utils": "^11.11.0", "bignumber.js": "^9.3.1", - "lodash": "^4.17.21" + "lodash-es": "^4.17.21" }, "devDependencies": { "@metamask/auto-changelog": "^6.1.1", "@metamask/messenger": "^2.0.0", - "@ts-bridge/cli": "^0.6.4", "@types/jest": "^30.0.0", - "@types/lodash": "^4.17.15", + "@types/lodash-es": "^4.17.12", "deepmerge": "^4.2.2", "jest": "30.0.3", + "rimraf": "^6.0.1", "ts-jest": "^29.4.1", "tsx": "^4.20.5", "typedoc": "^0.25.13", @@ -94,6 +75,6 @@ "typescript": "~5.8.3" }, "engines": { - "node": ">=20" + "node": "^22.14.0 || ^24" } } diff --git a/packages/snap-networks-utils/src/index.ts b/packages/snap-networks-utils/src/index.ts index 77ed424d5..29193938d 100644 --- a/packages/snap-networks-utils/src/index.ts +++ b/packages/snap-networks-utils/src/index.ts @@ -2,38 +2,38 @@ export { ASSETS_PROVIDER_NAME, AssetsProvider, type AssetsProviderMessenger, -} from './providers/assets/AssetsProvider'; +} from './providers/assets/AssetsProvider.js'; export { REMOTE_FEATURE_FLAGS_PROVIDER_NAME, RemoteFeatureFlagsProvider, type RemoteFeatureFlagsProviderMessenger, -} from './providers/remote-feature-flags/RemoteFeatureFlagsProvider'; -export { safeMerge } from './utils/safeMerge/safeMerge'; -export { buildUrl } from './utils/buildUrl/buildUrl'; -export type { BuildUrlParams } from './utils/buildUrl/buildUrl'; +} from './providers/remote-feature-flags/RemoteFeatureFlagsProvider.js'; +export { safeMerge } from './utils/safeMerge/safeMerge.js'; +export { buildUrl } from './utils/buildUrl/buildUrl.js'; +export type { BuildUrlParams } from './utils/buildUrl/buildUrl.js'; export { sanitizeControlCharacters, sanitizeUri, -} from './utils/sanitize/sanitize'; -export { UrlStruct } from './utils/urlStruct/urlStruct'; -export { UuidStruct } from './utils/uuidStruct/uuidStruct'; +} from './utils/sanitize/sanitize.js'; +export { UrlStruct } from './utils/urlStruct/urlStruct.js'; +export { UuidStruct } from './utils/uuidStruct/uuidStruct.js'; export { batchesAll, batchesAllSettled, batchesAllSettledWithChunks, batchesAllWithChunks, chunks, -} from './utils/async/async'; -export { Logger, LogLevel } from './utils/logger/Logger'; +} from './utils/async/async.js'; +export { Logger, LogLevel } from './utils/logger/Logger.js'; export type { LoggerOptions, LoggerMethod, LogMethod, LogMethodDecorator, LoggerDecorators, -} from './utils/logger/Logger'; -export { serialize, deserialize } from './utils/serialization/serialization'; -export type { Serializable } from './utils/serialization/types'; +} from './utils/logger/Logger.js'; +export { serialize, deserialize } from './utils/serialization/serialization.js'; +export type { Serializable } from './utils/serialization/types.js'; export { parseProofOfOwnershipMessage, ProofOfOwnershipBatchErrorStruct, @@ -59,17 +59,19 @@ export { DEFAULT_PROD_ORIGINS, DEFAULT_DEV_ORIGINS, DEFAULT_METAMASK_ORIGIN, -} from './utils/originPermissions/createOriginPermissions'; -export type { CreateOriginPermissionsParams } from './utils/originPermissions/createOriginPermissions'; -export { validateOrigin } from './utils/originPermissions/validateOrigin'; +} from './utils/originPermissions/createOriginPermissions.js'; +export type { CreateOriginPermissionsParams } from './utils/originPermissions/createOriginPermissions.js'; +export { validateOrigin } from './utils/originPermissions/validateOrigin.js'; export { createSnapErrorHandling, createTrackError, createWithCatchAndThrowSnapError, isSnapRpcError, normalizeError, -} from './utils/errors'; -export { InFlightCoalescer } from './utils/dedupe/InFlightCoalescer'; + // Directory imports require the explicit `/index.js` under Node16 ESM resolution. + // eslint-disable-next-line import-x/no-useless-path-segments +} from './utils/errors/index.js'; +export { InFlightCoalescer } from './utils/dedupe/InFlightCoalescer.js'; export type { CreateSnapErrorHandlingOptions, CreateTrackErrorOptions, @@ -82,4 +84,6 @@ export type { SnapTrackErrorRequest, TrackErrorCapableProvider, TrackErrorFn, -} from './utils/errors'; + // Directory imports require the explicit `/index.js` under Node16 ESM resolution. + // eslint-disable-next-line import-x/no-useless-path-segments +} from './utils/errors/index.js'; diff --git a/packages/snap-networks-utils/src/providers/assets/AssetsProvider.test.ts b/packages/snap-networks-utils/src/providers/assets/AssetsProvider.test.ts index 3f80890f7..bff170990 100644 --- a/packages/snap-networks-utils/src/providers/assets/AssetsProvider.test.ts +++ b/packages/snap-networks-utils/src/providers/assets/AssetsProvider.test.ts @@ -1,8 +1,8 @@ import type { AccountId, Caip19AssetId } from '@metamask/assets-controller'; import type { CaipChainId } from '@metamask/utils'; -import type { AssetsProviderMessenger } from './AssetsProvider'; -import { AssetsProvider } from './AssetsProvider'; +import type { AssetsProviderMessenger } from './AssetsProvider.js'; +import { AssetsProvider } from './AssetsProvider.js'; const ACCOUNT_ID: AccountId = '550e8400-e29b-41d4-a716-446655440000'; const ASSET_ID: Caip19AssetId = 'tron:728126428/slip44:195'; diff --git a/packages/snap-networks-utils/src/providers/remote-feature-flags/RemoteFeatureFlagsProvider.test.ts b/packages/snap-networks-utils/src/providers/remote-feature-flags/RemoteFeatureFlagsProvider.test.ts index 33225d36b..d55a85ee1 100644 --- a/packages/snap-networks-utils/src/providers/remote-feature-flags/RemoteFeatureFlagsProvider.test.ts +++ b/packages/snap-networks-utils/src/providers/remote-feature-flags/RemoteFeatureFlagsProvider.test.ts @@ -1,7 +1,7 @@ import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller'; -import type { RemoteFeatureFlagsProviderMessenger } from './RemoteFeatureFlagsProvider'; -import { RemoteFeatureFlagsProvider } from './RemoteFeatureFlagsProvider'; +import type { RemoteFeatureFlagsProviderMessenger } from './RemoteFeatureFlagsProvider.js'; +import { RemoteFeatureFlagsProvider } from './RemoteFeatureFlagsProvider.js'; const FLAG_KEY_A = 'flag-a'; const FLAG_KEY_B = 'flag-b'; diff --git a/packages/snap-networks-utils/src/utils/async/async.test.ts b/packages/snap-networks-utils/src/utils/async/async.test.ts index ea7979e96..b6ed914f4 100644 --- a/packages/snap-networks-utils/src/utils/async/async.test.ts +++ b/packages/snap-networks-utils/src/utils/async/async.test.ts @@ -4,7 +4,7 @@ import { batchesAllSettledWithChunks, batchesAllWithChunks, chunks, -} from './async'; +} from './async.js'; describe('batchesAll', () => { it('throws when batchSize is less than 1', async () => { diff --git a/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.test.ts b/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.test.ts index d59771175..1f5742399 100644 --- a/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.test.ts +++ b/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.test.ts @@ -1,4 +1,4 @@ -import { buildUrl } from './buildUrl'; +import { buildUrl } from './buildUrl.js'; describe('buildUrl', () => { it('builds and sanitizes URLs, including path and query parameters', () => { diff --git a/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.ts b/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.ts index 90a4c5f6c..7c88b2b17 100644 --- a/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.ts +++ b/packages/snap-networks-utils/src/utils/buildUrl/buildUrl.ts @@ -1,7 +1,10 @@ import { assert } from '@metamask/superstruct'; -import { sanitizeControlCharacters, sanitizeUri } from '../sanitize/sanitize'; -import { UrlStruct } from '../urlStruct/urlStruct'; +import { + sanitizeControlCharacters, + sanitizeUri, +} from '../sanitize/sanitize.js'; +import { UrlStruct } from '../urlStruct/urlStruct.js'; export type BuildUrlParams = { baseUrl: string; diff --git a/packages/snap-networks-utils/src/utils/dedupe/InFlightCoalescer.test.ts b/packages/snap-networks-utils/src/utils/dedupe/InFlightCoalescer.test.ts index 242a22874..601ce1672 100644 --- a/packages/snap-networks-utils/src/utils/dedupe/InFlightCoalescer.test.ts +++ b/packages/snap-networks-utils/src/utils/dedupe/InFlightCoalescer.test.ts @@ -1,4 +1,4 @@ -import { InFlightCoalescer } from './InFlightCoalescer'; +import { InFlightCoalescer } from './InFlightCoalescer.js'; describe('InFlightCoalescer', () => { it('returns the result of the wrapped function', async () => { diff --git a/packages/snap-networks-utils/src/utils/errors/errors.test.ts b/packages/snap-networks-utils/src/utils/errors/errors.test.ts index 0f4a42c6c..b752bb2da 100644 --- a/packages/snap-networks-utils/src/utils/errors/errors.test.ts +++ b/packages/snap-networks-utils/src/utils/errors/errors.test.ts @@ -18,10 +18,10 @@ import { UserRejectedRequestError, } from '@metamask/snaps-sdk'; -import { mockLogger } from '../logger/__mocks__/Logger'; -import { createWithCatchAndThrowSnapError, normalizeError } from './errors'; -import type { CreateWithCatchAndThrowSnapErrorOptions } from './errors'; -import { isSnapRpcError } from './snapRpcError'; +import { mockLogger } from '../logger/__mocks__/Logger.js'; +import { createWithCatchAndThrowSnapError, normalizeError } from './errors.js'; +import type { CreateWithCatchAndThrowSnapErrorOptions } from './errors.js'; +import { isSnapRpcError } from './snapRpcError.js'; type SetupTestResult = { trackError: jest.Mock; diff --git a/packages/snap-networks-utils/src/utils/errors/errors.ts b/packages/snap-networks-utils/src/utils/errors/errors.ts index 7a32c0373..b758b64ef 100644 --- a/packages/snap-networks-utils/src/utils/errors/errors.ts +++ b/packages/snap-networks-utils/src/utils/errors/errors.ts @@ -1,8 +1,8 @@ import { SnapError, getErrorMessage } from '@metamask/snaps-sdk'; -import type { Logger } from '../logger/Logger'; -import { isSnapRpcError } from './snapRpcError'; -import type { SnapRpcError } from './snapRpcError'; +import type { Logger } from '../logger/Logger.js'; +import { isSnapRpcError } from './snapRpcError.js'; +import type { SnapRpcError } from './snapRpcError.js'; /** * Sends an error to the snap's tracking transport (e.g. `snap_trackError`). diff --git a/packages/snap-networks-utils/src/utils/errors/index.ts b/packages/snap-networks-utils/src/utils/errors/index.ts index f057effee..42768eab9 100644 --- a/packages/snap-networks-utils/src/utils/errors/index.ts +++ b/packages/snap-networks-utils/src/utils/errors/index.ts @@ -1,6 +1,6 @@ -export { createSnapErrorHandling, createTrackError } from './trackError'; -export { createWithCatchAndThrowSnapError, normalizeError } from './errors'; -export { isSnapRpcError } from './snapRpcError'; +export { createSnapErrorHandling, createTrackError } from './trackError.js'; +export { createWithCatchAndThrowSnapError, normalizeError } from './errors.js'; +export { isSnapRpcError } from './snapRpcError.js'; export type { CreateSnapErrorHandlingOptions, CreateTrackErrorOptions, @@ -8,11 +8,11 @@ export type { ShouldTrackErrorFn, SnapTrackErrorRequest, TrackErrorCapableProvider, -} from './trackError'; +} from './trackError.js'; export type { CreateWithCatchAndThrowSnapErrorOptions, LogErrorFn, NormalizeErrorFn, TrackErrorFn, -} from './errors'; -export type { SnapRpcError } from './snapRpcError'; +} from './errors.js'; +export type { SnapRpcError } from './snapRpcError.js'; diff --git a/packages/snap-networks-utils/src/utils/errors/trackError.test.ts b/packages/snap-networks-utils/src/utils/errors/trackError.test.ts index 8f84ebe0f..2c359b08d 100644 --- a/packages/snap-networks-utils/src/utils/errors/trackError.test.ts +++ b/packages/snap-networks-utils/src/utils/errors/trackError.test.ts @@ -1,9 +1,9 @@ import { SnapError, UserRejectedRequestError } from '@metamask/snaps-sdk'; -import { mockLogger } from '../logger/__mocks__/Logger'; -import type { TrackErrorFn } from './errors'; -import { createSnapErrorHandling, createTrackError } from './trackError'; -import type { TrackErrorCapableProvider } from './trackError'; +import { mockLogger } from '../logger/__mocks__/Logger.js'; +import type { TrackErrorFn } from './errors.js'; +import { createSnapErrorHandling, createTrackError } from './trackError.js'; +import type { TrackErrorCapableProvider } from './trackError.js'; const setupTrackErrorTest = (): { request: jest.Mock; diff --git a/packages/snap-networks-utils/src/utils/errors/trackError.ts b/packages/snap-networks-utils/src/utils/errors/trackError.ts index 55d7d858a..c99e6294f 100644 --- a/packages/snap-networks-utils/src/utils/errors/trackError.ts +++ b/packages/snap-networks-utils/src/utils/errors/trackError.ts @@ -6,8 +6,8 @@ import type { CreateWithCatchAndThrowSnapErrorOptions, LogErrorFn, TrackErrorFn, -} from './errors'; -import { createWithCatchAndThrowSnapError } from './errors'; +} from './errors.js'; +import { createWithCatchAndThrowSnapError } from './errors.js'; /** * Converts a caught value into an {@link Error} before Sentry serialization. diff --git a/packages/snap-networks-utils/src/utils/logger/Logger.test.ts b/packages/snap-networks-utils/src/utils/logger/Logger.test.ts index 4d3a3c9fe..df7e053a7 100644 --- a/packages/snap-networks-utils/src/utils/logger/Logger.test.ts +++ b/packages/snap-networks-utils/src/utils/logger/Logger.test.ts @@ -1,4 +1,4 @@ -import { Logger, LogLevel } from './Logger'; +import { Logger, LogLevel } from './Logger.js'; const loggerMethodConfigurations = [ { method: 'log', consoleMethod: 'info', filteredAt: LogLevel.WARN }, diff --git a/packages/snap-networks-utils/src/utils/logger/__mocks__/Logger.ts b/packages/snap-networks-utils/src/utils/logger/__mocks__/Logger.ts index 567d97372..a453f8701 100644 --- a/packages/snap-networks-utils/src/utils/logger/__mocks__/Logger.ts +++ b/packages/snap-networks-utils/src/utils/logger/__mocks__/Logger.ts @@ -1,4 +1,4 @@ -import type { Logger } from '../Logger'; +import type { Logger } from '../Logger.js'; export const mockLogger = { log: jest.fn(), diff --git a/packages/snap-networks-utils/src/utils/originPermissions/createOriginPermissions.test.ts b/packages/snap-networks-utils/src/utils/originPermissions/createOriginPermissions.test.ts index 3f9220001..6a42b5db1 100644 --- a/packages/snap-networks-utils/src/utils/originPermissions/createOriginPermissions.test.ts +++ b/packages/snap-networks-utils/src/utils/originPermissions/createOriginPermissions.test.ts @@ -2,7 +2,7 @@ import { createOriginPermissions, DEFAULT_DEV_ORIGINS, DEFAULT_PROD_ORIGINS, -} from './createOriginPermissions'; +} from './createOriginPermissions.js'; describe('createOriginPermissions', () => { const dappMethods = ['keyring_getAccounts', 'computeFee']; diff --git a/packages/snap-networks-utils/src/utils/originPermissions/validateOrigin.test.ts b/packages/snap-networks-utils/src/utils/originPermissions/validateOrigin.test.ts index cc18c2ef6..78fc7d90a 100644 --- a/packages/snap-networks-utils/src/utils/originPermissions/validateOrigin.test.ts +++ b/packages/snap-networks-utils/src/utils/originPermissions/validateOrigin.test.ts @@ -1,6 +1,6 @@ import { UnauthorizedError } from '@metamask/snaps-sdk'; -import { validateOrigin } from './validateOrigin'; +import { validateOrigin } from './validateOrigin.js'; describe('validateOrigin', () => { const originPermissions = new Map>([ diff --git a/packages/snap-networks-utils/src/utils/safeMerge/safeMerge.test.ts b/packages/snap-networks-utils/src/utils/safeMerge/safeMerge.test.ts index 93666ab1c..fa7d5adfc 100644 --- a/packages/snap-networks-utils/src/utils/safeMerge/safeMerge.test.ts +++ b/packages/snap-networks-utils/src/utils/safeMerge/safeMerge.test.ts @@ -1,4 +1,4 @@ -import { safeMerge } from './safeMerge'; +import { safeMerge } from './safeMerge.js'; describe('safeMerge', () => { it('merges two objects and keeps existing values when overrider has undefined', () => { diff --git a/packages/snap-networks-utils/src/utils/sanitize/sanitize.test.ts b/packages/snap-networks-utils/src/utils/sanitize/sanitize.test.ts index ee4171df0..9d10ee478 100644 --- a/packages/snap-networks-utils/src/utils/sanitize/sanitize.test.ts +++ b/packages/snap-networks-utils/src/utils/sanitize/sanitize.test.ts @@ -1,4 +1,4 @@ -import { sanitizeControlCharacters, sanitizeUri } from './sanitize'; +import { sanitizeControlCharacters, sanitizeUri } from './sanitize.js'; describe('sanitize', () => { describe('sanitizeControlCharacters', () => { diff --git a/packages/snap-networks-utils/src/utils/serialization/serialization.test.ts b/packages/snap-networks-utils/src/utils/serialization/serialization.test.ts index 1d645ea28..149fdf9a1 100644 --- a/packages/snap-networks-utils/src/utils/serialization/serialization.test.ts +++ b/packages/snap-networks-utils/src/utils/serialization/serialization.test.ts @@ -1,6 +1,6 @@ import { BigNumber } from 'bignumber.js'; -import { deserialize, serialize } from './serialization'; +import { deserialize, serialize } from './serialization.js'; describe('serialize', () => { it('serializes primitive values', () => { diff --git a/packages/snap-networks-utils/src/utils/serialization/serialization.ts b/packages/snap-networks-utils/src/utils/serialization/serialization.ts index 6b5aaf7f6..f1cf18753 100644 --- a/packages/snap-networks-utils/src/utils/serialization/serialization.ts +++ b/packages/snap-networks-utils/src/utils/serialization/serialization.ts @@ -1,8 +1,8 @@ import type { Json } from '@metamask/snaps-sdk'; import { BigNumber } from 'bignumber.js'; -import { cloneDeepWith } from 'lodash'; +import { cloneDeepWith } from 'lodash-es'; -import type { Serializable } from './types'; +import type { Serializable } from './types.js'; /** * Serializes the passed value to a JSON object so it can be stored in JSON-serializable storage like the snap state and interface context. diff --git a/packages/snap-networks-utils/src/utils/urlStruct/urlStruct.test.ts b/packages/snap-networks-utils/src/utils/urlStruct/urlStruct.test.ts index 5b7e295e8..4e9082493 100644 --- a/packages/snap-networks-utils/src/utils/urlStruct/urlStruct.test.ts +++ b/packages/snap-networks-utils/src/utils/urlStruct/urlStruct.test.ts @@ -1,7 +1,7 @@ /* eslint-disable jest/require-to-throw-message */ import { assert, is } from '@metamask/superstruct'; -import { UrlStruct } from './urlStruct'; +import { UrlStruct } from './urlStruct.js'; describe('UrlStruct', () => { it('validates valid URLs', () => { diff --git a/packages/snap-networks-utils/src/utils/uuidStruct/uuidStruct.test.ts b/packages/snap-networks-utils/src/utils/uuidStruct/uuidStruct.test.ts index c159f5811..b84ff8bba 100644 --- a/packages/snap-networks-utils/src/utils/uuidStruct/uuidStruct.test.ts +++ b/packages/snap-networks-utils/src/utils/uuidStruct/uuidStruct.test.ts @@ -1,7 +1,7 @@ /* eslint-disable jest/require-to-throw-message */ import { assert, is } from '@metamask/superstruct'; -import { UuidStruct } from './uuidStruct'; +import { UuidStruct } from './uuidStruct.js'; describe('UuidStruct', () => { it('accepts UUID v4 strings', () => { diff --git a/packages/snap-networks-utils/tsconfig.build.json b/packages/snap-networks-utils/tsconfig.build.json index 18f6e935a..61702e8f7 100644 --- a/packages/snap-networks-utils/tsconfig.build.json +++ b/packages/snap-networks-utils/tsconfig.build.json @@ -1,9 +1,9 @@ { "extends": "../../tsconfig.packages.libs.build.json", "compilerOptions": { - "baseUrl": "./", "outDir": "./dist", - "rootDir": "./src" + "rootDir": "./src", + "tsBuildInfoFile": "./dist/tsconfig.build.tsbuildinfo" }, /** * Unlike `tsconfig.json`, for builds, we only include the source code. diff --git a/packages/solana-wallet-snap/package.json b/packages/solana-wallet-snap/package.json index 0e5795562..236111688 100644 --- a/packages/solana-wallet-snap/package.json +++ b/packages/solana-wallet-snap/package.json @@ -89,6 +89,6 @@ "typescript": "~5.8.3" }, "engines": { - "node": ">=20" + "node": "^22.14.0 || ^24" } } diff --git a/packages/stellar-wallet-snap/package.json b/packages/stellar-wallet-snap/package.json index 2d0f08c9a..1ec585aa8 100644 --- a/packages/stellar-wallet-snap/package.json +++ b/packages/stellar-wallet-snap/package.json @@ -72,6 +72,6 @@ "ts-jest": "^29.4.1" }, "engines": { - "node": ">=20" + "node": "^22.14.0 || ^24" } } diff --git a/packages/tron-wallet-snap/package.json b/packages/tron-wallet-snap/package.json index bf7ae2124..e97493133 100644 --- a/packages/tron-wallet-snap/package.json +++ b/packages/tron-wallet-snap/package.json @@ -75,6 +75,6 @@ "typescript": "~5.8.3" }, "engines": { - "node": ">=20" + "node": "^22.14.0 || ^24" } } diff --git a/packages/snap-networks-utils/jest.config.js b/scripts/create-package/library-template/jest.config.cjs similarity index 100% rename from packages/snap-networks-utils/jest.config.js rename to scripts/create-package/library-template/jest.config.cjs diff --git a/scripts/create-package/library-template/package.json b/scripts/create-package/library-template/package.json index 6abb84647..c4da03907 100644 --- a/scripts/create-package/library-template/package.json +++ b/scripts/create-package/library-template/package.json @@ -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" }, "./package.json": "./package.json" }, @@ -39,8 +32,8 @@ "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 --build --verbose tsconfig.build.json", + "build:clean": "tsc --build --clean tsconfig.build.json && rimraf ./dist", "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh PACKAGE_NAME", "changelog:validate": "../../scripts/validate-changelog.sh PACKAGE_NAME", @@ -52,10 +45,10 @@ }, "devDependencies": { "@metamask/auto-changelog": "^6.1.1", - "@ts-bridge/cli": "^0.6.4", "@types/jest": "^30.0.0", "deepmerge": "^4.2.2", "jest": "30.0.3", + "rimraf": "^6.0.1", "ts-jest": "^29.4.1", "tsx": "^4.20.5", "typedoc": "^0.25.13", diff --git a/scripts/create-package/library-template/src/index.test.ts b/scripts/create-package/library-template/src/index.test.ts index bc062d369..baa030ac1 100644 --- a/scripts/create-package/library-template/src/index.test.ts +++ b/scripts/create-package/library-template/src/index.test.ts @@ -1,4 +1,4 @@ -import greeter from '.'; +import greeter from './index.js'; describe('Test', () => { it('greets', () => { diff --git a/scripts/create-package/library-template/tsconfig.build.json b/scripts/create-package/library-template/tsconfig.build.json index 18f6e935a..61702e8f7 100644 --- a/scripts/create-package/library-template/tsconfig.build.json +++ b/scripts/create-package/library-template/tsconfig.build.json @@ -1,9 +1,9 @@ { "extends": "../../tsconfig.packages.libs.build.json", "compilerOptions": { - "baseUrl": "./", "outDir": "./dist", - "rootDir": "./src" + "rootDir": "./src", + "tsBuildInfoFile": "./dist/tsconfig.build.tsbuildinfo" }, /** * Unlike `tsconfig.json`, for builds, we only include the source code. diff --git a/tsconfig.base.json b/tsconfig.base.json index af0dfe8c2..15917a847 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -6,19 +6,18 @@ * `tsconfig.scripts.json` - Used for the `scripts/` directory. * `tsconfig.packages.json` - Shared by all `packages/`, whether Snaps or not. * - * `tsconfig.packages.libs.json` - INEXISTANT, it would be the same as `tsconfig.packages.json`. - * `tsconfig.packages.libs.build.json` - Configurations for `ts-bridge`'s emission of declarations. + * `tsconfig.packages.libs.build.json` - Configuration used by `tsc` to build library packages. * - * `tsconfig.packages.snaps.json` - Snap specific configurations. - * `tsconfig.packages.snaps.build.json` - INEXISTANT, `mm-snap` already handles everything. + * `tsconfig.packages.snaps.json` - Snap specific configurations. Snap packages have no build + * configuration, as `mm-snap` already handles everything. */ "compilerOptions": { "esModuleInterop": true, "isolatedModules": true, - "lib": ["ES2020", "DOM"], + "lib": ["ES2022", "DOM"], "module": "Node16", "moduleResolution": "Node16", "strict": true, - "target": "ES2020" + "target": "ES2022" } } diff --git a/tsconfig.json b/tsconfig.json index 724f194ed..c38faa31a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "forceConsistentCasingInFileNames": true, "jsx": "react-jsx", "jsxImportSource": "@metamask/snaps-sdk", - "lib": ["ES2020"], + "lib": ["ES2022"], "noEmit": true, "noErrorTruncation": true, "noUncheckedIndexedAccess": true, diff --git a/tsconfig.packages.libs.build.json b/tsconfig.packages.libs.build.json index 47be60037..e0b167e15 100644 --- a/tsconfig.packages.libs.build.json +++ b/tsconfig.packages.libs.build.json @@ -1,6 +1,6 @@ { /** - * Shared settings for library packages, used by `tsc` to emit declarations. + * Shared settings for library packages, used by `tsc` to emit JavaScript and declarations. * * Library packages extending this configuration must still define their own `outDir`, * `rootDir`, and `include`, since these are resolved relative to each package. @@ -10,7 +10,6 @@ "composite": true, "declaration": true, "declarationMap": true, - "emitDeclarationOnly": true, "inlineSources": true, "noEmit": false, "sourceMap": true diff --git a/tsconfig.packages.snaps.json b/tsconfig.packages.snaps.json index 49fbf5ea8..4f5d83c78 100644 --- a/tsconfig.packages.snaps.json +++ b/tsconfig.packages.snaps.json @@ -1,7 +1,7 @@ { /** * Shared settings for Snap packages, i.e. packages whose bundles are built by `mm-snap` - * rather than by `tsc` or `ts-bridge`. + * rather than by `tsc`. * * Snap packages must still set `baseUrl` to their own directory, so that the `paths` option * resolves correctly. diff --git a/yarn.config.cjs b/yarn.config.cjs index 2b1f91768..8fe797002 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -161,21 +161,21 @@ module.exports = defineConfig({ } // All non-root packages must have a "build" script. All packages that - // do not exclusively deploy documentation sites must use `ts-bridge`. + // do not exclusively deploy documentation sites must use `tsc`. if (DOCSITE_PACKAGES.includes(workspace.ident)) { expectWorkspaceField(workspace, 'scripts.build'); } else { expectWorkspaceField( workspace, 'scripts.build', - 'ts-bridge --project tsconfig.build.json --verbose --clean --no-references', + 'tsc --build --verbose tsconfig.build.json', ); - // All non-root packages must have the same "build:all" script. + // All non-root packages must have the same "build:clean" script. expectWorkspaceField( workspace, - 'scripts.build:all', - 'ts-bridge --project tsconfig.build.json --verbose --clean', + 'scripts.build:clean', + 'tsc --build --clean tsconfig.build.json && rimraf ./dist', ); } @@ -286,8 +286,9 @@ module.exports = defineConfig({ expectWorkspaceField(workspace, 'packageManager', 'yarn@4.17.1'); } - // All packages must specify a minimum Node.js version of 20. - expectWorkspaceField(workspace, 'engines.node', '>=20'); + // All packages must specify Node.js ^22.14.0 or ^24 as their minimum + // supported version. + expectWorkspaceField(workspace, 'engines.node', '^22.14.0 || ^24'); // All non-root public packages should be published to the NPM registry; // all non-root private packages should not. @@ -597,37 +598,13 @@ async function expectWorkspaceLicense(workspace) { * @param {Workspace} workspace - The workspace to check. */ function expectCorrectWorkspaceExports(workspace) { - // All non-root packages must provide the location of the ESM-compatible - // JavaScript entrypoint and its matching type declaration file. - expectWorkspaceField( - workspace, - 'exports["."].import.types', - './dist/index.d.mts', - ); - expectWorkspaceField( - workspace, - 'exports["."].import.default', - './dist/index.mjs', - ); - - // All non-root package must provide the location of the CommonJS-compatible - // entrypoint and its matching type declaration file. - expectWorkspaceField( - workspace, - 'exports["."].require.types', - './dist/index.d.cts', - ); - expectWorkspaceField( - workspace, - 'exports["."].require.default', - './dist/index.cjs', - ); - expectWorkspaceField(workspace, 'main', './dist/index.cjs'); - expectWorkspaceField(workspace, 'types', './dist/index.d.cts'); + // All non-root packages must be ESM-only: they must provide the location of + // the JavaScript entrypoint and its matching type declaration file. + expectWorkspaceField(workspace, 'exports["."].types', './dist/index.d.ts'); + expectWorkspaceField(workspace, 'exports["."].default', './dist/index.js'); - // Types should not be set in the export object directly, but rather in the - // `import` and `require` subfields. - expectWorkspaceField(workspace, 'exports["."].types', null); + // All non-root packages must declare that they are ES modules. + expectWorkspaceField(workspace, 'type', 'module'); // All non-root packages must export a `package.json` file. expectWorkspaceField( diff --git a/yarn.lock b/yarn.lock index 7cc652475..5ddd38c7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3332,13 +3332,13 @@ __metadata: "@metamask/snaps-sdk": "npm:^12.0.1" "@metamask/superstruct": "npm:^3.4.1" "@metamask/utils": "npm:^11.11.0" - "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^30.0.0" - "@types/lodash": "npm:^4.17.15" + "@types/lodash-es": "npm:^4.17.12" bignumber.js: "npm:^9.3.1" deepmerge: "npm:^4.2.2" jest: "npm:30.0.3" - lodash: "npm:^4.17.21" + lodash-es: "npm:^4.17.21" + rimraf: "npm:^6.0.1" ts-jest: "npm:^29.4.1" tsx: "npm:^4.20.5" typedoc: "npm:^0.25.13" @@ -5349,30 +5349,6 @@ __metadata: languageName: node linkType: hard -"@ts-bridge/cli@npm:^0.6.4": - version: 0.6.4 - resolution: "@ts-bridge/cli@npm:0.6.4" - dependencies: - "@ts-bridge/resolver": "npm:^0.2.0" - chalk: "npm:^5.3.0" - cjs-module-lexer: "npm:^1.3.1" - yargs: "npm:^17.7.2" - peerDependencies: - typescript: ">=4.8.0" - bin: - ts-bridge: ./dist/index.js - tsbridge: ./dist/index.js - checksum: 10/257ee0cacec71c1b3cc018825088e06b4bd554ba5fe95bdb98c4c82edd6cd4bcff1054d351e6c7cdfdd3bd2145a055b5d14fa453a6ece761645e42b48b88e9a0 - languageName: node - linkType: hard - -"@ts-bridge/resolver@npm:^0.2.0": - version: 0.2.0 - resolution: "@ts-bridge/resolver@npm:0.2.0" - checksum: 10/d4cfd1f47e9648a5f9c893b1b076adabde3a57cbe81ef823bcbbcc77a122fb6f06d99f40ff48198f8dc766bfc4b3b351d4e87cfcf2db64f7e6db924eb82a5db1 - languageName: node - linkType: hard - "@tybys/wasm-util@npm:^0.10.3": version: 0.10.3 resolution: "@tybys/wasm-util@npm:0.10.3" @@ -5562,6 +5538,22 @@ __metadata: languageName: node linkType: hard +"@types/lodash-es@npm:^4.17.12": + version: 4.17.12 + resolution: "@types/lodash-es@npm:4.17.12" + dependencies: + "@types/lodash": "npm:*" + checksum: 10/56b9a433348b11c31051c6fa9028540a033a08fb80b400c589d740446c19444d73b217cf1471d4036448ef686a83e8cf2a35d1fadcb3f2105f26701f94aebb07 + languageName: node + linkType: hard + +"@types/lodash@npm:*": + version: 4.17.25 + resolution: "@types/lodash@npm:4.17.25" + checksum: 10/f786e05664439cc8d327fd97c62c060d81b3c4ed52127d01fbc926139e1a669c1554bf3cd0dbb43f8fcc7d9b5c6c23c543cc36de8dc815c9f289ea852b26ebd6 + languageName: node + linkType: hard + "@types/lodash@npm:^4.17.15, @types/lodash@npm:^4.17.20": version: 4.17.24 resolution: "@types/lodash@npm:4.17.24" @@ -7592,13 +7584,6 @@ __metadata: languageName: node linkType: hard -"cjs-module-lexer@npm:^1.3.1": - version: 1.4.3 - resolution: "cjs-module-lexer@npm:1.4.3" - checksum: 10/d2b92f919a2dedbfd61d016964fce8da0035f827182ed6839c97cac56e8a8077cfa6a59388adfe2bc588a19cef9bbe830d683a76a6e93c51f65852062cfe2591 - languageName: node - linkType: hard - "cjs-module-lexer@npm:^2.1.0": version: 2.2.0 resolution: "cjs-module-lexer@npm:2.2.0" @@ -11748,6 +11733,13 @@ __metadata: languageName: node linkType: hard +"lodash-es@npm:^4.17.21": + version: 4.18.1 + resolution: "lodash-es@npm:4.18.1" + checksum: 10/8bfad225ef09ef42b04283cdaf7830efcc2ba29ae41b56501c74422155ee1ccaa1f0f6e8319def3451a1fe54dec501c8e4bee622bae2b2d98ac993731e0a5cce + languageName: node + linkType: hard + "lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" From 5b58d7a8827dd7465ee2dea585f4c5f2c9a046f7 Mon Sep 17 00:00:00 2001 From: Ulisses Ferreira Date: Fri, 4 Sep 2026 14:28:08 +0100 Subject: [PATCH 2/3] fix: resolve ESM-only utilities from source in snap Jest configs Jest's CommonJS runtime cannot require the now ESM-only `@metamask/snap-networks-utils`, so map it to its uncompiled source in each snap's Jest configuration (along with the source's Node16-style `.js` specifiers and `lodash-es`). Also dedupe `@types/lodash` in the lockfile. --- packages/bitcoin-wallet-snap/jest.config.mjs | 10 ++++++++++ packages/solana-wallet-snap/jest.config.js | 10 ++++++++++ packages/stellar-wallet-snap/jest.config.js | 8 ++++++++ packages/tron-wallet-snap/jest.config.mjs | 8 ++++++++ yarn.lock | 9 +-------- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/bitcoin-wallet-snap/jest.config.mjs b/packages/bitcoin-wallet-snap/jest.config.mjs index 0bbb8e9e8..8b7d7df44 100644 --- a/packages/bitcoin-wallet-snap/jest.config.mjs +++ b/packages/bitcoin-wallet-snap/jest.config.mjs @@ -35,6 +35,16 @@ const config = { transform: { '^.+\\.(t|j)sx?$': 'ts-jest', }, + moduleNameMapper: { + // `@metamask/snap-networks-utils` is ESM-only, which Jest's CommonJS + // runtime cannot require, so map it to the uncompiled source instead. + // The source uses Node16-style `.js` specifiers and `lodash-es`, which + // must be mapped as well. + '^@metamask/snap-networks-utils$': + '/../snap-networks-utils/src/index.ts', + '^lodash-es$': 'lodash', + '^(\\.{1,2}/.*)\\.js$': '$1', + }, resetMocks: true, testMatch: ['**/src/**/?(*.)+(spec|test).[tj]s?(x)'], }; diff --git a/packages/solana-wallet-snap/jest.config.js b/packages/solana-wallet-snap/jest.config.js index 462cb7ed4..65942d669 100644 --- a/packages/solana-wallet-snap/jest.config.js +++ b/packages/solana-wallet-snap/jest.config.js @@ -7,6 +7,16 @@ module.exports = { verbose: true, // Solana tests start a mock RPC on a fixed port (8899); parallel workers collide. maxWorkers: 1, + moduleNameMapper: { + // `@metamask/snap-networks-utils` is ESM-only, which Jest's CommonJS + // runtime cannot require, so map it to the uncompiled source instead. + // The source uses Node16-style `.js` specifiers and `lodash-es`, which + // must be mapped as well. + '^@metamask/snap-networks-utils$': + '/../snap-networks-utils/src/index.ts', + '^lodash-es$': 'lodash', + '^(\\.{1,2}/.*)\\.js$': '$1', + }, collectCoverage: true, setupFilesAfterEnv: ['./jest.setup.ts'], coverageReporters: ['html', 'json-summary', 'text', 'lcov'], diff --git a/packages/stellar-wallet-snap/jest.config.js b/packages/stellar-wallet-snap/jest.config.js index 859b3a371..030b1aa4b 100644 --- a/packages/stellar-wallet-snap/jest.config.js +++ b/packages/stellar-wallet-snap/jest.config.js @@ -46,6 +46,14 @@ const config = { }, moduleNameMapper: { '\\.svg$': 'jest-transform-stub', + // `@metamask/snap-networks-utils` is ESM-only, which Jest's CommonJS + // runtime cannot require, so map it to the uncompiled source instead. + // The source uses Node16-style `.js` specifiers and `lodash-es`, which + // must be mapped as well. + '^@metamask/snap-networks-utils$': + '/../snap-networks-utils/src/index.ts', + '^lodash-es$': 'lodash', + '^(\\.{1,2}/.*)\\.js$': '$1', }, resetMocks: true, restoreMocks: true, diff --git a/packages/tron-wallet-snap/jest.config.mjs b/packages/tron-wallet-snap/jest.config.mjs index 299fdc07d..3e938d645 100644 --- a/packages/tron-wallet-snap/jest.config.mjs +++ b/packages/tron-wallet-snap/jest.config.mjs @@ -37,6 +37,14 @@ const config = { }, moduleNameMapper: { '\\.svg$': 'jest-transform-stub', + // `@metamask/snap-networks-utils` is ESM-only, which Jest's CommonJS + // runtime cannot require, so map it to the uncompiled source instead. + // The source uses Node16-style `.js` specifiers and `lodash-es`, which + // must be mapped as well. + '^@metamask/snap-networks-utils$': + '/../snap-networks-utils/src/index.ts', + '^lodash-es$': 'lodash', + '^(\\.{1,2}/.*)\\.js$': '$1', }, resetMocks: true, testMatch: ['**/src/**/?(*.)+(spec|test).[tj]s?(x)'], diff --git a/yarn.lock b/yarn.lock index 5ddd38c7c..a8c6f386a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5547,20 +5547,13 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:*": +"@types/lodash@npm:*, @types/lodash@npm:^4.17.15, @types/lodash@npm:^4.17.20": version: 4.17.25 resolution: "@types/lodash@npm:4.17.25" checksum: 10/f786e05664439cc8d327fd97c62c060d81b3c4ed52127d01fbc926139e1a669c1554bf3cd0dbb43f8fcc7d9b5c6c23c543cc36de8dc815c9f289ea852b26ebd6 languageName: node linkType: hard -"@types/lodash@npm:^4.17.15, @types/lodash@npm:^4.17.20": - version: 4.17.24 - resolution: "@types/lodash@npm:4.17.24" - checksum: 10/0f2082565f60f9787eefc046edc38458054512be5a8b3584ef0bad5fd9e85d0ab55ec5a1fbfae1ed6ba015cf1f9e837d5fb4da1f99fc60b8f74b2a46146fb00f - languageName: node - linkType: hard - "@types/minimatch@npm:^3.0.3": version: 3.0.5 resolution: "@types/minimatch@npm:3.0.5" From 5130520e7ae459a01e7edd9357b473a72a735f2c Mon Sep 17 00:00:00 2001 From: Ulisses Ferreira Date: Fri, 4 Sep 2026 14:44:11 +0100 Subject: [PATCH 3/3] fix: add .js extensions to new proofOfOwnership imports --- packages/snap-networks-utils/src/index.ts | 4 ++-- .../src/utils/proofOfOwnership/proofOfOwnership.test.ts | 2 +- .../src/utils/proofOfOwnership/proofOfOwnership.ts | 2 +- tsconfig.scripts.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/snap-networks-utils/src/index.ts b/packages/snap-networks-utils/src/index.ts index 29193938d..ae8899854 100644 --- a/packages/snap-networks-utils/src/index.ts +++ b/packages/snap-networks-utils/src/index.ts @@ -44,7 +44,7 @@ export { ProofOfOwnershipBatchSuccessStruct, ProofOfOwnershipMessageStruct, PROOF_OF_OWNERSHIP_MESSAGE_PREFIX, -} from './utils/proofOfOwnership/proofOfOwnership'; +} from './utils/proofOfOwnership/proofOfOwnership.js'; export type { ProofOfOwnershipBatchError, ProofOfOwnershipBatchItemResponse, @@ -53,7 +53,7 @@ export type { ProofOfOwnershipBatchResponse, ProofOfOwnershipBatchSuccess, ProofOfOwnershipMessage, -} from './utils/proofOfOwnership/proofOfOwnership'; +} from './utils/proofOfOwnership/proofOfOwnership.js'; export { createOriginPermissions, DEFAULT_PROD_ORIGINS, diff --git a/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.test.ts b/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.test.ts index 96217e725..50a68a7fb 100644 --- a/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.test.ts +++ b/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.test.ts @@ -7,7 +7,7 @@ import { ProofOfOwnershipMessageStruct, parseProofOfOwnershipMessage, PROOF_OF_OWNERSHIP_MESSAGE_PREFIX, -} from './proofOfOwnership'; +} from './proofOfOwnership.js'; const accountId = '11111111-1111-4111-8111-111111111111'; diff --git a/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.ts b/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.ts index 7dab48aa3..132bb839f 100644 --- a/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.ts +++ b/packages/snap-networks-utils/src/utils/proofOfOwnership/proofOfOwnership.ts @@ -1,7 +1,7 @@ import type { Infer } from '@metamask/superstruct'; import { array, nonempty, object, string, union } from '@metamask/superstruct'; -import { UuidStruct } from '../uuidStruct/uuidStruct'; +import { UuidStruct } from '../uuidStruct/uuidStruct.js'; /** * Prefix for proof-of-ownership messages signed by network snaps. diff --git a/tsconfig.scripts.json b/tsconfig.scripts.json index 52fbb82ee..40074e11f 100644 --- a/tsconfig.scripts.json +++ b/tsconfig.scripts.json @@ -10,7 +10,7 @@ "baseUrl": "./", "exactOptionalPropertyTypes": true, "forceConsistentCasingInFileNames": true, - "lib": ["ES2020"], + "lib": ["ES2022"], "noEmit": true, "noErrorTruncation": true, "noUncheckedIndexedAccess": true