Skip to content

refactor: clean code audit — decompose 6 god-files and eliminate IPC boilerplate - #137

Merged
h4yfans merged 12 commits into
mainfrom
worktree-refactor+clean-code-audit
Apr 3, 2026
Merged

refactor: clean code audit — decompose 6 god-files and eliminate IPC boilerplate#137
h4yfans merged 12 commits into
mainfrom
worktree-refactor+clean-code-audit

Conversation

@h4yfans

@h4yfans h4yfans commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

What

Codebase-wide clean code audit: decompose 6 oversized files (1,000–2,089 lines each), eliminate 112 repetitive IPC try/catch blocks, add structured logging to sync-server, and introduce type-safe test mocks.

Why

Organic growth produced several "gravity well" files — monolithic modules that accumulate responsibility because they're the natural place to add the next feature. The top 6 files alone accounted for ~9K lines. This refactoring improves maintainability, testability, and code navigation without changing any user-facing behavior.

How

10 atomic refactoring commits across independent file trees, executed by a 5-agent team in parallel:

Commit What Impact
Split task-utils.ts 1,349 LOC → 5 focused modules (date, filters, sort, format, status) SRP, cohesion
Split queries/notes.ts 1,595 LOC → 7 sub-modules (CRUD, tags, journal, properties, snapshots, links, helpers) SRP, module cohesion
Decompose ContentArea.tsx 1,482 → 331 lines via 6 extracted hooks 78% reduction, useEffect audit
Decompose use-journal.ts 1,081 → 8 focused modules Hook composition, DRY IPC subscriptions
Split use-inbox.ts 993 → 5 modules (queries, mutations, operations) SRP, read/write separation
Decompose notes-tree.tsx 2,089 → 542 lines via 7 extracted modules 74% reduction, shared utils with virtualized tree
IPC handler wrapper 112 → 7 try/catch blocks via withDb/withErrorHandler HOFs 94% boilerplate reduction, -426 LOC
Sync-server logger 6 raw console.* → structured createLogger Consistent logging
Type-safe test mocks asClientDb()/asSyncDb() helpers + mock factories 28 as any eliminated

Key design decisions:

  • Barrel re-exports (index.ts) at every split point — zero breaking import changes
  • useEffect audit found all 38 effects are legitimate external system syncs (IPC, BlockNote, Yjs, DOM) — no derived-state antipatterns
  • Both tree components (notes-tree.tsx + virtualized-notes-tree.tsx) are actively used (strategy pair with 100-item threshold) — shared utils extracted, neither deleted

Type

  • refactor — restructure without behavior change

Test plan

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing (describe below)

New tests: ~100 new tests across all refactored modules
Full suite: 239 test files, 5,456 tests — all passing
Typecheck: 5/5 tasks clean
IPC contracts: up to date
Lint: 0 errors

Checklist

  • Self-reviewed the diff
  • No hardcoded secrets or credentials
  • Files stay under ~500 LOC
  • Follows immutable data patterns

h4yfans added 12 commits April 3, 2026 20:02
Split monolithic use-journal.ts into single-responsibility hook files:
- use-journal-entry.ts (374 lines) — entry CRUD, auto-save, external sync
- use-journal-heatmap.ts (44 lines) — heatmap data queries
- use-journal-month.ts (48 lines) — month entry previews
- use-journal-stats.ts (44 lines) — year statistics
- use-day-context.ts (77 lines) — day tasks/events
- use-ai-connections.ts (143 lines) — AI content analysis
- journal-query-keys.ts (19 lines) — shared query key factory
- use-journal-invalidation.ts (43 lines) — shared IPC subscription helper

DRY: 3 identical IPC subscription effects collapsed into useJournalChangeInvalidation()
Barrel re-export in use-journal.ts preserves all existing imports.
All 19 existing tests pass unchanged.
Replace monolithic notes.ts with queries/notes/ directory:
- note-crud.ts (210): CRUD, listing, bulk operations
- tag-queries.ts (402): tag ops + tag definitions
- link-queries.ts (111): wiki-links + backlinks
- property-queries.ts (201): note properties + definitions
- snapshot-queries.ts (127): version history
- journal-queries.ts (225): journal entries + heatmap
- query-helpers.ts (78): serialization + activity level
- index.ts (122): barrel re-export preserving public API

