Skip to the content

Capsid menu

app/lib/carrel/site-api.server.ts

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

Functions

The functions of site-api.server.ts
FunctionLinesComplexityCoveredCRAPMutation
carrelLimiter20 to 281No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
limit22 to 262No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
handleCarrelRequest31 to 482No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code

Imports

It imports app/lib/carrel/site-adapter.server.ts, app/lib/context.ts, app/lib/rate-limit.mjs. Imported by app/routes/api.carrel.v1.$.ts.

Source

// Mounts the site-api package for one request: the adapter, Carrel's key and the site's limiter.
// Here rather than in the route because the key is a secret, and secrets are read only in .server
// modules (check:secrets).

import { createSiteApi, type RateLimiter } from "@dustinedwards/site-api";
import { data, type RouterContextProvider } from "react-router";

import { carrelSiteAdapter } from "~/lib/carrel/site-adapter.server";
import { documentHandlerContext, getEnv, getExecutionContext } from "~/lib/context";
import { limitHit } from "~/lib/rate-limit.mjs";

const CARREL_RATE_LIMIT = 120;
const CARREL_RATE_PERIOD_SECONDS = 60;

/**
 * The site's own limiter, the ASK_BUDGET Durable Object, under a `carrel:` prefix. Not a `ratelimit`
 * binding: measured here, that binding refused 1, 2, 9 and 0 of twelve concurrent requests against a
 * limit of five (wrangler.jsonc.example). A missing limiter throws, which the package fails closed on.
 */
function carrelLimiter(env: Env): RateLimiter {
  return {
    async limit({ key }) {
      const verdict = await limitHit(env, `carrel:${key}`, CARREL_RATE_LIMIT, CARREL_RATE_PERIOD_SECONDS);
      if (verdict.status === "unavailable") throw new Error("the rate limiter is unavailable");
      return { success: verdict.status === "ok" };
    },
  };
}

/** The package guards in order: prefix, rate limit, key, route. Off the prefix is a 404. */
export async function handleCarrelRequest(
  request: Request,
  context: Readonly<RouterContextProvider>,
): Promise<Response> {
  const env = getEnv(context);
  const api = createSiteApi({
    adapter: carrelSiteAdapter({
      env,
      ctx: getExecutionContext(context),
      origin: new URL(request.url).origin,
      renderDocument: context.get(documentHandlerContext),
    }),
    key: env.CARREL_SITE_KEY,
    limiter: carrelLimiter(env),
  });
  if (!api.matches(request)) throw data("Not found", { status: 404 });
  return api.handle(request);
}