style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
+72 -63
View File
@@ -93,12 +93,14 @@ familysync/
## Directory Purposes
**`apps/api/src/`** — Backend HTTP server and background broker
- **Routes** respond to client requests (GET reads cache only; POST/PATCH/DELETE enqueue outbox)
- **Broker** runs background jobs (poller syncs with Fastmail; outbox worker drains writes)
- **Auth** handles OIDC session + user identity upsert
- **DB** defines schema and provides Drizzle ORM client
**`apps/pwa/src/`** — React PWA frontend
- **Components** render UI and handle user interactions
- **API** wraps typed fetch calls to backend endpoints
- **Store** owns UI-only state (view selection, modal open/close) via Zustand
@@ -107,6 +109,7 @@ familysync/
- **Styles** defines design tokens (colors, spacing, typography)
**`apps/api/tests/`** — Unit tests for backend
- **Routes** test endpoint validation, authorization, DB queries
- **Broker** test CalDAV sync logic, RRULE expansion, outbox draining
- **Auth** test user upsert, color assignment, OIDC claim handling
@@ -114,103 +117,104 @@ familysync/
- **Helpers** provide test utilities (mock Drizzle, mock tsdav clients)
**`packages/shared/`** — Shared types (future expansion for N-member)
- Currently a placeholder; will contain cross-app TypeScript interfaces when multi-member features need shared definitions
## Key File Locations
**Entry Points:**
| File | Purpose |
|------|---------|
| File | Purpose |
| ----------------------- | ------------------------------------------------------------------------- |
| `apps/api/src/index.ts` | Hono app definition, middleware stack, route registration, broker startup |
| `apps/pwa/src/main.tsx` | Vite entry point; React.createRoot, hydrate App |
| `apps/pwa/src/App.tsx` | Root component; renders CalendarShell |
| `apps/pwa/src/main.tsx` | Vite entry point; React.createRoot, hydrate App |
| `apps/pwa/src/App.tsx` | Root component; renders CalendarShell |
**Configuration:**
| File | Purpose |
|------|---------|
| `apps/api/package.json` | Backend dependencies (Hono, Drizzle, tsdav, ical.js, rrule, node-cron, zod, @hono/zod-validator, @hono/oidc-auth, mysql2) |
| `apps/pwa/package.json` | Frontend dependencies (React 19, Vite, @tanstack/react-query, Zustand, @schedule-x/react, lucide-react, etc.) |
| `apps/api/tsconfig.json` | strict: true; lib: es2022; module: es2022 |
| `apps/pwa/tsconfig.json` | strict: true; jsx: react-jsx; lib: es2022, dom |
| `apps/pwa/vite.config.ts` | Vite plugins (react, VitePWA); dev proxy to :3000; PWA manifest config |
| File | Purpose |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `apps/api/package.json` | Backend dependencies (Hono, Drizzle, tsdav, ical.js, rrule, node-cron, zod, @hono/zod-validator, @hono/oidc-auth, mysql2) |
| `apps/pwa/package.json` | Frontend dependencies (React 19, Vite, @tanstack/react-query, Zustand, @schedule-x/react, lucide-react, etc.) |
| `apps/api/tsconfig.json` | strict: true; lib: es2022; module: es2022 |
| `apps/pwa/tsconfig.json` | strict: true; jsx: react-jsx; lib: es2022, dom |
| `apps/pwa/vite.config.ts` | Vite plugins (react, VitePWA); dev proxy to :3000; PWA manifest config |
**Core Logic:**
| File | Purpose |
|------|---------|
| `apps/api/src/db/schema.ts` | Drizzle table definitions (users, member_credentials, calendars, calendar_events, calendar_outbox) |
| `apps/api/src/routes/events.ts` | GET /api/events (windowed + expanded), write endpoints (POST/PATCH/DELETE), sync-status polling, writable-calendars |
| `apps/api/src/broker/poller.ts` | 5-min background job; PROPFIND → ctag change detection |
| `apps/api/src/broker/sync.ts` | REPORT → ical.js parse → calendar_events upsert; prune deletes |
| `apps/api/src/broker/outboxWorker.ts` | 15-sec drain pending outbox rows; PUT/DELETE to Fastmail; exponential backoff |
| `apps/api/src/broker/expand.ts` | ical.js RecurExpansion; emit concrete occurrences (with VTIMEZONE + RRULE handled) |
| `apps/pwa/src/components/CalendarShell.tsx` | TanStack Query (events, me), Zustand (range, view), Schedule-X wiring |
| `apps/pwa/src/store/calendarStore.ts` | Zustand store; selectedView, openEventId, calendarRange, eventFormOpen, deleteDialogOpen |
| `apps/pwa/src/api/client.ts` | Typed fetch wrappers; MeResponse, CalendarOccurrence, CreateEventPayload interfaces |
| `apps/pwa/src/lib/hydrateEvents.ts` | Occurrence[] → Schedule-X CalendarEvent[] with Temporal.ZonedDateTime conversion |
| File | Purpose |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `apps/api/src/db/schema.ts` | Drizzle table definitions (users, member_credentials, calendars, calendar_events, calendar_outbox) |
| `apps/api/src/routes/events.ts` | GET /api/events (windowed + expanded), write endpoints (POST/PATCH/DELETE), sync-status polling, writable-calendars |
| `apps/api/src/broker/poller.ts` | 5-min background job; PROPFIND → ctag change detection |
| `apps/api/src/broker/sync.ts` | REPORT → ical.js parse → calendar_events upsert; prune deletes |
| `apps/api/src/broker/outboxWorker.ts` | 15-sec drain pending outbox rows; PUT/DELETE to Fastmail; exponential backoff |
| `apps/api/src/broker/expand.ts` | ical.js RecurExpansion; emit concrete occurrences (with VTIMEZONE + RRULE handled) |
| `apps/pwa/src/components/CalendarShell.tsx` | TanStack Query (events, me), Zustand (range, view), Schedule-X wiring |
| `apps/pwa/src/store/calendarStore.ts` | Zustand store; selectedView, openEventId, calendarRange, eventFormOpen, deleteDialogOpen |
| `apps/pwa/src/api/client.ts` | Typed fetch wrappers; MeResponse, CalendarOccurrence, CreateEventPayload interfaces |
| `apps/pwa/src/lib/hydrateEvents.ts` | Occurrence[] → Schedule-X CalendarEvent[] with Temporal.ZonedDateTime conversion |
**Testing:**
| File | Purpose |
|------|---------|
| `apps/api/tests/routes/events.test.ts` | Unit tests for route handlers (validation, ownership checks, SQL correctness) |
| `apps/api/tests/broker/expand.test.ts` | Unit tests for RRULE expansion (VTIMEZONE, EXDATE, DST) |
| `apps/pwa/src/components/CalendarShell.test.tsx` | Component integration test; mocked React Query + Zustand |
| `apps/pwa/src/lib/hydrateEvents.test.ts` | Unit tests for Temporal conversion logic |
| File | Purpose |
| ------------------------------------------------ | ----------------------------------------------------------------------------- |
| `apps/api/tests/routes/events.test.ts` | Unit tests for route handlers (validation, ownership checks, SQL correctness) |
| `apps/api/tests/broker/expand.test.ts` | Unit tests for RRULE expansion (VTIMEZONE, EXDATE, DST) |
| `apps/pwa/src/components/CalendarShell.test.tsx` | Component integration test; mocked React Query + Zustand |
| `apps/pwa/src/lib/hydrateEvents.test.ts` | Unit tests for Temporal conversion logic |
## Naming Conventions
**Files:**
| Pattern | Example | Where |
|---------|---------|-------|
| Kebab-case for route/route groups | `events.ts`, `health.ts` | `apps/api/src/routes/` |
| Kebab-case for modules | `poller.ts`, `sync.ts`, `outbox-worker.ts` (or camelCase `outboxWorker.ts`) | `apps/api/src/broker/` |
| PascalCase for React components | `CalendarShell.tsx`, `EventDetailPopover.tsx` | `apps/pwa/src/components/` |
| Kebab-case for utility functions | `hydrateEvents.ts`, `colorUtils.ts` | `apps/pwa/src/lib/` |
| `.test.ts` / `.test.tsx` for tests | `events.test.ts`, `CalendarShell.test.tsx` | Colocated with source |
| Pattern | Example | Where |
| ---------------------------------- | --------------------------------------------------------------------------- | -------------------------- |
| Kebab-case for route/route groups | `events.ts`, `health.ts` | `apps/api/src/routes/` |
| Kebab-case for modules | `poller.ts`, `sync.ts`, `outbox-worker.ts` (or camelCase `outboxWorker.ts`) | `apps/api/src/broker/` |
| PascalCase for React components | `CalendarShell.tsx`, `EventDetailPopover.tsx` | `apps/pwa/src/components/` |
| Kebab-case for utility functions | `hydrateEvents.ts`, `colorUtils.ts` | `apps/pwa/src/lib/` |
| `.test.ts` / `.test.tsx` for tests | `events.test.ts`, `CalendarShell.test.tsx` | Colocated with source |
**Functions:**
| Pattern | Example |
|---------|---------|
| camelCase for functions | `fetchEvents`, `expandOccurrences`, `upsertUser`, `syncCalendar` |
| PascalCase for React components | `CalendarShell`, `EventForm`, `SyncStateToast` |
| UPPER_CASE for module-level constants | `MAX_WINDOW_DAYS`, `COLOR_PALETTE`, `TRANSIENT_STATUSES` |
| Leading `$` for Drizzle special methods | `.$returningId()`, `.onDuplicateKeyUpdate()` |
| Pattern | Example |
| --------------------------------------- | ---------------------------------------------------------------- |
| camelCase for functions | `fetchEvents`, `expandOccurrences`, `upsertUser`, `syncCalendar` |
| PascalCase for React components | `CalendarShell`, `EventForm`, `SyncStateToast` |
| UPPER_CASE for module-level constants | `MAX_WINDOW_DAYS`, `COLOR_PALETTE`, `TRANSIENT_STATUSES` |
| Leading `$` for Drizzle special methods | `.$returningId()`, `.onDuplicateKeyUpdate()` |
**Variables:**
| Pattern | Example |
|---------|---------|
| camelCase for variables | `currentUserId`, `calendarRange`, `eventsQuery` |
| `is`/`has` prefix for booleans | `isShared`, `hasRrule`, `eventFormOpen` |
| Trailing `Id` for foreign keys | `userId`, `calendarId`, `groupId` |
| Descriptive names for arrays | `seenUids`, `usedColors`, `occurrences` |
| Pattern | Example |
| ------------------------------ | ----------------------------------------------- |
| camelCase for variables | `currentUserId`, `calendarRange`, `eventsQuery` |
| `is`/`has` prefix for booleans | `isShared`, `hasRrule`, `eventFormOpen` |
| Trailing `Id` for foreign keys | `userId`, `calendarId`, `groupId` |
| Descriptive names for arrays | `seenUids`, `usedColors`, `occurrences` |
**Types:**
| Pattern | Example |
|---------|---------|
| PascalCase for interfaces | `CalendarOccurrence`, `MeResponse`, `CreateEventPayload` |
| PascalCase for type aliases | `RecurrencePreset`, `BreakpointGroup` |
| Trailing `Schema` for Zod/validation | `eventsQuerySchema`, `eventFieldsSchema` |
| Trailing `Response` for API responses | `MeResponse`, `OccurrencesResponse` |
| Pattern | Example |
| ------------------------------------- | -------------------------------------------------------- |
| PascalCase for interfaces | `CalendarOccurrence`, `MeResponse`, `CreateEventPayload` |
| PascalCase for type aliases | `RecurrencePreset`, `BreakpointGroup` |
| Trailing `Schema` for Zod/validation | `eventsQuerySchema`, `eventFieldsSchema` |
| Trailing `Response` for API responses | `MeResponse`, `OccurrencesResponse` |
## Where to Add New Code
**New Feature:**
| Feature Type | Primary Code | Tests | Configuration |
|--------------|--------------|-------|---------------|
| Calendar event operation (read-only) | `apps/api/src/routes/events.ts` (new GET endpoint) | `apps/api/tests/routes/events.test.ts` | `apps/pwa/src/api/client.ts` (new fetchFn) |
| Calendar event operation (write) | `apps/api/src/routes/events.ts` (new POST/PATCH/DELETE) + `apps/api/src/broker/write.ts` (new builder) | Route tests + outbox drain tests | `apps/pwa/src/components/EventForm.tsx` (new field) |
| Recurring event handling | `apps/api/src/broker/expand.ts` (expansion logic) | `apps/api/tests/broker/expand.test.ts` | N/A (no UI change needed) |
| Shared list sync | `apps/api/src/routes/lists.ts` (new router) + `apps/api/src/broker/listsSync.ts` (if background job needed) | `apps/api/tests/routes/lists.test.ts` | `apps/pwa/src/api/client.ts` (new interfaces) |
| UI component (calendar display) | `apps/pwa/src/components/` | `apps/pwa/src/components/*.test.tsx` | N/A |
| UI component (modal/dialog) | `apps/pwa/src/components/` + `apps/pwa/src/store/calendarStore.ts` (add state if needed) | Component test | N/A |
| Feature Type | Primary Code | Tests | Configuration |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------- | -------------------------------------- | --------------------------------------------------- |
| Calendar event operation (read-only) | `apps/api/src/routes/events.ts` (new GET endpoint) | `apps/api/tests/routes/events.test.ts` | `apps/pwa/src/api/client.ts` (new fetchFn) |
| Calendar event operation (write) | `apps/api/src/routes/events.ts` (new POST/PATCH/DELETE) + `apps/api/src/broker/write.ts` (new builder) | Route tests + outbox drain tests | `apps/pwa/src/components/EventForm.tsx` (new field) |
| Recurring event handling | `apps/api/src/broker/expand.ts` (expansion logic) | `apps/api/tests/broker/expand.test.ts` | N/A (no UI change needed) |
| Shared list sync | `apps/api/src/routes/lists.ts` (new router) + `apps/api/src/broker/listsSync.ts` (if background job needed) | `apps/api/tests/routes/lists.test.ts` | `apps/pwa/src/api/client.ts` (new interfaces) |
| UI component (calendar display) | `apps/pwa/src/components/` | `apps/pwa/src/components/*.test.tsx` | N/A |
| UI component (modal/dialog) | `apps/pwa/src/components/` + `apps/pwa/src/store/calendarStore.ts` (add state if needed) | Component test | N/A |
**New Endpoint:**
@@ -241,6 +245,7 @@ familysync/
## Special Directories
**`apps/api/src/db/migrations/`:**
- Purpose: drizzle-kit-generated SQL migration files
- Generated: Yes (via `drizzle-kit generate:mysql`)
- Committed: Yes (must be version-controlled for reproducibility)
@@ -248,26 +253,30 @@ familysync/
- How to apply: Run `drizzle-kit migrate:mysql` to execute pending migrations against MariaDB
**`apps/pwa/public/`:**
- Purpose: PWA static assets served at root (manifest.webmanifest, service worker, icons, index.html)
- Generated: `sw.js` and `registerSW.js` are generated by vite-plugin-pwa; others are committed
- Committed: Yes (except dist/ and generated service worker code — PWA plugin handles registration)
- How to add: Place assets here; vite build copies to dist/ and serves at /
**`apps/api/dist/` and `apps/pwa/dist/`:**
- Purpose: Compiled output (JavaScript, CSS, bundled PWA)
- Generated: Yes (via build scripts)
- Committed: No (gitignored)
**`node_modules/`:**
- Purpose: pnpm-installed dependencies
- Generated: Yes (via `pnpm install`)
- Committed: No (gitignored; use `pnpm-lock.yaml` for reproducibility)
**`.planning/codebase/`:**
- Purpose: Auto-generated codebase analysis documents (this file, ARCHITECTURE.md, TESTING.md, etc.)
- Generated: Yes (by `/gsd-map-codebase` orchestrator)
- Committed: Yes (reference documentation for future phases)
---
*Structure analysis: 2026-06-09*
_Structure analysis: 2026-06-09_