diff --git a/scripts/lib/resolve-catalog.test.ts b/scripts/lib/resolve-catalog.test.ts index f6bb92c3a9aa..963d70711a50 100644 --- a/scripts/lib/resolve-catalog.test.ts +++ b/scripts/lib/resolve-catalog.test.ts @@ -34,4 +34,27 @@ describe("resolveCatalogDependencies", () => { /Expected key 'missing' in root workspace catalog/, ); }); + + it("resolves version-qualified overrides without changing their selectors", () => { + assert.deepStrictEqual( + resolveCatalogDependencies( + { + "undici@^8": "catalog:", + "ws@^8": "catalog:", + "@clerk/backend@^3": "catalog:", + "@scope/parent@^1>undici@^8": "catalog:", + "parent@^1>@clerk/backend@^3": "catalog:", + }, + { ...catalog, undici: "8.11.2", ws: "8.21.0" }, + "apps/desktop", + ), + { + "undici@^8": "8.11.2", + "ws@^8": "8.21.0", + "@clerk/backend@^3": "3.18.1", + "@scope/parent@^1>undici@^8": "8.11.2", + "parent@^1>@clerk/backend@^3": "3.18.1", + }, + ); + }); }); diff --git a/scripts/lib/resolve-catalog.ts b/scripts/lib/resolve-catalog.ts index 35bb66eafa61..b9d199462317 100644 --- a/scripts/lib/resolve-catalog.ts +++ b/scripts/lib/resolve-catalog.ts @@ -32,10 +32,12 @@ export function resolveCatalogDependencies( } const catalogKey = spec.slice("catalog:".length).trim(); - // An override key can be a selector such as `@scope/parent>effect`; like - // pnpm, a bare `catalog:` there means the catalog entry of the package - // the selector ends in. - const lookupKey = catalogKey.length > 0 ? catalogKey : (name.split(">").at(-1) ?? name); + // Overrides can include a parent selector and a version range. A bare + // `catalog:` looks up the final package name, keeping its scope intact. + const selector = name.split(">").at(-1) ?? name; + const versionIndex = selector.indexOf("@", 1); + const packageName = versionIndex === -1 ? selector : selector.slice(0, versionIndex); + const lookupKey = catalogKey.length > 0 ? catalogKey : packageName; const resolved = catalog[lookupKey]; if (typeof resolved !== "string" || resolved.length === 0) {