48 lines
1.2 KiB
TypeScript
48 lines
1.2 KiB
TypeScript
import { promises as fs } from "node:fs";
|
|
import path from "node:path";
|
|
import { withAdmin } from "@/lib/api-handler";
|
|
import { apiOk } from "@/lib/api-response";
|
|
import { PERMS } from "@/lib/permissions";
|
|
|
|
const CATALOGUE_DIR = path.join(
|
|
/*turbopackIgnore: true*/ process.cwd(),
|
|
"public",
|
|
"swf",
|
|
"c_images",
|
|
"catalogue",
|
|
);
|
|
|
|
export const GET = withAdmin(
|
|
{ permission: PERMS.CATALOG_VIEW },
|
|
async (request) => {
|
|
const sp = request.nextUrl.searchParams;
|
|
const limit = Math.min(
|
|
Math.max(Number(sp.get("limit") || 120) || 120, 1),
|
|
500,
|
|
);
|
|
const offset = Math.max(Number(sp.get("offset") || 0) || 0, 0);
|
|
const search = (sp.get("search") || "").trim().toLowerCase();
|
|
|
|
let icons: number[] = [];
|
|
try {
|
|
const files = await fs.readdir(CATALOGUE_DIR);
|
|
icons = files
|
|
.map((f) => /^icon_(\d+)\.(?:png|gif)$/i.exec(f))
|
|
.filter((m): m is RegExpExecArray => Boolean(m))
|
|
.map((m) => Number(m[1]))
|
|
.filter((n) => Number.isFinite(n))
|
|
.sort((a, b) => a - b);
|
|
} catch {
|
|
icons = [];
|
|
}
|
|
|
|
if (search) {
|
|
icons = icons.filter((id) => String(id).includes(search));
|
|
}
|
|
|
|
const total = icons.length;
|
|
const slice = icons.slice(offset, offset + limit);
|
|
return apiOk({ icons: slice, total });
|
|
},
|
|
);
|