diff --git a/db/kysely.cts b/db/kysely.cts index 2a548dc..3146b32 100644 --- a/db/kysely.cts +++ b/db/kysely.cts @@ -27,8 +27,19 @@ export interface CategoriesTable { updated_at: string; } +export interface CategoryGroupsTable { + id: number; + user_id: number; + name: string; + sort_order: number; + is_seeded: number; + created_at: string; + updated_at: string; +} + export interface Database { categories: CategoriesTable; + category_groups: CategoryGroupsTable; } // Build-only Kysely instance. The dialect supplies the SQLite compiler; its driver diff --git a/routes/categories.cts b/routes/categories.cts index b50fd21..7613ab9 100644 --- a/routes/categories.cts +++ b/routes/categories.cts @@ -5,6 +5,8 @@ const { ValidationError, NotFoundError, ConflictError } = require('../utils/apiE const router = express.Router(); const { getDb, ensureUserDefaultCategories } = require('../db/database.cts'); const { accountingActiveSql } = require('../services/paymentAccountingService.cts'); +const { kysely, all } = require('../db/kysely.cts'); +const { sql } = require('kysely'); // Maps a SQLite UNIQUE-constraint violation to a friendly 409; re-throws anything // else so the terminal handler returns a safe 500. @@ -198,19 +200,16 @@ router.put('/:id', (req: Req, res: Res) => { // ── Category groups ────────────────────────────────────────────────────────── -// GET /api/category-groups +// GET /api/category-groups — typed via Kysely (built, then run synchronously). router.get('/groups', (req: Req, res: Res) => { - const db = getDb(); - const groups = db - .prepare( - ` - SELECT id, name, sort_order, created_at, updated_at - FROM category_groups - WHERE user_id = ? - ORDER BY sort_order ASC, name COLLATE NOCASE ASC - `, - ) - .all(req.user.id); + const groups = all( + kysely() + .selectFrom('category_groups') + .select(['id', 'name', 'sort_order', 'created_at', 'updated_at']) + .where('user_id', '=', req.user.id) + .orderBy('sort_order', 'asc') + .orderBy(sql`name collate nocase`, 'asc'), + ); res.json(groups); });