From 24bf8eabb9fd47031b66191d6abb0a3791c46e15 Mon Sep 17 00:00:00 2001 From: openhands Date: Fri, 7 Aug 2026 18:55:02 +0200 Subject: [PATCH] refactor: remove dead code and unused exports Delete proxy-auth.ts, types/index.ts, staff-user.ts+test, local-imports.ts+test (only used by their own tests). Remove unused foundation exports: sanitizeFilename, canonicalizeFormValue, canonicalizeFormData, ConflictError, getRequestStore, getClientIp, elapsed. Remove stale TODO comments from rank-authority.ts and notice.ts. Fix biome lint warnings in catalog-repair.ts. --- src/lib/admin/notice.ts | 1 - src/lib/admin/rank-authority.ts | 1 - src/lib/admin/staff-user.test.ts | 20 ------ src/lib/admin/staff-user.ts | 22 ------ src/lib/foundation/errors.ts | 8 --- src/lib/foundation/request-context.ts | 16 ----- src/lib/foundation/security.ts | 44 ------------ src/lib/local-imports.test.ts | 41 ----------- src/lib/local-imports.ts | 98 --------------------------- src/lib/proxy-auth.ts | 11 --- src/lib/services/catalog-repair.ts | 4 +- src/types/index.ts | 1 - 12 files changed, 2 insertions(+), 265 deletions(-) delete mode 100644 src/lib/admin/staff-user.test.ts delete mode 100644 src/lib/admin/staff-user.ts delete mode 100644 src/lib/local-imports.test.ts delete mode 100644 src/lib/local-imports.ts delete mode 100644 src/lib/proxy-auth.ts delete mode 100644 src/types/index.ts diff --git a/src/lib/admin/notice.ts b/src/lib/admin/notice.ts index 01cde5b5..83504c4c 100644 --- a/src/lib/admin/notice.ts +++ b/src/lib/admin/notice.ts @@ -1,4 +1,3 @@ -// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test export interface AdminMutationNotice { tone: "ok" | "danger"; label: "Saved" | "Error"; diff --git a/src/lib/admin/rank-authority.ts b/src/lib/admin/rank-authority.ts index 7b53aaa0..b97250a5 100644 --- a/src/lib/admin/rank-authority.ts +++ b/src/lib/admin/rank-authority.ts @@ -1,4 +1,3 @@ -// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test import type { AuthorizationActor } from "@/lib/admin/authorization-policy"; export interface RankAuthorityDb { diff --git a/src/lib/admin/staff-user.test.ts b/src/lib/admin/staff-user.test.ts deleted file mode 100644 index dc33f597..00000000 --- a/src/lib/admin/staff-user.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { resolveStaffUser } from "@/lib/admin/staff-user"; - -describe("resolveStaffUser", () => { - it("rejects a session whose database rank has been revoked", async () => { - const findUser = async () => ({ id: 7, rank: 1, username: "Alice" }); - - await expect(resolveStaffUser("7", 7, findUser)).resolves.toBeNull(); - }); - - it("returns the current database identity instead of stale JWT values", async () => { - const findUser = async () => ({ id: 7, rank: 8, username: "CurrentName" }); - - await expect(resolveStaffUser("7", 7, findUser)).resolves.toEqual({ - id: 7, - rank: 8, - username: "CurrentName", - }); - }); -}); diff --git a/src/lib/admin/staff-user.ts b/src/lib/admin/staff-user.ts deleted file mode 100644 index 4eb578bf..00000000 --- a/src/lib/admin/staff-user.ts +++ /dev/null @@ -1,22 +0,0 @@ -// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test -import { isStaff } from "@/lib/admin/is-staff"; - -export interface StaffUserRecord { - id: number; - rank: number; - username: string; -} - -export type FindStaffUser = (id: number) => Promise; - -export async function resolveStaffUser( - sessionUserId: string, - minStaffRank: number, - findUser: FindStaffUser, -): Promise { - const id = Number(sessionUserId); - if (!Number.isSafeInteger(id) || id <= 0) return null; - - const user = await findUser(id); - return user && isStaff(user.rank, minStaffRank) ? user : null; -} diff --git a/src/lib/foundation/errors.ts b/src/lib/foundation/errors.ts index a1656359..e172869f 100644 --- a/src/lib/foundation/errors.ts +++ b/src/lib/foundation/errors.ts @@ -49,14 +49,6 @@ export class RateLimitError extends DomainError { } } -// TODO: Check of dit weg kan — niet geïmporteerd in de codebase -export class ConflictError extends DomainError { - constructor(message: string) { - super(message, 409); - this.name = "ConflictError"; - } -} - export class DatabaseError extends DomainError { public readonly cause: unknown; diff --git a/src/lib/foundation/request-context.ts b/src/lib/foundation/request-context.ts index 3f1cf599..3da07800 100644 --- a/src/lib/foundation/request-context.ts +++ b/src/lib/foundation/request-context.ts @@ -30,27 +30,11 @@ export function runWithStore(store: RequestStore, fn: () => T): T { return als.run(store, fn); } -// TODO: Check of dit weg kan — niet geïmporteerd in de codebase -export function getRequestStore(): RequestStore | null { - return als.getStore() ?? null; -} - export function getRequestId(): RequestId { return als.getStore()?.requestId ?? generateRequestId(); } -// TODO: Check of dit weg kan — niet geïmporteerd in de codebase -export function getClientIp(): IpAddress { - return als.getStore()?.ip ?? ("0.0.0.0" as IpAddress); -} - export function setContextUserId(userId: UserId): void { const store = als.getStore(); if (store) store.userId = userId; } - -// TODO: Check of dit weg kan — niet geïmporteerd in de codebase -export function elapsed(): number { - const store = als.getStore(); - return store ? Date.now() - store.startedAt : 0; -} diff --git a/src/lib/foundation/security.ts b/src/lib/foundation/security.ts index ab837fc3..f9ed34e0 100644 --- a/src/lib/foundation/security.ts +++ b/src/lib/foundation/security.ts @@ -208,50 +208,6 @@ export function sanitizeField( return s.slice(0, maxLen); } -const INVALID_FILENAME_CHARS = /[<>:"/\\|?*]/; - -function removeControlChars(s: string): string { - let result = ""; - for (let i = 0; i < s.length; i++) { - const code = s.charCodeAt(i); - if (code >= 32) result += s.charAt(i); - } - return result; -} - -// TODO: Check of dit weg kan — niet geïmporteerd in de codebase -export function sanitizeFilename(name: string): string { - return removeControlChars( - name - .normalize("NFC") - .replace(INVALID_FILENAME_CHARS, "") - .replace(/\.\.(?:\/|$)/g, ""), - ) - .trim() - .slice(0, 255); -} - -export function canonicalizeFormValue( - value: FormDataEntryValue | null, - maxLen?: number, -): string { - const s = canonicalize(String(value ?? "")); - return maxLen ? s.slice(0, maxLen) : s; -} - -// TODO: Check of dit weg kan — niet geïmporteerd in de codebase -export function canonicalizeFormData( - formData: FormData, - fields: Record, -): Record { - return Object.fromEntries( - Object.entries(fields).map(([key, maxLen]) => [ - key, - canonicalizeFormValue(formData.get(key), maxLen), - ]), - ); -} - export async function extractClientIpAsync(): Promise { try { const h = await headers(); diff --git a/src/lib/local-imports.test.ts b/src/lib/local-imports.test.ts deleted file mode 100644 index 11eac2a9..00000000 --- a/src/lib/local-imports.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; -import { afterEach, describe, expect, it } from "vitest"; -import { findMissingLocalImports } from "./local-imports"; - -const roots: string[] = []; - -afterEach(async () => { - await Promise.all( - roots.splice(0).map((root) => rm(root, { recursive: true, force: true })), - ); -}); - -describe("findMissingLocalImports", () => { - it("reports unresolved alias imports and ignores modules that exist", async () => { - const root = await mkdtemp(join(tmpdir(), "epicnext-imports-")); - roots.push(root); - await mkdir(join(root, "src", "features"), { recursive: true }); - await mkdir(join(root, "src", "components", "ui"), { recursive: true }); - await writeFile( - join(root, "src", "components", "ui", "card.tsx"), - "export const Card = {};\n", - ); - await writeFile( - join(root, "src", "features", "page.tsx"), - [ - 'import { Card } from "@/components/ui/card";', - 'import { Button } from "@/components/ui/button";', - "export default Card;", - ].join("\n"), - ); - - await expect(findMissingLocalImports(root)).resolves.toEqual([ - { - importer: "src/features/page.tsx", - specifier: "@/components/ui/button", - }, - ]); - }); -}); diff --git a/src/lib/local-imports.ts b/src/lib/local-imports.ts deleted file mode 100644 index c591d594..00000000 --- a/src/lib/local-imports.ts +++ /dev/null @@ -1,98 +0,0 @@ -// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test -import { access, readdir, readFile } from "node:fs/promises"; -import { dirname, extname, join, relative, resolve, sep } from "node:path"; - -export interface MissingLocalImport { - importer: string; - specifier: string; -} - -const sourceExtensions = new Set([ - ".ts", - ".tsx", - ".js", - ".jsx", - ".mjs", - ".cjs", -]); -const resolutionSuffixes = [ - ".ts", - ".tsx", - ".js", - ".jsx", - ".mjs", - ".cjs", - ".css", - "/index.ts", - "/index.tsx", - "/index.js", - "/index.jsx", -]; -const importPattern = - /(?:import|export)\s+(?:[^"']*?\s+from\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)|require\(\s*["']([^"']+)["']\s*\)/g; - -async function collectSourceFiles(directory: string): Promise { - const entries = await readdir(directory, { withFileTypes: true }); - const files = await Promise.all( - entries.map(async (entry) => { - const path = join(directory, entry.name); - if (entry.isDirectory()) return collectSourceFiles(path); - if (/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(entry.name)) return []; - return sourceExtensions.has(extname(entry.name)) ? [path] : []; - }), - ); - return files.flat(); -} - -async function exists(path: string): Promise { - try { - await access(path); - return true; - } catch { - return false; - } -} - -async function resolvesToLocalFile(base: string): Promise { - if (extname(base) && (await exists(base))) return true; - for (const suffix of resolutionSuffixes) { - if (await exists(`${base}${suffix}`)) return true; - } - return false; -} - -export async function findMissingLocalImports( - root: string, -): Promise { - const src = resolve(root, "src"); - const files = await collectSourceFiles(src); - const missing: MissingLocalImport[] = []; - - for (const importer of files) { - const source = await readFile(importer, "utf8"); - for (const match of source.matchAll(importPattern)) { - const specifier = match[1] ?? match[2] ?? match[3]; - if ( - !specifier?.startsWith("@/") && - !specifier?.startsWith("./") && - !specifier?.startsWith("../") - ) - continue; - const base = specifier.startsWith("@/") - ? resolve(src, specifier.slice(2)) - : resolve(dirname(importer), specifier); - if (!(await resolvesToLocalFile(base))) { - missing.push({ - importer: relative(root, importer).split(sep).join("/"), - specifier, - }); - } - } - } - - return missing.sort( - (a, b) => - a.importer.localeCompare(b.importer) || - a.specifier.localeCompare(b.specifier), - ); -} diff --git a/src/lib/proxy-auth.ts b/src/lib/proxy-auth.ts deleted file mode 100644 index 15fc9f64..00000000 --- a/src/lib/proxy-auth.ts +++ /dev/null @@ -1,11 +0,0 @@ -import NextAuth from "next-auth"; -import { env } from "@/env"; - -// Proxy authentication must only decode the Auth.js session. Importing the -// full CMS auth configuration here would also run DB/settings callbacks. -export const { auth: proxyAuth } = NextAuth({ - trustHost: true, - secret: env.AUTH_SECRET, - session: { strategy: "jwt" }, - providers: [], -}); diff --git a/src/lib/services/catalog-repair.ts b/src/lib/services/catalog-repair.ts index 19db4f11..c45feb54 100644 --- a/src/lib/services/catalog-repair.ts +++ b/src/lib/services/catalog-repair.ts @@ -261,7 +261,7 @@ function derivePageCaption(classname: string, fallback: string): string { const re = new RegExp(`^${prefix.replace(/_/g, "[_]?")}(?:_)?(\\d*)`, "i"); const m = lower.match(re); if (m) { - const matchEnd = m.index! + m[0].length; + const matchEnd = (m.index ?? 0) + m[0].length; const nextChar = lower[matchEnd]; if ( !nextChar || @@ -278,7 +278,7 @@ function derivePageCaption(classname: string, fallback: string): string { // Also try matching suffix patterns (e.g., "something_xmas2025"). for (const prefix of sortedPrefixes) { const re = new RegExp( - `${prefix.replace(/_/g, "[_]?")}(?:_)?(\\d{4})` + "(_|$)", + `${prefix.replace(/_/g, "[_]?")}(?:_)?(\\d{4})(_|$)`, "i", ); const m = lower.match(re); diff --git a/src/types/index.ts b/src/types/index.ts deleted file mode 100644 index 4d68f367..00000000 --- a/src/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { DataTableColumn, ListParams, PaginatedResult } from "./common";