LibrariesPage

tcmts.studio.LibrariesPage · #3mkeduo2 · term · runs on the server

is an async component

The codebase's libraries (other codebases' code, mounted read-only), as tcm lib lists them: each with what it is, who announced it, where it's fetched from, what it reaches outside itself and what uses it, and what its author and the people the codebase trusts say of it (a yank, an advisory, a review); on hover, Upgrade and Remove. Add a library, or find one on the registry (q, as tcm lib search), each found with its Add.

import { findOnRegistry } from "#codebase/tcmts/cli/libraries";
import type { FoundLibrary } from "#codebase/tcmts/cli/libraries";
import { at, codeHref, servedCodebase, shareNow } from "#codebase/tcmts/share";
import { AddLibraryButton, LibraryActions, libraryRows, StudioFrame, studioShare } from "#codebase/tcmts/studio";

export async function LibrariesPage({ q }: { q: string }) {
  studioShare();
  const s = shareNow();
  if (!s.signedIn)
    return (
      <StudioFrame tab="libraries" title="Sign in">
        {null}
      </StudioFrame>
    );
  const own = s.cb === servedCodebase().cb;
  const rows = await libraryRows(s.cb);
  let search: { registry: string; found: FoundLibrary[] } | { error: string } | undefined;
  if (q.trim())
    search = await findOnRegistry(s.cb, { query: q.trim() }).catch((e: Error) => ({ error: e.message }));
  // (a registry's add line, as arguments: `tcm lib add @alice.dev/geo@1.2.0`)
  const addArgs = (l: FoundLibrary) => l.add.replace(/^tcm lib add\s+/, "").split(/\s+/);
  return (
    <StudioFrame tab="libraries" title="Libraries">
      <div className="pagehead">
        <h2 className="title">Libraries</h2>
        <span className="muted">
          {rows.length
            ? `${rows.length} librar${rows.length === 1 ? "y" : "ies"}: other codebases' code, mounted read-only`
            : ""}
        </span>
        <span className="right actions">
          <form action={at("/libraries")} method="get">
            <input
              className="field"
              type="search"
              name="q"
              defaultValue={q}
              placeholder="Find one on the registry"
              aria-label="Find a library on the registry"
            />
          </form>
          {own && <AddLibraryButton />}
        </span>
      </div>
      {search && (
        <div className="box">
          <div className="boxhead">
            <b>{`Found for “${q.trim()}”`}</b>
            <span className="muted">{"error" in search ? "" : `on ${search.registry}`}</span>
          </div>
          {"error" in search ? (
            <div className="empty bad">{search.error}</div>
          ) : search.found.length ? (
            search.found.map((l) => {
              const [source, what] = addArgs(l);
              return (
                <div className="lrow" key={`${l.did} ${l.package}`}>
                  <div>
                    <b className="mono">{`@${l.handle ?? l.did}/${l.package}`}</b>{" "}
                    <span className="muted">
                      {`${l.version} · ${l.dependents} dependent${l.dependents === 1 ? "" : "s"}${l.stars ? ` · ★ ${l.stars}` : ""}`}
                    </span>
                    {l.description && <div style={{ fontSize: 13 }}>{l.description}</div>}
                    {l.hits.map((h) => (
                      <div className="apisig" key={h.name}>
                        <span className="mono">{h.name}</span> <span className="muted mono">{h.signature}</span>
                      </div>
                    ))}
                    {l.more > 0 && <div className="muted">{`and ${l.more} more`}</div>}
                  </div>
                  {own && source && <AddLibraryButton source={source} what={what ?? ""} label="Add it" />}
                </div>
              );
            })
          ) : (
            <div className="empty">{`Nothing in ${search.registry}'s libraries matches “${q.trim()}”.`}</div>
          )}
        </div>
      )}
      <div className="box">
        {rows.length ? (
          rows.map((l) => (
            <div className="lrow branchrow" key={l.path}>
              <div>
                <a className="mono" href={codeHref(l.path)}>
                  <b>{l.path}</b>
                </a>{" "}
                <span className="mono">{l.label}</span>
                <div className="muted" style={{ fontSize: 13 }}>
                  {[
                    `${l.by ? `by ${l.by}, ` : ""}from ${l.sources.join(", ")}`,
                    l.reaches.length ? `reaches ${l.reaches.join(", ")}` : "reaches nothing outside itself",
                    ...(l.unknown.length ? [`can't tell for ${l.unknown.join(", ")}`] : []),
                    l.users.length
                      ? `${l.users.length} definition${l.users.length === 1 ? " uses" : "s use"} it`
                      : "nothing uses it yet",
                    ...(l.changed ? ["its names aren't the namespace it was added as"] : []),
                  ].join(" · ")}
                </div>
                {l.said.map((a, i) => (
                  <div
                    key={i}
                    className={a.kind === "yank" ? "bad" : a.kind === "advisory" ? "warn" : "muted"}
                    style={{ fontSize: 13 }}
                  >
                    {a.kind === "yank"
                      ? `Yanked by its author ${a.who}: `
                      : a.kind === "advisory"
                        ? `Advisory${a.severity ? ` (${a.severity})` : ""} from ${a.who}: `
                        : `Reviewed by ${a.who}: `}
                    {a.text.split("\n")[0]}
                    {a.fixedIn ? ` (fixed in ${a.fixedIn})` : ""}
                  </div>
                ))}
              </div>
              {own && <LibraryActions path={l.path} users={l.users} />}
            </div>
          ))
        ) : (
          <div className="empty">
            No libraries yet: Add a library, or find one on the registry (tcm ships some of its own: from tcm).
          </div>
        )}
      </div>
    </StudioFrame>
  );
}

uses

used by