Skip to the content

Capsid menu

src/local.ts

29 lines and 5 functions in DrDustinEdwards/site-api, at commit d3b340f on 2026-10-24. It is in an import cycle. This file on GitHub.

Functions

The functions of local.ts
FunctionLinesComplexityCoveredCRAPMutation
inProcessKey17 to 201100%OkCRAP 1Ok100%
<anonymous:19>19 to 191100%OkCRAP 1Watch75%
localClient22 to 332100%OkCRAP 2Watch75%
limit28 to 281100%OkCRAP 1Ok100%
<anonymous:31>31 to 311100%OkCRAP 1No data: no mutants in this code

Imports

It imports src/adapter.ts, src/client.ts, src/server.ts. Imported by src/admin.ts, src/client.ts.

Source

// A site's own admin, talking to its own adapter in process. localClient(adapter) answers every
// method createSiteClient does, with the same types and the same SiteApiError, by handing each
// request straight to createSiteApi's handler: no network, no configured key, and the very code
// Carrel's requests meet. So every route rule, version check, upload check and zod parse is the one
// Carrel gets, and the content kit (./admin) runs the same against either client.

import type { SiteAdapter } from "./adapter.js";
import { createSiteClient, type SiteClient } from "./client.js";
import { createSiteApi } from "./server.js";

export interface LocalClientOptions {
  /** Where adapter failures and contract breaches are logged. Defaults to console, as createSiteApi does. */
  log?: (entry: Record<string, unknown>) => void;
}

/** A key that lives only in this closure: the handler insists on one, and nothing outside can learn it. */
function inProcessKey(): string {
  const bytes = crypto.getRandomValues(new Uint8Array(32));
  return [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
}

export function localClient(adapter: SiteAdapter, options: LocalClientOptions = {}): SiteClient {
  const key = inProcessKey();
  const api = createSiteApi({
    adapter,
    key,
    // One person in their own admin is not a burst from the internet; the site's own sign-in guards this door.
    limiter: { limit: async () => ({ success: true }) },
    ...(options.log ? { log: options.log } : {}),
  });
  const handle = (async (input: RequestInfo | URL, init?: RequestInit) => api.handle(new Request(input, init))) as typeof fetch;
  return createSiteClient({ baseUrl: adapter.site.origin, key, fetch: handle });
}