export interface AliasAmbiguity { alias: string; candidates: string[]; source: string; } export interface AliasTarget { key: string; canonicalId: string; metadata: T; } export interface AliasIndex { aliases: Map>; ambiguities: AliasAmbiguity[]; } export function buildAliasIndex(targets: AliasTarget[], source: string): AliasIndex { const candidatesByAlias = new Map[]>(); for (const target of targets) { const existing = candidatesByAlias.get(target.key) ?? []; existing.push(target); candidatesByAlias.set(target.key, existing); } const aliases = new Map>(); const ambiguities: AliasAmbiguity[] = []; for (const [alias, candidates] of candidatesByAlias) { const uniqueCanonicalIds = Array.from(new Set(candidates.map((candidate) => candidate.canonicalId))); if (uniqueCanonicalIds.length > 1) { ambiguities.push({ alias, candidates: uniqueCanonicalIds, source }); continue; } const [candidate] = candidates; if (candidate) aliases.set(alias, candidate); } return { aliases, ambiguities }; }