- Replace Prisma client runtime with Drizzle ORM (zero Prisma engine/query engine in production) - Add Prisma-compatible facade (@/lib/prisma-facade.ts) backed by Drizzle for backwards compatibility - Runtime queries route through Drizzle ORM; @prisma/client is now devDependency (types only) - Remove @prisma/adapter-mariadb dependency; delete prisma-pool.ts and types/prisma.ts - New Drizzle schema layer: src/db/schema.ts (176 tables) and src/lib/db.ts (connection) - Update README documenting the dual-layer ORM architecture - Restore src/generated/ gitignore (build artifact for local type generation) - 0 TypeScript errors, 583 tests passing The facade intentionally uses `any` types to match the Prisma Client API surface, allowing existing code to run unmodified while routing queries through Drizzle at runtime.
74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import { redirect } from "next/navigation";
|
|
import { calcPagination, parseListParams } from "./admin-helpers";
|
|
import { canAccess, getAdminContext, type PermissionSet } from "./permissions";
|
|
|
|
interface AdminListConfig<TRow> {
|
|
/** Permission slug required to view this page */
|
|
permission: string;
|
|
/** Default items per page. Default: 20 */
|
|
defaultPerPage?: number;
|
|
/**
|
|
* Runs the actual data query (Drizzle). Receives parsed list params and
|
|
* returns the rows + total count for the current page.
|
|
*/
|
|
fetch: (args: {
|
|
search: string;
|
|
page: number;
|
|
perPage: number;
|
|
rawParams: Record<string, string>;
|
|
}) => Promise<{ rows: TRow[]; total: number }>;
|
|
}
|
|
|
|
interface AdminListResult<TRow> {
|
|
rows: TRow[];
|
|
total: number;
|
|
page: number;
|
|
perPage: number;
|
|
lastPage: number;
|
|
locale: string;
|
|
permissions: PermissionSet;
|
|
rank: number;
|
|
}
|
|
|
|
/**
|
|
* Generic admin list data fetcher.
|
|
* Centralizes the common pattern: auth check, param parsing, pagination and
|
|
* row mapping. The caller supplies a Drizzle query via `config.fetch`.
|
|
*/
|
|
export async function fetchAdminList<TRow>(
|
|
config: AdminListConfig<TRow>,
|
|
paramsPromise: Promise<{ locale: string }>,
|
|
searchParamsPromise: Promise<Record<string, string>>,
|
|
): Promise<AdminListResult<TRow>> {
|
|
const { locale } = await paramsPromise;
|
|
const { session, permissions } = await getAdminContext();
|
|
|
|
if (!canAccess(permissions, config.permission, session.user.rank)) {
|
|
redirect("/admin");
|
|
}
|
|
|
|
const rawParams = await searchParamsPromise;
|
|
const sp = new URLSearchParams(rawParams);
|
|
const parsed = parseListParams(sp);
|
|
const perPage = config.defaultPerPage
|
|
? Number(rawParams.perPage) || config.defaultPerPage
|
|
: parsed.perPage;
|
|
|
|
const { rows, total } = await config.fetch({
|
|
search: parsed.search,
|
|
page: parsed.page,
|
|
perPage,
|
|
rawParams,
|
|
});
|
|
|
|
const pagination = calcPagination(total, parsed.page, perPage);
|
|
|
|
return {
|
|
rows,
|
|
...pagination,
|
|
locale,
|
|
permissions,
|
|
rank: session.user.rank,
|
|
};
|
|
}
|