Phase 2: migrate projects.ts onto pg

↗ view on GitHub · Claude · 2026-05-15 · bc2391db

Largest single route conversion so far. 881 lines, 29 db.from calls,
all now parameterised SQL via lib/db.

Highlights:
- GET / lists own + shared via shared_with @> $::jsonb (PostgREST cs
  equivalent), then per-project count queries for documents, chats,
  tabular_reviews.
- POST / inserts and returns the new row with documents:[] attached.
- GET /:id loads project + documents + folders, attaches active
  version paths via the already-migrated documentVersions helpers.
- GET /:id/people replaces db.auth.admin.listUsers({ perPage: 1000 })
  with a single SELECT id, email, display_name FROM users WHERE
  lower(email) = ANY($1). Owner is resolved by id. Members are
  resolved by email; missing accounts surface as
  display_name: null in the response.
- PATCH /:id builds the UPDATE column list dynamically from supplied
  fields, with shared_with normalised to lowercase + deduped, capped
  at 100 entries.
- DELETE /:id relies on schema-level ON DELETE CASCADE (Phase 2
  migrations 0007-0010) to tear down documents, chats, reviews,
  folders.
- /:id/folders POST + PATCH + DELETE. Cycle detection on parent
  reassignment walks up the proposed ancestor chain; folder delete
  moves direct documents to root in a transaction before removing
  the folder.
- handleDocumentUpload (shared with documents.ts) migrated. Its db
  parameter is retained for the still-Supabase documents.ts call
  site and ignored.

End-to-end verification against Postgres 16:
  - POST creates project, returns 201 with documents:[].
  - GET / returns count=1 with doc_count/chat_count/review_count=0
    and is_owner=true.
  - GET /:id returns the full project payload with documents and
    folders arrays.
  - GET /:id/people returns owner (with display_name) and members
    (display_name null for not-yet-registered emails).
  - PATCH rename applies.
  - Folder create, subfolder under parent, cycle detection on
    PATCH (400 with 'Cannot move a folder into itself or a
    descendant'), folder delete 204.
  - Project delete 204; GET / returns count=0.

Remaining: documents.ts (16), chat.ts (12), projectChat.ts (4),
tabular.ts (19), chatTools.ts (12). Then @supabase/supabase-js comes
out of the backend.
Repository cpatpa/PIP
Author Claude <noreply@anthropic.com>
Authored
Parents c198e804
Stats 2 files changed , +741 , -555
Part of Phase 2 - Supabase JS → plain pg cutover across the backend

Capture this commit into my fork

Download a Markdown prompt that tells Claude how to port this exact commit into your working tree. Run it via claude -p < capture-commit-bc2391db.md from inside the repo you want the change in.

⬇ Download capture-commit-bc2391db.md