Skip to content

Commit a7f157b

Browse files
committed
fix(plugin): normalize semver ranges to explicit bounded format
- Convert ^ and ~ ranges to >=min <max format for consistency - Fix change detection by snapshotting existing data before mutation - All peer dep ranges now use explicit bounds (e.g., ^2.0.0 -> >=2.0.0 <3.0.0)
1 parent 388e35b commit a7f157b

File tree

2 files changed

+70
-23
lines changed

2 files changed

+70
-23
lines changed

tools/compat-matrix.config.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://angular-threejs.github.io/schemas/compat-matrix.schema.json",
3-
"updatedAt": "2026-01-06T00:00:00.000Z",
3+
"updatedAt": "2026-01-06T15:28:27.198Z",
44
"description": "Compatibility matrix for angular-three ecosystem packages",
55
"combined": [
66
{
@@ -28,16 +28,16 @@
2828
{
2929
"version": ">=4.0.0",
3030
"peerDependencies": {
31-
"@monogrid/gainmap-js": "^3.0.0",
32-
"@pmndrs/vanilla": "^1.24.0",
33-
"camera-controls": "^2.8.0",
31+
"@monogrid/gainmap-js": ">=3.0.0 <4.0.0",
32+
"@pmndrs/vanilla": ">=1.24.0 <2.0.0",
33+
"camera-controls": ">=2.8.0 <3.0.0",
3434
"hls.js": ">=1.5.0",
3535
"maath": ">=0.10.0 <0.11.0",
36-
"meshline": "^3.1.0",
36+
"meshline": ">=3.1.0 <4.0.0",
3737
"stats-gl": ">=2.0.0",
3838
"three-custom-shader-material": ">=5.5.0 <6.5.0",
3939
"three-mesh-bvh": ">=0.5.0 <0.10.0",
40-
"three-stdlib": "^2.0.0",
40+
"three-stdlib": ">=2.0.0 <3.0.0",
4141
"troika-three-text": ">=0.47.0 <0.53.0"
4242
}
4343
}
@@ -49,9 +49,9 @@
4949
{
5050
"version": ">=4.0.0",
5151
"peerDependencies": {
52-
"@pmndrs/cannon-worker-api": "^2.0.0",
52+
"@pmndrs/cannon-worker-api": ">=2.0.0 <3.0.0",
5353
"cannon-es": ">=0.20.0 <0.21.0",
54-
"cannon-es-debugger": "^1.0.0"
54+
"cannon-es-debugger": ">=1.0.0 <2.0.0"
5555
}
5656
}
5757
]
@@ -63,7 +63,7 @@
6363
"version": ">=4.0.0",
6464
"peerDependencies": {
6565
"@dimforge/rapier3d-compat": ">=0.14.0 <0.20.0",
66-
"three-stdlib": "^2.0.0"
66+
"three-stdlib": ">=2.0.0 <3.0.0"
6767
}
6868
}
6969
]
@@ -76,8 +76,8 @@
7676
"peerDependencies": {
7777
"maath": ">=0.10.0 <0.11.0",
7878
"n8ao": ">=1.9.4 <2.0.0",
79-
"postprocessing": "^6.0.0",
80-
"three-stdlib": "^2.0.0"
79+
"postprocessing": ">=6.0.0 <7.0.0",
80+
"three-stdlib": ">=2.0.0 <3.0.0"
8181
}
8282
}
8383
]
@@ -100,8 +100,8 @@
100100
{
101101
"version": ">=4.0.0",
102102
"peerDependencies": {
103-
"@tweakpane/core": "^2.0.0",
104-
"tweakpane": "^4.0.0"
103+
"@tweakpane/core": ">=2.0.0 <3.0.0",
104+
"tweakpane": ">=4.0.0 <5.0.0"
105105
}
106106
}
107107
]

tools/scripts/generate-compat-matrix.mjs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,50 @@ function addUpperBound(oldRange, breakingMin) {
109109
return `>=${oldMin} <${breakingMin}`;
110110
}
111111

