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,48 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { createColorize, shouldColorize } from "./reportColors.js";
4
+ /**
5
+ * The nearest directory holding the lockfile, starting at `cwd` and walking up
6
+ * to the filesystem root; null when there is none.
7
+ *
8
+ * Nearest wins, which is the rule every package manager applies: a nested
9
+ * project carrying its own lockfile keeps resolving to itself rather than to the
10
+ * workspace above it.
11
+ */
12
+ export const findProjectRoot = ({ lockfileName, cwd = process.cwd(), }) => {
13
+ let dir = cwd;
14
+ for (;;) {
15
+ if (existsSync(join(dir, lockfileName)))
16
+ return dir;
17
+ const parent = dirname(dir);
18
+ if (parent === dir)
19
+ return null;
20
+ dir = parent;
21
+ }
22
+ };
23
+ /**
24
+ * `findProjectRoot` for a bin: the project root the run operates on, whatever
25
+ * subdirectory it was invoked from.
26
+ *
27
+ * Returns null when there is no project to work on — as `parseBinArgs` does, the
28
+ * reason is printed and the exit code already says so, leaving the caller
29
+ * nothing to do but return.
30
+ *
31
+ * The notice goes to stderr, and only when the root is not `cwd` — a run from
32
+ * the root prints exactly what it always did, and a redirected report stays
33
+ * parseable.
34
+ */
35
+ export const resolveProjectDir = ({ lockfileName, cwd = process.cwd(), }) => {
36
+ const projectDir = findProjectRoot({ lockfileName, cwd });
37
+ if (projectDir === null) {
38
+ console.error(`No ${lockfileName} found in ${cwd} or any parent directory`);
39
+ process.exitCode = 1;
40
+ return null;
41
+ }
42
+ if (projectDir !== cwd) {
43
+ const colorize = createColorize(shouldColorize(process.stderr));
44
+ console.error(colorize("dim", `using ${join(projectDir, lockfileName)}`));
45
+ }
46
+ return projectDir;
47
+ };
48
+ //# sourceMappingURL=findProjectRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findProjectRoot.js","sourceRoot":"","sources":["../src/findProjectRoot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOnE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAC9B,YAAY,EACZ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,GACA,EAAiB,EAAE;IACtC,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QACpD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAChC,YAAY,EACZ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,GACA,EAAiB,EAAE;IACtC,MAAM,UAAU,GAAG,eAAe,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC;IAE1D,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,MAAM,YAAY,aAAa,GAAG,0BAA0B,CAAC,CAAC;QAC5E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { afterEach, describe, it } from "bun:test";
2
+ import { strictEqual } from "node:assert/strict";
3
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { findProjectRoot } from "./findProjectRoot.js";
7
+ const lockfileName = "pm-tools.lock";
8
+ const dirs = [];
9
+ afterEach(() => {
10
+ for (const dir of dirs.splice(0)) {
11
+ rmSync(dir, { recursive: true, force: true });
12
+ }
13
+ });
14
+ const tempRoot = () => {
15
+ const dir = mkdtempSync(join(tmpdir(), `find-project-root-${process.pid}-`));
16
+ dirs.push(dir);
17
+ return dir;
18
+ };
19
+ const makeDir = (root, relativePath) => {
20
+ const dir = join(root, relativePath);
21
+ mkdirSync(dir, { recursive: true });
22
+ return dir;
23
+ };
24
+ const makeLockfile = (dir) => {
25
+ writeFileSync(join(dir, lockfileName), "");
26
+ };
27
+ describe("findProjectRoot", () => {
28
+ it("finds the lockfile in cwd", () => {
29
+ const root = tempRoot();
30
+ makeLockfile(root);
31
+ strictEqual(findProjectRoot({ lockfileName, cwd: root }), root);
32
+ });
33
+ it("walks up to an ancestor holding the lockfile", () => {
34
+ const root = tempRoot();
35
+ makeLockfile(root);
36
+ const nested = makeDir(root, join("packages", "app", "src"));
37
+ strictEqual(findProjectRoot({ lockfileName, cwd: nested }), root);
38
+ });
39
+ it("stops at the nearest one when two ancestors hold a lockfile", () => {
40
+ const root = tempRoot();
41
+ makeLockfile(root);
42
+ const nestedProject = makeDir(root, "examples/embedded");
43
+ makeLockfile(nestedProject);
44
+ const nested = makeDir(nestedProject, "src");
45
+ strictEqual(findProjectRoot({ lockfileName, cwd: nested }), nestedProject);
46
+ });
47
+ it("returns null when no ancestor up to the filesystem root has one", () => {
48
+ const root = tempRoot();
49
+ const nested = makeDir(root, "packages/app");
50
+ strictEqual(findProjectRoot({ lockfileName, cwd: nested }), null);
51
+ });
52
+ });
53
+ //# sourceMappingURL=findProjectRoot.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findProjectRoot.test.js","sourceRoot":"","sources":["../src/findProjectRoot.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,352 @@
1
+ import semver from "semver";
2
+ const accepts = (version, range) => semver.satisfies(version, range, { includePrerelease: true });
3
+ // Prefer a candidate that needs no edit to the user's own package.json — a pin
4
+ // is a decision, so changing it is a last resort, taken only when nothing else
5
+ // deduplicates anything. Then the candidate that deduplicates the most members,
6
+ // then the one already installed for the most of them (a version the lockfile
7
+ // never mentions for a member is a far weaker proposal), then the highest.
8
+ const betterCandidate = (a, b) => {
9
+ const aRespectsPins = a.pinsToEdit.length === 0 && a.convergentMembers.length > 0;
10
+ const bRespectsPins = b.pinsToEdit.length === 0 && b.convergentMembers.length > 0;
11
+ if (aRespectsPins !== bRespectsPins) {
12
+ return aRespectsPins ? a : b;
13
+ }
14
+ if (a.convergentMembers.length !== b.convergentMembers.length) {
15
+ return a.convergentMembers.length > b.convergentMembers.length ? a : b;
16
+ }
17
+ if (a.installedCount !== b.installedCount) {
18
+ return a.installedCount > b.installedCount ? a : b;
19
+ }
20
+ return semver.gt(a.version, b.version) ? a : b;
21
+ };
22
+ const directionOf = (replacedVersions, target) => {
23
+ if (replacedVersions.length === 0)
24
+ return "same";
25
+ return replacedVersions.some((version) => semver.gt(version, target))
26
+ ? "down"
27
+ : "up";
28
+ };
29
+ /**
30
+ * Compute dedupe opportunities for lockstep clusters (see
31
+ * `buildLockstepClusters`) that a per-package pass cannot: a family of
32
+ * co-versioned packages whose duplicate is kept alive only because a few
33
+ * externally-requested members resolve high. The fix converges the family onto
34
+ * a single version; fetching absent manifests and cascading the internal pins
35
+ * is left to the package manager, surfaced here as `reResolutionSet` /
36
+ * `needsRoundTrip`.
37
+ *
38
+ * Two kinds of external constraint are treated differently:
39
+ * - a third-party requester's range is immutable, so a member it rejects the
40
+ * target for is excluded from the convergence instead of sinking the whole
41
+ * cluster (clusters routinely span several publishers, and one unfixable
42
+ * member should not hide the rest);
43
+ * - a workspace pin belongs to the user, so it is reported as a
44
+ * `workspaceChanges` edit rather than a blocker.
45
+ *
46
+ * Ranges in `dependents` must be the ranges the requesters declare. A package
47
+ * manager that only stores resolved versions in its lockfile has to recover
48
+ * them (pnpm reads the installed manifests) or the constraints read as exact
49
+ * pins and no target is found.
50
+ */
51
+ export const identifyLockstepClusterFixes = (clusters, members, dependents) => {
52
+ const fixes = [];
53
+ for (const clusterMembers of clusters) {
54
+ const memberSet = new Set(clusterMembers);
55
+ const npmVersionsOf = (member) => members[member]?.npmVersions ?? [];
56
+ const duplicatedMembers = clusterMembers.filter((member) => (members[member]?.resolutionCount ?? 0) > 1);
57
+ // a cluster with no duplicated member has nothing to dedupe
58
+ if (duplicatedMembers.length === 0)
59
+ continue;
60
+ const memberVersions = Object.fromEntries(clusterMembers.map((member) => {
61
+ const versions = npmVersionsOf(member);
62
+ return [
63
+ member,
64
+ {
65
+ versions,
66
+ nonNpmCount: Math.max((members[member]?.resolutionCount ?? 0) - versions.length, 0),
67
+ },
68
+ ];
69
+ }));
70
+ const externalConstraints = [];
71
+ // ranges that can rule a version out: a third-party one, and a workspace one
72
+ // declared through an alias key. A workspace range under the package's own
73
+ // name belongs to the user, so it never blocks — it is ranked against
74
+ // instead (`pinsToEdit`), and proposed for editing only when nothing else
75
+ // deduplicates anything.
76
+ const bindingByMember = new Map();
77
+ const internalByMember = new Map();
78
+ const workspaceConstraints = [];
79
+ const exactWorkspacePins = [];
80
+ const membersWithExternalDependent = new Set();
81
+ for (const member of clusterMembers) {
82
+ for (const dependent of dependents.get(member) ?? []) {
83
+ // a range semver cannot read rules no version in or out; counted as an
84
+ // external constraint it would block every convergence it touches
85
+ if (dependent.nonSemver)
86
+ continue;
87
+ const isInternal = dependent.requesterName !== undefined &&
88
+ memberSet.has(dependent.requesterName);
89
+ if (isInternal) {
90
+ const forMember = internalByMember.get(member) ?? [];
91
+ forMember.push({
92
+ requesterName: dependent.requesterName,
93
+ range: dependent.range,
94
+ });
95
+ internalByMember.set(member, forMember);
96
+ continue;
97
+ }
98
+ const constraint = {
99
+ requester: dependent.requester,
100
+ requesterName: dependent.requesterName,
101
+ packageName: member,
102
+ range: dependent.range,
103
+ isAlias: dependent.isAlias,
104
+ resolvedVersion: dependent.resolvedVersion,
105
+ workspace: dependent.workspace,
106
+ };
107
+ externalConstraints.push(constraint);
108
+ membersWithExternalDependent.add(member);
109
+ // An exact workspace pin is as binding as a third-party range: the user
110
+ // chose that version, so the family has to live with it.
111
+ //
112
+ // A workspace declaration made through an alias key is binding outright:
113
+ // `"@typescript/native": "npm:typescript@7.0.2"` asks for a copy under a
114
+ // name of its own, beside whatever the `typescript` key resolves to.
115
+ // Moving its version is not a dedupe of the family, it is the undoing of
116
+ // the alias — so the range blocks the candidate instead of being
117
+ // proposed for editing. It only ever blocks a version the alias range
118
+ // already rejects, which is exactly the case where the edit would
119
+ // repoint the alias at another package version.
120
+ if (constraint.requesterName === undefined &&
121
+ constraint.isAlias !== true) {
122
+ workspaceConstraints.push(constraint);
123
+ if (semver.valid(constraint.range) !== null) {
124
+ exactWorkspacePins.push(constraint);
125
+ }
126
+ }
127
+ else {
128
+ const forMember = bindingByMember.get(member);
129
+ if (forMember) {
130
+ forMember.push(constraint);
131
+ }
132
+ else {
133
+ bindingByMember.set(member, [constraint]);
134
+ }
135
+ }
136
+ }
137
+ }
138
+ const candidateVersions = [
139
+ ...new Set(clusterMembers.flatMap(npmVersionsOf)),
140
+ ];
141
+ // A binding range decides whether a member is free to move at all — for a
142
+ // non-duplicated member that means being re-resolved along with the family.
143
+ const rejectingConstraints = (member, version) => (bindingByMember.get(member) ?? []).filter((constraint) => !accepts(version, constraint.range));
144
+ const canMove = (member, version) => rejectingConstraints(member, version).length === 0;
145
+ const isInstalled = (member, version) => npmVersionsOf(member).some((installed) => semver.eq(installed, version));
146
+ // A range that accepts every version the member has installed expresses no
147
+ // preference: it cannot be the reason two copies exist, and it follows
148
+ // whatever the family resolves to.
149
+ const isOpenRange = (member, range) => npmVersionsOf(member).every((version) => accepts(version, range));
150
+ const hasRealConstraint = (member) => [
151
+ ...(bindingByMember.get(member) ?? []),
152
+ ...workspaceConstraints.filter((constraint) => constraint.packageName === member),
153
+ ].some((constraint) => !isOpenRange(member, constraint.range));
154
+ const externalRangesOn = (member) => [
155
+ ...(bindingByMember.get(member) ?? []),
156
+ ...workspaceConstraints.filter((constraint) => constraint.packageName === member),
157
+ ].map((constraint) => constraint.range);
158
+ const rangeFloor = (range) => {
159
+ try {
160
+ return semver.minVersion(range)?.version ?? null;
161
+ }
162
+ catch {
163
+ return null;
164
+ }
165
+ };
166
+ // Re-resolving a member *to a named version* absent from the lock only makes
167
+ // sense when a dependent asks for that version line: `^8.59.1` is evidence
168
+ // that 8.59.1 exists, `*` and `0.83 - 0.86` are not. Without this, any
169
+ // externally-requested member looks free to move anywhere its ranges happen
170
+ // to admit — which is how a react-native@0.87.0 pulled into a metro cluster
171
+ // ends up "converging" on a metro version number.
172
+ const canReResolve = (member, version) => isInstalled(member, version) ||
173
+ !membersWithExternalDependent.has(member) ||
174
+ externalRangesOn(member).some((range) => {
175
+ const floor = rangeFloor(range);
176
+ return floor !== null && semver.eq(floor, version);
177
+ });
178
+ // Whether a member could hold a version it does not hold today. When every
179
+ // requester asks through an open range (`*`, `0.83 - 0.86`), its current
180
+ // version is an accident of resolution rather than a constraint: the
181
+ // resolver is free to land it elsewhere, and which version that is is not
182
+ // ours to name. Anything exactly pinned, or pinned to the line it already
183
+ // carries (`^0.87.0` on an 0.87.0), is not re-resolvable.
184
+ const isReResolvable = (member) => {
185
+ const ranges = externalRangesOn(member);
186
+ if (ranges.length === 0)
187
+ return true;
188
+ const floors = ranges.map(rangeFloor);
189
+ if (floors.includes(null))
190
+ return false;
191
+ const highestFloor = floors
192
+ .filter((floor) => floor !== null)
193
+ .toSorted((a, b) => semver.rcompare(a, b))[0];
194
+ return (ranges.every((range) => accepts(highestFloor, range)) &&
195
+ !isInstalled(member, highestFloor));
196
+ };
197
+ const duplicatedSet = new Set(duplicatedMembers);
198
+ // Members that end up on `version`, as a fixed point: start from those free
199
+ // to move — a duplicated one also has to already carry the version, since
200
+ // the pure-lock pass copies an existing entry and never fetches — then drop
201
+ // whoever an in-cluster requester pins elsewhere. Iterating matters because
202
+ // such a requester only stops pinning if it converges too, and the family's
203
+ // dependency edges run both ways.
204
+ // Members whose version the resolver will choose: they hold a version the
205
+ // family is leaving, and nothing pins them to it. Their current pins do not
206
+ // block the family — the install round-trip moves them — but the version
207
+ // they land on has to be verified afterwards, not asserted here.
208
+ const floatingFor = (version) => new Set(clusterMembers.filter((member) =>
209
+ // a duplicated member is what the fix is about: it converges or it
210
+ // is excluded, never "the resolver will sort it out"
211
+ !duplicatedSet.has(member) &&
212
+ !isInstalled(member, version) &&
213
+ !canReResolve(member, version) &&
214
+ isReResolvable(member)));
215
+ const convergentSetFor = (version, floating) => {
216
+ const converging = new Set(clusterMembers.filter((member) => canMove(member, version) &&
217
+ canReResolve(member, version) &&
218
+ (!duplicatedSet.has(member) || isInstalled(member, version))));
219
+ let settled = false;
220
+ while (!settled) {
221
+ settled = true;
222
+ for (const member of converging) {
223
+ const pinnedElsewhere = (internalByMember.get(member) ?? []).some((internal) => !accepts(version, internal.range) &&
224
+ !converging.has(internal.requesterName) &&
225
+ !floating.has(internal.requesterName));
226
+ if (pinnedElsewhere) {
227
+ converging.delete(member);
228
+ settled = false;
229
+ }
230
+ }
231
+ }
232
+ return converging;
233
+ };
234
+ const candidates = candidateVersions.map((version) => {
235
+ const floating = floatingFor(version);
236
+ const converging = convergentSetFor(version, floating);
237
+ return {
238
+ version,
239
+ floatingMembers: [...floating].toSorted((a, b) => a.localeCompare(b)),
240
+ // a pin the user would have to edit makes a candidate a last resort
241
+ pinsToEdit: workspaceConstraints.filter((constraint) => !floating.has(constraint.packageName) &&
242
+ !accepts(version, constraint.range)),
243
+ convergentMembers: duplicatedMembers.filter((member) => converging.has(member)),
244
+ excluded: new Map(duplicatedMembers
245
+ .filter((member) => !converging.has(member))
246
+ .map((member) => [member, rejectingConstraints(member, version)])),
247
+ installedCount: [...converging].filter((member) => isInstalled(member, version)).length,
248
+ };
249
+ });
250
+ // The version an exact workspace pin fixes the family at, used to spot open
251
+ // ranges that ignored it. Ambiguous pins (two members pinned to different
252
+ // versions) anchor nothing. A pin is preferred, not immutable: a candidate
253
+ // that violates one is ranked last, and proposed as a `workspaceChanges`
254
+ // edit when nothing else deduplicates anything.
255
+ const anchor = (() => {
256
+ const pinned = new Set(exactWorkspacePins
257
+ .filter((constraint) => isInstalled(constraint.packageName, constraint.range))
258
+ .map((constraint) => constraint.range));
259
+ return pinned.size === 1 ? [...pinned][0] : null;
260
+ })();
261
+ // Open ranges that accept the anchored version, carry the anchored version
262
+ // in the lock, and still resolved somewhere else.
263
+ const reuseFixes = anchor === null
264
+ ? []
265
+ : clusterMembers.flatMap((member) => isInstalled(member, anchor)
266
+ ? (bindingByMember.get(member) ?? []).flatMap((constraint) => constraint.requesterName !== undefined &&
267
+ constraint.resolvedVersion !== undefined &&
268
+ !semver.eq(constraint.resolvedVersion, anchor) &&
269
+ accepts(anchor, constraint.range)
270
+ ? [
271
+ {
272
+ requester: constraint.requester,
273
+ requesterName: constraint.requesterName,
274
+ packageName: member,
275
+ range: constraint.range,
276
+ from: constraint.resolvedVersion,
277
+ to: anchor,
278
+ },
279
+ ]
280
+ : [])
281
+ : []);
282
+ let best;
283
+ for (const candidate of candidates) {
284
+ best = best ? betterCandidate(best, candidate) : candidate;
285
+ }
286
+ if (!best || best.convergentMembers.length === 0) {
287
+ fixes.push({
288
+ members: clusterMembers,
289
+ duplicatedMembers,
290
+ memberVersions,
291
+ target: null,
292
+ direction: "none",
293
+ convergentMembers: [],
294
+ driverMembers: [],
295
+ excludedMembers: [],
296
+ anchor,
297
+ reuseFixes,
298
+ floatingMembers: [],
299
+ workspaceChanges: [],
300
+ reResolutionSet: [],
301
+ externalConstraints,
302
+ needsRoundTrip: false,
303
+ applicable: false,
304
+ });
305
+ continue;
306
+ }
307
+ const target = best.version;
308
+ const workspaceChanges = best.pinsToEdit
309
+ .filter((constraint) => canMove(constraint.packageName, target))
310
+ .map((constraint) => ({ ...constraint, to: target }));
311
+ // re-resolution set: members free to move that are pulled from outside the
312
+ // cluster and do not carry the target version, so a pure-lock copy is
313
+ // impossible. Internal-only members cascade from these.
314
+ const floatingSet = new Set(best.floatingMembers);
315
+ const reResolutionSet = clusterMembers
316
+ .filter((member) => membersWithExternalDependent.has(member) &&
317
+ !floatingSet.has(member) &&
318
+ canMove(member, target) &&
319
+ canReResolve(member, target) &&
320
+ !isInstalled(member, target))
321
+ .toSorted((a, b) => a.localeCompare(b));
322
+ const replacedVersions = [
323
+ ...best.convergentMembers,
324
+ ...reResolutionSet,
325
+ ].flatMap((member) => npmVersionsOf(member).filter((version) => !semver.eq(version, target)));
326
+ fixes.push({
327
+ members: clusterMembers,
328
+ duplicatedMembers,
329
+ memberVersions,
330
+ target,
331
+ direction: directionOf(replacedVersions, target),
332
+ convergentMembers: best.convergentMembers,
333
+ driverMembers: best.convergentMembers.filter(hasRealConstraint),
334
+ excludedMembers: [...best.excluded].map(([packageName, blockedBy]) => ({
335
+ packageName,
336
+ blockedBy,
337
+ })),
338
+ anchor,
339
+ reuseFixes,
340
+ floatingMembers: best.floatingMembers,
341
+ workspaceChanges,
342
+ reResolutionSet,
343
+ needsRoundTrip: reResolutionSet.length > 0 ||
344
+ workspaceChanges.length > 0 ||
345
+ best.floatingMembers.length > 0,
346
+ externalConstraints,
347
+ applicable: true,
348
+ });
349
+ }
350
+ return fixes;
351
+ };
352
+ //# sourceMappingURL=identifyLockstepClusterFixes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifyLockstepClusterFixes.js","sourceRoot":"","sources":["../src/identifyLockstepClusterFixes.ts"],"names":[],"mappings":"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"}