feat(14-03): convert core data services to async PostgreSQL operations

- item.service.ts: 6 functions async, removed .all()/.get()/.run()
- category.service.ts: 4 functions async, transaction uses async callback
- thread.service.ts: 10 functions async, transactions in resolveThread/reorderCandidates use async callbacks
- setup.service.ts: 8 functions async, syncSetupItems transaction uses async callback
- totals.service.ts: 2 functions async, removed .all()/.get()
This commit is contained in:
2026-04-04 12:32:58 +02:00
parent 295be8c09d
commit 4d705af3f1
5 changed files with 184 additions and 193 deletions

View File

@@ -5,11 +5,13 @@ import type { CreateSetup, UpdateSetup } from "../../shared/types.ts";
type Db = typeof prodDb;
export function createSetup(db: Db = prodDb, data: CreateSetup) {
return db.insert(setups).values({ name: data.name }).returning().get();
export async function createSetup(db: Db = prodDb, data: CreateSetup) {
const [row] = await db.insert(setups).values({ name: data.name }).returning();
return row;
}
export function getAllSetups(db: Db = prodDb) {
export async function getAllSetups(db: Db = prodDb) {
return db
.select({
id: setups.id,
@@ -31,15 +33,14 @@ export function getAllSetups(db: Db = prodDb) {
WHERE setup_items.setup_id = setups.id
), 0)`.as("total_cost"),
})
.from(setups)
.all();
.from(setups);
}
export function getSetupWithItems(db: Db = prodDb, setupId: number) {
const setup = db.select().from(setups).where(eq(setups.id, setupId)).get();
export async function getSetupWithItems(db: Db = prodDb, setupId: number) {
const [setup] = await db.select().from(setups).where(eq(setups.id, setupId));
if (!setup) return null;
const itemList = db
const itemList = await db
.select({
id: items.id,
name: items.name,
@@ -59,59 +60,56 @@ export function getSetupWithItems(db: Db = prodDb, setupId: number) {
.from(setupItems)
.innerJoin(items, eq(setupItems.itemId, items.id))
.innerJoin(categories, eq(items.categoryId, categories.id))
.where(eq(setupItems.setupId, setupId))
.all();
.where(eq(setupItems.setupId, setupId));
return { ...setup, items: itemList };
}
export function updateSetup(
export async function updateSetup(
db: Db = prodDb,
setupId: number,
data: UpdateSetup,
) {
const existing = db
const [existing] = await db
.select({ id: setups.id })
.from(setups)
.where(eq(setups.id, setupId))
.get();
.where(eq(setups.id, setupId));
if (!existing) return null;
return db
const [row] = await db
.update(setups)
.set({ name: data.name, updatedAt: new Date() })
.where(eq(setups.id, setupId))
.returning()
.get();
.returning();
return row;
}
export function deleteSetup(db: Db = prodDb, setupId: number) {
const existing = db
export async function deleteSetup(db: Db = prodDb, setupId: number) {
const [existing] = await db
.select({ id: setups.id })
.from(setups)
.where(eq(setups.id, setupId))
.get();
.where(eq(setups.id, setupId));
if (!existing) return false;
db.delete(setups).where(eq(setups.id, setupId)).run();
await db.delete(setups).where(eq(setups.id, setupId));
return true;
}
export function syncSetupItems(
export async function syncSetupItems(
db: Db = prodDb,
setupId: number,
itemIds: number[],
) {
return db.transaction((tx) => {
return await db.transaction(async (tx) => {
// Save existing classifications before deleting
const existing = tx
const existing = await tx
.select({
itemId: setupItems.itemId,
classification: setupItems.classification,
})
.from(setupItems)
.where(eq(setupItems.setupId, setupId))
.all();
.where(eq(setupItems.setupId, setupId));
const classificationMap = new Map<number, string>();
for (const row of existing) {
@@ -119,43 +117,41 @@ export function syncSetupItems(
}
// Delete all existing items for this setup
tx.delete(setupItems).where(eq(setupItems.setupId, setupId)).run();
await tx.delete(setupItems).where(eq(setupItems.setupId, setupId));
// Re-insert new items, preserving classifications for retained items
for (const itemId of itemIds) {
tx.insert(setupItems)
.values({
setupId,
itemId,
classification: classificationMap.get(itemId) ?? "base",
})
.run();
await tx.insert(setupItems).values({
setupId,
itemId,
classification: classificationMap.get(itemId) ?? "base",
});
}
});
}
export function updateItemClassification(
export async function updateItemClassification(
db: Db = prodDb,
setupId: number,
itemId: number,
classification: string,
) {
db.update(setupItems)
await db
.update(setupItems)
.set({ classification })
.where(
sql`${setupItems.setupId} = ${setupId} AND ${setupItems.itemId} = ${itemId}`,
)
.run();
);
}
export function removeSetupItem(
export async function removeSetupItem(
db: Db = prodDb,
setupId: number,
itemId: number,
) {
db.delete(setupItems)
await db
.delete(setupItems)
.where(
sql`${setupItems.setupId} = ${setupId} AND ${setupItems.itemId} = ${itemId}`,
)
.run();
);
}