From 944dcdf48f0325cff3b07a436002708c30e7f670 Mon Sep 17 00:00:00 2001 From: ginnoir Date: Tue, 9 Jun 2026 15:55:21 -0500 Subject: [PATCH] refactor: remove dead code identified by knip Delete unused Fab component (superseded by QuickAddFab), unused server actions and queries (listDashboards, reorderDashboards, deleteCareLog, canAccessContainer, getOverduePlants, getCareDueSoon, addItemToDefaultList, reorderItems, getOrCreateDefaultList), unused helpers (getCurrentUser, BrandWordmark, TopbarSpacer, DEV_LOGIN_COOKIE, no-arg ensureDefault* wrappers, addListItem re-export), and drop export keyword from five internal-only functions. Verified with typecheck, eslint, and production build after each removal. --- src/app/d/actions.ts | 29 -------- src/components/brand-mark.tsx | 9 --- src/components/fab.tsx | 14 ---- src/components/settings-section.tsx | 4 +- src/components/topbar.tsx | 12 ---- src/lib/auth.ts | 9 --- src/lib/dashboard.server.ts | 2 +- src/lib/dev-login-config.ts | 2 - src/modules/_core/reminders.ts | 2 +- src/modules/calendar/server/defaults.ts | 18 +---- src/modules/garden/server/actions.ts | 16 ----- src/modules/garden/server/lists-bridge.ts | 1 - src/modules/garden/server/queries.ts | 78 --------------------- src/modules/garden/server/species-lookup.ts | 2 +- src/modules/lists/server/actions.ts | 13 ---- src/modules/lists/server/defaults.ts | 21 ------ 16 files changed, 6 insertions(+), 226 deletions(-) delete mode 100644 src/components/fab.tsx diff --git a/src/app/d/actions.ts b/src/app/d/actions.ts index ad085b6..1493d4d 100644 --- a/src/app/d/actions.ts +++ b/src/app/d/actions.ts @@ -19,22 +19,6 @@ export type DashboardMeta = { position: number; }; -export async function listDashboards(): Promise { - const { user } = await getCurrentSession(); - const rows = await db - .select({ - id: dashboards.id, - name: dashboards.name, - slug: dashboards.slug, - isDefault: dashboards.isDefault, - position: dashboards.position, - }) - .from(dashboards) - .where(eq(dashboards.userId, user.id)) - .orderBy(asc(dashboards.position), asc(dashboards.createdAt)); - return rows; -} - export async function getDefaultDashboardSlug(): Promise { const { user } = await getCurrentSession(); const rows = await db @@ -160,19 +144,6 @@ export async function setDefaultDashboard(id: string): Promise { revalidatePath("/"); } -export async function reorderDashboards(orderedIds: string[]): Promise { - const { user } = await getCurrentSession(); - await Promise.all( - orderedIds.map((id, i) => - db - .update(dashboards) - .set({ position: i }) - .where(and(eq(dashboards.id, id), eq(dashboards.userId, user.id))), - ), - ); - revalidatePath("/"); -} - export async function saveDashboardLayout(id: string, layout: DashboardLayout): Promise { const { user } = await getCurrentSession(); // Validate each widget's config against its registered schema diff --git a/src/components/brand-mark.tsx b/src/components/brand-mark.tsx index 7e07c1f..3d2f427 100644 --- a/src/components/brand-mark.tsx +++ b/src/components/brand-mark.tsx @@ -21,12 +21,3 @@ export function BrandMark({ size = "md", className }: { size?: "sm" | "md"; clas ); } - -export function BrandWordmark({ className }: { className?: string }) { - return ( - - - famapp - - ); -} diff --git a/src/components/fab.tsx b/src/components/fab.tsx deleted file mode 100644 index 5cc4446..0000000 --- a/src/components/fab.tsx +++ /dev/null @@ -1,14 +0,0 @@ -"use client"; - -import { useQuickAdd } from "@/components/quick-add-provider"; -import { NavIcon } from "@/components/nav-icon"; - -export function Fab() { - const { openSheet } = useQuickAdd(); - - return ( - - ); -} diff --git a/src/components/settings-section.tsx b/src/components/settings-section.tsx index f263e99..589b594 100644 --- a/src/components/settings-section.tsx +++ b/src/components/settings-section.tsx @@ -17,7 +17,7 @@ const SECTIONS = [ export type SectionId = (typeof SECTIONS)[number]["id"]; -export function SettingsSidebar({ active }: { active: SectionId }) { +function SettingsSidebar({ active }: { active: SectionId }) { const router = useRouter(); const pathname = usePathname(); @@ -78,7 +78,7 @@ function SectionHashSync({ pathname }: { pathname: string | null }) { return null; } -export function SettingsTabsMobile({ active }: { active: SectionId }) { +function SettingsTabsMobile({ active }: { active: SectionId }) { const router = useRouter(); return (
diff --git a/src/components/topbar.tsx b/src/components/topbar.tsx index ffd4903..d59ce86 100644 --- a/src/components/topbar.tsx +++ b/src/components/topbar.tsx @@ -6,7 +6,6 @@ import { NotificationBell } from "@/components/notification-bell"; import { TopbarSearch } from "@/components/topbar-search"; import { TopbarTitle } from "@/components/topbar-title"; import { TopbarNewButton } from "@/components/topbar-new-button"; -import { NavIcon } from "@/components/nav-icon"; async function getNotifications(userId: string) { const rows = await db @@ -78,14 +77,3 @@ export async function Topbar() {
); } - -export function TopbarSpacer() { - return ( -
-

famapp

-
- -
-
- ); -} diff --git a/src/lib/auth.ts b/src/lib/auth.ts index fd7233e..7887f1f 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -49,12 +49,3 @@ export const { handlers, auth, signIn, signOut } = NextAuth({ }, }, }); - -export async function getCurrentUser() { - const session = await auth(); - if (!session?.user?.id) return null; - const user = await db.query.users.findFirst({ - where: (u, { eq }) => eq(u.id, session.user.id), - }); - return user ?? null; -} diff --git a/src/lib/dashboard.server.ts b/src/lib/dashboard.server.ts index 7017c38..61786cf 100644 --- a/src/lib/dashboard.server.ts +++ b/src/lib/dashboard.server.ts @@ -7,7 +7,7 @@ import { computePresetLayoutFromMetas } from "./dashboard"; /** Build a layout matching one of the design's three dashboard arrangements * using the live module registry. Server-only — the registry is empty on * the client. */ -export function computePresetLayout(preset: PresetId): DashboardLayout { +function computePresetLayout(preset: PresetId): DashboardLayout { const { widgets } = getRegistry(); if (widgets.length === 0) return { version: 1, widgets: [] }; diff --git a/src/lib/dev-login-config.ts b/src/lib/dev-login-config.ts index 60d7050..ce0a000 100644 --- a/src/lib/dev-login-config.ts +++ b/src/lib/dev-login-config.ts @@ -1,5 +1,3 @@ -export const DEV_LOGIN_COOKIE = "authjs.session-token"; - if ( process.env.NODE_ENV === "production" && process.env.ENABLE_DEV_LOGIN === "true" && diff --git a/src/modules/_core/reminders.ts b/src/modules/_core/reminders.ts index ff83e12..015feb4 100644 --- a/src/modules/_core/reminders.ts +++ b/src/modules/_core/reminders.ts @@ -54,7 +54,7 @@ export async function listReminders(entityType: string, entityId: string) { .where(and(eq(reminders.entityType, entityType), eq(reminders.entityId, entityId))); } -export async function tickReminders() { +async function tickReminders() { let dueReminders: (typeof reminders.$inferSelect)[] = []; try { diff --git a/src/modules/calendar/server/defaults.ts b/src/modules/calendar/server/defaults.ts index 282275d..6559fc5 100644 --- a/src/modules/calendar/server/defaults.ts +++ b/src/modules/calendar/server/defaults.ts @@ -1,6 +1,6 @@ import { and, eq } from "drizzle-orm"; import { db } from "@/lib/db"; -import { householdMembers, households, users } from "@/modules/_core/schema"; +import { householdMembers } from "@/modules/_core/schema"; import { calendars } from "../schema"; const HOME_COLOR = "#2563eb"; @@ -17,22 +17,6 @@ export async function ensureDefaultCalendarsForMembership({ await ensurePersonalCalendar({ householdId, userId }); } -export async function ensureDefaultCalendars() { - const householdRows = await db.select().from(households); - for (const household of householdRows) { - await ensureHomeCalendar(household.id); - } - - const memberships = await db - .select({ householdId: householdMembers.householdId, userId: users.id }) - .from(householdMembers) - .innerJoin(users, eq(householdMembers.userId, users.id)); - - for (const membership of memberships) { - await ensurePersonalCalendar(membership); - } -} - async function ensureHomeCalendar(householdId: string) { const [existing] = await db .select({ id: calendars.id }) diff --git a/src/modules/garden/server/actions.ts b/src/modules/garden/server/actions.ts index 233dad7..d1104b5 100644 --- a/src/modules/garden/server/actions.ts +++ b/src/modules/garden/server/actions.ts @@ -451,22 +451,6 @@ export async function logCare(input: z.input) { return log; } -export async function deleteCareLog(input: { id: string }) { - const parsed = z.object({ id: z.string().uuid() }).parse(input); - const { household } = await getCurrentSession(); - - const [row] = await db - .select({ id: gardenCareLogs.id, plantId: gardenCareLogs.plantId }) - .from(gardenCareLogs) - .where(and(eq(gardenCareLogs.id, parsed.id), eq(gardenCareLogs.householdId, household.id))) - .limit(1); - - if (!row) throw new Error("Forbidden"); - - await db.delete(gardenCareLogs).where(eq(gardenCareLogs.id, parsed.id)); - revalidatePath(`/garden/plants/${row.plantId}`); -} - // ─── Care schedule actions ──────────────────────────────────────────────────── const careScheduleInput = z.object({ diff --git a/src/modules/garden/server/lists-bridge.ts b/src/modules/garden/server/lists-bridge.ts index 19b9a23..f9425ba 100644 --- a/src/modules/garden/server/lists-bridge.ts +++ b/src/modules/garden/server/lists-bridge.ts @@ -1,4 +1,3 @@ -export { addItem as addListItem } from "@/modules/lists/server/actions"; export { getList, listLists } from "@/modules/lists/server/queries"; import { addItem } from "@/modules/lists/server/actions"; diff --git a/src/modules/garden/server/queries.ts b/src/modules/garden/server/queries.ts index 65eabfd..eb28493 100644 --- a/src/modules/garden/server/queries.ts +++ b/src/modules/garden/server/queries.ts @@ -110,16 +110,6 @@ export async function getContainer(id: string): Promise { - const [row] = await db - .select({ id: gardenContainers.id }) - .from(gardenContainers) - .where(and(eq(gardenContainers.id, id), eq(gardenContainers.householdId, householdId))) - .limit(1); - - return !!row; -} - export async function searchContainers(query: string, householdId: string) { const rows = await db .select({ id: gardenContainers.id, name: gardenContainers.name }) @@ -430,74 +420,6 @@ export async function getCareSchedules(plantId: string): Promise { - const rows = await db - .select({ - id: gardenPlants.id, - name: gardenPlants.name, - primaryImageUrl: gardenPlants.primaryImageUrl, - mostOverdueAt: sql`min(${gardenCareSchedules.nextDueAt})`, - }) - .from(gardenPlants) - .innerJoin( - gardenCareSchedules, - and( - eq(gardenCareSchedules.plantId, gardenPlants.id), - eq(gardenCareSchedules.enabled, true), - lte(gardenCareSchedules.nextDueAt, sql`now()`), - ), - ) - .where(eq(gardenPlants.householdId, householdId)) - .groupBy(gardenPlants.id, gardenPlants.name, gardenPlants.primaryImageUrl) - .orderBy(sql`min(${gardenCareSchedules.nextDueAt})`); - - return rows; -} - -export type CareDueSoonDto = { - id: string; - name: string; - primaryImageUrl: string | null; - nextDueAt: Date; -}; - -export async function getCareDueSoon( - householdId: string, - withinDays: number, -): Promise { - const cutoff = new Date(); - cutoff.setDate(cutoff.getDate() + withinDays); - - const rows = await db - .select({ - id: gardenPlants.id, - name: gardenPlants.name, - primaryImageUrl: gardenPlants.primaryImageUrl, - nextDueAt: sql`min(${gardenCareSchedules.nextDueAt})`, - }) - .from(gardenPlants) - .innerJoin( - gardenCareSchedules, - and( - eq(gardenCareSchedules.plantId, gardenPlants.id), - eq(gardenCareSchedules.enabled, true), - lte(gardenCareSchedules.nextDueAt, cutoff), - ), - ) - .where(eq(gardenPlants.householdId, householdId)) - .groupBy(gardenPlants.id, gardenPlants.name, gardenPlants.primaryImageUrl) - .orderBy(sql`min(${gardenCareSchedules.nextDueAt})`); - - return rows; -} - // ─── Widget queries ─────────────────────────────────────────────────────────── export type CareDueWidgetRow = { diff --git a/src/modules/garden/server/species-lookup.ts b/src/modules/garden/server/species-lookup.ts index f98e1c0..8c5796d 100644 --- a/src/modules/garden/server/species-lookup.ts +++ b/src/modules/garden/server/species-lookup.ts @@ -102,7 +102,7 @@ export async function searchSpecies(query: string): Promise } } -export async function getSpeciesById(id: string): Promise { +async function getSpeciesById(id: string): Promise { const cutoff = new Date(Date.now() - CACHE_TTL_MS); const [cached] = await db .select() diff --git a/src/modules/lists/server/actions.ts b/src/modules/lists/server/actions.ts index 4d6c9ef..a3c9a2a 100644 --- a/src/modules/lists/server/actions.ts +++ b/src/modules/lists/server/actions.ts @@ -8,7 +8,6 @@ import { getCurrentSession } from "@/lib/session"; import { logActivity } from "@/modules/_core/activity"; import { fireItemToggleHooks } from "@/modules/_core/registry"; import { listItems, lists } from "../schema"; -import { getOrCreateDefaultList } from "./defaults"; import { canAccessList, getList } from "./queries"; import { notifyListChanged } from "./realtime"; @@ -122,18 +121,6 @@ export async function addItem(input: z.input) { return getList(parsed.listId); } -export async function addItemToDefaultList(input: { type: string; text: string }) { - const parsed = z - .object({ - type: listInput.shape.type, - text: itemInput.shape.text, - }) - .parse(input); - const { household } = await getCurrentSession(); - const list = await getOrCreateDefaultList({ householdId: household.id, type: parsed.type }); - return addItem({ listId: list.id, text: parsed.text }); -} - export async function toggleItem(input: { id: string; done?: boolean }) { const parsed = z.object({ id: z.string().uuid(), done: z.boolean().optional() }).parse(input); const { household, user } = await getCurrentSession(); diff --git a/src/modules/lists/server/defaults.ts b/src/modules/lists/server/defaults.ts index 1b65c4b..ca44ffc 100644 --- a/src/modules/lists/server/defaults.ts +++ b/src/modules/lists/server/defaults.ts @@ -1,6 +1,5 @@ import { and, eq } from "drizzle-orm"; import { db } from "@/lib/db"; -import { households } from "@/modules/_core/schema"; import { lists } from "../schema"; const DEFAULT_LISTS = [ @@ -14,26 +13,6 @@ export async function ensureDefaultListsForHousehold(householdId: string) { } } -export async function ensureDefaultLists() { - const householdRows = await db.select({ id: households.id }).from(households); - for (const household of householdRows) { - await ensureDefaultListsForHousehold(household.id); - } -} - -export async function getOrCreateDefaultList({ - householdId, - type, -}: { - householdId: string; - type: "shopping" | "task" | string; -}) { - const defaults = DEFAULT_LISTS.find((list) => list.type === type); - const name = defaults?.name ?? type; - - return ensureDefaultList({ householdId, type, name }); -} - async function ensureDefaultList({ householdId, type,