diff --git a/.eslintrc.js b/.eslintrc.js index f71ff43b3e..4b28719e52 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,9 +1,9 @@ module.exports = { root: true, - extends: ['@metamask/eslint-config', '@metamask/eslint-config-nodejs'], + extends: ['@metamask/eslint-config'], ignorePatterns: [ '!.eslintrc.js', - '!jest.config.js', + '!.prettierrc.js', 'node_modules', '**/dist', '**/docs', @@ -12,6 +12,19 @@ module.exports = { 'scripts/create-package/package-template', ], overrides: [ + { + files: [ + '**/jest.config.js', + '**/jest.environment.js', + '**/tests/**/*.{ts,js}', + '*.js', + '*.test.{ts,js}', + 'scripts/*.ts', + 'scripts/create-package/*.ts', + 'yarn.config.cjs', + ], + extends: ['@metamask/eslint-config-nodejs'], + }, { files: ['*.test.{ts,js}', '**/tests/**/*.{ts,js}'], extends: ['@metamask/eslint-config-jest'], diff --git a/packages/message-manager/README.md b/packages/message-manager/README.md index 54c03863d6..f49f66919a 100644 --- a/packages/message-manager/README.md +++ b/packages/message-manager/README.md @@ -10,6 +10,10 @@ or `npm install @metamask/message-manager` +## Compatibility + +This package relies implicitly upon the `EventEmitter` module. This module is available natively in Node.js, but when using this package for the browser, make sure to use a polyfill such as `events`. + ## Contributing This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme). diff --git a/packages/message-manager/src/AbstractMessageManager.ts b/packages/message-manager/src/AbstractMessageManager.ts index 9ede9ce7a1..bdd8401f54 100644 --- a/packages/message-manager/src/AbstractMessageManager.ts +++ b/packages/message-manager/src/AbstractMessageManager.ts @@ -2,6 +2,8 @@ import type { BaseConfig, BaseState } from '@metamask/base-controller'; import { BaseControllerV1 } from '@metamask/base-controller'; import type { ApprovalType } from '@metamask/controller-utils'; import type { Hex, Json } from '@metamask/utils'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import { EventEmitter } from 'events'; import { v1 as random } from 'uuid'; diff --git a/packages/network-controller/src/NetworkController.ts b/packages/network-controller/src/NetworkController.ts index 6b42d86d27..9484b2317a 100644 --- a/packages/network-controller/src/NetworkController.ts +++ b/packages/network-controller/src/NetworkController.ts @@ -19,13 +19,11 @@ import { errorCodes } from '@metamask/rpc-errors'; import { createEventEmitterProxy } from '@metamask/swappable-obj-proxy'; import type { SwappableProxy } from '@metamask/swappable-obj-proxy'; import type { Hex } from '@metamask/utils'; -import { isStrictHexString, hasProperty, isPlainObject } from '@metamask/utils'; -import { strict as assert } from 'assert'; +import { hasProperty, isPlainObject, isStrictHexString } from '@metamask/utils'; import type { Draft } from 'immer'; import type { Logger } from 'loglevel'; import { createSelector } from 'reselect'; import * as URI from 'uri-js'; -import { inspect } from 'util'; import { v4 as uuidV4 } from 'uuid'; import { INFURA_BLOCKED_KEY, NetworkStatus } from './constants'; @@ -515,7 +513,7 @@ function getDefaultNetworkConfigurationsByChainId(): Record< >((obj, infuraNetworkType) => { const chainId = ChainId[infuraNetworkType]; const rpcEndpointUrl = - // False negative - this is a string. + // This ESLint rule mistakenly produces an error. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `https://${infuraNetworkType}.infura.io/v3/{infuraProjectId}` as const; @@ -788,9 +786,9 @@ function validateNetworkControllerState(state: NetworkState) { if (!networkClientIds.includes(state.selectedNetworkClientId)) { throw new Error( - `NetworkController state is invalid: \`selectedNetworkClientId\` ${inspect( - state.selectedNetworkClientId, - )} does not refer to an RPC endpoint within a network configuration`, + // This ESLint rule mistakenly produces an error. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `NetworkController state is invalid: \`selectedNetworkClientId\` '${state.selectedNetworkClientId}' does not refer to an RPC endpoint within a network configuration`, ); } } @@ -1354,19 +1352,16 @@ export class NetworkController extends BaseController< * removed in a future release */ async setProviderType(type: InfuraNetworkType) { - assert.notStrictEqual( - type, - NetworkType.rpc, - // TODO: Either fix this lint violation or explain why it's necessary to ignore. - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `NetworkController - cannot call "setProviderType" with type "${NetworkType.rpc}". Use "setActiveNetwork"`, - ); - assert.ok( - isInfuraNetworkType(type), - // TODO: Either fix this lint violation or explain why it's necessary to ignore. - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `Unknown Infura provider type "${type}".`, - ); + if ((type as unknown) === NetworkType.rpc) { + throw new Error( + // This ESLint rule mistakenly produces an error. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `NetworkController - cannot call "setProviderType" with type "${NetworkType.rpc}". Use "setActiveNetwork"`, + ); + } + if (!isInfuraNetworkType(type)) { + throw new Error(`Unknown Infura provider type "${String(type)}".`); + } await this.setActiveNetwork(type); } @@ -1635,9 +1630,7 @@ export class NetworkController extends BaseController< if (existingNetworkConfiguration === undefined) { throw new Error( - `Could not update network: Cannot find network configuration for chain ${inspect( - chainId, - )}`, + `Could not update network: Cannot find network configuration for chain '${chainId}'`, ); } @@ -1802,7 +1795,7 @@ export class NetworkController extends BaseController< }) ) { throw new Error( - // False negative - this is a string. + // This ESLint rule mistakenly produces an error. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Could not update network: Cannot update RPC endpoints in such a way that the selected network '${this.state.selectedNetworkClientId}' would be removed without a replacement. Choose a different RPC endpoint as the selected network via the \`replacementSelectedRpcEndpointIndex\` option.`, ); @@ -1899,7 +1892,7 @@ export class NetworkController extends BaseController< if (existingNetworkConfiguration === undefined) { throw new Error( - `Cannot find network configuration for chain ${inspect(chainId)}`, + `Cannot find network configuration for chain '${chainId}'`, ); } @@ -2031,9 +2024,7 @@ export class NetworkController extends BaseController< !isSafeChainId(networkFields.chainId) ) { throw new Error( - `${errorMessagePrefix}: Invalid \`chainId\` ${inspect( - networkFields.chainId, - )} (must start with "0x" and not exceed the maximum)`, + `${errorMessagePrefix}: Invalid \`chainId\` '${networkFields.chainId}' (must start with "0x" and not exceed the maximum)`, ); } @@ -2046,13 +2037,13 @@ export class NetworkController extends BaseController< if (existingNetworkConfigurationViaChainId !== undefined) { if (existingNetworkConfiguration === null) { throw new Error( - // False negative - these are strings. + // This ESLint rule mistakenly produces an error. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Could not add network for chain ${args.networkFields.chainId} as another network for that chain already exists ('${existingNetworkConfigurationViaChainId.name}')`, ); } else { throw new Error( - // False negative - these are strings. + // This ESLint rule mistakenly produces an error. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Cannot move network from chain ${existingNetworkConfiguration.chainId} to ${networkFields.chainId} as another network for that chain already exists ('${existingNetworkConfigurationViaChainId.name}')`, ); @@ -2082,9 +2073,9 @@ export class NetworkController extends BaseController< for (const rpcEndpointFields of networkFields.rpcEndpoints) { if (!isValidUrl(rpcEndpointFields.url)) { throw new Error( - `${errorMessagePrefix}: An entry in \`rpcEndpoints\` has invalid URL ${inspect( - rpcEndpointFields.url, - )}`, + // This ESLint rule mistakenly produces an error. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `${errorMessagePrefix}: An entry in \`rpcEndpoints\` has invalid URL '${rpcEndpointFields.url}'`, ); } const networkClientId = @@ -2113,13 +2104,9 @@ export class NetworkController extends BaseController< ) ) { throw new Error( - `${errorMessagePrefix}: RPC endpoint '${ - // This is a string. - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - rpcEndpointFields.url - }' refers to network client ${inspect( - networkClientId, - )} that does not exist`, + // This is a string. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `${errorMessagePrefix}: RPC endpoint '${rpcEndpointFields.url}' refers to network client '${networkClientId}' that does not exist`, ); } @@ -2149,15 +2136,19 @@ export class NetworkController extends BaseController< URI.equal(rpcEndpointFields.url, existingRpcEndpoint.url), ); if (rpcEndpoint) { - throw new Error( - mode === 'update' - ? // False negative - these are strings. - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `Could not update network to point to same RPC endpoint as existing network for chain ${networkConfiguration.chainId} ('${networkConfiguration.name}')` - : // False negative - these are strings. - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `Could not add network that points to same RPC endpoint as existing network for chain ${networkConfiguration.chainId} ('${networkConfiguration.name}')`, - ); + if (mode === 'update') { + throw new Error( + // This ESLint rule mistakenly produces an error. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Could not update network to point to same RPC endpoint as existing network for chain ${networkConfiguration.chainId} ('${networkConfiguration.name}')`, + ); + } else { + throw new Error( + // This ESLint rule mistakenly produces an error. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Could not add network that points to same RPC endpoint as existing network for chain ${networkConfiguration.chainId} ('${networkConfiguration.name}')`, + ); + } } } } @@ -2561,7 +2552,7 @@ export class NetworkController extends BaseController< /* istanbul ignore if */ if (!possibleAutoManagedNetworkClient) { throw new Error( - `No Infura network client found with ID ${inspect(networkClientId)}`, + `No Infura network client found with ID '${networkClientId}'`, ); } @@ -2573,9 +2564,7 @@ export class NetworkController extends BaseController< ]; if (!possibleAutoManagedNetworkClient) { - throw new Error( - `No network client found with ID ${inspect(networkClientId)}`, - ); + throw new Error(`No network client found with ID '${networkClientId}'`); } autoManagedNetworkClient = possibleAutoManagedNetworkClient; diff --git a/packages/signature-controller/README.md b/packages/signature-controller/README.md index 76ea0cad92..179546cd6b 100644 --- a/packages/signature-controller/README.md +++ b/packages/signature-controller/README.md @@ -10,6 +10,10 @@ or `npm install @metamask/signature-controller` +## Compatibility + +This package relies implicitly upon the `EventEmitter` module. This module is available natively in Node.js, but when using this package for the browser, make sure to use a polyfill such as `events`. + ## Contributing This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme). diff --git a/packages/signature-controller/src/SignatureController.ts b/packages/signature-controller/src/SignatureController.ts index 86660b0cb1..b6a61f374d 100644 --- a/packages/signature-controller/src/SignatureController.ts +++ b/packages/signature-controller/src/SignatureController.ts @@ -29,6 +29,8 @@ import { } from '@metamask/logging-controller'; import type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller'; import type { Hex, Json } from '@metamask/utils'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import { v1 as random } from 'uuid'; diff --git a/packages/transaction-controller/README.md b/packages/transaction-controller/README.md index 8c7b8af337..16447e874f 100644 --- a/packages/transaction-controller/README.md +++ b/packages/transaction-controller/README.md @@ -10,6 +10,10 @@ or `npm install @metamask/transaction-controller` +## Compatibility + +This package relies implicitly upon the `EventEmitter` module. This module is available natively in Node.js, but when using this package for the browser, make sure to use a polyfill such as `events`. + ## Contributing This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme). diff --git a/packages/transaction-controller/src/TransactionController.ts b/packages/transaction-controller/src/TransactionController.ts index 8dbfafc876..e6d0c06c59 100644 --- a/packages/transaction-controller/src/TransactionController.ts +++ b/packages/transaction-controller/src/TransactionController.ts @@ -46,6 +46,8 @@ import { errorCodes, rpcErrors, providerErrors } from '@metamask/rpc-errors'; import type { Hex } from '@metamask/utils'; import { add0x, hexToNumber } from '@metamask/utils'; import { Mutex } from 'async-mutex'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import { EventEmitter } from 'events'; import { cloneDeep, mapValues, merge, pickBy, sortBy } from 'lodash'; import { v1 as random } from 'uuid'; diff --git a/packages/transaction-controller/src/helpers/GasFeePoller.ts b/packages/transaction-controller/src/helpers/GasFeePoller.ts index 1e8a94a1c4..b4b87a94dc 100644 --- a/packages/transaction-controller/src/helpers/GasFeePoller.ts +++ b/packages/transaction-controller/src/helpers/GasFeePoller.ts @@ -6,6 +6,8 @@ import type { import type { NetworkClientId, Provider } from '@metamask/network-controller'; import type { Hex } from '@metamask/utils'; import { createModuleLogger } from '@metamask/utils'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import { projectLogger } from '../logger'; diff --git a/packages/transaction-controller/src/helpers/IncomingTransactionHelper.ts b/packages/transaction-controller/src/helpers/IncomingTransactionHelper.ts index e1ce6f0d07..12c6ddb445 100644 --- a/packages/transaction-controller/src/helpers/IncomingTransactionHelper.ts +++ b/packages/transaction-controller/src/helpers/IncomingTransactionHelper.ts @@ -2,6 +2,8 @@ import type { AccountsController } from '@metamask/accounts-controller'; import type { BlockTracker } from '@metamask/network-controller'; import type { Hex } from '@metamask/utils'; import { Mutex } from 'async-mutex'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import { diff --git a/packages/transaction-controller/src/helpers/MethodDataHelper.ts b/packages/transaction-controller/src/helpers/MethodDataHelper.ts index 864aee8c2c..54dbdb6ab4 100644 --- a/packages/transaction-controller/src/helpers/MethodDataHelper.ts +++ b/packages/transaction-controller/src/helpers/MethodDataHelper.ts @@ -2,6 +2,8 @@ import type { NetworkClientId, Provider } from '@metamask/network-controller'; import { createModuleLogger } from '@metamask/utils'; import { Mutex } from 'async-mutex'; import { MethodRegistry } from 'eth-method-registry'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import { projectLogger } from '../logger'; diff --git a/packages/transaction-controller/src/helpers/PendingTransactionTracker.ts b/packages/transaction-controller/src/helpers/PendingTransactionTracker.ts index c159e66f01..5520fe3a71 100644 --- a/packages/transaction-controller/src/helpers/PendingTransactionTracker.ts +++ b/packages/transaction-controller/src/helpers/PendingTransactionTracker.ts @@ -4,6 +4,8 @@ import type { BlockTracker, NetworkClientId, } from '@metamask/network-controller'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import { cloneDeep, merge } from 'lodash'; diff --git a/packages/user-operation-controller/README.md b/packages/user-operation-controller/README.md index 4994989e8d..2359ee1e9a 100644 --- a/packages/user-operation-controller/README.md +++ b/packages/user-operation-controller/README.md @@ -10,6 +10,10 @@ or `npm install @metamask/user-operation-controller` +## Compatibility + +This package relies implicitly upon the `EventEmitter` module. This module is available natively in Node.js, but when using this package for the browser, make sure to use a polyfill such as `events`. + ## Contributing This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme). diff --git a/packages/user-operation-controller/src/UserOperationController.ts b/packages/user-operation-controller/src/UserOperationController.ts index 492233d33c..2c70bd80c6 100644 --- a/packages/user-operation-controller/src/UserOperationController.ts +++ b/packages/user-operation-controller/src/UserOperationController.ts @@ -25,6 +25,8 @@ import { type TransactionType, } from '@metamask/transaction-controller'; import { add0x } from '@metamask/utils'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import type { Patch } from 'immer'; import { cloneDeep } from 'lodash'; diff --git a/packages/user-operation-controller/src/helpers/PendingUserOperationTracker.ts b/packages/user-operation-controller/src/helpers/PendingUserOperationTracker.ts index 2d5c1ca366..54fa8ce602 100644 --- a/packages/user-operation-controller/src/helpers/PendingUserOperationTracker.ts +++ b/packages/user-operation-controller/src/helpers/PendingUserOperationTracker.ts @@ -7,6 +7,8 @@ import type { } from '@metamask/network-controller'; import { BlockTrackerPollingControllerOnly } from '@metamask/polling-controller'; import { createModuleLogger, type Hex } from '@metamask/utils'; +// This package purposefully relies on Node's EventEmitter module. +// eslint-disable-next-line import/no-nodejs-modules import EventEmitter from 'events'; import { projectLogger } from '../logger'; diff --git a/scripts/create-package/utils.test.ts b/scripts/create-package/utils.test.ts index b33e268b5a..1c5615fb95 100644 --- a/scripts/create-package/utils.test.ts +++ b/scripts/create-package/utils.test.ts @@ -14,6 +14,7 @@ jest.mock('fs', () => ({ mkdir: jest.fn(), readFile: jest.fn(), writeFile: jest.fn(), + stat: jest.fn(), }, })); @@ -86,7 +87,9 @@ describe('create-package/utils', () => { nodeVersions: '>=18.0.0', }; - (fs.existsSync as jest.Mock).mockReturnValueOnce(false); + (fs.promises.stat as jest.Mock).mockResolvedValueOnce({ + isDirectory: () => false, + }); (fsUtils.readAllFiles as jest.Mock).mockResolvedValueOnce({ 'src/index.ts': 'export default 42;', @@ -167,7 +170,9 @@ describe('create-package/utils', () => { nodeVersions: '20.0.0', }; - (fs.existsSync as jest.Mock).mockReturnValueOnce(true); + (fs.promises.stat as jest.Mock).mockResolvedValueOnce({ + isDirectory: () => true, + }); await expect( finalizeAndWriteData(packageData, monorepoFileData), diff --git a/scripts/create-package/utils.ts b/scripts/create-package/utils.ts index 02a731e2f6..85c24d10a8 100644 --- a/scripts/create-package/utils.ts +++ b/scripts/create-package/utils.ts @@ -1,5 +1,5 @@ import execa from 'execa'; -import { existsSync, promises as fs } from 'fs'; +import { promises as fs } from 'fs'; import path from 'path'; import { format as prettierFormat } from 'prettier'; import type { Options as PrettierOptions } from 'prettier'; @@ -94,7 +94,7 @@ export async function finalizeAndWriteData( monorepoFileData: MonorepoFileData, ) { const packagePath = path.join(PACKAGES_PATH, packageData.directoryName); - if (existsSync(packagePath)) { + if ((await fs.stat(packagePath)).isDirectory()) { throw new Error(`The package directory already exists: ${packagePath}`); }