@gjsify/cli 0.4.33 → 0.4.35

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.
@@ -0,0 +1,86 @@
1
+ // Workspace-aware dependency aggregation for `gjsify upgrade`.
2
+ //
3
+ // Given a flat list of per-workspace dependency declarations, group them by
4
+ // package name and surface inconsistencies (the same package declared at
5
+ // different version ranges across workspaces). Used by:
6
+ //
7
+ // - `gjsify upgrade` interactive table — shows fan-out (count of workspaces
8
+ // declaring the dep) and flags inconsistent declarations with `⚠`.
9
+ // - `gjsify upgrade --align` — offline mode that detects inconsistencies
10
+ // and proposes a single range (the highest semver-satisfying one) without
11
+ // hitting the registry.
12
+ // - `gjsify upgrade --check` — CI gate that exits non-zero when any
13
+ // inconsistency exists.
14
+ import { compare, parse } from '@gjsify/semver';
15
+ /** Local `gt` shim: `@gjsify/semver` exports `compare` returning -1|0|1. */
16
+ function semverGt(a, b) {
17
+ try {
18
+ return compare(a, b) === 1;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ /**
25
+ * Group a flat list of `DepDeclaration`s by dep name. Each group has the full
26
+ * occurrence list plus pre-computed aggregates (consensus range, highest
27
+ * declared version) so callers don't have to re-scan.
28
+ */
29
+ export function groupByDependency(decls) {
30
+ const map = new Map();
31
+ for (const d of decls) {
32
+ let g = map.get(d.name);
33
+ if (!g) {
34
+ g = {
35
+ name: d.name,
36
+ occurrences: [],
37
+ declaredRanges: new Set(),
38
+ dominantRange: d.currentRange,
39
+ highestVersion: d.currentVersion,
40
+ };
41
+ map.set(d.name, g);
42
+ }
43
+ g.occurrences.push(d);
44
+ g.declaredRanges.add(d.currentRange);
45
+ if (d.currentVersion) {
46
+ if (!g.highestVersion || semverGt(d.currentVersion, g.highestVersion)) {
47
+ g.highestVersion = d.currentVersion;
48
+ }
49
+ }
50
+ }
51
+ // Second pass: dominantRange = the range with the most occurrences;
52
+ // ties resolve by highest semver, then by lexicographic order.
53
+ for (const g of map.values()) {
54
+ const counts = new Map();
55
+ for (const occ of g.occurrences) {
56
+ counts.set(occ.currentRange, (counts.get(occ.currentRange) ?? 0) + 1);
57
+ }
58
+ let bestRange = g.occurrences[0].currentRange;
59
+ let bestCount = -1;
60
+ let bestVersion = null;
61
+ for (const [range, count] of counts.entries()) {
62
+ const v = parse(range.replace(/^[\^~>=<]+/, ''));
63
+ const version = v?.version ?? null;
64
+ if (count > bestCount ||
65
+ (count === bestCount && version && bestVersion && semverGt(version, bestVersion)) ||
66
+ (count === bestCount && range < bestRange)) {
67
+ bestRange = range;
68
+ bestCount = count;
69
+ bestVersion = version;
70
+ }
71
+ }
72
+ g.dominantRange = bestRange;
73
+ }
74
+ return [...map.values()].sort((a, b) => a.name.localeCompare(b.name));
75
+ }
76
+ /** `true` when the group's workspaces declare the dep at >1 distinct range. */
77
+ export function isInconsistent(group) {
78
+ return group.declaredRanges.size > 1;
79
+ }
80
+ /**
81
+ * Filter to just the inconsistent groups (>1 distinct range across workspaces).
82
+ * Convenience wrapper for `--align` and `--check` modes.
83
+ */
84
+ export function findInconsistencies(groups) {
85
+ return groups.filter(isInconsistent);
86
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/cli",
3
- "version": "0.4.33",
3
+ "version": "0.4.35",
4
4
  "description": "CLI for Gjsify",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -120,18 +120,18 @@
120
120
  "cli"
121
121
  ],
122
122
  "dependencies": {
123
- "@gjsify/buffer": "^0.4.33",
124
- "@gjsify/create-app": "^0.4.33",
125
- "@gjsify/node-globals": "^0.4.33",
126
- "@gjsify/node-polyfills": "^0.4.33",
127
- "@gjsify/npm-registry": "^0.4.33",
128
- "@gjsify/resolve-npm": "^0.4.33",
129
- "@gjsify/rolldown-plugin-gjsify": "^0.4.33",
130
- "@gjsify/rolldown-plugin-pnp": "^0.4.33",
131
- "@gjsify/semver": "^0.4.33",
132
- "@gjsify/tar": "^0.4.33",
133
- "@gjsify/web-polyfills": "^0.4.33",
134
- "@gjsify/workspace": "^0.4.33",
123
+ "@gjsify/buffer": "^0.4.35",
124
+ "@gjsify/create-app": "^0.4.35",
125
+ "@gjsify/node-globals": "^0.4.35",
126
+ "@gjsify/node-polyfills": "^0.4.35",
127
+ "@gjsify/npm-registry": "^0.4.35",
128
+ "@gjsify/resolve-npm": "^0.4.35",
129
+ "@gjsify/rolldown-plugin-gjsify": "^0.4.35",
130
+ "@gjsify/rolldown-plugin-pnp": "^0.4.35",
131
+ "@gjsify/semver": "^0.4.35",
132
+ "@gjsify/tar": "^0.4.35",
133
+ "@gjsify/web-polyfills": "^0.4.35",
134
+ "@gjsify/workspace": "^0.4.35",
135
135
  "cosmiconfig": "^9.0.1",
136
136
  "get-tsconfig": "^4.14.0",
137
137
  "pkg-types": "^2.3.1",
@@ -139,12 +139,12 @@
139
139
  "yargs": "^18.0.0"
140
140
  },
141
141
  "devDependencies": {
142
- "@gjsify/unit": "^0.4.33",
142
+ "@gjsify/unit": "^0.4.35",
143
143
  "@types/yargs": "^17.0.35",
144
144
  "typescript": "^6.0.3"
145
145
  },
146
146
  "peerDependencies": {
147
- "@gjsify/rolldown-native": "^0.4.33"
147
+ "@gjsify/rolldown-native": "^0.4.35"
148
148
  },
149
149
  "peerDependenciesMeta": {
150
150
  "@gjsify/rolldown-native": {