app/components/media/upload.ts
29 lines and 2 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| uploadImage | 20 to 32 | 7 | 0% | CriticalCRAP 56 | No data: mutation testing has not run on this repo yet |
| <anonymous:29> | 29 to 29 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
Imports
It imports no other module of this repo. Imported by app/components/editor/writing-surface.tsx, app/components/media/library-insert.tsx.
Source
// The editor's image upload: one file to Carrel's per-project media endpoint, which hands it to the site
// through the site API. Never rejects with anything but an Error that says why, so the editor shows it.
export type EditorMedia = {
/** Carrel's media endpoint for this project: GET lists for the picker, POST uploads. */
endpoint: string;
/** The types the site accepts, for the file chooser's `accept`. A hint, not a control: the site checks. */
accept: string;
/** The site's own Markdown for an image with its alt text. */
figure: (url: string, alt: string) => string;
};
export type Uploaded = {
/** What the Markdown carries: the site's own address for the file. */
url: string;
/** Where Carrel's page loads it from, since Carrel is a different host. */
src: string;
};
export async function uploadImage(endpoint: string, file: File): Promise<Uploaded> {
let response: Response;
try {
const form = new FormData();
form.set("file", file);
response = await fetch(endpoint, { method: "POST", body: form });
} catch (error) {
throw new Error(`Upload failed: ${error instanceof Error ? error.message : String(error)}`);
}
const body = (await response.json().catch(() => ({}))) as { url?: string; src?: string; error?: string };
if (!response.ok || !body.url) throw new Error(body.error ?? `Upload failed (${response.status}).`);
return { url: body.url, src: body.src ?? body.url };
}