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:
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user