feat: upload/recipe/job API routes + Klarbild visual identity
- api: /uploads (multipart, HEIC, 25MB guard, S3), /recipes (GET/POST), /jobs (create+snapshot+enqueue, list), /jobs/:id (status+items), /jobs/:id/:action (pause/resume/cancel/retry-failed), /items/:id/retry - design: adopt Till mockup identity — Space Grotesk + Space Mono (self-hosted, no google/US), blue accent, paper/card, registration-mark motif; OKLCH tokens - verified: astro build passes
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { query, one } from '../../lib/db';
|
||||
|
||||
export const prerender = false;
|
||||
const json = (b: unknown, s = 200) =>
|
||||
new Response(JSON.stringify(b), { status: s, headers: { 'Content-Type': 'application/json' } });
|
||||
|
||||
export const GET: APIRoute = async ({ locals }) => {
|
||||
if (!locals.user) return new Response('Unauthorized', { status: 401 });
|
||||
const rows = await query('SELECT * FROM recipes ORDER BY is_default DESC, name');
|
||||
return json({ recipes: rows });
|
||||
};
|
||||
|
||||
export const POST: APIRoute = async ({ request, locals }) => {
|
||||
if (!locals.user) return new Response('Unauthorized', { status: 401 });
|
||||
const b = await request.json();
|
||||
const row = await one(
|
||||
`INSERT INTO recipes (name, tasks, output_format, orientation, crop_mode, dpi, contour_mm,
|
||||
model_key, delivery, picdrop_gallery, custom_instruction, is_default, created_by)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,false,$12) RETURNING *`,
|
||||
[b.name, JSON.stringify(b.tasks || []), b.output_format, b.orientation, b.crop_mode || 'crop',
|
||||
b.dpi || 300, b.contour_mm ?? null, b.model_key ?? null, b.delivery || 'library',
|
||||
b.picdrop_gallery ?? null, b.custom_instruction ?? null, locals.user.uid]);
|
||||
return json({ recipe: row });
|
||||
};
|
||||
Reference in New Issue
Block a user