1const MAX_UPLOAD = 1_100_000;
2
3// Files and search reach your Klippy only through here: signed in, and the agent picked from your session.
4export default createController(routes.sources, {
5 middleware: [requireUser],
6 actions: {
7 // POST /sources/file (a form with a "file" field): pass the file on to your Klippy, which ingests it.
8 async upload(context) {
9 const request = context.request;
10 const type = request.headers.get('Content-Type') ?? '';
11 const size = Number(request.headers.get('Content-Length') ?? NaN);
12 if (!type.startsWith('multipart/form-data')) return new Response('Send a form with a file.', { status: 400 });
13 if (!(size <= MAX_UPLOAD)) return new Response('Files can be up to 1 MB.', { status: 413 });
14 const body = await request.arrayBuffer();
15 if (body.byteLength > MAX_UPLOAD) return new Response('Files can be up to 1 MB.', { status: 413 });
16 const reply = await agentFetch(`/agents/klippy/${agentName(context.auth.identity)}/file`, {
17 method: 'POST',
18 headers: { 'Content-Type': type },
19 body,
20 });
21 if (reply.ok) return redirect(`${routes.notes.index.href()}?sent=1`, 303);
22 const { error } = await reply.json<{ error?: string }>().catch(() => ({ error: undefined }));
23 return new Response(error ?? `Klippy didn't take the file (HTTP ${reply.status}).`, { status: reply.status < 500 ? reply.status : 502 });