|
1 | | -import type { ResolvedPackageConfig } from "../config/types.js"; |
| 1 | +import type { EcosystemKey } from "../ecosystem/catalog.js"; |
| 2 | +import { packageKey } from "../utils/package-key.js"; |
2 | 3 |
|
3 | 4 | export function createKeyResolver( |
4 | | - packages: Pick<ResolvedPackageConfig, "name" | "path">[], |
| 5 | + packages: { name: string; path: string; ecosystem: EcosystemKey }[], |
5 | 6 | ): (key: string) => string { |
6 | | - const nameToPath = new Map(packages.map((p) => [p.name, p.path])); |
7 | | - const validPaths = new Set(packages.map((p) => p.path)); |
| 7 | + const validKeys = new Set(packages.map((p) => packageKey(p))); |
| 8 | + const pathEcosystems = new Map<string, EcosystemKey[]>(); |
| 9 | + const nameEcosystems = new Map<string, EcosystemKey[]>(); |
| 10 | + for (const p of packages) { |
| 11 | + const existingPath = pathEcosystems.get(p.path) ?? []; |
| 12 | + if (!existingPath.includes(p.ecosystem)) existingPath.push(p.ecosystem); |
| 13 | + pathEcosystems.set(p.path, existingPath); |
| 14 | + |
| 15 | + const existingName = nameEcosystems.get(p.name) ?? []; |
| 16 | + if (!existingName.includes(p.ecosystem)) existingName.push(p.ecosystem); |
| 17 | + nameEcosystems.set(p.name, existingName); |
| 18 | + } |
8 | 19 |
|
9 | 20 | return (key: string): string => { |
10 | | - if (validPaths.has(key)) return key; |
11 | | - const resolved = nameToPath.get(key); |
12 | | - if (resolved) return resolved; |
| 21 | + if (validKeys.has(key)) return key; |
| 22 | + const ecosystems = pathEcosystems.get(key); |
| 23 | + if (ecosystems) { |
| 24 | + if (ecosystems.length === 1) { |
| 25 | + return `${key}::${ecosystems[0]}`; |
| 26 | + } |
| 27 | + throw new Error( |
| 28 | + `Ambiguous changeset key "${key}": directory contains multiple ecosystems (${ecosystems.join(", ")}). ` + |
| 29 | + `Use "${key}::${ecosystems[0]}" or "${key}::${ecosystems[1]}" to specify.`, |
| 30 | + ); |
| 31 | + } |
| 32 | + const nameEcos = nameEcosystems.get(key); |
| 33 | + if (nameEcos) { |
| 34 | + if (nameEcos.length === 1) { |
| 35 | + const pkg = packages.find((p) => p.name === key); |
| 36 | + if (pkg) return packageKey(pkg); |
| 37 | + } |
| 38 | + throw new Error( |
| 39 | + `Ambiguous changeset key "${key}": name is shared across ecosystems (${nameEcos.join(", ")}). ` + |
| 40 | + `Use the path::ecosystem format to specify.`, |
| 41 | + ); |
| 42 | + } |
13 | 43 | return key; |
14 | 44 | }; |
15 | 45 | } |
0 commit comments