diff --git a/yarn.config.cjs b/yarn.config.cjs index 548f434d4b4..7786e1cea9f 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -32,9 +32,8 @@ module.exports = defineConfig({ const isChildWorkspace = workspace.cwd !== '.'; const isPrivate = 'private' in workspace.manifest && workspace.manifest.private === true; - const workspaceDependencies = Yarn.dependencies({ workspace }); const dependenciesByIdentAndType = getDependenciesByIdentAndType( - workspaceDependencies, + Yarn.dependencies({ workspace }), ); // All packages must have a name. @@ -232,8 +231,9 @@ module.exports = defineConfig({ }); /** - * Construct a nested map of dependencies where the first layer is keyed by - * dependency ident and the second layer is keyed by dependency type. + * Construct a nested map of dependencies. The inner layer categorizes + * instances of the same dependency by its location in the manifest; the outer + * layer categorizes the inner layer by the name of the dependency. * * @param {Dependency[]} dependencies - The list of dependencies to transform. * @returns {Map>} The resulting map. @@ -260,8 +260,10 @@ function getDependenciesByIdentAndType(dependencies) { } /** - * Construct a nested map of dependencies where the first layer is keyed by - * dependency ident and the second layer is keyed by dependency range. + * Construct a nested map of non-peer dependencies (`dependencies` and + * `devDependencies`). The inner layer categorizes instances of the same + * dependency by the version range specified; the outer layer categorizes the + * inner layer by the name of the dependency itself. * * @param {Dependency[]} dependencies - The list of dependencies to transform. * @returns {Map>} The resulting map. @@ -513,11 +515,11 @@ function expectDependenciesNotInBothProdAndDev( ) { for (const [ dependencyIdent, - dependenciesByType, + dependencyInstancesByType, ] of dependenciesByIdentAndType.entries()) { if ( - dependenciesByType.size > 1 && - !dependenciesByType.has('peerDependencies') + dependencyInstancesByType.size > 1 && + !dependencyInstancesByType.has('peerDependencies') ) { workspace.error( `\`${dependencyIdent}\` cannot be listed in both \`dependencies\` and \`devDependencies\``, @@ -532,15 +534,13 @@ function expectDependenciesNotInBothProdAndDev( * listed in the workspace's `peerDependencies` and the version range satisfies * the current version of the controller package. * - * The expectation in this case is that the client will instantiate B in - * order to pass it into A. Therefore, it needs to list not only A as a - * dependency, but also B. Additionally, the version of B that the client - * is using with A needs to match the version that A itself is expecting - * internally. + * The expectation in this case is that the client will instantiate B in order + * to pass it into A. Therefore, it needs to list not only A as a dependency, + * but also B. Additionally, the version of B that the client is using with A + * needs to match the version that A itself is expecting internally. * - * Note that this constraint does not apply for packages that seem to - * represent controller singletons but actually represent abstract - * classes. + * Note that this constraint does not apply for packages that seem to represent + * instantiable controllers but actually represent abstract classes. * * @param {Yarn} Yarn - The Yarn "global". * @param {Workspace} workspace - The workspace to check. @@ -552,28 +552,29 @@ function expectControllerDependenciesListedAsPeerDependencies( workspace, dependenciesByIdentAndType, ) { - for (const dependenciesByType of dependenciesByIdentAndType.values()) { - const dependency = dependenciesByType.get('dependencies'); - - if (dependency === undefined) { + for (const [ + dependencyIdent, + dependencyInstancesByType, + ] of dependenciesByIdentAndType.entries()) { + if (!dependencyInstancesByType.has('dependencies')) { continue; } - const dependencyWorkspace = Yarn.workspace({ ident: dependency.ident }); + const dependencyWorkspace = Yarn.workspace({ ident: dependencyIdent }); if ( dependencyWorkspace !== null && - dependency.ident.endsWith('-controller') && - dependency.ident !== '@metamask/base-controller' && - dependency.ident !== '@metamask/polling-controller' && - !dependenciesByType.has('peerDependencies') + dependencyIdent.endsWith('-controller') && + dependencyIdent !== '@metamask/base-controller' && + dependencyIdent !== '@metamask/polling-controller' && + !dependencyInstancesByType.has('peerDependencies') ) { const dependencyWorkspaceVersion = new semver.SemVer( dependencyWorkspace.manifest.version, ); expectWorkspaceField( workspace, - `peerDependencies["${dependency.ident}"]`, + `peerDependencies["${dependencyIdent}"]`, `^${dependencyWorkspaceVersion.major}.0.0`, ); } @@ -594,13 +595,16 @@ function expectConsistentDependenciesAndDevDependencies(Yarn) { Yarn.dependencies(), ); - for (const dependencyRangesForIdent of nonPeerDependenciesByIdent.values()) { - const dependencyRanges = [...dependencyRangesForIdent.keys()].sort(); - if (dependencyRangesForIdent.size > 1) { - for (const dependencies of dependencyRangesForIdent.values()) { + for (const [ + dependencyIdent, + dependenciesByRange, + ] of nonPeerDependenciesByIdent.entries()) { + const dependencyRanges = [...dependenciesByRange.keys()].sort(); + if (dependenciesByRange.size > 1) { + for (const dependencies of dependenciesByRange.values()) { for (const dependency of dependencies) { dependency.error( - `Expected version range for ${dependency.ident} (in ${ + `Expected version range for ${dependencyIdent} (in ${ dependency.type }) to be consistent across monorepo. Pick one: ${inspect( dependencyRanges,