From f7b41f56742ccb62caf0b4587aef338674a4e316 Mon Sep 17 00:00:00 2001 From: Kaan Karaca Date: Fri, 3 Apr 2026 21:09:25 +0300 Subject: [PATCH 1/2] refactor: remove dead code across monorepo (~762 lines) Delete 6 unused files (handler-utils, 5 scaffolded hooks), remove 11 unused exported functions, un-export 2 internal-only schemas, and drop superseded reminder schemas with their 25 orphaned tests. Verified: 236 test files, 5373 tests passing, typecheck green. --- apps/desktop/src/main/database/fts-tasks.ts | 5 - apps/desktop/src/main/ipc/handler-utils.ts | 7 - apps/desktop/src/main/lib/reminders.ts | 25 -- .../renderer/src/hooks/use-account-info.ts | 48 ---- .../renderer/src/hooks/use-backup-settings.ts | 72 ------ .../src/renderer/src/hooks/use-devices.ts | 76 ------ .../src/renderer/src/hooks/use-inbox.ts | 32 --- .../renderer/src/hooks/use-is-item-active.ts | 25 -- .../renderer/src/hooks/use-linking-events.ts | 35 --- .../src/renderer/src/hooks/use-notes-query.ts | 16 -- .../src/renderer/src/hooks/use-reminders.ts | 14 +- .../renderer/src/hooks/use-sync-settings.ts | 70 ------ .../src/renderer/src/lib/graph-builder.ts | 10 - packages/contracts/src/reminders-api.test.ts | 237 ------------------ packages/contracts/src/reminders-api.ts | 44 +--- packages/shared/src/file-types.ts | 49 ---- 16 files changed, 3 insertions(+), 762 deletions(-) delete mode 100644 apps/desktop/src/main/ipc/handler-utils.ts delete mode 100644 apps/desktop/src/renderer/src/hooks/use-account-info.ts delete mode 100644 apps/desktop/src/renderer/src/hooks/use-backup-settings.ts delete mode 100644 apps/desktop/src/renderer/src/hooks/use-devices.ts delete mode 100644 apps/desktop/src/renderer/src/hooks/use-linking-events.ts delete mode 100644 apps/desktop/src/renderer/src/hooks/use-sync-settings.ts diff --git a/apps/desktop/src/main/database/fts-tasks.ts b/apps/desktop/src/main/database/fts-tasks.ts index c6f19d6a9..8e48da946 100644 --- a/apps/desktop/src/main/database/fts-tasks.ts +++ b/apps/desktop/src/main/database/fts-tasks.ts @@ -83,11 +83,6 @@ export function clearFtsTasksTable(db: DrizzleDb): void { db.run(sql`DELETE FROM fts_tasks`) } -export function getFtsTasksCount(db: DrizzleDb): number { - const result = db.get<{ count: number }>(sql`SELECT COUNT(*) as count FROM fts_tasks`) - return result?.count ?? 0 -} - export function initializeFtsTasks(db: DrizzleDb): void { createFtsTasksTable(db) createFtsTasksTriggers(db) diff --git a/apps/desktop/src/main/ipc/handler-utils.ts b/apps/desktop/src/main/ipc/handler-utils.ts deleted file mode 100644 index fc663b0a2..000000000 --- a/apps/desktop/src/main/ipc/handler-utils.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function extractError(error: unknown, fallback: string): string { - return error instanceof Error ? error.message : fallback -} - -export type MutationResult = Record> = - | ({ success: true } & T) - | ({ success: false; error: string } & { [K in keyof T]?: null }) diff --git a/apps/desktop/src/main/lib/reminders.ts b/apps/desktop/src/main/lib/reminders.ts index cf1ba5c30..be33c1514 100644 --- a/apps/desktop/src/main/lib/reminders.ts +++ b/apps/desktop/src/main/lib/reminders.ts @@ -713,31 +713,6 @@ export function isSchedulerRunning(): boolean { return schedulerInterval !== null } -// ============================================================================ -// Cleanup -// ============================================================================ - -/** - * Delete all reminders for a target (used when target is deleted) - * @param targetType - Type of target - * @param targetId - ID of the target - * @returns Number of reminders deleted - */ -export function deleteRemindersForTarget(targetType: string, targetId: string): number { - const db = getDatabase() - - const result = db - .delete(reminders) - .where(and(eq(reminders.targetType, targetType), eq(reminders.targetId, targetId))) - .run() - - if (result.changes > 0) { - logger.info(`Deleted ${result.changes} reminders for ${targetType}:${targetId}`) - } - - return result.changes -} - /** * Count pending reminders (for badge display) * @returns Number of pending reminders diff --git a/apps/desktop/src/renderer/src/hooks/use-account-info.ts b/apps/desktop/src/renderer/src/hooks/use-account-info.ts deleted file mode 100644 index 111e3faa5..000000000 --- a/apps/desktop/src/renderer/src/hooks/use-account-info.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { useState, useEffect } from 'react' -import { extractErrorMessage } from '@/lib/ipc-error' - -export interface AccountInfo { - email: string | null - joinedAt: number | null -} - -interface UseAccountInfoReturn { - accountInfo: AccountInfo | null - isLoading: boolean - error: string | null - refresh: () => void -} - -export function useAccountInfo(): UseAccountInfoReturn { - const [accountInfo, setAccountInfo] = useState(null) - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState(null) - const [refreshKey, setRefreshKey] = useState(0) - - useEffect(() => { - let mounted = true - const load = async (): Promise => { - try { - setIsLoading(true) - setError(null) - const result = await window.api.account.getInfo() - if (mounted) setAccountInfo(result) - } catch (err) { - if (mounted) setError(extractErrorMessage(err, 'Failed to load account info')) - } finally { - if (mounted) setIsLoading(false) - } - } - void load() - return () => { - mounted = false - } - }, [refreshKey]) - - return { - accountInfo, - isLoading, - error, - refresh: () => setRefreshKey((k) => k + 1) - } -} diff --git a/apps/desktop/src/renderer/src/hooks/use-backup-settings.ts b/apps/desktop/src/renderer/src/hooks/use-backup-settings.ts deleted file mode 100644 index 0f87c0670..000000000 --- a/apps/desktop/src/renderer/src/hooks/use-backup-settings.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' -import { extractErrorMessage } from '@/lib/ipc-error' -import type { BackupSettingsDTO } from '../../../preload/index.d' - -const DEFAULTS: BackupSettingsDTO = { - autoBackup: false, - frequencyHours: 24, - maxBackups: 5, - lastBackupAt: null -} - -interface UseBackupSettingsReturn { - settings: BackupSettingsDTO - isLoading: boolean - error: string | null - updateSettings: (updates: Partial) => Promise -} - -export function useBackupSettings(): UseBackupSettingsReturn { - const [settings, setSettings] = useState(DEFAULTS) - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState(null) - - useEffect(() => { - let mounted = true - const load = async (): Promise => { - try { - setIsLoading(true) - setError(null) - const result = await window.api.settings.getBackupSettings() - if (mounted) setSettings(result) - } catch (err) { - if (mounted) setError(extractErrorMessage(err, 'Failed to load backup settings')) - } finally { - if (mounted) setIsLoading(false) - } - } - load() - return () => { - mounted = false - } - }, []) - - useEffect(() => { - const unsubscribe = window.api.onSettingsChanged((event) => { - if (event.key === 'backup') { - setSettings((prev) => ({ ...prev, ...(event.value as Partial) })) - } - }) - return unsubscribe - }, []) - - const updateSettings = useCallback( - async (updates: Partial): Promise => { - try { - const result = await window.api.settings.setBackupSettings(updates) - if (result.success) { - setSettings((prev) => ({ ...prev, ...updates })) - return true - } - setError(result.error ?? 'Update failed') - return false - } catch (err) { - setError(extractErrorMessage(err, 'Failed to update backup settings')) - return false - } - }, - [] - ) - - return { settings, isLoading, error, updateSettings } -} diff --git a/apps/desktop/src/renderer/src/hooks/use-devices.ts b/apps/desktop/src/renderer/src/hooks/use-devices.ts deleted file mode 100644 index 851c1831b..000000000 --- a/apps/desktop/src/renderer/src/hooks/use-devices.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' -import { extractErrorMessage } from '@/lib/ipc-error' -import { deviceService } from '@/services/device-service' - -export interface Device { - id: string - name: string - platform: 'macos' | 'windows' | 'linux' | 'ios' | 'android' - linkedAt: number - lastSyncAt?: number - isCurrentDevice: boolean -} - -interface UseDevicesReturn { - devices: Device[] - email: string | undefined - isLoading: boolean - error: string | null - removeDevice: (deviceId: string) => Promise - refresh: () => void -} - -export function useDevices(): UseDevicesReturn { - const [devices, setDevices] = useState([]) - const [email, setEmail] = useState(undefined) - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState(null) - const [refreshKey, setRefreshKey] = useState(0) - - useEffect(() => { - let mounted = true - const load = async (): Promise => { - try { - setIsLoading(true) - setError(null) - const result = await deviceService.getDevices() - if (mounted) { - setDevices(result.devices as Device[]) - setEmail(result.email) - } - } catch (err) { - if (mounted) setError(extractErrorMessage(err, 'Failed to load devices')) - } finally { - if (mounted) setIsLoading(false) - } - } - void load() - return () => { - mounted = false - } - }, [refreshKey]) - - const removeDevice = useCallback(async (deviceId: string): Promise => { - try { - const result = await deviceService.removeDevice({ deviceId }) - if (result.success) { - setDevices((prev) => prev.filter((d) => d.id !== deviceId)) - return true - } - setError(result.error ?? 'Failed to remove device') - return false - } catch (err) { - setError(extractErrorMessage(err, 'Failed to remove device')) - return false - } - }, []) - - return { - devices, - email, - isLoading, - error, - removeDevice, - refresh: () => setRefreshKey((k) => k + 1) - } -} diff --git a/apps/desktop/src/renderer/src/hooks/use-inbox.ts b/apps/desktop/src/renderer/src/hooks/use-inbox.ts index dd65a98fc..97084fb9a 100644 --- a/apps/desktop/src/renderer/src/hooks/use-inbox.ts +++ b/apps/desktop/src/renderer/src/hooks/use-inbox.ts @@ -35,7 +35,6 @@ import { onInboxSnoozeDue, onInboxTranscriptionComplete, onInboxMetadataComplete, - onInboxProcessingError, type CaptureTextInput, type CaptureLinkInput, type CaptureImageInput, @@ -631,23 +630,6 @@ export function useConvertToTask() { }) } -/** - * Hook for linking an inbox item to an existing note. - */ -export function useLinkToNote() { - const queryClient = useQueryClient() - - return useMutation({ - mutationFn: ({ itemId, noteId }: { itemId: string; noteId: string }) => - inboxService.linkToNote(itemId, noteId), - onSuccess: (_, { itemId }) => { - void queryClient.invalidateQueries({ queryKey: inboxKeys.item(itemId) }) - void queryClient.invalidateQueries({ queryKey: inboxKeys.lists() }) - void queryClient.invalidateQueries({ queryKey: inboxKeys.stats() }) - } - }) -} - // ============================================================================= // Tag Mutations // ============================================================================= @@ -819,20 +801,6 @@ export function useRetryMetadata() { // Processing Error Subscription Hook // ============================================================================= -/** - * Hook for subscribing to processing error events. - * - * @param callback - Callback to invoke when a processing error occurs - */ -export function useInboxProcessingErrors( - callback: (event: { id: string; operation: string; error: string }) => void -): void { - useEffect(() => { - const unsub = onInboxProcessingError(callback) - return unsub - }, [callback]) -} - export interface ArchivedListOptions { search?: string limit?: number diff --git a/apps/desktop/src/renderer/src/hooks/use-is-item-active.ts b/apps/desktop/src/renderer/src/hooks/use-is-item-active.ts index 68e5ccebd..8de76bf7f 100644 --- a/apps/desktop/src/renderer/src/hooks/use-is-item-active.ts +++ b/apps/desktop/src/renderer/src/hooks/use-is-item-active.ts @@ -82,29 +82,4 @@ export const useIsItemActive = () => { return isActiveItem } -/** - * Hook that returns the active tab identity for components that need - * to react to active tab changes (e.g., highlighting) - * - * Use this when you need to RE-RENDER on active tab change. - * Use useIsItemActive when you just need to CHECK if something is active. - */ -export const useActiveTabIdentity = (): ActiveTabIdentity | null => { - const { state } = useTabs() - - return useMemo((): ActiveTabIdentity | null => { - const group = state.tabGroups[state.activeGroupId] - if (!group || !group.activeTabId) return null - - const activeTab = group.tabs.find((t) => t.id === group.activeTabId) - if (!activeTab) return null - - return { - type: activeTab.type, - entityId: activeTab.entityId ?? '', - path: activeTab.path ?? '' - } - }, [state.tabGroups, state.activeGroupId]) -} - export default useIsItemActive diff --git a/apps/desktop/src/renderer/src/hooks/use-linking-events.ts b/apps/desktop/src/renderer/src/hooks/use-linking-events.ts deleted file mode 100644 index c991570bc..000000000 --- a/apps/desktop/src/renderer/src/hooks/use-linking-events.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' -import type { LinkingRequestEvent } from '@memry/contracts/ipc-events' - -interface LinkingEventsState { - pendingRequest: LinkingRequestEvent | null - recentlyApproved: string | null - clearRequest: () => void - clearApproved: () => void -} - -export function useLinkingEvents(): LinkingEventsState { - const [pendingRequest, setPendingRequest] = useState(null) - const [recentlyApproved, setRecentlyApproved] = useState(null) - - useEffect(() => { - const unsubRequest = window.api.onLinkingRequest((event) => { - setPendingRequest(event) - }) - - const unsubApproved = window.api.onLinkingApproved((event) => { - setPendingRequest(null) - setRecentlyApproved(event.sessionId) - }) - - return () => { - unsubRequest() - unsubApproved() - } - }, []) - - const clearRequest = useCallback(() => setPendingRequest(null), []) - const clearApproved = useCallback(() => setRecentlyApproved(null), []) - - return { pendingRequest, recentlyApproved, clearRequest, clearApproved } -} diff --git a/apps/desktop/src/renderer/src/hooks/use-notes-query.ts b/apps/desktop/src/renderer/src/hooks/use-notes-query.ts index bc21ead41..4c13a3465 100644 --- a/apps/desktop/src/renderer/src/hooks/use-notes-query.ts +++ b/apps/desktop/src/renderer/src/hooks/use-notes-query.ts @@ -519,21 +519,5 @@ export function useNoteMutations() { // Prefetch Utilities // ============================================================================= -/** - * Prefetch a note into the cache. - * Useful for hover prefetching in lists. - */ -export function usePrefetchNote() { - const queryClient = useQueryClient() - - return (id: string) => { - queryClient.prefetchQuery({ - queryKey: notesKeys.note(id), - queryFn: () => notesService.get(id), - staleTime: NOTE_STALE_TIME - }) - } -} - // Re-export types export type { Note, NoteListItem, NoteListResponse, NoteLinksResponse } diff --git a/apps/desktop/src/renderer/src/hooks/use-reminders.ts b/apps/desktop/src/renderer/src/hooks/use-reminders.ts index 162ead93a..4c0fffd00 100644 --- a/apps/desktop/src/renderer/src/hooks/use-reminders.ts +++ b/apps/desktop/src/renderer/src/hooks/use-reminders.ts @@ -14,15 +14,13 @@ import { onReminderCreated, onReminderUpdated, onReminderDeleted, - onReminderDue, onReminderDismissed, onReminderSnoozed, type CreateReminderInput, type UpdateReminderInput, type SnoozeReminderInput, type ListRemindersInput, - type ReminderTargetType, - type ReminderDueEvent + type ReminderTargetType } from '@/services/reminder-service' // ============================================================================ @@ -157,16 +155,6 @@ export function useRemindersForTarget( } } -/** - * Hook for subscribing to due reminders (for notifications) - */ -export function useDueReminderNotifications(onDue: (event: ReminderDueEvent) => void) { - useEffect(() => { - const unsub = onReminderDue(onDue) - return unsub - }, [onDue]) -} - // ============================================================================ // Mutations // ============================================================================ diff --git a/apps/desktop/src/renderer/src/hooks/use-sync-settings.ts b/apps/desktop/src/renderer/src/hooks/use-sync-settings.ts deleted file mode 100644 index ae6d7e5db..000000000 --- a/apps/desktop/src/renderer/src/hooks/use-sync-settings.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' -import { extractErrorMessage } from '@/lib/ipc-error' -import type { SyncSettingsDTO } from '../../../preload/index.d' - -const DEFAULTS: SyncSettingsDTO = { - enabled: true, - autoSync: true -} - -interface UseSyncSettingsReturn { - settings: SyncSettingsDTO - isLoading: boolean - error: string | null - updateSettings: (updates: Partial) => Promise -} - -export function useSyncSettings(): UseSyncSettingsReturn { - const [settings, setSettings] = useState(DEFAULTS) - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState(null) - - useEffect(() => { - let mounted = true - const load = async (): Promise => { - try { - setIsLoading(true) - setError(null) - const result = await window.api.settings.getSyncSettings() - if (mounted) setSettings(result) - } catch (err) { - if (mounted) setError(extractErrorMessage(err, 'Failed to load sync settings')) - } finally { - if (mounted) setIsLoading(false) - } - } - load() - return () => { - mounted = false - } - }, []) - - useEffect(() => { - const unsubscribe = window.api.onSettingsChanged((event) => { - if (event.key === 'sync') { - setSettings((prev) => ({ ...prev, ...(event.value as Partial) })) - } - }) - return unsubscribe - }, []) - - const updateSettings = useCallback( - async (updates: Partial): Promise => { - try { - const result = await window.api.settings.setSyncSettings(updates) - if (result.success) { - setSettings((prev) => ({ ...prev, ...updates })) - return true - } - setError(result.error ?? 'Update failed') - return false - } catch (err) { - setError(extractErrorMessage(err, 'Failed to update sync settings')) - return false - } - }, - [] - ) - - return { settings, isLoading, error, updateSettings } -} diff --git a/apps/desktop/src/renderer/src/lib/graph-builder.ts b/apps/desktop/src/renderer/src/lib/graph-builder.ts index 686761ee0..b602987ea 100644 --- a/apps/desktop/src/renderer/src/lib/graph-builder.ts +++ b/apps/desktop/src/renderer/src/lib/graph-builder.ts @@ -188,13 +188,3 @@ export function computeFocusSet(graph: Graph, nodeId: string, depth: number): Se return visited } - -export function extractAllTags(data: GraphDataResponse): string[] { - const tagSet = new Set() - for (const node of data.nodes) { - for (const tag of node.tags) { - tagSet.add(tag) - } - } - return Array.from(tagSet).sort() -} diff --git a/packages/contracts/src/reminders-api.test.ts b/packages/contracts/src/reminders-api.test.ts index 84d935b44..673fc0ddf 100644 --- a/packages/contracts/src/reminders-api.test.ts +++ b/packages/contracts/src/reminders-api.test.ts @@ -1,10 +1,5 @@ import { describe, it, expect } from 'vitest' import { - ReminderTargetTypeSchema, - ReminderStatusSchema, - CreateNoteReminderSchema, - CreateJournalReminderSchema, - CreateHighlightReminderSchema, CreateReminderSchema, UpdateReminderSchema, SnoozeReminderSchema, @@ -13,238 +8,6 @@ import { BulkDismissSchema } from './reminders-api' -// ============================================================================= -// ReminderTargetTypeSchema Tests -// ============================================================================= - -describe('ReminderTargetTypeSchema', () => { - it('should validate note target type', () => { - const result = ReminderTargetTypeSchema.safeParse('note') - expect(result.success).toBe(true) - }) - - it('should validate journal target type', () => { - const result = ReminderTargetTypeSchema.safeParse('journal') - expect(result.success).toBe(true) - }) - - it('should validate highlight target type', () => { - const result = ReminderTargetTypeSchema.safeParse('highlight') - expect(result.success).toBe(true) - }) - - it('should reject invalid target type', () => { - const result = ReminderTargetTypeSchema.safeParse('task') - expect(result.success).toBe(false) - }) -}) - -// ============================================================================= -// ReminderStatusSchema Tests -// ============================================================================= - -describe('ReminderStatusSchema', () => { - it('should validate pending status', () => { - const result = ReminderStatusSchema.safeParse('pending') - expect(result.success).toBe(true) - }) - - it('should validate triggered status', () => { - const result = ReminderStatusSchema.safeParse('triggered') - expect(result.success).toBe(true) - }) - - it('should validate dismissed status', () => { - const result = ReminderStatusSchema.safeParse('dismissed') - expect(result.success).toBe(true) - }) - - it('should validate snoozed status', () => { - const result = ReminderStatusSchema.safeParse('snoozed') - expect(result.success).toBe(true) - }) - - it('should reject invalid status', () => { - const result = ReminderStatusSchema.safeParse('completed') - expect(result.success).toBe(false) - }) -}) - -// ============================================================================= -// CreateNoteReminderSchema Tests -// ============================================================================= - -describe('CreateNoteReminderSchema', () => { - it('should validate correct note reminder', () => { - const result = CreateNoteReminderSchema.safeParse({ - noteId: 'note-abc123', - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(true) - }) - - it('should validate with optional title and note', () => { - const result = CreateNoteReminderSchema.safeParse({ - noteId: 'note-abc123', - remindAt: '2025-01-15T09:00:00.000Z', - title: 'Review this note', - note: 'Check the action items' - }) - expect(result.success).toBe(true) - }) - - it('should reject empty noteId', () => { - const result = CreateNoteReminderSchema.safeParse({ - noteId: '', - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) - - it('should reject invalid datetime format', () => { - const result = CreateNoteReminderSchema.safeParse({ - noteId: 'note-abc123', - remindAt: '2025-01-15' - }) - expect(result.success).toBe(false) - }) - - it('should reject title exceeding 200 characters', () => { - const result = CreateNoteReminderSchema.safeParse({ - noteId: 'note-abc123', - remindAt: '2025-01-15T09:00:00.000Z', - title: 'a'.repeat(201) - }) - expect(result.success).toBe(false) - }) - - it('should reject note exceeding 1000 characters', () => { - const result = CreateNoteReminderSchema.safeParse({ - noteId: 'note-abc123', - remindAt: '2025-01-15T09:00:00.000Z', - note: 'a'.repeat(1001) - }) - expect(result.success).toBe(false) - }) -}) - -// ============================================================================= -// CreateJournalReminderSchema Tests -// ============================================================================= - -describe('CreateJournalReminderSchema', () => { - it('should validate correct journal reminder', () => { - const result = CreateJournalReminderSchema.safeParse({ - journalDate: '2025-01-03', - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(true) - }) - - it('should validate with optional fields', () => { - const result = CreateJournalReminderSchema.safeParse({ - journalDate: '2025-01-03', - remindAt: '2025-01-15T09:00:00.000Z', - title: 'Revisit this entry', - note: 'Remember the insights' - }) - expect(result.success).toBe(true) - }) - - it('should reject invalid date format', () => { - const result = CreateJournalReminderSchema.safeParse({ - journalDate: '01-03-2025', - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) -}) - -// ============================================================================= -// CreateHighlightReminderSchema Tests -// ============================================================================= - -describe('CreateHighlightReminderSchema', () => { - it('should validate correct highlight reminder', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: 'Important passage to remember', - highlightStart: 100, - highlightEnd: 130, - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(true) - }) - - it('should validate with optional title and note', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: 'Key insight', - highlightStart: 50, - highlightEnd: 61, - remindAt: '2025-01-15T09:00:00.000Z', - title: 'Review highlight', - note: 'This was important' - }) - expect(result.success).toBe(true) - }) - - it('should reject highlightEnd not greater than highlightStart', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: 'Some text', - highlightStart: 100, - highlightEnd: 100, - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) - - it('should reject highlightEnd less than highlightStart', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: 'Some text', - highlightStart: 100, - highlightEnd: 50, - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) - - it('should reject empty highlightText', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: '', - highlightStart: 0, - highlightEnd: 10, - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) - - it('should reject highlightText exceeding 5000 characters', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: 'a'.repeat(5001), - highlightStart: 0, - highlightEnd: 5001, - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) - - it('should reject negative highlightStart', () => { - const result = CreateHighlightReminderSchema.safeParse({ - noteId: 'note-abc123', - highlightText: 'Some text', - highlightStart: -1, - highlightEnd: 10, - remindAt: '2025-01-15T09:00:00.000Z' - }) - expect(result.success).toBe(false) - }) -}) - // ============================================================================= // CreateReminderSchema (Discriminated Union) Tests // ============================================================================= diff --git a/packages/contracts/src/reminders-api.ts b/packages/contracts/src/reminders-api.ts index aef05d5b6..b8631b978 100644 --- a/packages/contracts/src/reminders-api.ts +++ b/packages/contracts/src/reminders-api.ts @@ -26,45 +26,8 @@ export { reminderTargetType, reminderStatus, type ReminderTargetType, type Remin // Zod Schemas // ============================================================================ -export const ReminderTargetTypeSchema = z.enum(['note', 'journal', 'highlight']) -export const ReminderStatusSchema = z.enum(['pending', 'triggered', 'dismissed', 'snoozed']) - -/** - * Schema for creating a reminder for a note - */ -export const CreateNoteReminderSchema = z.object({ - noteId: z.string().min(1), - remindAt: z.string().datetime(), - title: z.string().max(200).optional(), - note: z.string().max(1000).optional() -}) - -/** - * Schema for creating a reminder for a journal entry - */ -export const CreateJournalReminderSchema = z.object({ - journalDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), // YYYY-MM-DD - remindAt: z.string().datetime(), - title: z.string().max(200).optional(), - note: z.string().max(1000).optional() -}) - -/** - * Schema for creating a reminder for highlighted text - */ -export const CreateHighlightReminderSchema = z - .object({ - noteId: z.string().min(1), - highlightText: z.string().min(1).max(5000), - highlightStart: z.number().int().min(0), - highlightEnd: z.number().int().min(0), - remindAt: z.string().datetime(), - title: z.string().max(200).optional(), - note: z.string().max(1000).optional() - }) - .refine((data) => data.highlightEnd > data.highlightStart, { - message: 'highlightEnd must be greater than highlightStart' - }) +const ReminderTargetTypeSchema = z.enum(['note', 'journal', 'highlight']) +const ReminderStatusSchema = z.enum(['pending', 'triggered', 'dismissed', 'snoozed']) /** * Generic create schema that accepts all reminder types @@ -146,9 +109,6 @@ export const BulkDismissSchema = z.object({ // TypeScript Types // ============================================================================ -export type CreateNoteReminderInput = z.infer -export type CreateJournalReminderInput = z.infer -export type CreateHighlightReminderInput = z.infer export type CreateReminderInput = z.infer export type UpdateReminderInput = z.infer export type SnoozeReminderInput = z.infer diff --git a/packages/shared/src/file-types.ts b/packages/shared/src/file-types.ts index 41d058ac2..2eb48d612 100644 --- a/packages/shared/src/file-types.ts +++ b/packages/shared/src/file-types.ts @@ -129,46 +129,6 @@ export function isEditable(fileType: FileType): boolean { return fileType === 'markdown' } -/** - * Check if a file type is a media type (audio or video) - */ -export function isMedia(fileType: FileType): boolean { - return fileType === 'audio' || fileType === 'video' -} - -/** - * Get a human-readable label for a file type - */ -export function getFileTypeLabel(fileType: FileType): string { - const labels: Record = { - markdown: 'Markdown', - pdf: 'PDF', - image: 'Image', - audio: 'Audio', - video: 'Video' - } - return labels[fileType] -} - -// ============================================================================ -// File Type Icons (for use with @/lib/icons) -// ============================================================================ - -/** - * Get the icon name for a file type - * Use with: import { FileText, FileType2, Image, Music, Video } from '@/lib/icons' - */ -export function getFileTypeIconName(fileType: FileType): string { - const icons: Record = { - markdown: 'FileText', - pdf: 'FileType2', - image: 'Image', - audio: 'Music', - video: 'Video' - } - return icons[fileType] -} - /** * Get the tab icon identifier for a file type * Used when opening file tabs to set the correct icon @@ -188,15 +148,6 @@ export function getTabIconForFileType(fileType: FileType): string { // Glob Patterns (for file watching) // ============================================================================ -/** - * Get glob patterns for all supported file types - * Used by chokidar file watcher - */ -export function getSupportedGlobPatterns(): string[] { - const extensions = getAllSupportedExtensions() - return extensions.map((ext) => `**/*.${ext}`) -} - /** * Check if a path matches any supported file type */ From 4161b06efe558985e5177bcf67b4d00646ae6b1a Mon Sep 17 00:00:00 2001 From: Kaan Karaca Date: Fri, 3 Apr 2026 21:10:05 +0300 Subject: [PATCH 2/2] docs: add changelog entry for dead code cleanup --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31b1d5501..05d10d9a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ Format: weekly entries grouped by feature area. --- +## 2026-04-03 — Dead Code Cleanup + +### Changed +- Remove 6 unused files and 11 unused exports across monorepo (~762 lines) +- Remove superseded per-type reminder schemas in favor of unified `CreateReminderSchema` +- Un-export internal-only `ReminderTargetTypeSchema` and `ReminderStatusSchema` + +--- + ## 2026-04-02 — Journal Redesign and Task Improvements ### Added