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,7 +5,7 @@ import type { CreateItem } from "../../shared/types.ts";
type Db = typeof prodDb;
export function getAllItems(db: Db = prodDb) {
export async function getAllItems(db: Db = prodDb) {
return db
.select({
id: items.id,
@@ -24,33 +24,31 @@ export function getAllItems(db: Db = prodDb) {
categoryIcon: categories.icon,
})
.from(items)
.innerJoin(categories, eq(items.categoryId, categories.id))
.all();
.innerJoin(categories, eq(items.categoryId, categories.id));
}
export function getItemById(db: Db = prodDb, id: number) {
return (
db
.select({
id: items.id,
name: items.name,
weightGrams: items.weightGrams,
priceCents: items.priceCents,
categoryId: items.categoryId,
notes: items.notes,
productUrl: items.productUrl,
imageFilename: items.imageFilename,
imageSourceUrl: items.imageSourceUrl,
createdAt: items.createdAt,
updatedAt: items.updatedAt,
})
.from(items)
.where(eq(items.id, id))
.get() ?? null
);
export async function getItemById(db: Db = prodDb, id: number) {
const [row] = await db
.select({
id: items.id,
name: items.name,
weightGrams: items.weightGrams,
priceCents: items.priceCents,
categoryId: items.categoryId,
notes: items.notes,
productUrl: items.productUrl,
imageFilename: items.imageFilename,
imageSourceUrl: items.imageSourceUrl,
createdAt: items.createdAt,
updatedAt: items.updatedAt,
})
.from(items)
.where(eq(items.id, id));
return row ?? null;
}
export function createItem(
export async function createItem(
db: Db = prodDb,
data: Partial<CreateItem> & {
name: string;
@@ -58,7 +56,7 @@ export function createItem(
imageFilename?: string;
},
) {
return db
const [row] = await db
.insert(items)
.values({
name: data.name,
@@ -71,11 +69,12 @@ export function createItem(
imageFilename: data.imageFilename ?? null,
imageSourceUrl: data.imageSourceUrl ?? null,
})
.returning()
.get();
.returning();
return row;
}
export function updateItem(
export async function updateItem(
db: Db = prodDb,
id: number,
data: Partial<{
@@ -91,28 +90,28 @@ export function updateItem(
}>,
) {
// Check if item exists first
const existing = db
const [existing] = await db
.select({ id: items.id })
.from(items)
.where(eq(items.id, id))
.get();
.where(eq(items.id, id));
if (!existing) return null;
return db
const [row] = await db
.update(items)
.set({ ...data, updatedAt: new Date() })
.where(eq(items.id, id))
.returning()
.get();
.returning();
return row;
}
export function duplicateItem(db: Db = prodDb, id: number) {
const source = db.select().from(items).where(eq(items.id, id)).get();
export async function duplicateItem(db: Db = prodDb, id: number) {
const [source] = await db.select().from(items).where(eq(items.id, id));
if (!source) return null;
return db
const [row] = await db
.insert(items)
.values({
name: `${source.name} (copy)`,
@@ -125,17 +124,18 @@ export function duplicateItem(db: Db = prodDb, id: number) {
imageSourceUrl: source.imageSourceUrl,
quantity: source.quantity,
})
.returning()
.get();
.returning();
return row;
}
export function deleteItem(db: Db = prodDb, id: number) {
export async function deleteItem(db: Db = prodDb, id: number) {
// Get item first (for image cleanup info)
const item = db.select().from(items).where(eq(items.id, id)).get();
const [item] = await db.select().from(items).where(eq(items.id, id));
if (!item) return null;
db.delete(items).where(eq(items.id, id)).run();
await db.delete(items).where(eq(items.id, id));
return item;
}