Docs + seed script: non-prod DB workflow#141
Conversation
Document Production, Preview, and Local mapping for Neon, Vercel env scopes, Daily, and optional BUDDY_REQUIRE_FRIENDSHIP. Clarify that POSTGRES_URL_TEST is not read by the app. Note vercel.json ignoreCommand and common failure modes. Extend .env.example with optional vars. Closes #138 Made-with: Cursor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdded two optional env vars to Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Dev as Developer
participant Env as Environment
participant Script as Seed Script
participant DB as Database (Neon)
Dev->>Script: run `npm run db:seed` / `tsx scripts/seed.ts`
Script->>Env: read NODE_ENV, SEED_CONFIRM, POSTGRES_URL
Env-->>Script: return values
Script->>Script: validate (not prod, confirmation token, POSTGRES_URL present, Neon hostname)
alt validation fails
Script->>Dev: log error and exit(1)
else validation passes
Script->>DB: begin transaction
DB-->>Script: tx started
Script->>DB: delete existing seed users by email
Script->>DB: insert seed users (bcrypt-hashed password)
Script->>DB: query inserted user ids
Script->>DB: insert sessions and thoughts
Script->>DB: upsert friendship (on conflict do nothing)
DB-->>Script: commit
Script->>Dev: log success
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📋 Issue PlannerBuilt with CodeRabbit's Coding Plans for faster development and fewer bugs. View plan used: ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@README.md`:
- Line 64: The README and .env.example disagree on how to generate JWT_SECRET;
standardize both to the same command. Replace the `openssl rand -hex 32` entry
in README (the JWT_SECRET row referencing src/lib/auth.ts and src/middleware.ts)
with the same command used in .env.example (`openssl rand -base64 32`), or
vice‑versa if you prefer hex—ensure both README and .env.example use the
identical command so JWT_SECRET generation is consistent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8fce13e2-cf22-4858-b573-cb7aec23d778
📒 Files selected for processing (2)
.env.exampleREADME.md
Add an idempotent seed script with explicit non-production confirmation so dev and preview environments can be populated safely without touching production data. Made-with: Cursor
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/seed.ts`:
- Around line 26-38: Add an explicit DB-target safety guard before any writes by
validating the POSTGRES_URL value against an allowed DB host/database or
requiring an explicit override env var; after the existing NODE_ENV and
CONFIRMATION_KEY checks (around the POSTGRES_URL check), parse
process.env.POSTGRES_URL and either (a) enforce it does not match production
host/database patterns (e.g., disallow production host or prod DB name) or (b)
require an additional env flag like DB_ALLOW_TARGET or DB_TARGET_CONFIRM that
equals the expected host/db string before proceeding. Use the existing symbols
POSTGRES_URL, CONFIRMATION_KEY and REQUIRED_CONFIRMATION and fail fast with a
clear Error if the DB target is not explicitly approved.
- Around line 41-172: Wrap the entire seed flow (from the initial select/delete
of users through inserting sessions, thoughts and friendships) inside a single
database transaction by calling db.transaction(async (tx) => { ... }) and
replace usages of db with the transactional handle tx (so
select/insert/delete/returning use tx). Also change the friendship
check-then-insert to a race-safe operation inside that same transaction—either
perform an upsert/insert with conflict handling (e.g.,
.insert(friendships).values(...).onConflict([friendships.user1Id,
friendships.user2Id]).doNothing()) or perform the existence check and insert
using tx to ensure atomicity; ensure all references to users, sessions, thoughts
and friendships use the transactional tx handle.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 018f8968-61c3-459a-b31a-ee8dd661f65c
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (3)
README.mdpackage.jsonscripts/seed.ts
✅ Files skipped from review due to trivial changes (1)
- package.json
🚧 Files skipped from review as they are similar to previous changes (1)
- README.md
Align README JWT generation with .env.example and document additional seed safety guards. Co-authored-by: Bretton Auerbach <auerbachb@users.noreply.github.com>
Co-authored-by: Bretton Auerbach <auerbachb@users.noreply.github.com>
There was a problem hiding this comment.
🧹 Nitpick comments (2)
scripts/seed.ts (2)
71-71: Consider omitting the explicit type annotation fortx.The
AppDbtype is technically incorrect for the transaction callback parameter—Drizzle provides a transaction-specific type. It works here due to structural typing, but omitting the annotation lets TypeScript infer the correct type.♻️ Suggested change
- await db.transaction(async (tx: AppDb) => { + await db.transaction(async (tx) => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/seed.ts` at line 71, The transaction callback uses an explicit, incorrect AppDb annotation on the parameter (async (tx: AppDb) => ...)—remove the explicit type so TypeScript/Drizzle can infer the transaction-specific type; update the db.transaction call to use async (tx) => { ... } (or omit the annotation) and leave rest of the logic unchanged to avoid the structural-typing mismatch.
81-81: Consider moving password hashing outside the transaction.
bcrypt.hashwith cost factor 12 is CPU-bound and can take 250–500ms. Performing it inside the transaction holds the connection open during that work. For a seed script this is acceptable, but moving it beforedb.transaction()would minimize transaction duration.♻️ Suggested change
assertNeonNonProdPostgresUrl(postgresUrl); const seedEmails = seedUsers.map((user) => user.email); + const passwordHash = await bcrypt.hash("SeedPassword123!", 12); await db.transaction(async (tx: AppDb) => { const existing = await tx .select({ id: users.id }) .from(users) .where(inArray(users.email, seedEmails)); if (existing.length > 0) { await tx.delete(users).where(inArray(users.id, existing.map((row) => row.id))); } - const passwordHash = await bcrypt.hash("SeedPassword123!", 12); await tx.insert(users).values(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/seed.ts` at line 81, Move the CPU-bound bcrypt.hash call out of the transaction to avoid holding the DB connection during hashing: compute passwordHash = await bcrypt.hash("SeedPassword123!", 12) before invoking db.transaction(), then pass the precomputed passwordHash into the transaction block where user creation or inserts occur (referencing passwordHash, bcrypt.hash and db.transaction()) so the transaction only covers the DB operations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/seed.ts`:
- Line 71: The transaction callback uses an explicit, incorrect AppDb annotation
on the parameter (async (tx: AppDb) => ...)—remove the explicit type so
TypeScript/Drizzle can infer the transaction-specific type; update the
db.transaction call to use async (tx) => { ... } (or omit the annotation) and
leave rest of the logic unchanged to avoid the structural-typing mismatch.
- Line 81: Move the CPU-bound bcrypt.hash call out of the transaction to avoid
holding the DB connection during hashing: compute passwordHash = await
bcrypt.hash("SeedPassword123!", 12) before invoking db.transaction(), then pass
the precomputed passwordHash into the transaction block where user creation or
inserts occur (referencing passwordHash, bcrypt.hash and db.transaction()) so
the transaction only covers the DB operations.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1032a619-ca68-4866-9e82-a569d8c4f051
📒 Files selected for processing (1)
scripts/seed.ts
Summary
Adds a concrete non-production database workflow end to end:
README.md.README.md.scripts/seed.tsandnpm run db:seedfor deterministic fixture data with safety guards:SEED_CONFIRM=still-point-nonprodNODE_ENV=productionCloses #138
Refs #1
Test plan
npx tsc --noEmitpassesnpm run db:seedfails safely without confirmation (SEED_CONFIRM) as expecteddb:seedflow and non-production-only safety notes.env*files were modifiedMade with Cursor
Summary by CodeRabbit
Documentation
Chores
New Features