All checks were successful
CI / ci (push) Successful in 15s
Run biome check --write --unsafe to fix tabs, import ordering, and non-null assertions across entire codebase. Disable a11y rules not applicable to this single-user app. Exclude auto-generated routeTree. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
113 lines
2.4 KiB
TypeScript
113 lines
2.4 KiB
TypeScript
import { eq } from "drizzle-orm";
|
|
import { db as prodDb } from "../../db/index.ts";
|
|
import { categories, items } from "../../db/schema.ts";
|
|
import type { CreateItem } from "../../shared/types.ts";
|
|
|
|
type Db = typeof prodDb;
|
|
|
|
export function getAllItems(db: Db = prodDb) {
|
|
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,
|
|
createdAt: items.createdAt,
|
|
updatedAt: items.updatedAt,
|
|
categoryName: categories.name,
|
|
categoryIcon: categories.icon,
|
|
})
|
|
.from(items)
|
|
.innerJoin(categories, eq(items.categoryId, categories.id))
|
|
.all();
|
|
}
|
|
|
|
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,
|
|
createdAt: items.createdAt,
|
|
updatedAt: items.updatedAt,
|
|
})
|
|
.from(items)
|
|
.where(eq(items.id, id))
|
|
.get() ?? null
|
|
);
|
|
}
|
|
|
|
export function createItem(
|
|
db: Db = prodDb,
|
|
data: Partial<CreateItem> & {
|
|
name: string;
|
|
categoryId: number;
|
|
imageFilename?: string;
|
|
},
|
|
) {
|
|
return db
|
|
.insert(items)
|
|
.values({
|
|
name: data.name,
|
|
weightGrams: data.weightGrams ?? null,
|
|
priceCents: data.priceCents ?? null,
|
|
categoryId: data.categoryId,
|
|
notes: data.notes ?? null,
|
|
productUrl: data.productUrl ?? null,
|
|
imageFilename: data.imageFilename ?? null,
|
|
})
|
|
.returning()
|
|
.get();
|
|
}
|
|
|
|
export function updateItem(
|
|
db: Db = prodDb,
|
|
id: number,
|
|
data: Partial<{
|
|
name: string;
|
|
weightGrams: number;
|
|
priceCents: number;
|
|
categoryId: number;
|
|
notes: string;
|
|
productUrl: string;
|
|
imageFilename: string;
|
|
}>,
|
|
) {
|
|
// Check if item exists first
|
|
const existing = db
|
|
.select({ id: items.id })
|
|
.from(items)
|
|
.where(eq(items.id, id))
|
|
.get();
|
|
|
|
if (!existing) return null;
|
|
|
|
return db
|
|
.update(items)
|
|
.set({ ...data, updatedAt: new Date() })
|
|
.where(eq(items.id, id))
|
|
.returning()
|
|
.get();
|
|
}
|
|
|
|
export 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();
|
|
|
|
if (!item) return null;
|
|
|
|
db.delete(items).where(eq(items.id, id)).run();
|
|
|
|
return item;
|
|
}
|