feat(14-03): convert auth/oauth/csv services to async, await seedDefaults
- auth.service.ts: 10 functions async, removed .all()/.get()/.run() - oauth.service.ts: 7 functions async, boolean conversion (used: true/false) - csv.service.ts: export/import functions async, removed .all()/.get()/.run() - server index.ts: seedDefaults() now awaited for async DB - PGlite smoke test confirms async services work end-to-end
This commit is contained in:
@@ -84,8 +84,8 @@ function parseCsv(content: string): { headers: string[]; rows: string[][] } {
|
||||
|
||||
// ─── Export ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export function exportItemsCsv(db: Db = prodDb): string {
|
||||
const rows = db
|
||||
export async function exportItemsCsv(db: Db = prodDb): Promise<string> {
|
||||
const rows = await db
|
||||
.select({
|
||||
name: items.name,
|
||||
quantity: items.quantity,
|
||||
@@ -96,8 +96,7 @@ export function exportItemsCsv(db: Db = prodDb): string {
|
||||
productUrl: items.productUrl,
|
||||
})
|
||||
.from(items)
|
||||
.innerJoin(categories, eq(items.categoryId, categories.id))
|
||||
.all();
|
||||
.innerJoin(categories, eq(items.categoryId, categories.id));
|
||||
|
||||
const header =
|
||||
"name,quantity,weightGrams,priceCents,category,notes,productUrl";
|
||||
@@ -124,10 +123,10 @@ export interface ImportResult {
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export function importItemsCsv(
|
||||
export async function importItemsCsv(
|
||||
db: Db = prodDb,
|
||||
csvContent: string,
|
||||
): ImportResult {
|
||||
): Promise<ImportResult> {
|
||||
const { headers, rows } = parseCsv(csvContent);
|
||||
|
||||
const result: ImportResult = {
|
||||
@@ -152,10 +151,9 @@ export function importItemsCsv(
|
||||
|
||||
// Build a local category cache (name → id) seeded from the DB
|
||||
const categoryCache = new Map<string, number>();
|
||||
const existingCategories = db
|
||||
const existingCategories = await db
|
||||
.select({ id: categories.id, name: categories.name })
|
||||
.from(categories)
|
||||
.all();
|
||||
.from(categories);
|
||||
for (const cat of existingCategories) {
|
||||
categoryCache.set(cat.name.toLowerCase(), cat.id);
|
||||
}
|
||||
@@ -181,11 +179,10 @@ export function importItemsCsv(
|
||||
categoryId = categoryCache.get(cacheKey)!;
|
||||
} else {
|
||||
// Create a new category
|
||||
const inserted = db
|
||||
const [inserted] = await db
|
||||
.insert(categories)
|
||||
.values({ name: categoryName, icon: "package" })
|
||||
.returning()
|
||||
.get();
|
||||
.returning();
|
||||
categoryId = inserted.id;
|
||||
categoryCache.set(cacheKey, categoryId);
|
||||
result.createdCategories.push(categoryName);
|
||||
@@ -222,19 +219,17 @@ export function importItemsCsv(
|
||||
const notes = notesIdx >= 0 ? row[notesIdx]?.trim() || null : null;
|
||||
const productUrl = urlIdx >= 0 ? row[urlIdx]?.trim() || null : null;
|
||||
|
||||
db.insert(items)
|
||||
.values({
|
||||
name,
|
||||
quantity,
|
||||
weightGrams,
|
||||
priceCents,
|
||||
categoryId,
|
||||
notes,
|
||||
productUrl,
|
||||
imageFilename: null,
|
||||
imageSourceUrl: null,
|
||||
})
|
||||
.run();
|
||||
await db.insert(items).values({
|
||||
name,
|
||||
quantity,
|
||||
weightGrams,
|
||||
priceCents,
|
||||
categoryId,
|
||||
notes,
|
||||
productUrl,
|
||||
imageFilename: null,
|
||||
imageSourceUrl: null,
|
||||
});
|
||||
|
||||
result.imported++;
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user