Skip to the content

Capsid menu

app/db/pages.ts

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

Functions

The functions of pages.ts
FunctionLinesComplexityCoveredCRAPMutation
getPageByPath20 to 302No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
getPublishedPageMarkdown33 to 422No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
getPublishedPageTitles45 to 522No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
<anonymous:51>51 to 511No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
listPublishedPageTitles58 to 641No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
<anonymous:63>63 to 631No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
listPublishedPageSources67 to 731No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
<anonymous:72>72 to 721No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
listPublishedPageHtml76 to 821No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
<anonymous:81>81 to 811No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
listPageRows85 to 911No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
<anonymous:90>90 to 901No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code

Imports

It imports app/db/client.ts, app/db/schema.ts, app/lib/pages/compile.mjs, app/lib/search/visibility.mjs. Imported by app/lib/carrel/page-handler.server.ts, app/lib/llms/save.server.ts, app/lib/operator/api.server.ts, app/lib/pages/save.server.ts, app/lib/site-urls.server.ts, app/routes/about.tsx, app/routes/content-page.tsx, app/routes/content-page[.md].ts, app/routes/phages.tsx, app/routes/protocols.tsx, app/routes/protocols[.md].ts.

Source

// The pages table: read by the content-page route, its twin, the sitemap and the operator API. Written only
// by writeRow in app/lib/pages/save.server.ts and by sync:content, from a compile
// (app/lib/pages/compile.mjs).
import { and, asc, eq, inArray } from "drizzle-orm";

import { PUBLISHED_STATUS } from "~/lib/search/visibility.mjs";
import type { PageRecord } from "~/lib/pages/compile.mjs";

import { getDb } from "./client";
import { pages } from "./schema";

export type PageRow = {
  slug: string;
  path: string;
  status: "draft" | "published";
  record: PageRecord;
};

/** The page's row, or null. A draft comes back too: the route decides who may see it. */
export async function getPageByPath(env: Env, path: string): Promise<PageRow | null> {
  const row = (
    await getDb(env)
      .select({ slug: pages.slug, path: pages.path, status: pages.status, record: pages.record })
      .from(pages)
      .where(eq(pages.path, path))
      .limit(1)
  )[0];
  if (!row) return null;
  return { ...row, record: JSON.parse(row.record) as PageRecord };
}

/** The twin, published rows only: a draft's twin answers 404 like its page. */
export async function getPublishedPageMarkdown(env: Env, path: string) {
  const row = (
    await getDb(env)
      .select({ markdown: pages.markdown })
      .from(pages)
      .where(and(eq(pages.path, path), eq(pages.status, PUBLISHED_STATUS)))
      .limit(1)
  )[0];
  return row?.markdown ?? null;
}

/** The titles of other pages, for the trail above a page that sits under one. Published rows only. */
export async function getPublishedPageTitles(env: Env, paths: string[]) {
  if (paths.length === 0) return new Map<string, string>();
  const rows = await getDb(env)
    .select({ path: pages.path, title: pages.title })
    .from(pages)
    .where(and(inArray(pages.path, paths), eq(pages.status, PUBLISHED_STATUS)));
  return new Map(rows.map((row) => [row.path, row.title]));
}

/**
 * Every published page's title, by path: the sitemap's list (app/lib/site-urls.server.ts) and the llms.txt save.
 * No IN list: D1 binds at most 100 parameters, and the page registry is not bounded by that.
 */
export async function listPublishedPageTitles(env: Env) {
  const rows = await getDb(env)
    .select({ path: pages.path, title: pages.title })
    .from(pages)
    .where(eq(pages.status, PUBLISHED_STATUS));
  return new Map(rows.map((row) => [row.path, row.title]));
}

/** For the sitemap's dates (app/lib/site-urls.server.ts): every published page's source file, by path. */
export async function listPublishedPageSources(env: Env) {
  const rows = await getDb(env)
    .select({ path: pages.path, sourcePath: pages.sourcePath })
    .from(pages)
    .where(eq(pages.status, PUBLISHED_STATUS));
  return new Map(rows.map((row) => [row.path, row.sourcePath]));
}

/** For the save-time link check: every published page's rendered HTML, by path. */
export async function listPublishedPageHtml(env: Env) {
  const rows = await getDb(env)
    .select({ path: pages.path, record: pages.record })
    .from(pages)
    .where(eq(pages.status, PUBLISHED_STATUS));
  return new Map(rows.map((row) => [row.path, (JSON.parse(row.record) as PageRecord).html]));
}

/** For list_pages and Carrel's list: every row, drafts included, with when D1 last wrote it. */
export async function listPageRows(env: Env) {
  const rows = await getDb(env)
    .select({ slug: pages.slug, path: pages.path, title: pages.title, status: pages.status, syncedAt: pages.syncedAt })
    .from(pages)
    .orderBy(asc(pages.path));
  return rows.map(({ status, ...row }) => ({ ...row, draft: status === "draft" }));
}