app/routes/preview.ts
37 lines and 1 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| loader | 15 to 42 | 10 | 76% | WatchCRAP 11.4 | No data: mutation testing has not run on this repo yet |
Imports
It imports app/lib/ai.server.ts, app/lib/content.server.ts, app/lib/context.ts, app/lib/preview.server.ts, app/lib/projects.server.ts, app/lib/sites.server.ts. No module of this repo imports it.
Source
// The preview document for the editor's iframe: the viewer's working copy (or the site's version when
// there is none), rendered by the site's own pipeline, served under a sandboxing policy of its own.
import { SiteApiError } from "@dustinedwards/site-api/client";
import { listAiDrafts, readAiDraft } from "~/lib/ai.server";
import { readDoc, readDraft } from "~/lib/content.server";
import { getEnv, getViewer } from "~/lib/context";
import { previewFailure, previewResponse, withLabel } from "~/lib/preview.server";
import { requireSiteProject } from "~/lib/projects.server";
import { siteClient, siteConnection, SiteNotConnected } from "~/lib/sites.server";
import type { Route } from "./+types/preview";
export async function loader({ params, context }: Route.LoaderArgs) {
const env = getEnv(context);
const viewer = getViewer(context);
const project = await requireSiteProject(env.DB, viewer, params.project, "read");
const itemId = params.item;
const connection = siteConnection(env, project.site);
if (connection.state !== "connected") return previewFailure(`The site is not connected: ${connection.detail}`);
try {
const draft = await readDraft(env.DB, project, viewer, itemId);
let source = draft?.source ?? (await readDoc(env, project, itemId))?.source;
let label: string | null = null;
if (source === undefined) {
// Nothing of the person's own and nothing on the site: show the newest AI draft, labelled as theirs to take or leave.
const [latest] = await listAiDrafts(env.DB, project, viewer, itemId);
if (!latest) return previewFailure("There is nothing to preview yet.");
source = (await readAiDraft(env.DB, project, viewer, itemId, latest.id)).source;
label = `AI draft from ${latest.client}. It is not your draft and it is not on the site.`;
}
const html = await siteClient(env, project.site).preview({ id: itemId, source });
return previewResponse(label ? withLabel(html, label) : html, connection.origin);
} catch (error) {
if (error instanceof SiteNotConnected) return previewFailure(error.detail);
if (error instanceof SiteApiError && error.body) return previewFailure(`The site could not render this: ${error.body.message}`);
console.error(JSON.stringify({ preview: "failed", itemId, error: String(error) }));
return previewFailure("The site did not answer the preview request.");
}
}