Skip to the content

Capsid menu

app/kb/registry/host.server.ts

79 lines and 8 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.

Functions

The functions of host.server.ts
FunctionLinesComplexityCoveredCRAPMutation
githubHost21 to 271No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
paper23 to 231No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
recipe25 to 253No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
compile30 to 331No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
readPrimers39 to 494No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
readStrains52 to 624No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
readReagents65 to 754No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
readEquipment78 to 884No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code

Imports

It imports app/kb/procedures/parse.mjs, app/kb/procedures/render.mjs, app/kb/registry/compile.mjs, app/kb/registry/equipment.mjs, app/kb/registry/kinds.mjs, app/kb/registry/primer.mjs, app/kb/registry/reagent.mjs, app/kb/registry/strain.mjs, app/lib/content/load-pipeline.server.ts, app/lib/editor/github.server.ts, app/lib/publications/parse.mjs. Imported by app/kb/procedures/save.server.ts, app/kb/registry/save.server.ts.

Source

// What the Worker reads from the repository for the registry, which is what CI reads too: a field that names a paper means
// a paper this site has a file for, and a protocol that names a primer means a primer the registry holds a file for. Asking
// the repository rather than D1 keeps a save and a sync independent of whether the derived rows have been written yet.
// A module of its own so the procedure save can read primers without importing the registry save, which imports it.

import { loadPipeline } from "~/lib/content/load-pipeline.server";
import { readFile } from "~/lib/editor/github.server";
import { procedurePath } from "~/kb/procedures/parse.mjs";
import { PUBLICATIONS_DIR } from "~/lib/publications/parse.mjs";
import type { StoredEquipment, StoredPrimer, StoredReagent, StoredStrain } from "~/kb/procedures/render.mjs";

import { compileRegistryItem, registryPath, registrySlug } from "./compile.mjs";
import { KINDS, type KindSpec } from "./kinds.mjs";
import { storedPrimer } from "./primer.mjs";
import { storedEquipment } from "./equipment.mjs";
import { storedReagent } from "./reagent.mjs";
import { storedStrain } from "./strain.mjs";

type RegistryEnv = Env & { GITHUB_TOKEN?: string };

function githubHost(env: RegistryEnv) {
  return {
    paper: async (slug: string) => (await readFile(env, `${PUBLICATIONS_DIR}/${slug}.md`)) !== null,
    // A recipe is a procedure file whose front matter says profile: recipe.
    recipe: async (slug: string) => /^profile:\s*recipe\s*$/m.test(((await readFile(env, procedurePath(slug)))?.content ?? "").split(/^---\s*$/m)[1] ?? ""),
  };
}

/** The one compile door for a registry file: the save, get_registry, sync_registry and the primer reads go through it. */
export async function compile(env: RegistryEnv, slug: string, raw: string, kinds: Readonly<Record<string, KindSpec>> = KINDS) {
  const { findWideDashes } = await loadPipeline();
  return compileRegistryItem({ slug, raw, host: githubHost(env), pipeline: { findWideDashes }, kinds });
}

/**
 * The primers a protocol names, as the repository holds them, for the procedure compile. An id with no file, or a file that
 * does not compile, is left out of the answer, so the validator reports it as a primer the registry does not hold.
 */
export async function readPrimers(env: RegistryEnv, ids: string[]): Promise<Map<string, StoredPrimer>> {
  const found = new Map<string, StoredPrimer>();
  for (const id of ids) {
    const slug = registrySlug("primer", id);
    const file = await readFile(env, registryPath(slug));
    if (!file) continue;
    const compiled = await compile(env, slug, file.content);
    if (compiled.ok) found.set(id, storedPrimer(compiled.item));
  }
  return found;
}

/** The host strains a protocol names, as the repository holds them; an id with no compiling file is left out, and the validator names it. */
export async function readStrains(env: RegistryEnv, ids: string[]): Promise<Map<string, StoredStrain>> {
  const found = new Map<string, StoredStrain>();
  for (const id of ids) {
    const slug = registrySlug("strain", id);
    const file = await readFile(env, registryPath(slug));
    if (!file) continue;
    const compiled = await compile(env, slug, file.content);
    if (compiled.ok) found.set(id, storedStrain(compiled.item));
  }
  return found;
}

/** The reagents a protocol's materials name, as the repository holds them; an id with no compiling file is left out, and the validator names it. */
export async function readReagents(env: RegistryEnv, ids: string[]): Promise<Map<string, StoredReagent>> {
  const found = new Map<string, StoredReagent>();
  for (const id of ids) {
    const slug = registrySlug("reagent", id);
    const file = await readFile(env, registryPath(slug));
    if (!file) continue;
    const compiled = await compile(env, slug, file.content);
    if (compiled.ok) found.set(id, storedReagent(compiled.item));
  }
  return found;
}

/** The equipment a protocol's list names, as the repository holds it; an id with no compiling file is left out, and the validator names it. */
export async function readEquipment(env: RegistryEnv, ids: string[]): Promise<Map<string, StoredEquipment>> {
  const found = new Map<string, StoredEquipment>();
  for (const id of ids) {
    const slug = registrySlug("equipment", id);
    const file = await readFile(env, registryPath(slug));
    if (!file) continue;
    const compiled = await compile(env, slug, file.content);
    if (compiled.ok) found.set(id, storedEquipment(compiled.item));
  }
  return found;
}