Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 1x 1x 1x 1x 4x 4x 4x 4x 4x 2x 2x 2x 1x 1x 2x 1x 7x 7x 7x 7x 7x 6x 1x 1x 1x 1x 1x | import { Hono } from "hono";
import { eq, sql } from "drizzle-orm";
import { z } from "zod";
import { getDb } from "../../db";
import { pageContent } from "../../db/schema";
import { success, handleError, error } from "../../lib/response";
import { createDualCache } from "../../lib/cache";
type Env = { Bindings: CloudflareBindings };
const faqItemSchema = z.object({
question: z.string().min(1).max(500),
answer: z.string().min(1).max(10000),
});
const faqListSchema = z.array(faqItemSchema).max(50);
const pageContentRouter = new Hono<Env>();
pageContentRouter.get("/:pageKey", async (c) => {
try {
const db = getDb(c.env.DB);
const rows = await db
.select()
.from(pageContent)
.where(eq(pageContent.pageKey, c.req.param("pageKey")));
const row = rows[0];
if (row?.faqs) {
try {
const faqs = JSON.parse(row.faqs) as { question: string; answer: string }[];
return success(c, { pageKey: c.req.param("pageKey"), faqs });
} catch (parseErr) {
Eif (parseErr instanceof SyntaxError) {
return c.json(
{ success: false, error: { code: "FAQ_JSON_CORRUPT", raw: row.faqs } },
500,
);
}
throw parseErr;
}
}
return success(c, { pageKey: c.req.param("pageKey"), faqs: [] });
} catch (err) {
return handleError(c, err);
}
});
pageContentRouter.put("/:pageKey", async (c) => {
try {
const db = getDb(c.env.DB);
const body = await c.req.json<unknown>();
const parsed = faqListSchema.safeParse((body as { faqs?: unknown })?.faqs);
if (!parsed.success) {
return error(c, "VALIDATION_ERROR", "Invalid FAQ payload", 400);
}
const faqsJson = JSON.stringify(parsed.data);
await db
.insert(pageContent)
.values({ pageKey: c.req.param("pageKey"), faqs: faqsJson })
.onConflictDoUpdate({
target: pageContent.pageKey,
set: { faqs: faqsJson, dateUpdated: sql`(unixepoch())` },
});
const cache = createDualCache(c.env.KV_CACHE);
await cache.delete(`seo:page:${c.req.param("pageKey")}`);
return success(c, { pageKey: c.req.param("pageKey"), faqs: parsed.data });
} catch (err) {
return handleError(c, err);
}
});
export default pageContentRouter;
|