fetchFromSources
uses tcmts.cli.sync.openRemote, which uses process
Find what (a release, or a namespace hash) on the first of sources that has it, then fetch its namespace from
whichever has that, trying each in turn: what arrives is checked by hash, so it's no matter which answers. Each
that doesn't is said, and the next tried. open opens a source (default openRemote: a remote's name, a URL, a
directory; a registry gives publicRemote).
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { resolveLibrary } from "#codebase/tcmts/cli/libraries"; import { dim } from "#codebase/tcmts/cli/style"; import { fetchNamespaces, openRemote } from "#codebase/tcmts/cli/sync"; import type { Remote } from "#codebase/tcmts/cli/sync"; import { UsageError } from "#codebase/tcmts/cli/ui"; export async function fetchFromSources( cb: Codebase, sources: string[], what: string, open: (source: string) => Remote | Promise<Remote> = (s) => openRemote(cb, s).remote, o: { maxNames?: number } = {}, ): Promise<{ found: { namespace: string; release?: string }; from: string; received: number }> { const failed = new Map<string, string>(); const tell = (s: string, e: unknown) => { const why = e instanceof Error ? e.message.split("\n")[0]! : String(e); failed.set(s, why); console.log(dim(` tried ${s}: ${why}`)); }; let found: { namespace: string; release?: string } | undefined; for (const s of sources) { try { found = await resolveLibrary(await open(s), what); break; } catch (e) { tell(s, e); } } if (found) for (const s of sources.filter((x) => !failed.has(x))) { try { // (a library's: it doesn't move the package versions this codebase runs on) const received = await fetchNamespaces(cb, await open(s), [found.namespace], { ...o, keepLocks: true, }); return { found, from: s, received }; } catch (e) { tell(s, e); } } throw new UsageError( `no source has ${what}:\n ${[...failed].map(([s, why]) => `${s}: ${why}`).join("\n ")}`, ); }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.libraries.resolveLibrary
- tcmts.cli.style.dim
- tcmts.cli.sync.Remote
- tcmts.cli.sync.fetchNamespaces
- tcmts.cli.sync.openRemote
- tcmts.cli.ui.UsageError