112+
/**
113+
* Normalize a semver range to explicit bounded format
114+
* Converts ^ and ~ ranges to >=min <max format for consistency
115+
* @param {string} range - Semver range like "^2.0.0" or "~1.5.0"
116+
* @returns {string} - Normalized range like ">=2.0.0 <3.0.0"
117+
*/
118+
function normalizeRange(range) {
119+
if (!range) return range;
120+
121+
// Already in explicit format
122+
if (range.startsWith('>=')) return range;
123+
124+
const min = semver.minVersion(range);
125+
if (!min) return range;
126+
127+
// For ^ (caret): allows changes that do not modify the left-most non-zero digit
128+
// ^1.2.3 := >=1.2.3 <2.0.0
129+
// ^0.2.3 := >=0.2.3 <0.3.0
130+
// ^0.0.3 := >=0.0.3 <0.0.4
131+
if (range.startsWith('^')) {
132+
const { major, minor, patch } = min;
133+
let maxVersion;
134+
if (major !== 0) {
135+
maxVersion = `${major + 1}.0.0`;
136+
} else if (minor !== 0) {
137+
maxVersion = `0.${minor + 1}.0`;
138+
} else {
139+
maxVersion = `0.0.${patch + 1}`;
140+
}
141+
return `>=${min.version} <${maxVersion}`;
142+
}
143+
144+
// For ~ (tilde): allows patch-level changes
145+
// ~1.2.3 := >=1.2.3 <1.3.0
146+
// ~0.2.3 := >=0.2.3 <0.3.0
147+
if (range.startsWith('~')) {
148+
const { major, minor } = min;
149+
return `>=${min.version} <${major}.${minor + 1}.0`;
150+
}
151+
152+
// Fallback: just use >=min
153+
return `>=${min.version}`;
154+
}
155+
112156
// ============================================================================
113157
// File Helpers
114158
// ============================================================================
@@ -141,17 +185,19 @@ function writeJson(filePath, data) {
141185
// ============================================================================
142186

143187
/**
144-
* Extract peer deps from package.json, excluding common ones
188+
* Extract peer deps from package.json, excluding common ones and normalizing ranges
145189
*/
146190
function extractPeerDeps(packageJson, excludeCommon = true) {
147191
if (!packageJson?.peerDependencies) return {};
148192

149-
const peerDeps = { ...packageJson.peerDependencies };
193+
const peerDeps = {};
150194

151-
if (excludeCommon) {
152-
for (const dep of CONFIG.commonPeerDeps) {
153-
delete peerDeps[dep];
195+
for (const [dep, range] of Object.entries(packageJson.peerDependencies)) {
196+
if (excludeCommon && CONFIG.commonPeerDeps.includes(dep)) {
197+
continue;
154198
}
199+
// Normalize all ranges to explicit bounded format
200+
peerDeps[dep] = normalizeRange(range);
155201
}
156202

157203
return peerDeps;
@@ -336,6 +382,11 @@ function main() {
336382
throw new Error('Core package (angular-three) not found in dist. Run build first.');
337383
}
338384

385+
// Deep clone existing data BEFORE processing (since processing mutates in place)
386+
const existingDataSnapshot = existingMatrix
387+
? JSON.stringify({ combined: existingMatrix.combined, packages: existingMatrix.packages })
388+
: null;
389+
339390
// Process matrices
340391
console.log('\nProcessing combined matrix:');
341392
const combined = processCombinedMatrix(existingMatrix, corePackage);
@@ -350,11 +401,7 @@ function main() {
350401
};
351402

352403
// Check if there are actual changes (compare without metadata fields)
353-
const existingData = existingMatrix
354-
? { combined: existingMatrix.combined, packages: existingMatrix.packages }
355-
: null;
356-
357-
const hasChanges = JSON.stringify(outputData) !== JSON.stringify(existingData);
404+
const hasChanges = JSON.stringify(outputData) !== existingDataSnapshot;
358405

359406
// Build final output with metadata
360407
const output = {

0 commit comments

Comments
 (0)