| import { Hono } from 'hono'; |
| import { eq, desc, inArray } from 'drizzle-orm'; |
| import { prompts, images } from '../db/schema'; |
| import type { Env, Variables } from '../index'; |
|
|
| export const promptsApi = new Hono<{ Bindings: Env; Variables: Variables }>(); |
|
|
| const uid = () => crypto.randomUUID(); |
| const now = () => Date.now(); |
|
|
| |
| promptsApi.get('/', async (c) => { |
| const db = c.var.db; |
| const rows = await db.select().from(prompts).orderBy(desc(prompts.updatedAt)); |
| |
| const ids = rows.map((r) => r.id); |
| const imgs = ids.length |
| ? await db.select().from(images).where(inArray(images.promptId, ids)) |
| : []; |
| const grouped: Record<string, typeof imgs> = {}; |
| for (const im of imgs) { |
| (grouped[im.promptId] ||= []).push(im); |
| } |
| return c.json( |
| rows.map((r) => ({ |
| ...r, |
| tags: safeJson<string[]>(r.tags || '[]', []), |
| images: (grouped[r.id] || []).sort((a, b) => a.createdAt - b.createdAt), |
| })) |
| ); |
| }); |
|
|
| |
| promptsApi.get('/:id', async (c) => { |
| const db = c.var.db; |
| const id = c.req.param('id'); |
| const row = (await db.select().from(prompts).where(eq(prompts.id, id))).at(0); |
| if (!row) return c.json({ error: 'not_found' }, 404); |
| const imgs = await db.select().from(images).where(eq(images.promptId, id)); |
| return c.json({ |
| ...row, |
| tags: safeJson<string[]>(row.tags || '[]', []), |
| images: imgs.sort((a, b) => a.createdAt - b.createdAt), |
| }); |
| }); |
|
|
| |
| promptsApi.post('/', async (c) => { |
| const db = c.var.db; |
| const body = await c.req.json<{ |
| title: string; |
| contentImage?: string; |
| contentVideo?: string; |
| tags?: string[]; |
| sourceUrl?: string; |
| }>(); |
| if (!body.title?.trim()) return c.json({ error: 'title_required' }, 400); |
| const ci = (body.contentImage || '').trim(); |
| const cv = (body.contentVideo || '').trim(); |
| if (!ci && !cv) return c.json({ error: 'prompt_required' }, 400); |
| const id = uid(); |
| const t = now(); |
| await db.insert(prompts).values({ |
| id, |
| title: body.title.trim(), |
| contentImage: ci, |
| contentVideo: cv, |
| tags: JSON.stringify(body.tags || []), |
| sourceUrl: body.sourceUrl?.trim() || null, |
| isFavorite: false, |
| createdAt: t, |
| updatedAt: t, |
| }); |
| return c.json({ id }); |
| }); |
|
|
| |
| promptsApi.put('/:id', async (c) => { |
| const db = c.var.db; |
| const id = c.req.param('id'); |
| const body = await c.req.json<{ |
| title?: string; |
| contentImage?: string; |
| contentVideo?: string; |
| tags?: string[]; |
| sourceUrl?: string; |
| }>(); |
| const exists = (await db.select().from(prompts).where(eq(prompts.id, id))).at(0); |
| if (!exists) return c.json({ error: 'not_found' }, 404); |
| const ci = body.contentImage !== undefined ? body.contentImage.trim() : exists.contentImage || ''; |
| const cv = body.contentVideo !== undefined ? body.contentVideo.trim() : exists.contentVideo || ''; |
| if (!ci && !cv) return c.json({ error: 'prompt_required' }, 400); |
| const promptChanged = |
| ci !== (exists.contentImage || '') || cv !== (exists.contentVideo || ''); |
| await db |
| .update(prompts) |
| .set({ |
| title: body.title?.trim() || exists.title, |
| contentImage: ci, |
| contentVideo: cv, |
| tags: body.tags !== undefined ? JSON.stringify(body.tags) : exists.tags, |
| sourceUrl: body.sourceUrl !== undefined ? body.sourceUrl.trim() || null : exists.sourceUrl, |
| |
| translationImage: promptChanged ? null : exists.translationImage, |
| translationVideo: promptChanged ? null : exists.translationVideo, |
| updatedAt: now(), |
| }) |
| .where(eq(prompts.id, id)); |
| return c.json({ ok: true }); |
| }); |
|
|
| |
| promptsApi.delete('/:id', async (c) => { |
| const db = c.var.db; |
| const id = c.req.param('id'); |
| await db.delete(images).where(eq(images.promptId, id)); |
| await db.delete(prompts).where(eq(prompts.id, id)); |
| return c.json({ ok: true }); |
| }); |
|
|
| |
| promptsApi.post('/:id/favorite', async (c) => { |
| const db = c.var.db; |
| const id = c.req.param('id'); |
| const row = (await db.select().from(prompts).where(eq(prompts.id, id))).at(0); |
| if (!row) return c.json({ error: 'not_found' }, 404); |
| await db |
| .update(prompts) |
| .set({ isFavorite: !row.isFavorite, updatedAt: now() }) |
| .where(eq(prompts.id, id)); |
| return c.json({ isFavorite: !row.isFavorite }); |
| }); |
|
|
| function safeJson<T>(s: string, fb: T): T { |
| try { return JSON.parse(s) as T; } catch { return fb; } |
| } |
|
|