Phase 2: migrate projects.ts onto pg
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.