Download src/api/prompts.ts from ghuser1/pl: direct link, hf CLI and curl.
- Browser
- Download file 4.44 kB
-
https://huggingface.co/spaces/ghuser1/pl/resolve/main/src/api/prompts.ts
- Command line
-
hf download hf://spaces/ghuser1/pl/src/api/prompts.ts
-
curl -L -o prompts.ts https://huggingface.co/spaces/ghuser1/pl/resolve/main/src/api/prompts.ts
4.44 kB
| 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(); | |
| // List | |
| promptsApi.get('/', async (c) => { | |
| const db = c.var.db; | |
| const rows = await db.select().from(prompts).orderBy(desc(prompts.updatedAt)); | |
| // Attach images per prompt | |
| 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), | |
| })) | |
| ); | |
| }); | |
| // Get one | |
| 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), | |
| }); | |
| }); | |
| // Create | |
| 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 }); | |
| }); | |
| // Update | |
| 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 }); | |
| }); | |
| // Delete | |
| 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 }); | |
| }); | |
| // Toggle favorite | |
| 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; } | |
| } | |