provide
Which components the package carries, and what it takes from its sibling packages instead: a definition one of them exports comes from the oldest release of it that exports every such definition used, as it is here. One a sibling keeps to itself (it doesn't export it) is carried, like the package's own code: two packages of one codebase can share code without either publishing it.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import type { Sibling } from "#codebase/tcmts/cli/pack"; export function provide(cb: Codebase, roots: string[], siblings: Sibling[]) { const ownerOf = new Map<string, Sibling>(); for (const s of siblings) for (const h of s.owned.keys()) ownerOf.set(h, s); const rootSet = new Set(roots); const used = new Map<Sibling, Set<string>>(); const kept = new Set<string>(); const queue = [...roots]; while (queue.length) { const h = queue.pop()!; const owner = ownerOf.get(h); if (owner && !rootSet.has(h) && owner.exports.has(h)) { used.set(owner, (used.get(owner) ?? new Set()).add(h)); continue; } const rec = cb.store.getDef(h); if (!rec || kept.has(rec.componentHash)) continue; kept.add(rec.componentHash); for (const m of cb.store.componentMembers(rec.componentHash)) for (const d of m.deps) if (d.ref.startsWith("#")) queue.push(d.ref.slice(1)); } const provided = new Map<string, { module: string; name: string }>(); const links: Record<string, string> = {}; for (const [s, hashes] of used) { // the oldest release with all of it: the widest range of the other's versions this works with const release = s.releases.findLast((r) => [...hashes].every((h) => r.exported.has(h))); if (!release) { const latest = s.releases[0]; const missing = [...hashes] .filter((h) => !latest?.exported.has(h)) .map((h) => s.owned.get(h)!) .sort(); throw new Error( `this uses ${missing.join(", ")} from ${s.name}, which ${latest ? `${s.name}@${latest.version} doesn't export as it is here` : `${s.name} hasn't released yet`}: release ${s.name} first (\`tcm release ${s.name}\`)`, ); } links[s.name] = `^${release.version}`; for (const h of hashes) { const e = release.exported.get(h)!; provided.set(h, { module: e.subpath === "." ? s.name : `${s.name}/${e.subpath.replace(/^\.\//, "")}`, name: e.name, }); } } return { kept, provided, links }; }