Skip to the content

Capsid menu

app/lib/projects.server.ts

35 lines and 1 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.

Functions

The functions of projects.server.ts
FunctionLinesComplexityCoveredCRAPMutation
requireSiteProject21 to 384100%OkCRAP 4No data: mutation testing has not run on this repo yet

Imports

It imports app/db/schema.ts, app/lib/people.server.ts, app/lib/roles.ts, app/lib/sites.server.ts. Imported by app/lib/ai.server.ts, app/lib/bulk.server.ts, app/lib/content.server.ts, app/lib/google/drive.server.ts, app/lib/google/search-console.server.ts, app/lib/history.server.ts, app/lib/legal.server.ts, app/lib/mcp/tools.ts, app/lib/media.server.ts, app/lib/mentions.server.ts, app/lib/voice.server.ts, app/routes/ai-draft.preview.ts, app/routes/ai-draft.tsx, app/routes/editor.tsx, app/routes/history.tsx, app/routes/legal.tsx, app/routes/media.api.ts, app/routes/media.bulk.ts, app/routes/media.tsx, app/routes/mentions.api.ts, app/routes/mentions.tsx, app/routes/preview.ts, app/routes/project.bulk.ts, app/routes/project.flags.tsx, app/routes/project.new.tsx, app/routes/project.tsx, app/routes/project.voice.tsx, app/routes/unpublish.tsx.

Source

import { eq } from "drizzle-orm";
import { drizzle } from "drizzle-orm/d1";

import { projects } from "~/db/schema";
import { requireAction, type Viewer } from "~/lib/people.server";
import type { Action, Role } from "~/lib/roles";
import { isSiteId, type SiteId } from "~/lib/sites.server";

export type SiteProject = {
  id: number;
  slug: string;
  name: string;
  site: SiteId;
  role: Role;
};

/**
 * The project behind a URL, for a viewer allowed `action` on it. A project that does not exist, is
 * not shared with the viewer, or is not a site all answer 404, so a URL reveals nothing.
 */
export async function requireSiteProject(
  db: D1Database,
  viewer: Viewer,
  slug: string | undefined,
  action: Action,
): Promise<SiteProject> {
  const row = slug
    ? await drizzle(db)
        .select({ id: projects.id, slug: projects.slug, name: projects.name, site: projects.site })
        .from(projects)
        .where(eq(projects.slug, slug))
        .get()
    : undefined;
  if (!row) throw new Response("Not found", { status: 404 });
  const role = await requireAction(db, viewer, row.id, action);
  if (!isSiteId(row.site)) throw new Response("Not found", { status: 404 });
  return { id: row.id, slug: row.slug, name: row.name, site: row.site, role };
}