@@ -193,25 +193,27 @@ module.exports = defineConfig({
193
193
// If one workspace package lists another workspace package within
194
194
// `dependencies` or `devDependencies`, the version used within the
195
195
// dependency range must match the current version of the dependency.
196
- expectUpToDateWorkspaceDependenciesAndDevDependencies ( Yarn , workspace ) ;
196
+ expectUpToDateWorkspaceDependenciesAndDevDependencies (
197
+ Yarn ,
198
+ dependenciesByIdentAndType ,
199
+ ) ;
197
200
198
201
// If one workspace package lists another workspace package within
199
202
// `peerDependencies`, the dependency range must satisfy the current
200
203
// version of that package.
201
204
expectUpToDateWorkspacePeerDependencies ( Yarn , workspace ) ;
202
205
203
206
// No dependency may be listed under both `dependencies` and
204
- // `devDependencies`.
205
- expectDependenciesNotInBothProdAndDev (
207
+ // `devDependencies`, or under both `dependencies` and `peerDependencies` .
208
+ expectDependenciesNotInBothProdAndDevOrPeer (
206
209
workspace ,
207
210
dependenciesByIdentAndType ,
208
211
) ;
209
212
210
- // If one workspace package (A) lists another workspace package (B) in its
211
- // `dependencies`, and B is a controller package, then we need to ensure
212
- // that B is also listed in A's `peerDependencies` and that the version
213
- // range satisfies the current version of B.
214
- expectControllerDependenciesListedAsPeerDependencies (
213
+ // If one package A lists another package B in its `peerDependencies`,
214
+ // then B must also be listed in A's `devDependencies`, and if B is a
215
+ // workspace package, the dev dependency must match B's version.
216
+ expectPeerDependenciesAlsoListedAsDevDependencies (
215
217
Yarn ,
216
218
workspace ,
217
219
dependenciesByIdentAndType ,
@@ -250,15 +252,14 @@ module.exports = defineConfig({
250
252
}
251
253
252
254
// All version ranges in `dependencies` and `devDependencies` for the same
253
- // dependency across the monorepo must be the same.
255
+ // non-workspace dependency across the monorepo must be the same.
254
256
expectConsistentDependenciesAndDevDependencies ( Yarn ) ;
255
257
} ,
256
258
} ) ;
257
259
258
260
/**
259
- * Construct a nested map of dependencies. The inner layer categorizes
260
- * instances of the same dependency by its location in the manifest; the outer
261
- * layer categorizes the inner layer by the name of the dependency.
261
+ * Organizes the given dependencies by name and type (`dependencies`,
262
+ * `devDependencies`, or `peerDependencies`).
262
263
*
263
264
* @param {Dependency[] } dependencies - The list of dependencies to transform.
264
265
* @returns {Map<string, Map<DependencyType, Dependency>> } The resulting map.
@@ -381,12 +382,15 @@ async function workspaceFileExists(workspace, path) {
381
382
}
382
383
383
384
/**
384
- * Expect that the workspace has the given field, and that it is a non-null
385
- * value. If the field is not present, or is null, this will log an error, and
386
- * cause the constraint to fail.
385
+ * This function does one of three things depending on the arguments given:
387
386
*
388
- * If a value is provided, this will also verify that the field is equal to the
389
- * given value.
387
+ * - With no value provided, this will expect that the workspace has the given
388
+ * field and that it is a non-null value; if the field is not present or is
389
+ * null, this will log an error and cause the constraint to fail.
390
+ * - With a value is provided, and the value is non-null, this will verify that
391
+ * the field is equal to the given value.
392
+ * - With a value is provided, and the value is null, this will verify that the
393
+ * field is not present.
390
394
*
391
395
* @param {Workspace } workspace - The workspace to check.
392
396
* @param {string } fieldName - The field to check.
@@ -592,25 +596,37 @@ function expectCorrectWorkspaceChangelogScripts(workspace) {
592
596
593
597
/**
594
598
* Expect that if the workspace package lists another workspace package within
595
- * `dependencies` or `devDependencies`, the version used within the dependency
596
- * range is exactly equal to the current version of the dependency (and the
597
- * range uses the `^` modifier).
599
+ * `devDependencies`, or lists another workspace package within `dependencies`
600
+ * (and does not already list it in `peerDependencies`), the version used within
601
+ * the dependency range is exactly equal to the current version of the
602
+ * dependency (and the range uses the `^` modifier).
598
603
*
599
604
* @param {Yarn } Yarn - The Yarn "global".
600
- * @param {Workspace } workspace - The workspace to check.
605
+ * @param {Map<string, Map<DependencyType, Dependency>> } dependenciesByIdentAndType -
606
+ * Map of dependency ident to dependency type and dependency.
601
607
*/
602
608
function expectUpToDateWorkspaceDependenciesAndDevDependencies (
603
609
Yarn ,
604
- workspace ,
610
+ dependenciesByIdentAndType ,
605
611
) {
606
- for ( const dependency of Yarn . dependencies ( { workspace } ) ) {
607
- const dependencyWorkspace = Yarn . workspace ( { ident : dependency . ident } ) ;
612
+ for ( const [
613
+ dependencyIdent ,
614
+ dependencyInstancesByType ,
615
+ ] of dependenciesByIdentAndType . entries ( ) ) {
616
+ const dependencyWorkspace = Yarn . workspace ( { ident : dependencyIdent } ) ;
608
617
609
- if (
610
- dependencyWorkspace !== null &&
611
- dependency . type !== 'peerDependencies'
612
- ) {
613
- const ignoredRanges = ALLOWED_INCONSISTENT_DEPENDENCIES [ dependency . ident ] ;
618
+ if ( ! dependencyWorkspace ) {
619
+ continue ;
620
+ }
621
+
622
+ const devDependency = dependencyInstancesByType . get ( 'devDependencies' ) ;
623
+ const prodDependency = dependencyInstancesByType . get ( 'dependencies' ) ;
624
+ const peerDependency = dependencyInstancesByType . get ( 'peerDependencies' ) ;
625
+
626
+ if ( devDependency || ( prodDependency && ! peerDependency ) ) {
627
+ const dependency = devDependency ?? prodDependency ;
628
+
629
+ const ignoredRanges = ALLOWED_INCONSISTENT_DEPENDENCIES [ dependencyIdent ] ;
614
630
if ( ignoredRanges ?. includes ( dependency . range ) ) {
615
631
continue ;
616
632
}
@@ -645,63 +661,64 @@ function expectUpToDateWorkspacePeerDependencies(Yarn, workspace) {
645
661
dependency . range ,
646
662
)
647
663
) {
648
- expectWorkspaceField (
649
- workspace ,
650
- `peerDependencies["${ dependency . ident } "]` ,
651
- `^${ dependencyWorkspaceVersion . major } .0.0` ,
652
- ) ;
664
+ dependency . update ( `^${ dependencyWorkspaceVersion . major } .0.0` ) ;
653
665
}
654
666
}
655
667
}
656
668
}
657
669
658
670
/**
659
671
* Expect that a workspace package does not list a dependency in both
660
- * `dependencies` and `devDependencies`.
672
+ * `dependencies` and `devDependencies`, or in both `dependencies` and
673
+ * `peerDependencies`.
661
674
*
662
675
* @param {Workspace } workspace - The workspace to check.
663
- * @param {Map<string, Map<DependencyType, Dependency>> } dependenciesByIdentAndType - Map of
664
- * dependency ident to dependency type and dependency.
676
+ * @param {Map<string, Map<DependencyType, Dependency>> } dependenciesByIdentAndType -
677
+ * Map of dependency ident to dependency type and dependency.
665
678
*/
666
- function expectDependenciesNotInBothProdAndDev (
679
+ function expectDependenciesNotInBothProdAndDevOrPeer (
667
680
workspace ,
668
681
dependenciesByIdentAndType ,
669
682
) {
670
683
for ( const [
671
684
dependencyIdent ,
672
685
dependencyInstancesByType ,
673
686
] of dependenciesByIdentAndType . entries ( ) ) {
674
- if (
675
- dependencyInstancesByType . size > 1 &&
676
- ! dependencyInstancesByType . has ( 'peerDependencies' )
677
- ) {
687
+ const dependency = dependencyInstancesByType . get ( 'dependencies' ) ;
688
+ if ( dependency === undefined ) {
689
+ continue ;
690
+ }
691
+ if ( dependencyInstancesByType . has ( 'devDependencies' ) ) {
678
692
workspace . error (
679
693
`\`${ dependencyIdent } \` cannot be listed in both \`dependencies\` and \`devDependencies\`` ,
680
694
) ;
695
+ } else if ( dependencyInstancesByType . has ( 'peerDependencies' ) ) {
696
+ expectWorkspaceField (
697
+ workspace ,
698
+ `devDependencies["${ dependencyIdent } "]` ,
699
+ dependency . range ,
700
+ ) ;
701
+ expectWorkspaceField (
702
+ workspace ,
703
+ `dependencies["${ dependencyIdent } "]` ,
704
+ null ,
705
+ ) ;
681
706
}
682
707
}
683
708
}
684
709
685
710
/**
686
- * Expect that if the workspace package lists another workspace package in its
687
- * dependencies, and it is a controller package, that the controller package is
688
- * listed in the workspace's `peerDependencies` and the version range satisfies
689
- * the current version of the controller package.
690
- *
691
- * The expectation in this case is that the client will instantiate B in order
692
- * to pass it into A. Therefore, it needs to list not only A as a dependency,
693
- * but also B. Additionally, the version of B that the client is using with A
694
- * needs to match the version that A itself is expecting internally.
695
- *
696
- * Note that this constraint does not apply for packages that seem to represent
697
- * instantiable controllers but actually represent abstract classes.
711
+ * Expect that if the workspace package lists another package in its
712
+ * `peerDependencies`, the package is also listed in the workspace's
713
+ * `devDependencies`. If the other package is a workspace package, also expect
714
+ * that the dev dependency matches the current version of the package.
698
715
*
699
716
* @param {Yarn } Yarn - The Yarn "global".
700
717
* @param {Workspace } workspace - The workspace to check.
701
718
* @param {Map<string, Map<DependencyType, Dependency>> } dependenciesByIdentAndType - Map of
702
719
* dependency ident to dependency type and dependency.
703
720
*/
704
- function expectControllerDependenciesListedAsPeerDependencies (
721
+ function expectPeerDependenciesAlsoListedAsDevDependencies (
705
722
Yarn ,
706
723
workspace ,
707
724
dependenciesByIdentAndType ,
@@ -710,27 +727,20 @@ function expectControllerDependenciesListedAsPeerDependencies(
710
727
dependencyIdent ,
711
728
dependencyInstancesByType ,
712
729
] of dependenciesByIdentAndType . entries ( ) ) {
713
- if ( ! dependencyInstancesByType . has ( 'dependencies ' ) ) {
730
+ if ( ! dependencyInstancesByType . has ( 'peerDependencies ' ) ) {
714
731
continue ;
715
732
}
716
733
717
734
const dependencyWorkspace = Yarn . workspace ( { ident : dependencyIdent } ) ;
718
735
719
- if (
720
- dependencyWorkspace !== null &&
721
- dependencyIdent . endsWith ( '-controller' ) &&
722
- dependencyIdent !== '@metamask/base-controller' &&
723
- dependencyIdent !== '@metamask/polling-controller' &&
724
- ! dependencyInstancesByType . has ( 'peerDependencies' )
725
- ) {
726
- const dependencyWorkspaceVersion = new semver . SemVer (
727
- dependencyWorkspace . manifest . version ,
728
- ) ;
736
+ if ( dependencyWorkspace ) {
729
737
expectWorkspaceField (
730
738
workspace ,
731
- `peerDependencies ["${ dependencyIdent } "]` ,
732
- `^${ dependencyWorkspaceVersion . major } .0.0 ` ,
739
+ `devDependencies ["${ dependencyIdent } "]` ,
740
+ `^${ dependencyWorkspace . manifest . version } ` ,
733
741
) ;
742
+ } else {
743
+ expectWorkspaceField ( workspace , `devDependencies["${ dependencyIdent } "]` ) ;
734
744
}
735
745
}
736
746
}
@@ -758,11 +768,10 @@ function getInconsistentDependenciesAndDevDependencies(
758
768
}
759
769
760
770
/**
761
- * Expect that all version ranges in `dependencies` and `devDependencies` for
762
- * the same dependency across the entire monorepo are the same. As it is
763
- * impossible to compare NPM version ranges, let the user decide if there are
764
- * conflicts. (`peerDependencies` is a special case, and we handle that
765
- * particularly for workspace packages elsewhere.)
771
+ * Expect that across the entire monorepo all version ranges in `dependencies`
772
+ * and `devDependencies` for the same dependency are the same (as long as it is
773
+ * not a dependency on a workspace package). As it is impossible to compare NPM
774
+ * version ranges, let the user decide if there are conflicts.
766
775
*
767
776
* @param {Yarn } Yarn - The Yarn "global".
768
777
*/
@@ -775,15 +784,19 @@ function expectConsistentDependenciesAndDevDependencies(Yarn) {
775
784
dependencyIdent ,
776
785
dependenciesByRange ,
777
786
] of nonPeerDependenciesByIdent . entries ( ) ) {
778
- if ( dependenciesByRange . size <= 1 ) {
787
+ const dependencyWorkspace = Yarn . workspace ( { ident : dependencyIdent } ) ;
788
+
789
+ if ( dependenciesByRange . size <= 1 || dependencyWorkspace ) {
779
790
continue ;
780
791
}
792
+
781
793
const dependenciesToConsider =
782
794
getInconsistentDependenciesAndDevDependencies (
783
795
dependencyIdent ,
784
796
dependenciesByRange ,
785
797
) ;
786
798
const dependencyRanges = [ ...dependenciesToConsider . keys ( ) ] . sort ( ) ;
799
+
787
800
for ( const dependencies of dependenciesToConsider . values ( ) ) {
788
801
for ( const dependency of dependencies ) {
789
802
dependency . error (
0 commit comments