88 lines
2.9 KiB
TypeScript
88 lines
2.9 KiB
TypeScript
import { openDB, type IDBPDatabase } from 'idb';
|
|
import type { Diary, Product } from '$lib/types/api';
|
|
|
|
const DB_NAME = 'fooder';
|
|
const DB_VERSION = 2;
|
|
|
|
export interface QueuedMutation {
|
|
id?: number;
|
|
method: 'POST' | 'PATCH' | 'DELETE';
|
|
url: string;
|
|
body: unknown;
|
|
createdAt: number;
|
|
}
|
|
|
|
let dbInstance: IDBPDatabase | null = null;
|
|
|
|
export async function getDb() {
|
|
if (dbInstance) return dbInstance;
|
|
dbInstance = await openDB(DB_NAME, DB_VERSION, {
|
|
upgrade(db, oldVersion) {
|
|
if (oldVersion < 1) {
|
|
db.createObjectStore('diaries', { keyPath: 'date' });
|
|
db.createObjectStore('mutation_queue', { keyPath: 'id', autoIncrement: true });
|
|
}
|
|
if (oldVersion < 2) {
|
|
if (!db.objectStoreNames.contains('products')) {
|
|
db.createObjectStore('products', { keyPath: 'id' });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return dbInstance;
|
|
}
|
|
|
|
// ── Diary cache ──────────────────────────────────────────────────────────────
|
|
|
|
export async function cacheDiary(diary: Diary): Promise<void> {
|
|
const db = await getDb();
|
|
await db.put('diaries', diary);
|
|
}
|
|
|
|
export async function getCachedDiary(date: string): Promise<Diary | undefined> {
|
|
const db = await getDb();
|
|
return db.get('diaries', date);
|
|
}
|
|
|
|
// ── Product cache ─────────────────────────────────────────────────────────────
|
|
|
|
export async function cacheProducts(products: Product[]): Promise<void> {
|
|
if (products.length === 0) return;
|
|
const db = await getDb();
|
|
const tx = db.transaction('products', 'readwrite');
|
|
await Promise.all(products.map(p => tx.store.put(p)));
|
|
await tx.done;
|
|
}
|
|
|
|
export async function searchCachedProducts(q: string): Promise<Product[]> {
|
|
const db = await getDb();
|
|
const all = await db.getAll('products');
|
|
if (!q.trim()) return all.slice(0, 30);
|
|
const lower = q.toLowerCase();
|
|
return all
|
|
.filter(p => p.name.toLowerCase().includes(lower))
|
|
.sort((a, b) => (b.usage_count_cached ?? 0) - (a.usage_count_cached ?? 0))
|
|
.slice(0, 30);
|
|
}
|
|
|
|
// ── Mutation queue ────────────────────────────────────────────────────────────
|
|
|
|
export async function enqueueMutation(mutation: Omit<QueuedMutation, 'id' | 'createdAt'>): Promise<void> {
|
|
const db = await getDb();
|
|
await db.add('mutation_queue', { ...mutation, createdAt: Date.now() });
|
|
}
|
|
|
|
export async function getMutationQueue(): Promise<QueuedMutation[]> {
|
|
const db = await getDb();
|
|
return db.getAll('mutation_queue');
|
|
}
|
|
|
|
export async function dequeueMutation(id: number): Promise<void> {
|
|
const db = await getDb();
|
|
await db.delete('mutation_queue', id);
|
|
}
|
|
|
|
export async function getMutationQueueLength(): Promise<number> {
|
|
const db = await getDb();
|
|
return db.count('mutation_queue');
|
|
}
|