app/routes/procedure.tsx
84 lines and 5 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| headers | 32 to 34 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| loader | 36 to 54 | 5 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| meta | 56 to 64 | 3 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| ProcedureRoute | 66 to 91 | 2 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:75> | 75 to 77 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
Imports
It imports app/components/breadcrumb.tsx, app/components/enhance.tsx, app/components/page-shell.tsx, app/components/procedure.tsx, app/db/procedure-versions.ts, app/db/procedures.ts, app/kb/procedures/json-ld.mjs, app/kb/procedures/library.mjs, app/kb/procedures/lineage.server.ts, app/kb/procedures/proof.server.ts, app/kb/procedures/route.ts, app/lib/access.server.ts, app/lib/context.ts, app/lib/json-ld.mjs, app/lib/seo.ts. No module of this repo imports it.
Source
import { data } from "react-router";
import { Breadcrumb } from "~/components/breadcrumb";
import { Enhance } from "~/components/enhance";
import { PageShell } from "~/components/page-shell";
import { ProcedureView } from "~/components/procedure";
import { listFrozenVersions } from "~/db/procedure-versions";
import { getProcedureByPath, listPublishedLibraryRecords } from "~/db/procedures";
import { isAdminViewer } from "~/lib/access.server";
import { getEnv } from "~/lib/context";
import { jsonLd as serializeJsonLd } from "~/lib/json-ld.mjs";
import { procedureJsonLd } from "~/kb/procedures/json-ld.mjs";
import { lineageFor } from "~/kb/procedures/lineage.server";
import { libraryItems, workflowContext } from "~/kb/procedures/library.mjs";
import { proofFor } from "~/kb/procedures/proof.server";
import { procedureTrail, PROCEDURES_CACHE_TAG, readScale } from "~/kb/procedures/route";
import { SITE, SITE_ORIGIN, breadcrumbJsonLd, pageMeta, personId, publicHtmlHeaders } from "~/lib/seo";
import type { Route } from "./+types/procedure";
// prose.css is route-scoped: a page using `.prose` without importing it renders unstyled.
import "~/styles/prose.css";
import "~/styles/procedure.css";
import "~/styles/run.css";
/**
* Every procedure page (docs/PROCEDURES.md): a protocol, a recipe or a computational procedure, drawn
* from its D1 row at request time, so an edit saved through the operator API is live without a deploy.
* A draft is served only to the signed-in admin; that request carries a cookie, and the Worker never
* stores a cookie-bearing response.
*/
export function headers() {
return new Headers(publicHtmlHeaders(PROCEDURES_CACHE_TAG));
}
export async function loader({ request, context }: Route.LoaderArgs) {
const env = getEnv(context);
const url = new URL(request.url);
const path = url.pathname.replace(/\/+$/, "");
const row = await getProcedureByPath(env, path);
if (!row) throw data(null, { status: 404 });
if (row.status === "draft" && !(await isAdminViewer(env, request))) throw data(null, { status: 404 });
const { count, factor, units } = readScale(row.record, url);
// Where a protocol sits in the phage workflow: its neighbours are the other published protocols, so they are read here.
const workflow =
row.record.profile === "protocol" ? workflowContext(libraryItems(await listPublishedLibraryRecords(env)), row.record.path) : null;
// Proof of use is slugs in the file; the papers' and phages' words and addresses are read from their rows.
const proof = await proofFor(env, row.record.proofOfUse);
// The versions with a frozen copy, which the history links.
const frozen = await listFrozenVersions(env, row.slug);
// A variant's parent: its title and the frozen copy it was taken from are the parent's own facts (P3).
const lineage = await lineageFor(env, row.record);
return { record: row.record, draft: row.status === "draft", count, factor, units, workflow, proof, frozen, lineage };
}
export function meta({ loaderData }: Route.MetaArgs) {
if (!loaderData) return [];
const { record, draft } = loaderData;
return [
...pageMeta({ title: record.seoTitle, description: record.description, path: record.path }),
{ tagName: "link", rel: "alternate", type: "text/markdown", href: `${SITE_ORIGIN}${record.path}.md` },
...(draft ? [{ name: "robots", content: "noindex" }] : []),
];
}
export default function ProcedureRoute({ loaderData }: Route.ComponentProps) {
const { record, draft, count, factor, units, workflow, proof, frozen, lineage } = loaderData;
const trail = procedureTrail(record);
const person = { "@type": "Person", "@id": personId(SITE_ORIGIN), name: SITE.name, url: SITE_ORIGIN };
const blocks = [breadcrumbJsonLd(SITE_ORIGIN, trail), procedureJsonLd(record, SITE_ORIGIN, person, lineage)];
return (
<PageShell
trail={
<>
{blocks.map((block, i) => (
<script key={i} type="application/ld+json" dangerouslySetInnerHTML={{ __html: serializeJsonLd(block) }} />
))}
</>
}
>
<Breadcrumb trail={trail} />
<h1 className="page-title">{record.title}</h1>
{draft ? <p className="procedure-draft">Draft: only you can see this page.</p> : null}
<ProcedureView record={record} count={count} factor={factor} units={units} workflow={workflow} proof={proof} frozen={frozen} lineage={lineage} />
{/* Run mode (app/enhance/run.ts): the page is complete as served; this adds the bench checklist. */}
<Enhance module="run" />
{/* Keep on this device (app/enhance/offline.ts): a copy that opens with no connection, only when the reader asks. */}
<Enhance module="offline" />
</PageShell>
);
}