success pt. 4
This commit is contained in:
@@ -7,5 +7,14 @@ import { SQLocalDrizzle } from "sqlocal/drizzle";
|
||||
const { driver, batchDriver, overwriteDatabaseFile } = new SQLocalDrizzle(
|
||||
"database.sqlite3",
|
||||
);
|
||||
|
||||
export const db = drizzle(driver, batchDriver);
|
||||
|
||||
/**
|
||||
* Concrete client DB type (SQLocal-backed Drizzle via sqlite-proxy).
|
||||
* Exported to allow query helpers to accept the specific type without
|
||||
* creating circular type references.
|
||||
*/
|
||||
export type ClientDb = typeof db;
|
||||
|
||||
export { overwriteDatabaseFile };
|
||||
|
||||
@@ -1,41 +1,29 @@
|
||||
import { desc, like } from "drizzle-orm";
|
||||
import { animeTable } from "$lib/db/schema";
|
||||
import type { ClientDb } from "./index";
|
||||
|
||||
/**
|
||||
* Client-side DB query helpers (read-only).
|
||||
*
|
||||
* These functions assume the SQLocal-backed Drizzle `db` is already wired up.
|
||||
* Seeding/overwriting the database file should be handled separately (see `seed.ts`).
|
||||
* These functions are intentionally side-effect free — seeding/overwriting the DB
|
||||
* file should be done separately (see `seed.ts`).
|
||||
*
|
||||
* Keep these as pure query operations so pages/components can:
|
||||
* 1) ensure seeded
|
||||
* 2) query
|
||||
* We accept the concrete SQLocal-backed Drizzle DB type so callers get full type inference.
|
||||
*/
|
||||
|
||||
export const DEFAULT_LIST_LIMIT = 20;
|
||||
export const MAX_LIST_LIMIT = 200;
|
||||
|
||||
export type AnimeListItem = {
|
||||
annId: number;
|
||||
mainName: string;
|
||||
year: number;
|
||||
seasonId: number;
|
||||
malId: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a short list of anime entries for browsing.
|
||||
*
|
||||
* Sorted by (year desc, seasonId desc, annId desc).
|
||||
*/
|
||||
export async function getAnimeList(
|
||||
db: { select: (...args: any[]) => any },
|
||||
limit = DEFAULT_LIST_LIMIT,
|
||||
): Promise<AnimeListItem[]> {
|
||||
export async function getAnimeList(db: ClientDb, limit = DEFAULT_LIST_LIMIT) {
|
||||
const safeLimit = clampLimit(limit);
|
||||
|
||||
// NOTE: using explicit selection keeps payload small and stable
|
||||
const rows = await (db as any)
|
||||
// Explicit selection keeps payload small and gives a stable, inferred return type
|
||||
return db
|
||||
.select({
|
||||
annId: animeTable.annId,
|
||||
mainName: animeTable.mainName,
|
||||
@@ -50,8 +38,6 @@ export async function getAnimeList(
|
||||
desc(animeTable.annId),
|
||||
)
|
||||
.limit(safeLimit);
|
||||
|
||||
return rows as AnimeListItem[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,17 +47,17 @@ export async function getAnimeList(
|
||||
* in the snapshot DB, and querying that instead.
|
||||
*/
|
||||
export async function searchAnimeByName(
|
||||
db: { select: (...args: any[]) => any },
|
||||
db: ClientDb,
|
||||
query: string,
|
||||
limit = DEFAULT_LIST_LIMIT,
|
||||
): Promise<AnimeListItem[]> {
|
||||
) {
|
||||
const q = query.trim();
|
||||
if (!q) return [];
|
||||
|
||||
const safeLimit = clampLimit(limit);
|
||||
const pattern = `%${q}%`;
|
||||
|
||||
const rows = await (db as any)
|
||||
return db
|
||||
.select({
|
||||
annId: animeTable.annId,
|
||||
mainName: animeTable.mainName,
|
||||
@@ -87,8 +73,6 @@ export async function searchAnimeByName(
|
||||
desc(animeTable.annId),
|
||||
)
|
||||
.limit(safeLimit);
|
||||
|
||||
return rows as AnimeListItem[];
|
||||
}
|
||||
|
||||
function clampLimit(limit: number) {
|
||||
|
||||
Reference in New Issue
Block a user