All 30+ consumer imports unchanged (TypeScript resolves
queries/notes → queries/notes/index.ts transparently).
Split monolithic use-inbox.ts into domain-grouped hook files:
- inbox-query-keys.ts (21 lines) — shared query key factory + constants
- use-inbox-queries.ts (431 lines) — 11 query hooks with IPC subscriptions
- use-inbox-mutations.ts (327 lines) — 19 mutation hooks (capture, CRUD, filing, tags, snooze, bulk)
- use-inbox-operations.ts (71 lines) — composite useInboxOperations()

Barrel re-export in use-inbox.ts preserves all existing imports.
All 19 existing tests pass unchanged.
Replace monolithic task-utils.ts with task-utils/ directory:
- task-date-utils.ts (133): pure date math, no task dependencies
- task-formatting.ts (102): due date display, overdue tiers
- task-status-helpers.ts (186): status checks, sorting, grouping
- task-view-helpers.ts (392): today/upcoming/completed views, counts
- task-filters.ts (326): advanced filter pipeline + sort
- index.ts (87): barrel re-export preserving public API

All 31 consumer imports unchanged (TypeScript resolves
lib/task-utils → lib/task-utils/index.ts transparently).
380/380 tests pass, both typechecks clean.
Extract 16 useEffects from monolithic ContentArea.tsx into single-responsibility hooks:
- useBlockNoteSetup: AI extension, spellcheck, focus, link clicks, highlight scroll
- useEditorSync: initial content loading, debounced change handler
- useWikiLinkSuggestions: wiki link cache, fuzzy search, selection
- useTagSuggestions: hashTag plugin, recoloring, tag click navigation
- useEditorDragDrop: drag state, global event listeners, drop target highlight
- useEditorFileUpload: file upload, capture-phase drop for non-images

Also extract markdown-utils.ts for blank-preserving markdown parsing.

ContentArea.tsx reduced from 1,482 to 331 lines (78% reduction).
Eliminated ~290 lines of duplicate utility code (already in wiki-link-utils.ts).
Narrowed eslint-disable from 6 rules to just no-explicit-any.
18 new tests (9 drag-drop + 9 file-upload).

All 75 content-area tests pass. Full typecheck clean.
…ests

Add asClientDb() and asSyncDb() helpers to test-db.ts that bridge the
type gap between TestDb and the two DrizzleDb variants (database/client
full-schema vs sync/item-handlers data-schema). Update 6 sync test files
to use these helpers instead of `as any` casts, removing 28 instances of
`as any` and their associated eslint-disable comments.

Files updated: task-sync, project-sync, inbox-sync, filter-sync,
manifest-check, settings-sync test files. All 60 tests pass.
Extract shared logic between notes-tree.tsx and virtualized-notes-tree.tsx:
- notes-tree-utils.tsx: shared pure utilities (getDisplayName, getFileIcon, buildTreeFromNotes, etc.)
- use-note-tree-data.ts: data fetching hook (notes, folders, positions, template names, tree building)
- use-note-tree-actions.ts: CRUD actions hook (create, rename, delete, move, reorder)
- note-tree-dialogs.tsx: delete confirmation dialog + template selector
- note-tree-states.tsx: loading skeleton, empty state, error state components
- note-tree-internal.tsx: tree-internal helpers (RevealHandler, FolderRevealHandler, TreeActionsExposer)

Results:
- notes-tree.tsx: 2,089 → 542 lines (74% reduction)
- virtualized-notes-tree.tsx: 1,099 → 1,055 lines (removed duplicated getDisplayName/getFileIcon)
- 33 new unit tests for shared utilities
- 36 existing integration tests still passing
- Zero type errors
Add createMockDb(), createMockSyncDb(), and createMockApplyContext()
factories to tests/utils/type-safe-mocks.ts. Update 4 test files to
use factories and existing asSyncDb() cast helper instead of as-any.
Add createLogger(scope) utility that outputs structured JSON via
console methods (Workers-compatible). Replace all 6 raw console.*
calls across 4 production files with scoped logger instances.
… boilerplate

Add withErrorHandler(fn, fallback) and withDb(fn, fallback) higher-order
functions to validate.ts. withDb acquires the database and catches errors;
withErrorHandler catches errors only. Refactor 14 handler files (112 → 7
occurrences). Remaining 7 are intentional: infrastructure (2), batch error
collection (2), retry logic (1), secure cleanup (1), utility (1).
@h4yfans
h4yfans merged commit 558ddff into main Apr 3, 2026
3 checks passed
@h4yfans
h4yfans deleted the worktree-refactor+clean-code-audit branch April 3, 2026 17:21
h4yfans added a commit that referenced this pull request May 6, 2026
…udit

refactor: clean code audit — decompose 6 god-files and eliminate IPC boilerplate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant