pm-dedup-core 2.1.0

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 (228) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/dist/buildIdentifiedFixesMap.js +6 -0
  4. package/dist/buildIdentifiedFixesMap.js.map +1 -0
  5. package/dist/buildLockstepClusters.js +119 -0
  6. package/dist/buildLockstepClusters.js.map +1 -0
  7. package/dist/buildLockstepClusters.test.js +71 -0
  8. package/dist/buildLockstepClusters.test.js.map +1 -0
  9. package/dist/clusterLabel.js +59 -0
  10. package/dist/clusterLabel.js.map +1 -0
  11. package/dist/clusterLabel.test.js +56 -0
  12. package/dist/clusterLabel.test.js.map +1 -0
  13. package/dist/compareCandidateVersions.js +18 -0
  14. package/dist/compareCandidateVersions.js.map +1 -0
  15. package/dist/compareCandidateVersions.test.js +32 -0
  16. package/dist/compareCandidateVersions.test.js.map +1 -0
  17. package/dist/createPackageFilter.js +81 -0
  18. package/dist/createPackageFilter.js.map +1 -0
  19. package/dist/createPackageFilter.test.js +115 -0
  20. package/dist/createPackageFilter.test.js.map +1 -0
  21. package/dist/definitions/buildIdentifiedFixesMap.d.ts +4 -0
  22. package/dist/definitions/buildIdentifiedFixesMap.d.ts.map +1 -0
  23. package/dist/definitions/buildLockstepClusters.d.ts +8 -0
  24. package/dist/definitions/buildLockstepClusters.d.ts.map +1 -0
  25. package/dist/definitions/buildLockstepClusters.test.d.ts +2 -0
  26. package/dist/definitions/buildLockstepClusters.test.d.ts.map +1 -0
  27. package/dist/definitions/clusterLabel.d.ts +8 -0
  28. package/dist/definitions/clusterLabel.d.ts.map +1 -0
  29. package/dist/definitions/clusterLabel.test.d.ts +2 -0
  30. package/dist/definitions/clusterLabel.test.d.ts.map +1 -0
  31. package/dist/definitions/compareCandidateVersions.d.ts +10 -0
  32. package/dist/definitions/compareCandidateVersions.d.ts.map +1 -0
  33. package/dist/definitions/compareCandidateVersions.test.d.ts +2 -0
  34. package/dist/definitions/compareCandidateVersions.test.d.ts.map +1 -0
  35. package/dist/definitions/createPackageFilter.d.ts +45 -0
  36. package/dist/definitions/createPackageFilter.d.ts.map +1 -0
  37. package/dist/definitions/createPackageFilter.test.d.ts +2 -0
  38. package/dist/definitions/createPackageFilter.test.d.ts.map +1 -0
  39. package/dist/definitions/duplicateSnapshot.d.ts +8 -0
  40. package/dist/definitions/duplicateSnapshot.d.ts.map +1 -0
  41. package/dist/definitions/fileSnapshot.d.ts +7 -0
  42. package/dist/definitions/fileSnapshot.d.ts.map +1 -0
  43. package/dist/definitions/findProjectRoot.d.ts +27 -0
  44. package/dist/definitions/findProjectRoot.d.ts.map +1 -0
  45. package/dist/definitions/findProjectRoot.test.d.ts +2 -0
  46. package/dist/definitions/findProjectRoot.test.d.ts.map +1 -0
  47. package/dist/definitions/identifyLockstepClusterFixes.d.ts +89 -0
  48. package/dist/definitions/identifyLockstepClusterFixes.d.ts.map +1 -0
  49. package/dist/definitions/identifyLockstepClusterFixes.test.d.ts +2 -0
  50. package/dist/definitions/identifyLockstepClusterFixes.test.d.ts.map +1 -0
  51. package/dist/definitions/identifyResolutionFixes.d.ts +28 -0
  52. package/dist/definitions/identifyResolutionFixes.d.ts.map +1 -0
  53. package/dist/definitions/identifyResolutionFixes.test.d.ts +2 -0
  54. package/dist/definitions/identifyResolutionFixes.test.d.ts.map +1 -0
  55. package/dist/definitions/index.d.ts +44 -0
  56. package/dist/definitions/index.d.ts.map +1 -0
  57. package/dist/definitions/packageDependenciesUtils.d.ts +47 -0
  58. package/dist/definitions/packageDependenciesUtils.d.ts.map +1 -0
  59. package/dist/definitions/packageDependenciesUtils.test.d.ts +2 -0
  60. package/dist/definitions/packageDependenciesUtils.test.d.ts.map +1 -0
  61. package/dist/definitions/packageFilterArgs.d.ts +74 -0
  62. package/dist/definitions/packageFilterArgs.d.ts.map +1 -0
  63. package/dist/definitions/packageFilterArgs.test.d.ts +2 -0
  64. package/dist/definitions/packageFilterArgs.test.d.ts.map +1 -0
  65. package/dist/definitions/packageStyles.d.ts +14 -0
  66. package/dist/definitions/packageStyles.d.ts.map +1 -0
  67. package/dist/definitions/packageStyles.test.d.ts +2 -0
  68. package/dist/definitions/packageStyles.test.d.ts.map +1 -0
  69. package/dist/definitions/parseBinArgs.d.ts +14 -0
  70. package/dist/definitions/parseBinArgs.d.ts.map +1 -0
  71. package/dist/definitions/parseBinArgs.test.d.ts +2 -0
  72. package/dist/definitions/parseBinArgs.test.d.ts.map +1 -0
  73. package/dist/definitions/planClusterApply.d.ts +39 -0
  74. package/dist/definitions/planClusterApply.d.ts.map +1 -0
  75. package/dist/definitions/planClusterApply.test.d.ts +2 -0
  76. package/dist/definitions/planClusterApply.test.d.ts.map +1 -0
  77. package/dist/definitions/renderApplyPlan.d.ts +22 -0
  78. package/dist/definitions/renderApplyPlan.d.ts.map +1 -0
  79. package/dist/definitions/renderApplyPlan.test.d.ts +2 -0
  80. package/dist/definitions/renderApplyPlan.test.d.ts.map +1 -0
  81. package/dist/definitions/renderDedupeSummary.d.ts +22 -0
  82. package/dist/definitions/renderDedupeSummary.d.ts.map +1 -0
  83. package/dist/definitions/renderDedupeSummary.test.d.ts +2 -0
  84. package/dist/definitions/renderDedupeSummary.test.d.ts.map +1 -0
  85. package/dist/definitions/renderDuplicatesReport.d.ts +39 -0
  86. package/dist/definitions/renderDuplicatesReport.d.ts.map +1 -0
  87. package/dist/definitions/renderDuplicatesReport.test.d.ts +2 -0
  88. package/dist/definitions/renderDuplicatesReport.test.d.ts.map +1 -0
  89. package/dist/definitions/reportColors.d.ts +25 -0
  90. package/dist/definitions/reportColors.d.ts.map +1 -0
  91. package/dist/definitions/reportColors.test.d.ts +2 -0
  92. package/dist/definitions/reportColors.test.d.ts.map +1 -0
  93. package/dist/definitions/reportText.d.ts +29 -0
  94. package/dist/definitions/reportText.d.ts.map +1 -0
  95. package/dist/definitions/selectExplainedPackages.d.ts +22 -0
  96. package/dist/definitions/selectExplainedPackages.d.ts.map +1 -0
  97. package/dist/definitions/selectExplainedPackages.test.d.ts +2 -0
  98. package/dist/definitions/selectExplainedPackages.test.d.ts.map +1 -0
  99. package/dist/definitions/unconditionalOverrides.d.ts +24 -0
  100. package/dist/definitions/unconditionalOverrides.d.ts.map +1 -0
  101. package/dist/definitions/unconditionalOverrides.test.d.ts +2 -0
  102. package/dist/definitions/unconditionalOverrides.test.d.ts.map +1 -0
  103. package/dist/definitions/versionsSnapshot.d.ts +40 -0
  104. package/dist/definitions/versionsSnapshot.d.ts.map +1 -0
  105. package/dist/definitions/versionsSnapshot.test.d.ts +2 -0
  106. package/dist/definitions/versionsSnapshot.test.d.ts.map +1 -0
  107. package/dist/definitions/workspaceManifest.d.ts +21 -0
  108. package/dist/definitions/workspaceManifest.d.ts.map +1 -0
  109. package/dist/definitions/workspaceManifest.test.d.ts +2 -0
  110. package/dist/definitions/workspaceManifest.test.d.ts.map +1 -0
  111. package/dist/duplicateSnapshot.js +10 -0
  112. package/dist/duplicateSnapshot.js.map +1 -0
  113. package/dist/fileSnapshot.js +21 -0
  114. package/dist/fileSnapshot.js.map +1 -0
  115. package/dist/findProjectRoot.js +48 -0
  116. package/dist/findProjectRoot.js.map +1 -0
  117. package/dist/findProjectRoot.test.js +53 -0
  118. package/dist/findProjectRoot.test.js.map +1 -0
  119. package/dist/identifyLockstepClusterFixes.js +352 -0
  120. package/dist/identifyLockstepClusterFixes.js.map +1 -0
  121. package/dist/identifyLockstepClusterFixes.test.js +372 -0
  122. package/dist/identifyLockstepClusterFixes.test.js.map +1 -0
  123. package/dist/identifyResolutionFixes.js +102 -0
  124. package/dist/identifyResolutionFixes.js.map +1 -0
  125. package/dist/identifyResolutionFixes.test.js +70 -0
  126. package/dist/identifyResolutionFixes.test.js.map +1 -0
  127. package/dist/index.js +24 -0
  128. package/dist/index.js.map +1 -0
  129. package/dist/packageDependenciesUtils.js +91 -0
  130. package/dist/packageDependenciesUtils.js.map +1 -0
  131. package/dist/packageDependenciesUtils.test.js +539 -0
  132. package/dist/packageDependenciesUtils.test.js.map +1 -0
  133. package/dist/packageFilterArgs.js +65 -0
  134. package/dist/packageFilterArgs.js.map +1 -0
  135. package/dist/packageFilterArgs.test.js +93 -0
  136. package/dist/packageFilterArgs.test.js.map +1 -0
  137. package/dist/packageStyles.js +33 -0
  138. package/dist/packageStyles.js.map +1 -0
  139. package/dist/packageStyles.test.js +58 -0
  140. package/dist/packageStyles.test.js.map +1 -0
  141. package/dist/parseBinArgs.js +28 -0
  142. package/dist/parseBinArgs.js.map +1 -0
  143. package/dist/parseBinArgs.test.js +62 -0
  144. package/dist/parseBinArgs.test.js.map +1 -0
  145. package/dist/planClusterApply.js +69 -0
  146. package/dist/planClusterApply.js.map +1 -0
  147. package/dist/planClusterApply.test.js +152 -0
  148. package/dist/planClusterApply.test.js.map +1 -0
  149. package/dist/renderApplyPlan.js +51 -0
  150. package/dist/renderApplyPlan.js.map +1 -0
  151. package/dist/renderApplyPlan.test.js +106 -0
  152. package/dist/renderApplyPlan.test.js.map +1 -0
  153. package/dist/renderDedupeSummary.js +38 -0
  154. package/dist/renderDedupeSummary.js.map +1 -0
  155. package/dist/renderDedupeSummary.test.js +91 -0
  156. package/dist/renderDedupeSummary.test.js.map +1 -0
  157. package/dist/renderDuplicatesReport.js +375 -0
  158. package/dist/renderDuplicatesReport.js.map +1 -0
  159. package/dist/renderDuplicatesReport.test.js +598 -0
  160. package/dist/renderDuplicatesReport.test.js.map +1 -0
  161. package/dist/reportColors.js +51 -0
  162. package/dist/reportColors.js.map +1 -0
  163. package/dist/reportColors.test.js +49 -0
  164. package/dist/reportColors.test.js.map +1 -0
  165. package/dist/reportText.js +29 -0
  166. package/dist/reportText.js.map +1 -0
  167. package/dist/selectExplainedPackages.js +42 -0
  168. package/dist/selectExplainedPackages.js.map +1 -0
  169. package/dist/selectExplainedPackages.test.js +55 -0
  170. package/dist/selectExplainedPackages.test.js.map +1 -0
  171. package/dist/unconditionalOverrides.js +36 -0
  172. package/dist/unconditionalOverrides.js.map +1 -0
  173. package/dist/unconditionalOverrides.test.js +71 -0
  174. package/dist/unconditionalOverrides.test.js.map +1 -0
  175. package/dist/versionsSnapshot.js +49 -0
  176. package/dist/versionsSnapshot.js.map +1 -0
  177. package/dist/versionsSnapshot.test.js +79 -0
  178. package/dist/versionsSnapshot.test.js.map +1 -0
  179. package/dist/workspaceManifest.js +63 -0
  180. package/dist/workspaceManifest.js.map +1 -0
  181. package/dist/workspaceManifest.test.js +159 -0
  182. package/dist/workspaceManifest.test.js.map +1 -0
  183. package/package.json +68 -0
  184. package/src/buildIdentifiedFixesMap.ts +22 -0
  185. package/src/buildLockstepClusters.test.ts +90 -0
  186. package/src/buildLockstepClusters.ts +155 -0
  187. package/src/clusterLabel.test.ts +79 -0
  188. package/src/clusterLabel.ts +75 -0
  189. package/src/compareCandidateVersions.test.ts +39 -0
  190. package/src/compareCandidateVersions.ts +23 -0
  191. package/src/createPackageFilter.test.ts +156 -0
  192. package/src/createPackageFilter.ts +142 -0
  193. package/src/duplicateSnapshot.ts +24 -0
  194. package/src/fileSnapshot.ts +28 -0
  195. package/src/findProjectRoot.test.ts +66 -0
  196. package/src/findProjectRoot.ts +61 -0
  197. package/src/identifyLockstepClusterFixes.test.ts +462 -0
  198. package/src/identifyLockstepClusterFixes.ts +602 -0
  199. package/src/identifyResolutionFixes.test.ts +133 -0
  200. package/src/identifyResolutionFixes.ts +183 -0
  201. package/src/index.ts +123 -0
  202. package/src/packageDependenciesUtils.test.ts +593 -0
  203. package/src/packageDependenciesUtils.ts +156 -0
  204. package/src/packageFilterArgs.test.ts +116 -0
  205. package/src/packageFilterArgs.ts +98 -0
  206. package/src/packageStyles.test.ts +77 -0
  207. package/src/packageStyles.ts +42 -0
  208. package/src/parseBinArgs.test.ts +73 -0
  209. package/src/parseBinArgs.ts +33 -0
  210. package/src/planClusterApply.test.ts +163 -0
  211. package/src/planClusterApply.ts +105 -0
  212. package/src/renderApplyPlan.test.ts +136 -0
  213. package/src/renderApplyPlan.ts +95 -0
  214. package/src/renderDedupeSummary.test.ts +121 -0
  215. package/src/renderDedupeSummary.ts +78 -0
  216. package/src/renderDuplicatesReport.test.ts +724 -0
  217. package/src/renderDuplicatesReport.ts +645 -0
  218. package/src/reportColors.test.ts +57 -0
  219. package/src/reportColors.ts +78 -0
  220. package/src/reportText.ts +58 -0
  221. package/src/selectExplainedPackages.test.ts +67 -0
  222. package/src/selectExplainedPackages.ts +79 -0
  223. package/src/unconditionalOverrides.test.ts +99 -0
  224. package/src/unconditionalOverrides.ts +60 -0
  225. package/src/versionsSnapshot.test.ts +146 -0
  226. package/src/versionsSnapshot.ts +93 -0
  227. package/src/workspaceManifest.test.ts +220 -0
  228. package/src/workspaceManifest.ts +100 -0
