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