refactor(db): typed query helpers, shared test FormData helper
CI / check (push) Successful in 4m10s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m4s

Replace raw db.execute tuple casts with queryRows/rowsFrom/execResult/
affectedRows helpers from lib/db, drop redundant mysql2 casts on typed
query builders, and centralize per-test fakeForm into test/fake-form.
Update db mocks in tests so helpers resolve against mocked execute.
This commit is contained in:
openhands committed 2026-09-17 21:02:57 +02:00
1 parent 2e25b39364
commit 8638e81444
116 files changed
+866 -897

No files matched your search

+27 -52
View File
@@ -1,6 +1,6 @@
import { readdir } from "node:fs/promises";
import { sql } from "drizzle-orm";
import { db } from "@/lib/db";
import { queryRows } from "@/lib/db";
import { fetchSourceFurnidata } from "@/lib/services/clone-import";
import { listSources } from "@/lib/services/clone-sources";
import {
@@ -215,20 +215,10 @@ export async function runCatalogAudit(
interaction_type: string;
}>;
try {
const [rows] = (await db.execute(sql`
items = await queryRows<(typeof items)[number]>(sql`
SELECT id, item_name, public_name, type, interaction_type
FROM items_base ORDER BY id
`)) as unknown as [
Array<{
id: number;
item_name: string;
public_name: string;
type: string;
interaction_type: string;
}>,
unknown,
];
items = rows;
`);
} catch (err) {
onEvent?.({
type: "error",
@@ -262,13 +252,9 @@ export async function runCatalogAudit(
catalog_name: string;
}>;
try {
const [rows] = (await db.execute(sql`
catalogItems = await queryRows<(typeof catalogItems)[number]>(sql`
SELECT id, item_ids, catalog_name FROM catalog_items ORDER BY id
`)) as unknown as [
Array<{ id: number; item_ids: string; catalog_name: string }>,
unknown,
];
catalogItems = rows;
`);
} catch (err) {
onEvent?.({
type: "error",
@@ -625,12 +611,13 @@ export async function runCatalogAudit(
orphanedCleaned = orphanResult.cleaned;
// Re-derive orphaned_catalog issues from the fixed data.
const [afterCatalog] = (await db.execute(sql`
const afterCatalog = await queryRows<{
id: number;
item_ids: string;
catalog_name: string;
}>(sql`
SELECT id, item_ids, catalog_name FROM catalog_items ORDER BY id
`)) as unknown as [
Array<{ id: number; item_ids: string; catalog_name: string }>,
unknown,
];
`);
const orphanedCatalogIds = new Set<number>();
for (const ci of afterCatalog) {
const ids = ci.item_ids.split(";").map(Number).filter(Boolean);
@@ -650,9 +637,9 @@ export async function runCatalogAudit(
remappedReferences = duplicateResult.remapped;
// Re-derive duplicate_classname issues from the fixed data.
const [afterItems] = (await db.execute(sql`
const afterItems = await queryRows<{ item_name: string }>(sql`
SELECT item_name FROM items_base
`)) as unknown as [Array<{ item_name: string }>, unknown];
`);
const afterCount = new Map<string, number>();
for (const row of afterItems) {
afterCount.set(row.item_name, (afterCount.get(row.item_name) ?? 0) + 1);
@@ -683,27 +670,19 @@ export async function runCatalogAudit(
// state, otherwise the generated catalog SQL would insert orphaned
// catalog_items rows (item_ids pointing at deleted sprite ids).
if (duplicateRowsRemoved > 0 || orphanedRemoved > 0) {
const [postItems] = (await db.execute(sql`
const postItems = await queryRows<(typeof items)[number]>(sql`
SELECT id, item_name, public_name, type, interaction_type
FROM items_base ORDER BY id
`)) as unknown as [
Array<{
id: number;
item_name: string;
public_name: string;
type: string;
interaction_type: string;
}>,
unknown,
];
`);
items = postItems;
const [postCatalog] = (await db.execute(sql`
const postCatalog = await queryRows<{
id: number;
item_ids: string;
catalog_name: string;
}>(sql`
SELECT id, item_ids, catalog_name FROM catalog_items ORDER BY id
`)) as unknown as [
Array<{ id: number; item_ids: string; catalog_name: string }>,
unknown,
];
`);
const postCatalogIds = new Set<number>();
for (const ci of postCatalog) {
const ids = ci.item_ids.split(";").map(Number).filter(Boolean);
@@ -971,13 +950,13 @@ export async function inspectLiveCatalogIntegrity(catalog: "normal" | "bc") {
catalog === "bc" ? "catalog_items_bc" : "catalog_items",
);
const [pageResult, itemResult, offerResult] = await Promise.all([
db.execute(
queryRows<import("./catalog-integrity").IntegrityPage>(
sql`SELECT id, parent_id AS parentId, caption FROM ${pagesTable} ORDER BY id`,
),
db.execute(
queryRows<import("./catalog-integrity").IntegrityItem>(
sql`SELECT id, item_name, public_name, type, interaction_type FROM items_base ORDER BY id`,
),
db.execute(
queryRows<import("./catalog-integrity").IntegrityOffer>(
sql`SELECT id, page_id AS pageId, item_ids AS itemIds, catalog_name AS name, ${catalog === "bc" ? sql`NULL` : sql`offer_id`} AS offerId FROM ${offersTable} ORDER BY id`,
),
]);
@@ -990,13 +969,9 @@ export async function inspectLiveCatalogIntegrity(catalog: "normal" | "bc") {
}
return inspectCatalogIntegrity({
catalog,
pages:
pageResult[0] as unknown as import("./catalog-integrity").IntegrityPage[],
items:
itemResult[0] as unknown as import("./catalog-integrity").IntegrityItem[],
offers: (
offerResult[0] as unknown as import("./catalog-integrity").IntegrityOffer[]
).map((row) => ({
pages: pageResult,
items: itemResult,
offers: offerResult.map((row) => ({
...row,
pageId: Number(row.pageId),
offerId: row.offerId === null ? null : Number(row.offerId),