From 904d45e011075e567da99ac761aa8e1614462e2a Mon Sep 17 00:00:00 2001 From: Egor Date: Fri, 31 Jul 2026 12:50:29 +0300 Subject: [PATCH] fix(combos): include DB id column in combo records for dashboard links getCombos() selected only data/sort_order/context_cache_protection, so combos whose JSON blob lacked an id field returned id: undefined. The dashboard then linked to /dashboard/combos/undefined and Combo Control Center failed with 'Combo not found'. Merge the id column into parsed rows (authoritative, only when the blob has no id). --- src/lib/db/combos.ts | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/lib/db/combos.ts b/src/lib/db/combos.ts index fd0423f52c..0a7f618062 100644 --- a/src/lib/db/combos.ts +++ b/src/lib/db/combos.ts @@ -27,6 +27,21 @@ function getSortOrder(value: unknown): number | null { return typeof row.sort_order === "number" ? row.sort_order : null; } +function getComboId(value: unknown): string | null { + const row = asRecord(value); + return typeof row.id === "string" && row.id.trim().length > 0 ? row.id : null; +} + +function withRowId(payload: string, row: JsonRecord): JsonRecord | null { + const parsed = withSortOrder(payload, getSortOrder(row)); + if (!parsed) return null; + const comboId = getComboId(row); + if (comboId && typeof parsed.id !== "string") { + parsed.id = comboId; + } + return parsed; +} + function withSortOrder(payload: string, sortOrder: number | null): JsonRecord | null { let parsed: JsonRecord; try { @@ -78,7 +93,7 @@ function normalizeStoredCombo( function parseComboRow(row: unknown): JsonRecord | null { const payload = getSerializedData(row); if (!payload) return null; - const parsed = withSortOrder(payload, getSortOrder(row)); + const parsed = withRowId(payload, asRecord(row)); if (!parsed) return null; // Merge deduplicated column values back into the record const record = asRecord(row); @@ -104,7 +119,7 @@ function getNextSortOrder() { export async function getCombos(limit?: number, offset?: number) { const db = getDbInstance(); let sql = - "SELECT data, sort_order, context_cache_protection FROM combos ORDER BY sort_order ASC, name COLLATE NOCASE ASC"; + "SELECT id, data, sort_order, context_cache_protection FROM combos ORDER BY sort_order ASC, name COLLATE NOCASE ASC"; const params: unknown[] = []; if (limit !== undefined) { sql += " LIMIT ? OFFSET ?"; @@ -136,7 +151,7 @@ export function getCombosCount(): number { export async function getComboById(id: string) { const db = getDbInstance(); const row = db - .prepare("SELECT data, sort_order, context_cache_protection FROM combos WHERE id = ?") + .prepare("SELECT id, data, sort_order, context_cache_protection FROM combos WHERE id = ?") .get(id); const combo = parseComboRow(row); if (!combo) return null; @@ -146,7 +161,7 @@ export async function getComboById(id: string) { export async function getComboByName(name: string) { const db = getDbInstance(); const row = db - .prepare("SELECT data, sort_order, context_cache_protection FROM combos WHERE name = ?") + .prepare("SELECT id, data, sort_order, context_cache_protection FROM combos WHERE name = ?") .get(name); const combo = parseComboRow(row); if (!combo) return null; @@ -162,7 +177,7 @@ export async function getComboByNameInsensitive(name: string) { const db = getDbInstance(); const row = db .prepare( - "SELECT data, sort_order, context_cache_protection FROM combos WHERE name = ? COLLATE NOCASE" + "SELECT id, data, sort_order, context_cache_protection FROM combos WHERE name = ? COLLATE NOCASE" ) .get(name); const combo = parseComboRow(row); @@ -207,7 +222,7 @@ export async function createCombo(data: JsonRecord) { export async function updateCombo(id: string, data: JsonRecord) { const db = getDbInstance(); const existing = db - .prepare("SELECT data, sort_order, context_cache_protection FROM combos WHERE id = ?") + .prepare("SELECT id, data, sort_order, context_cache_protection FROM combos WHERE id = ?") .get(id); if (!existing) return null;