100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
import { Hono } from 'hono';
|
|
import { z } from 'zod';
|
|
|
|
import {
|
|
SITE_TEXT_KINDS,
|
|
createSiteTextBlock,
|
|
deleteSiteTextBlock,
|
|
getSiteTextBlock,
|
|
listSiteTextBlocks,
|
|
updateSiteTextBlock,
|
|
upsertSiteTextBlock,
|
|
} from '@/entities/site-text';
|
|
import type { SiteTextBlockDraft, SiteTextBlockPatch } from '@/entities/site-text';
|
|
import { getDb } from '@/shared/db';
|
|
import { badRequest } from '@/shared/http/errors';
|
|
|
|
const idParam = z.coerce.number().int().positive();
|
|
|
|
const draftSchema = z.object({
|
|
kind: z.enum(SITE_TEXT_KINDS),
|
|
namespace: z.string().default(''),
|
|
key: z.string().min(1),
|
|
value: z.string().optional(),
|
|
listJson: z.string().nullable().optional(),
|
|
sortOrder: z.number().int().optional(),
|
|
providerSlug: z.string().optional(),
|
|
});
|
|
|
|
const patchSchema = z.object({
|
|
kind: z.enum(SITE_TEXT_KINDS).optional(),
|
|
namespace: z.string().optional(),
|
|
key: z.string().min(1).optional(),
|
|
value: z.string().optional(),
|
|
listJson: z.string().nullable().optional(),
|
|
sortOrder: z.number().int().optional(),
|
|
providerSlug: z.string().optional(),
|
|
});
|
|
|
|
export const siteTextRouter = new Hono()
|
|
.get('/', async (c) => {
|
|
const kind = c.req.query('kind');
|
|
const provider = c.req.query('provider');
|
|
const parsedKind = kind ? z.enum(SITE_TEXT_KINDS).safeParse(kind) : null;
|
|
if (parsedKind && !parsedKind.success) throw badRequest('bad_kind', 'invalid kind filter');
|
|
return c.json(
|
|
await listSiteTextBlocks(getDb(), {
|
|
...(parsedKind?.success ? { kind: parsedKind.data } : {}),
|
|
...(provider ? { providerSlug: provider } : {}),
|
|
}),
|
|
);
|
|
})
|
|
.get('/:id', async (c) => {
|
|
const id = idParam.parse(c.req.param('id'));
|
|
return c.json(await getSiteTextBlock(getDb(), id));
|
|
})
|
|
.post('/', async (c) => {
|
|
const raw = draftSchema.parse(await c.req.json());
|
|
const draft: SiteTextBlockDraft = {
|
|
kind: raw.kind,
|
|
namespace: raw.namespace,
|
|
key: raw.key,
|
|
...(raw.value !== undefined ? { value: raw.value } : {}),
|
|
...(raw.listJson !== undefined ? { listJson: raw.listJson } : {}),
|
|
...(raw.sortOrder !== undefined ? { sortOrder: raw.sortOrder } : {}),
|
|
...(raw.providerSlug !== undefined ? { providerSlug: raw.providerSlug } : {}),
|
|
};
|
|
return c.json(await createSiteTextBlock(getDb(), draft), 201);
|
|
})
|
|
.put('/upsert', async (c) => {
|
|
const raw = draftSchema.parse(await c.req.json());
|
|
const draft: SiteTextBlockDraft = {
|
|
kind: raw.kind,
|
|
namespace: raw.namespace,
|
|
key: raw.key,
|
|
...(raw.value !== undefined ? { value: raw.value } : {}),
|
|
...(raw.listJson !== undefined ? { listJson: raw.listJson } : {}),
|
|
...(raw.sortOrder !== undefined ? { sortOrder: raw.sortOrder } : {}),
|
|
...(raw.providerSlug !== undefined ? { providerSlug: raw.providerSlug } : {}),
|
|
};
|
|
return c.json(await upsertSiteTextBlock(getDb(), draft));
|
|
})
|
|
.put('/:id', async (c) => {
|
|
const id = idParam.parse(c.req.param('id'));
|
|
const raw = patchSchema.parse(await c.req.json());
|
|
const patch: SiteTextBlockPatch = {
|
|
...(raw.kind !== undefined ? { kind: raw.kind } : {}),
|
|
...(raw.namespace !== undefined ? { namespace: raw.namespace } : {}),
|
|
...(raw.key !== undefined ? { key: raw.key } : {}),
|
|
...(raw.value !== undefined ? { value: raw.value } : {}),
|
|
...(raw.listJson !== undefined ? { listJson: raw.listJson } : {}),
|
|
...(raw.sortOrder !== undefined ? { sortOrder: raw.sortOrder } : {}),
|
|
...(raw.providerSlug !== undefined ? { providerSlug: raw.providerSlug } : {}),
|
|
};
|
|
return c.json(await updateSiteTextBlock(getDb(), id, patch));
|
|
})
|
|
.delete('/:id', async (c) => {
|
|
const id = idParam.parse(c.req.param('id'));
|
|
await deleteSiteTextBlock(getDb(), id);
|
|
return c.body(null, 204);
|
|
});
|