@@ -0,0 +1,65 @@
1
+ // `node:util` parseArgs shape, spread into a bin's own options so the four
2
+ // filter flags read the same whatever the package manager.
3
+ export const packageFilterParseArgsOptions = {
4
+ packages: { type: "string", multiple: true },
5
+ scopes: { type: "string", multiple: true },
6
+ exclude: { type: "string", multiple: true },
7
+ "exclude-scopes": { type: "string", multiple: true },
8
+ };
9
+ // the `--help` block for the flags above, so every tool documents them alike
10
+ export const packageFilterUsage = ` --packages <names> only these packages, as names or globs
11
+ --scopes <scopes> only these scopes
12
+ --exclude <names> never these packages
13
+ --exclude-scopes <scopes> never these scopes
14
+
15
+ Every filter flag takes a comma list, or is repeated.`;
16
+ // A repeated flag is how parseArgs collects several values; a comma list is what
17
+ // people type. Both mean the same thing here.
18
+ const toNames = (values) => {
19
+ if (!values)
20
+ return undefined;
21
+ const names = values
22
+ .flatMap((value) => value.split(","))
23
+ .map((name) => name.trim())
24
+ .filter((name) => name !== "");
25
+ return names.length > 0 ? names : undefined;
26
+ };
27
+ export const toPackageFilterOptions = (values) => ({
28
+ include: toNames(values.packages),
29
+ includeScopes: toNames(values.scopes),
30
+ exclude: toNames(values.exclude),
31
+ excludeScopes: toNames(values["exclude-scopes"]),
32
+ });
33
+ // the two flags every `why-duplicate` bin takes on top of the filters
34
+ export const whyDuplicateParseArgsOptions = {
35
+ all: { type: "boolean", short: "a" },
36
+ details: { type: "boolean", short: "d" },
37
+ ...packageFilterParseArgsOptions,
38
+ };
39
+ export const whyDuplicateUsage = ` -a, --all keep packages that are not duplicated
40
+ -d, --details every dependent of every version, not one line each
41
+
42
+ ${packageFilterUsage}`;
43
+ /**
44
+ * The positional a `why-duplicate` bin takes is the short form of `--packages`.
45
+ * Naming something to explain is what separates the two reports: without it
46
+ * there is nothing to be `--all` about, and the whole lockfile is listed.
47
+ *
48
+ * Naming one is also asking why it is duplicated, which the one-line form does
49
+ * not answer — so an explained selection is detailed unless it is a listing.
50
+ */
51
+ export const toWhyDuplicateRequest = (values, positionals) => {
52
+ const filter = toPackageFilterOptions(values);
53
+ const include = [...(filter.include ?? []), ...positionals];
54
+ const explains = include.length > 0 || filter.includeScopes !== undefined;
55
+ return {
56
+ filter: {
57
+ ...filter,
58
+ include: include.length > 0 ? include : undefined,
59
+ },
60
+ explains,
61
+ all: values.all ?? false,
62
+ details: values.details === true || explains,
63
+ };
64
+ };
65
+ //# sourceMappingURL=packageFilterArgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageFilterArgs.js","sourceRoot":"","sources":["../src/packageFilterArgs.ts"],"names":[],"mappings":"AAEA,2EAA2E;AAC3E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC1C,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC3C,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;CAC5C,CAAC;AAEX,6EAA6E;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;sDAKoB,CAAC;AASvD,iFAAiF;AACjF,8CAA8C;AAC9C,MAAM,OAAO,GAAG,CAAC,MAA4B,EAAwB,EAAE;IACrE,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,KAAK,GAAG,MAAM;SACjB,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACpC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,MAA8B,EACR,EAAE,CAAC,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;IAChC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;CACjD,CAAC,CAAC;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;IACpC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;IACxC,GAAG,6BAA6B;CACxB,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;EAG/B,kBAAkB,EAAE,CAAC;AAgBvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,MAA6B,EAC7B,WAAqB,EACA,EAAE;IACvB,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,aAAa,KAAK,SAAS,CAAC;IAE1E,OAAO;QACL,MAAM,EAAE;YACN,GAAG,MAAM;YACT,OAAO,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;SAClD;QACD,QAAQ;QACR,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,KAAK;QACxB,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,QAAQ;KAC7C,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { describe, it } from "bun:test";
2
+ import { deepStrictEqual } from "node:assert/strict";
3
+ import { parseArgs } from "node:util";
4
+ import { toPackageFilterOptions, toWhyDuplicateRequest, whyDuplicateParseArgsOptions, } from "./packageFilterArgs.js";
5
+ const parseFlags = (args) => parseArgs({
6
+ args,
7
+ options: { ...whyDuplicateParseArgsOptions },
8
+ allowPositionals: true,
9
+ });
10
+ const parse = (args) => toPackageFilterOptions(parseFlags(args).values);
11
+ const request = (args) => {
12
+ const { values, positionals } = parseFlags(args);
13
+ return toWhyDuplicateRequest(values, positionals);
14
+ };
15
+ describe("toPackageFilterOptions", () => {
16
+ it("leaves every list undefined when no flag is passed", () => {
17
+ deepStrictEqual(parse([]), {
18
+ include: undefined,
19
+ includeScopes: undefined,
20
+ exclude: undefined,
21
+ excludeScopes: undefined,
22
+ });
23
+ });
24
+ it("reads the four flags", () => {
25
+ deepStrictEqual(parse([
26
+ "--packages",
27
+ "lodash",
28
+ "--scopes",
29
+ "@babel",
30
+ "--exclude",
31
+ "react",
32
+ "--exclude-scopes",
33
+ "@types",
34
+ ]), {
35
+ include: ["lodash"],
36
+ includeScopes: ["@babel"],
37
+ exclude: ["react"],
38
+ excludeScopes: ["@types"],
39
+ });
40
+ });
41
+ it("reads a repeated flag and a comma list the same way", () => {
42
+ const repeated = parse(["--packages", "lodash", "--packages", "react"]);
43
+ const commaSeparated = parse(["--packages", "lodash,react"]);
44
+ deepStrictEqual(repeated.include, ["lodash", "react"]);
45
+ deepStrictEqual(commaSeparated.include, ["lodash", "react"]);
46
+ });
47
+ it("drops the blanks a trailing comma or a stray space leaves behind", () => {
48
+ deepStrictEqual(parse(["--packages", " lodash , ,"]).include, ["lodash"]);
49
+ deepStrictEqual(parse(["--packages", ","]).include, undefined);
50
+ });
51
+ });
52
+ describe("toWhyDuplicateRequest", () => {
53
+ it("takes a positional as an included name", () => {
54
+ deepStrictEqual(request(["lodash"]), {
55
+ filter: {
56
+ include: ["lodash"],
57
+ includeScopes: undefined,
58
+ exclude: undefined,
59
+ excludeScopes: undefined,
60
+ },
61
+ explains: true,
62
+ all: false,
63
+ // naming a package is asking why, which the one-line form does not answer
64
+ details: true,
65
+ });
66
+ });
67
+ it("merges the positionals with the names the flag carries", () => {
68
+ deepStrictEqual(request(["--packages", "lodash", "react"]).filter.include, [
69
+ "lodash",
70
+ "react",
71
+ ]);
72
+ });
73
+ it("explains a scope with nothing named", () => {
74
+ const { filter, explains } = request(["--scopes", "@babel"]);
75
+ deepStrictEqual(filter.include, undefined);
76
+ deepStrictEqual(filter.includeScopes, ["@babel"]);
77
+ deepStrictEqual(explains, true);
78
+ });
79
+ it("lists the whole lockfile when only exclusions are given", () => {
80
+ deepStrictEqual(request(["--exclude", "lodash"]).explains, false);
81
+ deepStrictEqual(request([]).explains, false);
82
+ });
83
+ it("leaves a listing on one line per package until --details is asked for", () => {
84
+ deepStrictEqual(request([]).details, false);
85
+ deepStrictEqual(request(["--details"]).details, true);
86
+ deepStrictEqual(request(["-d"]).details, true);
87
+ });
88
+ it("reads --all", () => {
89
+ deepStrictEqual(request(["lodash"]).all, false);
90
+ deepStrictEqual(request(["lodash", "--all"]).all, true);
91
+ });
92
+ });
93
+ //# sourceMappingURL=packageFilterArgs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageFilterArgs.test.js","sourceRoot":"","sources":["../src/packageFilterArgs.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A package name in two tones: the scope one shade deeper than the name it
3
+ * prefixes, so the half that identifies stays the readable one without the
4
+ * other fading out.
5
+ */
6
+ export const stylePackageName = (color, name, styles = ["packageName"]) => {
7
+ // 0 when unscoped, since indexOf returns -1
8
+ const scopeEnd = name.startsWith("@") ? name.indexOf("/") + 1 : 0;
9
+ if (scopeEnd === 0)
10
+ return color(styles, name);
11
+ const scopeStyles = styles.map((style) => style === "packageName" ? "scope" : style);
12
+ return `${color(scopeStyles, name.slice(0, scopeEnd))}${color(styles, name.slice(scopeEnd))}`;
13
+ };
14
+ // The version part of `name@version`, past the scope's own `@`. Yarn's
15
+ // `lodash@npm:4.17.21` and pnpm's `metro@0.84.5(react@19)` both split here.
16
+ const versionStart = (reference) => {
17
+ const nameStart = reference.startsWith("@") ? reference.indexOf("/") + 1 : 0;
18
+ if (nameStart === 0 && reference.startsWith("@"))
19
+ return -1;
20
+ return reference.indexOf("@", nameStart);
21
+ };
22
+ /**
23
+ * A `name@version` reference. Anything without a version is returned untouched:
24
+ * the reports also list requesters that are not packages at all, such as
25
+ * `package.json in devDependencies`.
26
+ */
27
+ export const stylePackageReference = (color, reference) => {
28
+ const at = versionStart(reference);
29
+ if (at <= 0)
30
+ return reference;
31
+ return `${stylePackageName(color, reference.slice(0, at))}${color("yellow", reference.slice(at))}`;
32
+ };
33
+ //# sourceMappingURL=packageStyles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageStyles.js","sourceRoot":"","sources":["../src/packageStyles.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAe,EACf,IAAY,EACZ,MAAM,GAAkB,CAAC,aAAa,CAAC,EAC/B,EAAE;IACV,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACvC,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC1C,CAAC;IACF,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;AAChG,CAAC,CAAC;AAEF,uEAAuE;AACvE,4EAA4E;AAC5E,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAU,EAAE;IACjD,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,IAAI,SAAS,KAAK,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,OAAO,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,KAAe,EACf,SAAiB,EACT,EAAE;IACV,MAAM,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,GAAG,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACrG,CAAC,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { afterEach, describe, it } from "bun:test";
2
+ import { ok, strictEqual } from "node:assert/strict";
3
+ import { stylePackageName, stylePackageReference } from "./packageStyles.js";
4
+ import { createColorize } from "./reportColors.js";
5
+ const environment = { ...process.env };
6
+ afterEach(() => {
7
+ process.env = { ...environment };
8
+ });
9
+ const colorize = createColorize(true);
10
+ // eslint-disable-next-line no-control-regex
11
+ const escapePattern = /\u001B\[[\d;]+m/gu;
12
+ const plainText = (text) => text.replaceAll(escapePattern, "");
13
+ describe("stylePackageName", () => {
14
+ it("returns the name untouched when colour is off", () => {
15
+ strictEqual(stylePackageName(createColorize(false), "@babel/core"), "@babel/core");
16
+ });
17
+ it("styles the scope apart from the rest of the name", () => {
18
+ const styled = stylePackageName(colorize, "@babel/core");
19
+ strictEqual(plainText(styled), "@babel/core");
20
+ // the two are not in the same run of escape codes
21
+ ok(!styled.includes("@babel/core"));
22
+ });
23
+ it("renders the scope and the name in two shades of one hue", () => {
24
+ delete process.env.COLORTERM;
25
+ const styled = stylePackageName(colorize, "@babel/core");
26
+ ok(styled.startsWith("\u001B[38;5;166m@babel/"));
27
+ ok(styled.includes("\u001B[38;5;173mcore"));
28
+ });
29
+ it("switches to 24-bit colour when the terminal advertises it", () => {
30
+ process.env.COLORTERM = "truecolor";
31
+ ok(stylePackageName(colorize, "metro").startsWith("\u001B[38;2;215;135;95m"));
32
+ });
33
+ it("styles an unscoped name in one run", () => {
34
+ strictEqual(plainText(stylePackageName(colorize, "metro")), "metro");
35
+ });
36
+ });
37
+ describe("stylePackageReference", () => {
38
+ it("splits the name from the version", () => {
39
+ const styled = stylePackageReference(colorize, "metro@0.84.5");
40
+ strictEqual(plainText(styled), "metro@0.84.5");
41
+ ok(!styled.includes("metro@"));
42
+ });
43
+ it("splits past the scope", () => {
44
+ const styled = stylePackageReference(colorize, "@babel/core@7.28.0");
45
+ strictEqual(plainText(styled), "@babel/core@7.28.0");
46
+ ok(!styled.includes("core@"));
47
+ });
48
+ it("keeps a peer suffix with the version", () => {
49
+ const styled = stylePackageReference(colorize, "metro@0.84.5(react@19)");
50
+ strictEqual(plainText(styled), "metro@0.84.5(react@19)");
51
+ ok(!styled.includes("metro@"));
52
+ });
53
+ it("leaves a reference carrying no version untouched", () => {
54
+ strictEqual(stylePackageReference(colorize, "package.json in devDependencies"), "package.json in devDependencies");
55
+ strictEqual(stylePackageReference(colorize, "@babel/core"), "@babel/core");
56
+ });
57
+ });
58
+ //# sourceMappingURL=packageStyles.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageStyles.test.js","sourceRoot":"","sources":["../src/packageStyles.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { parseArgs } from "node:util";
2
+ /**
3
+ * `parseArgs` with the two things a bin still has to do itself: answer
4
+ * `--help`, and turn an unknown flag into a readable line instead of a stack
5
+ * trace. Rejecting the unknown flag matters more than it reads: a mistyped
6
+ * `--dry-run` silently ignored is a run that applies its changes.
7
+ *
8
+ * Returns null when the bin has nothing left to do — the usage was asked for,
9
+ * or the arguments were rejected and the exit code already says so.
10
+ */
11
+ export const parseBinArgs = (usage, config) => {
12
+ const args = config.args ?? process.argv.slice(2);
13
+ if (args.includes("--help") || args.includes("-h")) {
14
+ console.log(usage);
15
+ return null;
16
+ }
17
+ try {
18
+ return parseArgs(config);
19
+ }
20
+ catch (error) {
21
+ console.error(error instanceof Error ? error.message : String(error));
22
+ console.error();
23
+ console.error(usage);
24
+ process.exitCode = 1;
25
+ return null;
26
+ }
27
+ };
28
+ //# sourceMappingURL=parseBinArgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseBinArgs.js","sourceRoot":"","sources":["../src/parseBinArgs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAa,EACb,MAAS,EAC+B,EAAE;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { afterEach, describe, it } from "bun:test";
2
+ import { deepStrictEqual, strictEqual } from "node:assert/strict";
3
+ import { parseBinArgs } from "./parseBinArgs.js";
4
+ const usage = "Usage: tool [options]";
5
+ const originalLog = console.log;
6
+ const originalError = console.error;
7
+ afterEach(() => {
8
+ console.log = originalLog;
9
+ console.error = originalError;
10
+ });
11
+ // `process.exitCode` is the test runner's own, so the error path has to hand it
12
+ // back untouched.
13
+ const withCapturedOutput = (run) => {
14
+ const lines = [];
15
+ const record = (message = "") => {
16
+ lines.push(message);
17
+ };
18
+ console.log = record;
19
+ console.error = record;
20
+ const exitCodeBefore = process.exitCode;
21
+ try {
22
+ return { result: run(), output: lines.join("\n") };
23
+ }
24
+ finally {
25
+ if (process.exitCode !== exitCodeBefore) {
26
+ // bun ignores `process.exitCode = undefined` (node resets it), so the
27
+ // whole run would end on 1 with every test passing.
28
+ process.exitCode = exitCodeBefore ?? 0;
29
+ }
30
+ }
31
+ };
32
+ describe("parseBinArgs", () => {
33
+ const parse = (args) => parseBinArgs(usage, {
34
+ args,
35
+ options: { check: { type: "boolean" } },
36
+ allowPositionals: true,
37
+ });
38
+ it("parses the arguments it knows", () => {
39
+ const parsed = parse(["--check", "lodash"]);
40
+ // `parseArgs` returns a null-prototype `values`, and `deepStrictEqual`
41
+ // compares prototypes.
42
+ deepStrictEqual(parsed?.values, { __proto__: null, check: true });
43
+ deepStrictEqual(parsed?.positionals, ["lodash"]);
44
+ });
45
+ it("prints the usage and stops on --help", () => {
46
+ const { result, output } = withCapturedOutput(() => parse(["--help"]));
47
+ strictEqual(result, null);
48
+ strictEqual(output, usage);
49
+ strictEqual(process.exitCode, undefined);
50
+ });
51
+ it("names an unknown flag and fails instead of ignoring it", () => {
52
+ const { result, output } = withCapturedOutput(() => {
53
+ const parsed = parse(["--chekc"]);
54
+ strictEqual(process.exitCode, 1);
55
+ return parsed;
56
+ });
57
+ strictEqual(result, null);
58
+ strictEqual(output.includes("--chekc"), true);
59
+ strictEqual(output.includes(usage), true);
60
+ });
61
+ });
62
+ //# sourceMappingURL=parseBinArgs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseBinArgs.test.js","sourceRoot":"","sources":["../src/parseBinArgs.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Turn the detector's records into the two edits every package manager
3
+ * understands:
4
+ *
5
+ * - a `workspaceChanges` entry is a range the user declares, so it is edited in
6
+ * place in the importer's `package.json`;
7
+ * - everything else is a transitive edge, which only an override can repoint.
8
+ *
9
+ * The overrides are per package name and carry no scoping: a package manager
10
+ * whose overrides apply unconditionally (bun) has to drop the ones a third-party
11
+ * range would reject, where one with conditional overrides (pnpm's convergence
12
+ * overrides) can write them all and let the resolver spare the members
13
+ * `excludedMembers` lists.
14
+ *
15
+ * `reuseFixes` come first: they converge on `anchor`, the version the user
16
+ * pinned, and a pin outranks a version the detector merely computed.
17
+ */
18
+ export const planClusterApply = (fixes) => {
19
+ const manifestEdits = [];
20
+ const unresolvableChanges = [];
21
+ const conflicts = [];
22
+ const overrides = new Map();
23
+ const addOverride = (packageName, version, reason) => {
24
+ const existing = overrides.get(packageName);
25
+ if (existing) {
26
+ if (existing.version !== version) {
27
+ conflicts.push({
28
+ packageName,
29
+ kept: existing.version,
30
+ dropped: version,
31
+ });
32
+ }
33
+ return;
34
+ }
35
+ overrides.set(packageName, { packageName, version, reason });
36
+ };
37
+ for (const fix of fixes) {
38
+ for (const reuse of fix.reuseFixes) {
39
+ addOverride(reuse.packageName, reuse.to, "reuse");
40
+ }
41
+ }
42
+ for (const fix of fixes) {
43
+ if (!fix.applicable || fix.target === null)
44
+ continue;
45
+ for (const change of fix.workspaceChanges) {
46
+ if (!change.workspace) {
47
+ unresolvableChanges.push(`${change.packageName} in ${change.requester}`);
48
+ continue;
49
+ }
50
+ manifestEdits.push({
51
+ importerPath: change.workspace.path,
52
+ depType: change.workspace.depType,
53
+ packageName: change.packageName,
54
+ range: change.range,
55
+ to: change.to,
56
+ });
57
+ }
58
+ for (const member of [...fix.convergentMembers, ...fix.reResolutionSet]) {
59
+ addOverride(member, fix.target, "converge");
60
+ }
61
+ }
62
+ return {
63
+ manifestEdits,
64
+ overrides: [...overrides.values()].toSorted((a, b) => a.packageName.localeCompare(b.packageName)),
65
+ conflicts,
66
+ unresolvableChanges,
67
+ };
68
+ };
69
+ //# sourceMappingURL=planClusterApply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planClusterApply.js","sourceRoot":"","sources":["../src/planClusterApply.ts"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAmB,EAAoB,EAAE;IACxE,MAAM,aAAa,GAA0B,EAAE,CAAC;IAChD,MAAM,mBAAmB,GAAa,EAAE,CAAC;IACzC,MAAM,SAAS,GAAkC,EAAE,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAErD,MAAM,WAAW,GAAG,CAClB,WAAmB,EACnB,OAAe,EACf,MAAiC,EAC3B,EAAE;QACR,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,QAAQ,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBACjC,SAAS,CAAC,IAAI,CAAC;oBACb,WAAW;oBACX,IAAI,EAAE,QAAQ,CAAC,OAAO;oBACtB,OAAO,EAAE,OAAO;iBACjB,CAAC,CAAC;YACL,CAAC;YACD,OAAO;QACT,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACnC,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI;YAAE,SAAS;QAErD,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBACtB,mBAAmB,CAAC,IAAI,CACtB,GAAG,MAAM,CAAC,WAAW,OAAO,MAAM,CAAC,SAAS,EAAE,CAC/C,CAAC;gBACF,SAAS;YACX,CAAC;YACD,aAAa,CAAC,IAAI,CAAC;gBACjB,YAAY,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI;gBACnC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,OAAO;gBACjC,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,EAAE,EAAE,MAAM,CAAC,EAAE;aACd,CAAC,CAAC;QACL,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,GAAG,CAAC,iBAAiB,EAAE,GAAG,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YACxE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa;QACb,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnD,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAC3C;QACD,SAAS;QACT,mBAAmB;KACpB,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,152 @@
1
+ import { describe, it } from "bun:test";
2
+ import { deepStrictEqual } from "node:assert/strict";
3
+ import { planClusterApply } from "./planClusterApply.js";
4
+ const fix = (overrides) => ({
5
+ members: [],
6
+ duplicatedMembers: [],
7
+ memberVersions: {},
8
+ target: null,
9
+ direction: "none",
10
+ convergentMembers: [],
11
+ driverMembers: [],
12
+ excludedMembers: [],
13
+ anchor: null,
14
+ reuseFixes: [],
15
+ floatingMembers: [],
16
+ workspaceChanges: [],
17
+ reResolutionSet: [],
18
+ externalConstraints: [],
19
+ needsRoundTrip: false,
20
+ applicable: false,
21
+ ...overrides,
22
+ });
23
+ describe("planClusterApply", () => {
24
+ it("edits the importer the workspace change points at", () => {
25
+ const plan = planClusterApply([
26
+ fix({
27
+ applicable: true,
28
+ target: "0.87.0",
29
+ workspaceChanges: [
30
+ {
31
+ requester: "package.json in devDependencies",
32
+ requesterName: undefined,
33
+ packageName: "metro",
34
+ range: "0.84.5",
35
+ to: "0.87.0",
36
+ workspace: { path: ".", depType: "devDependencies" },
37
+ },
38
+ ],
39
+ }),
40
+ ]);
41
+ deepStrictEqual(plan.manifestEdits, [
42
+ {
43
+ importerPath: ".",
44
+ depType: "devDependencies",
45
+ packageName: "metro",
46
+ range: "0.84.5",
47
+ to: "0.87.0",
48
+ },
49
+ ]);
50
+ deepStrictEqual(plan.unresolvableChanges, []);
51
+ });
52
+ it("reports a workspace change it cannot locate on disk", () => {
53
+ const plan = planClusterApply([
54
+ fix({
55
+ applicable: true,
56
+ target: "0.87.0",
57
+ workspaceChanges: [
58
+ {
59
+ requester: "package.json in devDependencies",
60
+ requesterName: undefined,
61
+ packageName: "metro",
62
+ range: "0.84.5",
63
+ to: "0.87.0",
64
+ },
65
+ ],
66
+ }),
67
+ ]);
68
+ deepStrictEqual(plan.manifestEdits, []);
69
+ deepStrictEqual(plan.unresolvableChanges, [
70
+ "metro in package.json in devDependencies",
71
+ ]);
72
+ });
73
+ it("overrides the convergent members and the ones to re-resolve", () => {
74
+ const plan = planClusterApply([
75
+ fix({
76
+ applicable: true,
77
+ target: "8.59.1",
78
+ convergentMembers: ["@typescript-eslint/types"],
79
+ reResolutionSet: ["@typescript-eslint/parser"],
80
+ // spared by construction: a convergence override skips the edges whose
81
+ // declared range rejects the target
82
+ excludedMembers: [
83
+ { packageName: "@typescript-eslint/utils", blockedBy: [] },
84
+ ],
85
+ }),
86
+ ]);
87
+ deepStrictEqual(plan.overrides, [
88
+ {
89
+ packageName: "@typescript-eslint/parser",
90
+ version: "8.59.1",
91
+ reason: "converge",
92
+ },
93
+ {
94
+ packageName: "@typescript-eslint/types",
95
+ version: "8.59.1",
96
+ reason: "converge",
97
+ },
98
+ ]);
99
+ });
100
+ it("lets the anchored reuse win over a computed target", () => {
101
+ const plan = planClusterApply([
102
+ fix({
103
+ applicable: true,
104
+ target: "0.87.0",
105
+ convergentMembers: ["mini-metro-config"],
106
+ anchor: "0.84.5",
107
+ reuseFixes: [
108
+ {
109
+ requester: "mini-plugin@1.0.0",
110
+ requesterName: "mini-plugin",
111
+ packageName: "mini-metro-config",
112
+ range: "*",
113
+ from: "0.87.0",
114
+ to: "0.84.5",
115
+ },
116
+ ],
117
+ }),
118
+ ]);
119
+ deepStrictEqual(plan.overrides, [
120
+ {
121
+ packageName: "mini-metro-config",
122
+ version: "0.84.5",
123
+ reason: "reuse",
124
+ },
125
+ ]);
126
+ deepStrictEqual(plan.conflicts, [
127
+ { packageName: "mini-metro-config", kept: "0.84.5", dropped: "0.87.0" },
128
+ ]);
129
+ });
130
+ it("ignores a cluster with no applicable fix but keeps its reuse fixes", () => {
131
+ const plan = planClusterApply([
132
+ fix({
133
+ applicable: false,
134
+ convergentMembers: ["ignored"],
135
+ reuseFixes: [
136
+ {
137
+ requester: "plugin@1",
138
+ requesterName: "plugin",
139
+ packageName: "leaf",
140
+ range: "*",
141
+ from: "2.0.0",
142
+ to: "1.0.0",
143
+ },
144
+ ],
145
+ }),
146
+ ]);
147
+ deepStrictEqual(plan.overrides, [
148
+ { packageName: "leaf", version: "1.0.0", reason: "reuse" },
149
+ ]);
150
+ });
151
+ });
152
+ //# sourceMappingURL=planClusterApply.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planClusterApply.test.js","sourceRoot":"","sources":["../src/planClusterApply.test.ts"],"names":[],"mappings":"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"}