yarn-berry-deduplicate 6.1.3 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -141
  3. package/dist/applyClusterFixes.js +246 -0
  4. package/dist/applyClusterFixes.js.map +1 -0
  5. package/dist/applyClusterFixes.test.js +306 -0
  6. package/dist/applyClusterFixes.test.js.map +1 -0
  7. package/dist/bin/yarn-berry-deduplicate.js +37 -0
  8. package/dist/bin/yarn-berry-deduplicate.js.map +1 -0
  9. package/dist/bin/yarn-berry-deduplicate.test.js +177 -0
  10. package/dist/bin/yarn-berry-deduplicate.test.js.map +1 -0
  11. package/dist/bin/yarn-berry-why-duplicate.js +23 -0
  12. package/dist/bin/yarn-berry-why-duplicate.js.map +1 -0
  13. package/dist/dedupeEndToEnd.test.js +140 -0
  14. package/dist/dedupeEndToEnd.test.js.map +1 -0
  15. package/dist/definitions/applyClusterFixes.d.ts +23 -0
  16. package/dist/definitions/applyClusterFixes.d.ts.map +1 -0
  17. package/dist/definitions/applyClusterFixes.test.d.ts +2 -0
  18. package/dist/definitions/applyClusterFixes.test.d.ts.map +1 -0
  19. package/dist/definitions/bin/yarn-berry-deduplicate.d.ts +3 -0
  20. package/dist/definitions/bin/yarn-berry-deduplicate.d.ts.map +1 -0
  21. package/dist/definitions/bin/yarn-berry-deduplicate.test.d.ts +2 -0
  22. package/dist/definitions/bin/yarn-berry-deduplicate.test.d.ts.map +1 -0
  23. package/dist/definitions/bin/yarn-berry-why-duplicate.d.ts +3 -0
  24. package/dist/definitions/bin/yarn-berry-why-duplicate.d.ts.map +1 -0
  25. package/dist/definitions/dedupeEndToEnd.test.d.ts +2 -0
  26. package/dist/definitions/dedupeEndToEnd.test.d.ts.map +1 -0
  27. package/dist/definitions/displayMany.d.ts +17 -0
  28. package/dist/definitions/displayMany.d.ts.map +1 -0
  29. package/dist/definitions/displayMany.test.d.ts +2 -0
  30. package/dist/definitions/displayMany.test.d.ts.map +1 -0
  31. package/dist/definitions/helpers/applyIdentifiedFixesToYarnLock.d.ts +25 -0
  32. package/dist/definitions/helpers/applyIdentifiedFixesToYarnLock.d.ts.map +1 -0
  33. package/dist/definitions/helpers/applyIdentifiedFixesToYarnLock.test.d.ts +2 -0
  34. package/dist/definitions/helpers/applyIdentifiedFixesToYarnLock.test.d.ts.map +1 -0
  35. package/dist/definitions/helpers/buildYarnPackagesMap.d.ts +11 -0
  36. package/dist/definitions/helpers/buildYarnPackagesMap.d.ts.map +1 -0
  37. package/dist/definitions/helpers/buildYarnPackagesMap.test.d.ts +2 -0
  38. package/dist/definitions/helpers/buildYarnPackagesMap.test.d.ts.map +1 -0
  39. package/dist/definitions/helpers/collectWorkspaces.d.ts +25 -0
  40. package/dist/definitions/helpers/collectWorkspaces.d.ts.map +1 -0
  41. package/dist/definitions/helpers/collectWorkspaces.test.d.ts +2 -0
  42. package/dist/definitions/helpers/collectWorkspaces.test.d.ts.map +1 -0
  43. package/dist/definitions/helpers/collectYarnDependents.d.ts +26 -0
  44. package/dist/definitions/helpers/collectYarnDependents.d.ts.map +1 -0
  45. package/dist/definitions/helpers/collectYarnDependents.test.d.ts +2 -0
  46. package/dist/definitions/helpers/collectYarnDependents.test.d.ts.map +1 -0
  47. package/dist/definitions/helpers/duplicateSnapshot.d.ts +3 -0
  48. package/dist/definitions/helpers/duplicateSnapshot.d.ts.map +1 -0
  49. package/dist/definitions/helpers/fixtures.d.ts +14 -0
  50. package/dist/definitions/helpers/fixtures.d.ts.map +1 -0
  51. package/dist/definitions/helpers/packageJsonResolutions.d.ts +8 -0
  52. package/dist/definitions/helpers/packageJsonResolutions.d.ts.map +1 -0
  53. package/dist/definitions/helpers/packageJsonResolutions.test.d.ts +2 -0
  54. package/dist/definitions/helpers/packageJsonResolutions.test.d.ts.map +1 -0
  55. package/dist/definitions/helpers/parseYarnLockPackages.d.ts +21 -0
  56. package/dist/definitions/helpers/parseYarnLockPackages.d.ts.map +1 -0
  57. package/dist/definitions/helpers/parseYarnLockPackages.test.d.ts +2 -0
  58. package/dist/definitions/helpers/parseYarnLockPackages.test.d.ts.map +1 -0
  59. package/dist/definitions/helpers/projectDir.d.ts +3 -0
  60. package/dist/definitions/helpers/projectDir.d.ts.map +1 -0
  61. package/dist/definitions/helpers/runYarn.d.ts +11 -0
  62. package/dist/definitions/helpers/runYarn.d.ts.map +1 -0
  63. package/dist/definitions/helpers/syml.d.ts +27 -0
  64. package/dist/definitions/helpers/syml.d.ts.map +1 -0
  65. package/dist/definitions/helpers/tempProjects.d.ts +8 -0
  66. package/dist/definitions/helpers/tempProjects.d.ts.map +1 -0
  67. package/dist/definitions/helpers/toLockstepGraph.d.ts +4 -0
  68. package/dist/definitions/helpers/toLockstepGraph.d.ts.map +1 -0
  69. package/dist/definitions/helpers/toLockstepGraph.test.d.ts +2 -0
  70. package/dist/definitions/helpers/toLockstepGraph.test.d.ts.map +1 -0
  71. package/dist/definitions/helpers/versionsSnapshot.d.ts +5 -0
  72. package/dist/definitions/helpers/versionsSnapshot.d.ts.map +1 -0
  73. package/dist/definitions/helpers/writeYarnLockFile.d.ts +3 -0
  74. package/dist/definitions/helpers/writeYarnLockFile.d.ts.map +1 -0
  75. package/dist/definitions/helpers/yarnDescriptor.d.ts +6 -0
  76. package/dist/definitions/helpers/yarnDescriptor.d.ts.map +1 -0
  77. package/dist/definitions/helpers/yarnDescriptor.test.d.ts +2 -0
  78. package/dist/definitions/helpers/yarnDescriptor.test.d.ts.map +1 -0
  79. package/dist/definitions/helpers/yarnProtocol.d.ts +2 -0
  80. package/dist/definitions/helpers/yarnProtocol.d.ts.map +1 -0
  81. package/dist/definitions/identifyClusterFixes.d.ts +7 -0
  82. package/dist/definitions/identifyClusterFixes.d.ts.map +1 -0
  83. package/dist/definitions/identifyClusterFixes.test.d.ts +2 -0
  84. package/dist/definitions/identifyClusterFixes.test.d.ts.map +1 -0
  85. package/dist/definitions/identifyResolutionFixes.test.d.ts +2 -0
  86. package/dist/definitions/identifyResolutionFixes.test.d.ts.map +1 -0
  87. package/dist/definitions/index.d.ts +40 -0
  88. package/dist/definitions/index.d.ts.map +1 -0
  89. package/dist/definitions/readYarnLock.d.ts +10 -0
  90. package/dist/definitions/readYarnLock.d.ts.map +1 -0
  91. package/dist/definitions/readYarnLock.test.d.ts +2 -0
  92. package/dist/definitions/readYarnLock.test.d.ts.map +1 -0
  93. package/dist/displayMany.js +61 -0
  94. package/dist/displayMany.js.map +1 -0
  95. package/dist/displayMany.test.js +79 -0
  96. package/dist/displayMany.test.js.map +1 -0
  97. package/dist/helpers/applyIdentifiedFixesToYarnLock.js +99 -0
  98. package/dist/helpers/applyIdentifiedFixesToYarnLock.js.map +1 -0
  99. package/dist/helpers/applyIdentifiedFixesToYarnLock.test.js +245 -0
  100. package/dist/helpers/applyIdentifiedFixesToYarnLock.test.js.map +1 -0
  101. package/dist/helpers/buildYarnPackagesMap.js +22 -0
  102. package/dist/helpers/buildYarnPackagesMap.js.map +1 -0
  103. package/dist/helpers/buildYarnPackagesMap.test.js +37 -0
  104. package/dist/helpers/buildYarnPackagesMap.test.js.map +1 -0
  105. package/dist/helpers/collectWorkspaces.js +53 -0
  106. package/dist/helpers/collectWorkspaces.js.map +1 -0
  107. package/dist/helpers/collectWorkspaces.test.js +60 -0
  108. package/dist/helpers/collectWorkspaces.test.js.map +1 -0
  109. package/dist/helpers/collectYarnDependents.js +138 -0
  110. package/dist/helpers/collectYarnDependents.js.map +1 -0
  111. package/dist/helpers/collectYarnDependents.test.js +156 -0
  112. package/dist/helpers/collectYarnDependents.test.js.map +1 -0
  113. package/dist/helpers/duplicateSnapshot.js +5 -0
  114. package/dist/helpers/duplicateSnapshot.js.map +1 -0
  115. package/dist/helpers/fixtures.js +20 -0
  116. package/dist/helpers/fixtures.js.map +1 -0
  117. package/dist/helpers/packageJsonResolutions.js +16 -0
  118. package/dist/helpers/packageJsonResolutions.js.map +1 -0
  119. package/dist/helpers/packageJsonResolutions.test.js +17 -0
  120. package/dist/helpers/packageJsonResolutions.test.js.map +1 -0
  121. package/dist/helpers/parseYarnLockPackages.js +47 -0
  122. package/dist/helpers/parseYarnLockPackages.js.map +1 -0
  123. package/dist/helpers/parseYarnLockPackages.test.js +63 -0
  124. package/dist/helpers/parseYarnLockPackages.test.js.map +1 -0
  125. package/dist/helpers/projectDir.js +10 -0
  126. package/dist/helpers/projectDir.js.map +1 -0
  127. package/dist/helpers/runYarn.js +12 -0
  128. package/dist/helpers/runYarn.js.map +1 -0
  129. package/dist/helpers/syml.js +9 -0
  130. package/dist/helpers/syml.js.map +1 -0
  131. package/dist/helpers/tempProjects.js +85 -0
  132. package/dist/helpers/tempProjects.js.map +1 -0
  133. package/dist/helpers/toLockstepGraph.js +44 -0
  134. package/dist/helpers/toLockstepGraph.js.map +1 -0
  135. package/dist/helpers/toLockstepGraph.test.js +41 -0
  136. package/dist/helpers/toLockstepGraph.test.js.map +1 -0
  137. package/dist/helpers/versionsSnapshot.js +6 -0
  138. package/dist/helpers/versionsSnapshot.js.map +1 -0
  139. package/dist/helpers/writeYarnLockFile.js +16 -0
  140. package/dist/helpers/writeYarnLockFile.js.map +1 -0
  141. package/dist/helpers/yarnDescriptor.js +25 -0
  142. package/dist/helpers/yarnDescriptor.js.map +1 -0
  143. package/dist/helpers/yarnDescriptor.test.js +53 -0
  144. package/dist/helpers/yarnDescriptor.test.js.map +1 -0
  145. package/dist/helpers/yarnProtocol.js +2 -0
  146. package/dist/helpers/yarnProtocol.js.map +1 -0
  147. package/dist/identifyClusterFixes.js +52 -0
  148. package/dist/identifyClusterFixes.js.map +1 -0
  149. package/dist/identifyClusterFixes.test.js +99 -0
  150. package/dist/identifyClusterFixes.test.js.map +1 -0
  151. package/dist/identifyResolutionFixes.test.js +79 -0
  152. package/dist/identifyResolutionFixes.test.js.map +1 -0
  153. package/dist/index.js +174 -55
  154. package/dist/index.js.map +1 -1
  155. package/dist/readYarnLock.js +17 -0
  156. package/dist/readYarnLock.js.map +1 -0
  157. package/dist/readYarnLock.test.js +34 -0
  158. package/dist/readYarnLock.test.js.map +1 -0
  159. package/package.json +73 -77
  160. package/src/applyClusterFixes.test.ts +365 -0
  161. package/src/applyClusterFixes.ts +443 -0
  162. package/src/bin/yarn-berry-deduplicate.test.ts +249 -0
  163. package/src/bin/yarn-berry-deduplicate.ts +46 -0
  164. package/src/bin/yarn-berry-why-duplicate.ts +34 -0
  165. package/src/dedupeEndToEnd.test.ts +201 -0
  166. package/src/displayMany.test.ts +103 -0
  167. package/src/displayMany.ts +106 -0
  168. package/src/helpers/applyIdentifiedFixesToYarnLock.test.ts +352 -0
  169. package/src/helpers/applyIdentifiedFixesToYarnLock.ts +130 -0
  170. package/src/helpers/buildYarnPackagesMap.test.ts +48 -0
  171. package/src/helpers/buildYarnPackagesMap.ts +45 -0
  172. package/src/helpers/collectWorkspaces.test.ts +73 -0
  173. package/src/helpers/collectWorkspaces.ts +90 -0
  174. package/src/helpers/collectYarnDependents.test.ts +197 -0
  175. package/src/helpers/collectYarnDependents.ts +232 -0
  176. package/src/helpers/duplicateSnapshot.ts +20 -0
  177. package/src/helpers/fixtures.ts +38 -0
  178. package/src/helpers/packageJsonResolutions.test.ts +28 -0
  179. package/src/helpers/packageJsonResolutions.ts +24 -0
  180. package/src/helpers/parseYarnLockPackages.test.ts +88 -0
  181. package/src/helpers/parseYarnLockPackages.ts +83 -0
  182. package/src/helpers/projectDir.ts +14 -0
  183. package/src/helpers/runYarn.ts +30 -0
  184. package/src/helpers/syml.ts +45 -0
  185. package/src/helpers/tempProjects.ts +94 -0
  186. package/src/helpers/toLockstepGraph.test.ts +48 -0
  187. package/src/helpers/toLockstepGraph.ts +60 -0
  188. package/src/helpers/versionsSnapshot.ts +12 -0
  189. package/src/helpers/writeYarnLockFile.ts +25 -0
  190. package/src/helpers/yarnDescriptor.test.ts +71 -0
  191. package/src/helpers/yarnDescriptor.ts +41 -0
  192. package/src/helpers/yarnProtocol.ts +14 -0
  193. package/src/identifyClusterFixes.test.ts +122 -0
  194. package/src/identifyClusterFixes.ts +95 -0
  195. package/src/identifyResolutionFixes.test.ts +115 -0
  196. package/src/index.ts +327 -0
  197. package/src/readYarnLock.test.ts +44 -0
  198. package/src/readYarnLock.ts +22 -0
  199. package/AUTHORS.md +0 -30
  200. package/CHANGELOG.md +0 -307
  201. package/CODE_OF_CONDUCT.md +0 -44
  202. package/LICENSE.md +0 -160
  203. package/dist/cli.d.ts +0 -3
  204. package/dist/cli.d.ts.map +0 -1
  205. package/dist/cli.js +0 -89
  206. package/dist/cli.js.map +0 -1
  207. package/dist/computePackageInstances.d.ts +0 -5
  208. package/dist/computePackageInstances.d.ts.map +0 -1
  209. package/dist/computePackageInstances.js +0 -89
  210. package/dist/computePackageInstances.js.map +0 -1
  211. package/dist/extractPackages.d.ts +0 -27
  212. package/dist/extractPackages.d.ts.map +0 -1
  213. package/dist/extractPackages.js +0 -78
  214. package/dist/extractPackages.js.map +0 -1
  215. package/dist/index.d.ts +0 -7
  216. package/dist/index.d.ts.map +0 -1
  217. package/dist/sharedTypes.d.ts +0 -11
  218. package/dist/sharedTypes.d.ts.map +0 -1
  219. package/dist/sharedTypes.js +0 -3
  220. package/dist/sharedTypes.js.map +0 -1
  221. package/dist/yarnlock.d.ts +0 -12
  222. package/dist/yarnlock.d.ts.map +0 -1
  223. package/dist/yarnlock.js +0 -14
  224. package/dist/yarnlock.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Christophe Hurpeau <christophe@hurpeau.com> (https://christophe.hurpeau.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,178 +1,199 @@
1
- # yarn-berry-deduplicate
1
+ <h1 align="center">
2
+ yarn-berry-deduplicate
3
+ </h1>
2
4
 
3
- _This is a fork of [yarn-deduplicate](https://www.npmjs.com/package/yarn-deduplicate) for yarn
4
- berry. _
5
+ <p align="center">
6
+ List duplicates and dedupe yarn berry lock file
7
+ </p>
5
8
 
6
- Cleans up `yarn.lock` by removing duplicates.
7
-
8
- Yarn berry includes [`yarn dedupe`](https://yarnpkg.com/cli/dedupe) that currently only supports
9
- "highest" strategy. Follow this issue: https://github.com/yarnpkg/berry/issues/2297.
10
-
11
- In the meantime, this is a fork of
12
- [yarn-deduplicate](https://www.npmjs.com/package/yarn-deduplicate) that works with both highest and
13
- fewer (renamed "mostCommon") strategies as well as a new "fewerHighest" strategy which combines
14
- "mostCommon" and "highest".
9
+ <p align="center">
10
+ <a href="https://npmjs.org/package/yarn-berry-deduplicate"><img src="https://img.shields.io/npm/v/yarn-berry-deduplicate.svg?style=flat-square" alt="npm version"></a>
11
+ <a href="https://npmjs.org/package/yarn-berry-deduplicate"><img src="https://img.shields.io/npm/dw/yarn-berry-deduplicate.svg?style=flat-square" alt="npm downloads"></a>
12
+ <a href="https://npmjs.org/package/yarn-berry-deduplicate"><img src="https://img.shields.io/node/v/yarn-berry-deduplicate.svg?style=flat-square" alt="node version"></a>
13
+ <a href="https://npmjs.org/package/yarn-berry-deduplicate"><img src="https://img.shields.io/npm/types/yarn-berry-deduplicate.svg?style=flat-square" alt="types"></a>
14
+ </p>
15
15
 
16
16
  ## Usage
17
17
 
18
- ```sh
19
- yarn dlx yarn-berry-deduplicate
20
- ```
18
+ Requires yarn berry (>= 2). Nothing needs to be installed: `yarn dlx` fetches the
19
+ package. The dedupe bin carries the package's own name, so it runs bare; the
20
+ report bin does not, and `-p yarn-berry-deduplicate` is what tells `yarn dlx`
21
+ which package to fetch for it.
21
22
 
22
- This will use the fewest then highest strategy to remove duplicated packages in `yarn.lock`.
23
+ Installing it (`yarn add -D yarn-berry-deduplicate`) is only worth it to pin a
24
+ version — for a CI gate, say. `yarn exec <bin>` then runs the local one.
23
25
 
24
- If you do not specify the yarn.lock path, it defaults to `yarn.lock`.
26
+ Both bins may be run from any subdirectory of the project: they walk up to the
27
+ nearest `yarn.lock` and operate on that project, naming the lockfile they found
28
+ on stderr when it is not the working directory.
25
29
 
26
- Check all available options with:
30
+ ### List duplicates, or explain one
27
31
 
28
- ```sh
29
- yarn dlx yarn-berry-deduplicate --help
32
+ ```
33
+ yarn dlx -p yarn-berry-deduplicate yarn-berry-why-duplicate # one line per duplicated package
34
+ yarn dlx -p yarn-berry-deduplicate yarn-berry-why-duplicate --details # every dependent, and the lockstep clusters
35
+ yarn dlx -p yarn-berry-deduplicate yarn-berry-why-duplicate <dependencyName> # explains the matching packages, detailed
36
+ yarn dlx -p yarn-berry-deduplicate yarn-berry-why-duplicate <dependencyName> --all
30
37
  ```
31
38
 
32
- Note: you can apply multiple times deduplication and each time dedupe more. To prevent issues, try
33
- running `yarn dedupe` after each `yarn-berry-deduplicate`.
34
-
35
- ---
36
-
37
- ## Duplicated packages
38
-
39
- `yarn.lock` contains a list of all the dependencies required by your project (including transitive
40
- dependencies), and the actual package version installed to satisfy those dependencies.
41
-
42
- For the context of this project, a "duplicated package" is a package that appears on multiple nodes
43
- of the dependency tree with overlapping version ranges but resolved to different versions.
44
-
45
- For example, imagine that your project directly depends on `lodash` and `babel`, and `babel` depends
46
- on `lodash` as well. Specifically, your project depends on `lodash@^1.0.0` and `babel` depends on
47
- `lodash@^1.1.0`. Because how the resolution algorithm works in Yarn, you might end up with two
48
- different copies of `lodash` (for example, version `1.0.1` and `1.2.0`) in your project, even when
49
- `1.2.0` will suffice to satisfy both requirements for `lodash`. That's a "duplicated package".
50
-
51
- It is important to note that we do not consider duplicated packages when the version ranges don't
52
- overlap. For example, if your project depends on `underscore@^1.0.0` and `underscore@^2.0.0`. Your
53
- project will end up with two versions of `underscore`, and `yarn-deduplicate` won't change that.
54
-
55
- When using `yarn-deduplicate` remember that **it will change your dependency tree**. There are
56
- certain code paths that now will run with a different set of dependencies. It is highly recommended
57
- that you review each change to `yarn.lock`. If the change is too big, use the flag `--packages` to
58
- deduplicate them gradually.
59
-
60
- ### Why is this necessary?
61
-
62
- Yarn documentation seems to suggest this package shouldn't be necessary. For example, in
63
- https://classic.yarnpkg.com/en/docs/cli/dedupe/, it says
64
-
65
- > The dedupe command isn’t necessary. `yarn install` will already dedupe.
66
-
67
- This is, however, not exactly true. There are cases where yarn will _not_ deduplicate existing
68
- packages. For example, this scenario:
69
-
70
- - Install `libA`. It depends on `libB ^1.1.0`. At this point, the latest version of `libB` is
71
- `1.1.2`, so it gets installed as a transitive dependency in your repo
39
+ `<dependencyName>` is a glob, so `@babel/*` works, and several may be named.
40
+ `--all` (`-a`) keeps packages that are not duplicated.
72
41
 
73
- - After a few days, install `libC`. It also depends on `libB ^1.1.0`. But this time, the latest
74
- `libB` version is `1.1.3`.
42
+ A named package that is not duplicated still gets its dependents listed —
43
+ "nothing found" is not an answer to "why is this duplicated". `--all` is only
44
+ needed to keep single-version matches next to duplicated ones.
75
45
 
76
- In the above scenario, you'll end up with `libB@1.1.2` and `libB@1.1.3` in your repo.
46
+ By default the report is one line per duplicated package — the versions it
47
+ resolved to, and what it can be deduped to:
77
48
 
78
- Find more examples in:
49
+ ```
50
+ - @eslint/plugin-kit resolved to 2 versions (0.7.1, 0.6.1)
51
+ - picomatch resolved to 3 versions (4.0.4, 4.0.3, 2.3.1), can be deduped to 2 versions
52
+ ```
79
53
 
80
- - [yarn-deduplicate — The Hero We Need](https://medium.com/@bnaya/yarn-deduplicate-the-hero-we-need-f4497a362128)
81
- - [De-duplicating yarn.lock](https://medium.com/@scinos/de-duplicating-yarn-lock-ae30be4aa41a)
82
- - https://github.com/yarnpkg/yarn/issues/3778
54
+ `can be deduped to N versions` always means N remain, never N merged away.
83
55
 
84
- ### Deduplication strategies
56
+ `--details` (`-d`), implied when a package is named, files every dependent under
57
+ the version it resolved to, so the range that keeps each copy alive is read off
58
+ the version it sits under:
85
59
 
86
- `--strategy <strategy>`
60
+ ```
61
+ @eslint/plugin-kit — 2 versions
62
+ 0.7.1
63
+ - check-package-dependencies requires "^0.7.1"
64
+ - eslint requires "^0.7.1"
65
+ 0.6.1
66
+ - @eslint/json requires "^0.6.1"
67
+ ```
87
68
 
88
- `highest` will try to use the highest installed version. For example, with the following
89
- `yarn.lock`:
69
+ After the packages come the lockstep clusters — families published together,
70
+ whose duplicates only go away when the whole family moves. A package a cluster
71
+ converges carries the family's target and a `(cluster N)` reference.
90
72
 
91
- ```text
92
- library@^1.1.0:
93
- version "1.2.0"
73
+ The dedupable count is a floor: merging a package collapses its own dependency
74
+ edges too, so a run can remove copies no per-package fix predicted.
94
75
 
95
- library@^1.2.0:
96
- version "1.2.0"
76
+ ### Dedupe
97
77
 
98
- library@^1.3.0:
99
- version "1.3.0"
78
+ ```
79
+ yarn dlx yarn-berry-deduplicate # apply
80
+ yarn dlx yarn-berry-deduplicate --dry-run # print the plan, change nothing, exit 0
81
+ yarn dlx yarn-berry-deduplicate --check # print the plan, change nothing, exit 1 if anything would change
100
82
  ```
101
83
 
102
- It will deduplicate `library@^1.1.0` and `library@^1.2.0` to `1.3.0`
84
+ `--check` is the CI gate; `--dry-run` (`-n`) is the same output without the
85
+ failing exit code.
103
86
 
104
- `fewer` will try to minimize the number of installed versions by trying to deduplicate to the
105
- version that satisfies most of the ranges first. For example, with the following `yarn.lock`:
87
+ Two passes run: the cluster pass edits `package.json` and runs `yarn install`,
88
+ reaching versions the lockfile does not carry; the pure-lock pass then collapses
89
+ the leaves yarn did not merge on its own, by merging descriptors onto one entry.
90
+ `--no-clusters` runs only the second.
106
91
 
107
- ```text
108
- library@*:
109
- version "2.0.0"
92
+ The cluster pass writes `resolutions` in the workspace root `package.json` as
93
+ scaffolding only: it re-resolves without them, and a fix that yarn resolves back
94
+ away from once the resolution is gone is reverted rather than applied. A dedupe
95
+ that needs a standing `resolutions` entry is not one this tool makes.
110
96
 
111
- library@>=1.1.0:
112
- version "3.0.0"
97
+ A run that changes something ends with what it merged, one line per package:
113
98
 
114
- library@^1.2.0:
115
- version "1.2.0"
99
+ ```
100
+ Deduped 2 packages, 2 copies merged:
101
+ barcode-detector: 2 versions (3.0.3, 3.2.2) -> 1 version (3.0.3)
102
+ zxing-wasm: 2 versions (2.2.4, 3.1.3) -> 1 version (2.2.4)
103
+ No duplicate left.
116
104
  ```
117
105
 
118
- It will deduplicate `library@*` and `library@>=1.1.0` to `1.2.0`.
119
-
120
- Note that this may cause some packages to be **downgraded**. Be sure to check the changelogs between
121
- all versions and understand the consequences of that downgrade. If unsure, don't use this strategy.
106
+ Both passes are covered by that one summary. Both sides of a line are counted
107
+ and named, so a family converging onto an older release reads as two copies
108
+ becoming one rather than as a downgrade; a package only partly collapsed lists
109
+ the versions it still has. The last line counts the duplicates left, as
110
+ `yarn-berry-why-duplicate` counts them.
122
111
 
123
- It is not recommended to use different strategies for different packages. There is no guarantee that
124
- the strategy will be honored in subsequent runs of `yarn-deduplicate` unless the same set of flags
125
- is specified again.
112
+ A rewritten lockfile is not an installed one: the run says `yarn.lock updated`
113
+ and asks for a `yarn install` to bring the project in line with it.
126
114
 
127
115
  ### Progressive deduplication
128
116
 
129
- `--packages <package1> <package2> <packageN>`
130
-
131
- Receives a list of packages to deduplicate. It will ignore any other duplicated package not in the
132
- list. This option is recommended when the number of duplicated packages in `yarn.lock` is too big to
133
- be easily reviewed by a human. This will allow for a more controlled and progressive deduplication
134
- of `yarn.lock`.
135
-
136
- `--scopes <scope1> <scope2> <scopeN>`
137
-
138
- Receives a list of scopes to deduplicate. It will ignore any other duplicated package not in the
139
- list. This option is recommended when deduplicating a large number of inter-dependent packages from
140
- a single scope, such as @babel. This will allow for a more controlled and progressive deduplication
141
- of `yarn.lock` without specifying each package individually.
142
-
143
- ### Excluding packages
144
-
145
- `--exclude <package1> <package2> <packageN`
146
-
147
- `--exclude-scopes <scope1> <scope2> <scopeN>`
117
+ Deduping the whole lockfile is the default: a run told nothing takes everything
118
+ it can. In case you only need to dedupe part of it, these flags bound a run to
119
+ the packages you name, and work on both commands:
148
120
 
149
- With these commands you can exclude certain packages/scopes from the deduplication process. This is
150
- specially useful if you want to apply a different strategy for a scope, for example.
151
-
152
- ### Pre-release versions
153
-
154
- By default, `yarn-deduplicate` will only match pre-release versions if they share they share the
155
- same `major`, `minor` and `patch` versions (example: `^1.2.3-alpha.1` and `1.2.3-alpha.2` can be
156
- deduplicated, but `^1.2.3` and `1.2.4-alpha.1` can't). This matches the behaviour of
157
- [semver](https://docs.npmjs.com/misc/semver#prerelease-tags).
158
-
159
- To change this behaviour you can use the flag `--includePrerelease`. This will treat all pre-release
160
- versionas as if they were normal versions (`^1.2.3` and `1.2.4-alpha.1` can be deduplicated).
161
-
162
- ### Usage in CI
163
-
164
- This tool can be used as part of a CI workflow. Adding the flag `--fail` will force the process to
165
- exit with status 1 if there are duplicated packages. Example:
166
-
167
- ```sh
168
- # Print the list of duplicated packages and exit with status 1
169
- yarn dlx yarn-berry-deduplicate --list --fail
170
-
171
- # Deduplicate yarn.lock and exit with status 1 if changes were required
172
- yarn dlx yarn-berry-deduplicate --fail
121
+ ```
122
+ yarn dlx yarn-berry-deduplicate --dry-run --scopes @babel # one scope
123
+ yarn dlx yarn-berry-deduplicate --dry-run --packages 'lodash,@babel/**' # names or globs
124
+ yarn dlx yarn-berry-deduplicate --dry-run --exclude lodash # everything but these
125
+ yarn dlx yarn-berry-deduplicate --dry-run --exclude-scopes @types
173
126
  ```
174
127
 
175
- ## License
128
+ Each flag takes a comma list or is repeated (`--packages a --packages b`).
129
+ Selecting nothing selects everything. `--packages`/`--scopes` say what may be
130
+ touched; `--exclude`/`--exclude-scopes` win over them, so a scope can be taken
131
+ minus a few of its packages. Patterns are globs whose `*` stops at `/`, so
132
+ `@babel/*` matches `@babel/core` and a bare `*` matches only unscoped names.
133
+
134
+ A lockstep cluster moves as one, so a fix is kept only when the filter selects
135
+ every member of its family — otherwise it is skipped and the plan names the
136
+ members that blocked it. Widen the filter to take the family, or leave it for
137
+ another run.
138
+
139
+ `yarn install` still runs during the cluster pass, and it may move entries the
140
+ filter did not select if it considers them stale.
141
+
142
+ Colors follow the terminal: `NO_COLOR` and a piped stdout turn them off,
143
+ `FORCE_COLOR` turns them on.
144
+
145
+ ## Peer dependencies
146
+
147
+ A `peerDependencies` range constrains its requester's resolved version exactly
148
+ as a dependency range does, and `yarn.lock` is where the _edge_ goes missing:
149
+ yarn folds a peer provision into the virtual package's `dependencies`, and
150
+ virtual packages are not written to the lockfile. So peer ranges sit in a block
151
+ of their own, with nothing saying who provided them.
152
+
153
+ Peer requesters are therefore read from `peerDependencies` directly, optional
154
+ ones included: whether a peer was actually provided cannot be told from the
155
+ lockfile, and a constraint that may not bind costs a suppressed merge, where a
156
+ missing one costs a merge that breaks a peer. Such a dependent is marked with a
157
+ dim `(peer)` after its range in the report.
158
+
159
+ A peer range never explains why a second version exists — yarn resolves peers
160
+ against what is already in the tree and warns instead of backtracking. It is an
161
+ extra constraint on a package duplicated for other reasons, which is why keeping
162
+ it changes the fixes.
163
+
164
+ Cluster membership is built from `dependencies` only. Adding peers there would
165
+ union unrelated packages into a family: `eslint-plugin-x@9.0.0` peer-depending on
166
+ `eslint@^9.0.0` is co-versioned by coincidence, not published in lockstep.
167
+
168
+ ## Notes
169
+
170
+ - `nodeLinker` never reaches the lockfile. Resolution runs before linking, so
171
+ `yarn.lock` is byte-identical under `pnp` and `node-modules`, and nothing here
172
+ reads an installed tree — the same fixes apply either way.
173
+ - Non-npm protocols (`workspace:`, `patch:`, `portal:`, git…) are parsed and
174
+ reported but never merged: only `npm:` resolutions are semver-comparable.
175
+ - The bins run on node (`>=22.18.0`), not on bun.
176
+
177
+ ## API
178
+
179
+ ```js
180
+ import {
181
+ fixDuplicates,
182
+ listDuplicates,
183
+ whyDuplicate,
184
+ } from "yarn-berry-deduplicate";
185
+
186
+ listDuplicates({ details: true });
187
+ whyDuplicate({ filter: { include: ["@babel/*"] }, all: true, details: true });
188
+ fixDuplicates({
189
+ mode: "dry-run",
190
+ clusters: true,
191
+ filter: { includeScopes: ["@babel"] },
192
+ });
193
+ ```
176
194
 
177
- Copyright (c) 2022 Sergio Cinos and others. Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt)
178
- file.
195
+ `mode` is `"apply"`, `"dry-run"` or `"check"` — the same three the CLI exposes.
196
+ The lockfile parsing and graph building steps are exported too
197
+ (`readAndParseYarnLock`, `parseYarnLockPackages`, `buildYarnPackagesMap`,
198
+ `collectYarnDependents`, `toLockstepGraph`, `writeYarnLockFile`), for building
199
+ something else on top; the algorithm itself lives in [pm-dedup-core](../pm-dedup-core).
@@ -0,0 +1,246 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { applyWorkspaceRangeEdit, captureFiles, createPackageFilter, describeSkippedClusterFix, diffDuplicates, partitionUnconditionalOverrides, planClusterApply, renderApplyPlan, restoreFiles, selectClusterFixes, shouldColorize, } from "pm-dedup-core";
4
+ import { buildYarnPackagesMap } from "./helpers/buildYarnPackagesMap.js";
5
+ import { collectWorkspaces, createManifestReader, } from "./helpers/collectWorkspaces.js";
6
+ import { readDuplicateSnapshot } from "./helpers/duplicateSnapshot.js";
7
+ import { addResolutions } from "./helpers/packageJsonResolutions.js";
8
+ import { parseYarnLockPackages } from "./helpers/parseYarnLockPackages.js";
9
+ import { lockPathOf } from "./helpers/projectDir.js";
10
+ import { runYarn } from "./helpers/runYarn.js";
11
+ import { identifyClusterFixes } from "./identifyClusterFixes.js";
12
+ import { readAndParseYarnLock } from "./readYarnLock.js";
13
+ const issuesUrl = "https://github.com/christophehurpeau/pm-tools/issues";
14
+ const defaultReadFixes = (projectDir) => {
15
+ const entries = readAndParseYarnLock(lockPathOf(projectDir));
16
+ const packages = parseYarnLockPackages(entries);
17
+ return identifyClusterFixes(buildYarnPackagesMap(packages), packages, collectWorkspaces(packages, createManifestReader(projectDir)));
18
+ };
19
+ // the root workspace is keyed "", which `join` already treats as the project
20
+ // directory itself
21
+ const manifestPathOf = (projectDir, importerPath) => join(projectDir, importerPath, "package.json");
22
+ const describeOverride = (override) => `"${override.packageName}": "${override.version}"`;
23
+ /**
24
+ * A yarn resolution is matched against the package a descriptor resolves to, so
25
+ * an edge declared through an npm alias
26
+ * (`"psc-pinned": "npm:printable-shell-command@~5.0.0"`) is repointed by a
27
+ * resolution on the *target* name. The resolution is still written, because an
28
+ * in-cluster requester declaring the package directly is repointed by it too,
29
+ * but naming the alias-only requesters keeps a revert from saying nothing.
30
+ */
31
+ const aliasOnlyRequesters = (fixes, packageName) => {
32
+ const constraints = fixes
33
+ .flatMap((fix) => fix.externalConstraints)
34
+ .filter((constraint) => constraint.packageName === packageName);
35
+ return constraints.length > 0 && constraints.every((c) => c.isAlias === true)
36
+ ? constraints.map((constraint) => constraint.requester)
37
+ : [];
38
+ };
39
+ const reuseKeys = (fixes) => new Set(fixes.flatMap((fix) => fix.reuseFixes.map((reuse) => `${reuse.requesterName}>${reuse.packageName}@${reuse.to}`)));
40
+ export const applyClusterFixes = ({ projectDir, dryRun = false, log = console.log,
41
+ // `yarn install` is the only way to reach a version whose manifest the
42
+ // lockfile does not carry, and the only thing that cascades a family's
43
+ // internal pins
44
+ resolve = () => runYarn(["install"], { cwd: projectDir }).status,
45
+ // the result has to be what CI would install from the manifests alone
46
+ verifyFrozen = () => runYarn(["install", "--immutable"], { cwd: projectDir }).status, readFixes = defaultReadFixes, readDuplicates = readDuplicateSnapshot, filter, packageManagerResiduals, color = shouldColorize(), }) => {
47
+ const packageFilter = createPackageFilter(filter);
48
+ const readSelectedFixes = (dir) => selectClusterFixes(readFixes(dir), packageFilter);
49
+ const lockPath = lockPathOf(projectDir);
50
+ const rootManifestPath = join(projectDir, "package.json");
51
+ const before = readDuplicates(lockPath);
52
+ const unchanged = (status, plannedChangeCount = 0) => ({
53
+ status,
54
+ before,
55
+ after: before,
56
+ stickyOverrides: [],
57
+ plannedChangeCount,
58
+ });
59
+ const { selected: fixes, skipped: filteredOut } = readSelectedFixes(projectDir);
60
+ const plan = planClusterApply(fixes);
61
+ // a yarn resolution applies to every requester of the package, so one a
62
+ // third-party range rejects would force that dependent too
63
+ const { safe: plannedOverrides, rejected } = partitionUnconditionalOverrides(fixes, plan.overrides);
64
+ const skipped = [
65
+ ...filteredOut.map(describeSkippedClusterFix),
66
+ ...plan.unresolvableChanges.map((unresolvable) => `${unresolvable}: no workspace file recorded for it`),
67
+ ...plan.conflicts.map((conflict) => `${conflict.packageName}: keeping ${conflict.kept}, ignoring ${conflict.dropped} asked by another cluster`),
68
+ ...rejected.flatMap(({ override, rejectedBy }) => rejectedBy.map((constraint) => `resolution ${describeOverride(override)}: ${constraint.requesterName ?? "workspace"} requires "${constraint.range}", and a yarn resolution would force it too`)),
69
+ ];
70
+ const changeCount = plan.manifestEdits.length + plannedOverrides.length;
71
+ const relativeManifestPath = (importerPath) => relative(projectDir, manifestPathOf(projectDir, importerPath));
72
+ const planFileChanges = () => [
73
+ ...[
74
+ ...new Set(plan.manifestEdits.map((edit) => relativeManifestPath(edit.importerPath))),
75
+ ].map((path) => ({
76
+ path,
77
+ changes: plan.manifestEdits
78
+ .filter((edit) => relativeManifestPath(edit.importerPath) === path)
79
+ .map((edit) => `"${edit.packageName}": "${edit.range}" -> "${edit.to}" (${edit.depType})`),
80
+ })),
81
+ {
82
+ path: `${relative(projectDir, rootManifestPath)} resolutions`,
83
+ transient: "removed once the result is verified",
84
+ changes: plannedOverrides.map((override) => `${describeOverride(override)} (${override.reason})`),
85
+ },
86
+ ];
87
+ // A dry run prints the plan through the shared renderer and stops.
88
+ const reportPlan = () => {
89
+ renderApplyPlan({
90
+ fileChanges: changeCount === 0 ? [] : planFileChanges(),
91
+ skipped,
92
+ packageManagerResiduals,
93
+ dedupeCommand: "yarn-berry-deduplicate",
94
+ log,
95
+ color,
96
+ });
97
+ return unchanged("dry-run", changeCount);
98
+ };
99
+ if (!dryRun) {
100
+ for (const entry of skipped) {
101
+ log(` Skipped ${entry}`);
102
+ }
103
+ }
104
+ if (changeCount === 0) {
105
+ return dryRun ? reportPlan() : unchanged("nothing-to-do");
106
+ }
107
+ if (dryRun) {
108
+ return reportPlan();
109
+ }
110
+ const touchedPaths = [
111
+ ...new Set([
112
+ ...plan.manifestEdits.map((edit) => manifestPathOf(projectDir, edit.importerPath)),
113
+ rootManifestPath,
114
+ ]),
115
+ lockPath,
116
+ ];
117
+ const originalSnapshot = captureFiles(touchedPaths);
118
+ const revertTo = (snapshot) => {
119
+ restoreFiles(snapshot);
120
+ resolve();
121
+ };
122
+ const editManifests = (edits) => edits.every((edit) => {
123
+ const path = manifestPathOf(projectDir, edit.importerPath);
124
+ const updated = applyWorkspaceRangeEdit(readFileSync(path, "utf8"), edit);
125
+ if (updated === undefined) {
126
+ log(` ${path} no longer declares "${edit.packageName}": "${edit.range}" — the lockfile is out of date`);
127
+ return false;
128
+ }
129
+ log(` ${path}: "${edit.packageName}" ${edit.range} -> ${edit.to} in ${edit.depType}`);
130
+ writeFileSync(path, updated);
131
+ return true;
132
+ });
133
+ // A reuse fix removes no duplicate — both copies keep their dependents — so
134
+ // the duplicate set cannot tell whether it took. The detector can: the fix is
135
+ // gone from its output once the edge points at the anchored version.
136
+ const readState = () => ({
137
+ duplicates: readDuplicates(lockPath),
138
+ reuses: reuseKeys(readSelectedFixes(projectDir).selected),
139
+ });
140
+ // A step keeps its edits as long as it broke nothing: a widened range often
141
+ // deduplicates nothing on its own and only makes the resolutions applicable.
142
+ const resolveAndCheck = (label) => {
143
+ if (resolve() !== 0) {
144
+ log(` \`yarn install\` failed after ${label} — reverting`);
145
+ return null;
146
+ }
147
+ const state = readState();
148
+ const { added } = diffDuplicates(before, state.duplicates);
149
+ if (added.length > 0) {
150
+ log(` ${label} introduced ${added.length} new duplicate(s) — reverting`);
151
+ return null;
152
+ }
153
+ return state;
154
+ };
155
+ if (plan.manifestEdits.length > 0) {
156
+ log("Editing workspace ranges:");
157
+ if (!editManifests(plan.manifestEdits)) {
158
+ revertTo(originalSnapshot);
159
+ return unchanged("reverted", changeCount);
160
+ }
161
+ if (resolveAndCheck("the workspace range edits") === null) {
162
+ revertTo(originalSnapshot);
163
+ return unchanged("reverted", changeCount);
164
+ }
165
+ }
166
+ const withoutOverridesSnapshot = captureFiles(touchedPaths);
167
+ const rootManifestBefore = withoutOverridesSnapshot.find((snapshot) => snapshot.path === rootManifestPath);
168
+ const remaining = readState();
169
+ // A resolution is still worth writing while its package is duplicated, or
170
+ // while the edge it repoints is still resolving elsewhere.
171
+ const outstanding = plannedOverrides.filter((override) => [...remaining.duplicates].some((resolution) => resolution.startsWith(`${override.packageName}@`)) ||
172
+ [...remaining.reuses].some((key) => key.endsWith(`>${override.packageName}@${override.version}`)));
173
+ // The result is only a fix if CI can install it from the manifests as they
174
+ // stand, resolutions removed and all.
175
+ const frozenFailure = () => {
176
+ if (verifyFrozen() === 0)
177
+ return null;
178
+ log(" `yarn install --immutable` rejects the result — reverting, the lockfile it produced is not one CI can reuse");
179
+ revertTo(withoutOverridesSnapshot);
180
+ return {
181
+ status: "reverted",
182
+ before,
183
+ after: readDuplicates(lockPath),
184
+ stickyOverrides: [],
185
+ plannedChangeCount: changeCount,
186
+ };
187
+ };
188
+ if (outstanding.length === 0) {
189
+ return (frozenFailure() ?? {
190
+ status: "applied",
191
+ before,
192
+ after: remaining.duplicates,
193
+ stickyOverrides: [],
194
+ plannedChangeCount: changeCount,
195
+ });
196
+ }
197
+ log(`Adding resolutions to ${rootManifestPath}:`);
198
+ for (const override of outstanding) {
199
+ log(` ${describeOverride(override)} (${override.reason})`);
200
+ const aliased = aliasOnlyRequesters(fixes, override.packageName);
201
+ if (aliased.length > 0) {
202
+ log(` every requester of ${override.packageName} declares it through an alias (${aliased.join(", ")}); a yarn resolution repoints the target, not those keys`);
203
+ }
204
+ }
205
+ writeFileSync(rootManifestPath, addResolutions(rootManifestBefore.content ?? "{}", new Map(outstanding.map((override) => [override.packageName, override.version]))));
206
+ const withOverrides = resolveAndCheck("the resolutions");
207
+ if (withOverrides === null) {
208
+ revertTo(withoutOverridesSnapshot);
209
+ return unchanged("reverted", changeCount);
210
+ }
211
+ // The resolutions are scaffolding: yarn has to hold the deduplicated result
212
+ // on its own, or the fix is not one we can ship.
213
+ log("Removing the resolutions and re-resolving to check the result holds:");
214
+ restoreFiles([rootManifestBefore]);
215
+ if (resolve() !== 0) {
216
+ log(" `yarn install` failed without the resolutions — reverting");
217
+ revertTo(withoutOverridesSnapshot);
218
+ return unchanged("reverted", changeCount);
219
+ }
220
+ const after = readState();
221
+ const returnedDuplicates = diffDuplicates(withOverrides.duplicates, after.duplicates).added;
222
+ const returnedReuses = [...after.reuses].filter((key) => !withOverrides.reuses.has(key));
223
+ if (returnedDuplicates.length > 0 || returnedReuses.length > 0) {
224
+ log(" The resolutions were the only thing holding the result: yarn resolves back without them. A fix that needs a standing resolution is not one this tool applies.");
225
+ log(` Please report this cluster at ${issuesUrl}:`);
226
+ for (const override of outstanding) {
227
+ log(` ${describeOverride(override)}`);
228
+ }
229
+ revertTo(withoutOverridesSnapshot);
230
+ return {
231
+ status: "reverted",
232
+ before,
233
+ after: readDuplicates(lockPath),
234
+ stickyOverrides: outstanding,
235
+ plannedChangeCount: changeCount,
236
+ };
237
+ }
238
+ return (frozenFailure() ?? {
239
+ status: "applied",
240
+ before,
241
+ after: after.duplicates,
242
+ stickyOverrides: [],
243
+ plannedChangeCount: changeCount,
244
+ });
245
+ };
246
+ //# sourceMappingURL=applyClusterFixes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyClusterFixes.js","sourceRoot":"","sources":["../src/applyClusterFixes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,uBAAuB,EACvB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,cAAc,EACd,+BAA+B,EAC/B,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,cAAc,GACf,MAAM,eAAe,CAAC;AAWvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,SAAS,GAAG,sDAAsD,CAAC;AAsCzE,MAAM,gBAAgB,GAAG,CAAC,UAAkB,EAAgB,EAAE;IAC5D,MAAM,OAAO,GAAG,oBAAoB,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,oBAAoB,CACzB,oBAAoB,CAAC,QAAQ,CAAC,EAC9B,QAAQ,EACR,iBAAiB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAC9D,CAAC;AACJ,CAAC,CAAC;AAEF,6EAA6E;AAC7E,mBAAmB;AACnB,MAAM,cAAc,GAAG,CAAC,UAAkB,EAAE,YAAoB,EAAU,EAAE,CAC1E,IAAI,CAAC,UAAU,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;AAEjD,MAAM,gBAAgB,GAAG,CAAC,QAAyB,EAAU,EAAE,CAC7D,IAAI,QAAQ,CAAC,WAAW,OAAO,QAAQ,CAAC,OAAO,GAAG,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,mBAAmB,GAAG,CAC1B,KAAmB,EACnB,WAAmB,EACT,EAAE;IACZ,MAAM,WAAW,GAAG,KAAK;SACtB,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC;SACzC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC;IAElE,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC;QAC3E,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QACvD,CAAC,CAAC,EAAE,CAAC;AACT,CAAC,CAAC;AASF,MAAM,SAAS,GAAG,CAAC,KAAmB,EAAe,EAAE,CACrD,IAAI,GAAG,CACL,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CACpB,GAAG,CAAC,UAAU,CAAC,GAAG,CAChB,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,EAAE,EAAE,CACrE,CACF,CACF,CAAC;AAEJ,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAChC,UAAU,EACV,MAAM,GAAG,KAAK,EACd,GAAG,GAAG,OAAO,CAAC,GAAG;AACjB,uEAAuE;AACvE,uEAAuE;AACvE,gBAAgB;AAChB,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM;AAChE,sEAAsE;AACtE,YAAY,GAAG,GAAG,EAAE,CAClB,OAAO,CAAC,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EACjE,SAAS,GAAG,gBAAgB,EAC5B,cAAc,GAAG,qBAAqB,EACtC,MAAM,EACN,uBAAuB,EACvB,KAAK,GAAG,cAAc,EAAE,GACC,EAAuB,EAAE;IAClD,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAwB,EAAE,CAC9D,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACxC,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,CAChB,MAA0B,EAC1B,kBAAkB,GAAG,CAAC,EACD,EAAE,CAAC,CAAC;QACzB,MAAM;QACN,MAAM;QACN,KAAK,EAAE,MAAM;QACb,eAAe,EAAE,EAAE;QACnB,kBAAkB;KACnB,CAAC,CAAC;IAEH,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,GAC7C,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAErC,wEAAwE;IACxE,2DAA2D;IAC3D,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,+BAA+B,CAC1E,KAAK,EACL,IAAI,CAAC,SAAS,CACf,CAAC;IAEF,MAAM,OAAO,GAAG;QACd,GAAG,WAAW,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAC7C,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAC7B,CAAC,YAAY,EAAE,EAAE,CAAC,GAAG,YAAY,qCAAqC,CACvE;QACD,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CACnB,CAAC,QAAQ,EAAE,EAAE,CACX,GAAG,QAAQ,CAAC,WAAW,aAAa,QAAQ,CAAC,IAAI,cAAc,QAAQ,CAAC,OAAO,2BAA2B,CAC7G;QACD,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,CAC/C,UAAU,CAAC,GAAG,CACZ,CAAC,UAAU,EAAE,EAAE,CACb,cAAc,gBAAgB,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC,aAAa,IAAI,WAAW,cAAc,UAAU,CAAC,KAAK,6CAA6C,CAClK,CACF;KACF,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAExE,MAAM,oBAAoB,GAAG,CAAC,YAAoB,EAAU,EAAE,CAC5D,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IAEjE,MAAM,eAAe,GAAG,GAA0B,EAAE,CAAC;QACnD,GAAG;YACD,GAAG,IAAI,GAAG,CACR,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC9B,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,CACxC,CACF;SACF,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACf,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,aAAa;iBACxB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;iBAClE,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,WAAW,OAAO,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,OAAO,GAAG,CAC7E;SACJ,CAAC,CAAC;QACH;YACE,IAAI,EAAE,GAAG,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,cAAc;YAC7D,SAAS,EAAE,qCAAqC;YAChD,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAC3B,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,gBAAgB,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CACnE;SACF;KACF,CAAC;IAEF,mEAAmE;IACnE,MAAM,UAAU,GAAG,GAAwB,EAAE;QAC3C,eAAe,CAAC;YACd,WAAW,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;YACvD,OAAO;YACP,uBAAuB;YACvB,aAAa,EAAE,wBAAwB;YACvC,GAAG;YACH,KAAK;SACN,CAAC,CAAC;QACH,OAAO,SAAS,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC3C,CAAC,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,GAAG,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,UAAU,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,YAAY,GAAG;QACnB,GAAG,IAAI,GAAG,CAAC;YACT,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACjC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAC9C;YACD,gBAAgB;SACjB,CAAC;QACF,QAAQ;KACT,CAAC;IAEF,MAAM,gBAAgB,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG,CAAC,QAAwB,EAAQ,EAAE;QAClD,YAAY,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,KAA4B,EAAW,EAAE,CAC9D,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACnB,MAAM,IAAI,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,uBAAuB,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1E,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,GAAG,CACD,KAAK,IAAI,wBAAwB,IAAI,CAAC,WAAW,OAAO,IAAI,CAAC,KAAK,iCAAiC,CACpG,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,GAAG,CACD,KAAK,IAAI,MAAM,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,EAAE,OAAO,IAAI,CAAC,OAAO,EAAE,CAClF,CAAC;QACF,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEL,4EAA4E;IAC5E,8EAA8E;IAC9E,qEAAqE;IACrE,MAAM,SAAS,GAAG,GAAe,EAAE,CAAC,CAAC;QACnC,UAAU,EAAE,cAAc,CAAC,QAAQ,CAAC;QACpC,MAAM,EAAE,SAAS,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC;KAC1D,CAAC,CAAC;IAEH,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,eAAe,GAAG,CAAC,KAAa,EAAqB,EAAE;QAC3D,IAAI,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;YACpB,GAAG,CAAC,mCAAmC,KAAK,cAAc,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAC1B,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,KAAK,KAAK,eAAe,KAAK,CAAC,MAAM,+BAA+B,CAAC,CAAC;YAC1E,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YAC3B,OAAO,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,eAAe,CAAC,2BAA2B,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YAC3B,OAAO,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,wBAAwB,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,IAAI,CACtD,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,gBAAgB,CAChD,CAAC;IAEH,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,2DAA2D;IAC3D,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CACzC,CAAC,QAAQ,EAAE,EAAE,CACX,CAAC,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAC5C,UAAU,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,WAAW,GAAG,CAAC,CAClD;QACD,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CACjC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,CAC7D,CACJ,CAAC;IAEF,2EAA2E;IAC3E,sCAAsC;IACtC,MAAM,aAAa,GAAG,GAA+B,EAAE;QACrD,IAAI,YAAY,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,GAAG,CACD,+GAA+G,CAChH,CAAC;QACF,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QACnC,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,MAAM;YACN,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC;YAC/B,eAAe,EAAE,EAAE;YACnB,kBAAkB,EAAE,WAAW;SAChC,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CACL,aAAa,EAAE,IAAI;YACjB,MAAM,EAAE,SAAS;YACjB,MAAM;YACN,KAAK,EAAE,SAAS,CAAC,UAAU;YAC3B,eAAe,EAAE,EAAE;YACnB,kBAAkB,EAAE,WAAW;SAChC,CACF,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,yBAAyB,gBAAgB,GAAG,CAAC,CAAC;IAClD,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,GAAG,CAAC,KAAK,gBAAgB,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;QACjE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,GAAG,CACD,0BAA0B,QAAQ,CAAC,WAAW,kCAAkC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,0DAA0D,CAC7J,CAAC;QACJ,CAAC;IACH,CAAC;IACD,aAAa,CACX,gBAAgB,EAChB,cAAc,CACZ,kBAAkB,CAAC,OAAO,IAAI,IAAI,EAClC,IAAI,GAAG,CACL,WAAW,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CACxE,CACF,CACF,CAAC;IAEF,MAAM,aAAa,GAAG,eAAe,CAAC,iBAAiB,CAAC,CAAC;IACzD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,4EAA4E;IAC5E,iDAAiD;IACjD,GAAG,CAAC,sEAAsE,CAAC,CAAC;IAC5E,YAAY,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAEnC,IAAI,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;QACpB,GAAG,CAAC,6DAA6D,CAAC,CAAC;QACnE,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,kBAAkB,GAAG,cAAc,CACvC,aAAa,CAAC,UAAU,EACxB,KAAK,CAAC,UAAU,CACjB,CAAC,KAAK,CAAC;IACR,MAAM,cAAc,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAC7C,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CACxC,CAAC;IAEF,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/D,GAAG,CACD,iKAAiK,CAClK,CAAC;QACF,GAAG,CAAC,mCAAmC,SAAS,GAAG,CAAC,CAAC;QACrD,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;YACnC,GAAG,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QACnC,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,MAAM;YACN,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC;YAC/B,eAAe,EAAE,WAAW;YAC5B,kBAAkB,EAAE,WAAW;SAChC,CAAC;IACJ,CAAC;IAED,OAAO,CACL,aAAa,EAAE,IAAI;QACjB,MAAM,EAAE,SAAS;QACjB,MAAM;QACN,KAAK,EAAE,KAAK,CAAC,UAAU;QACvB,eAAe,EAAE,EAAE;QACnB,kBAAkB,EAAE,WAAW;KAChC,CACF,CAAC;AACJ,CAAC,CAAC"}