fetchFromSources

tcmts.cli.libraries.fetchFromSources · #s2atxb5x · term · runs on the server

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 hub 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

used by