Skip to content

feat: Database schema with Drizzle ORM, migrations, and seed data#31

Merged
sortakool merged 7 commits intomainfrom
feat/database-schema-drizzle
Feb 26, 2026
Merged

feat: Database schema with Drizzle ORM, migrations, and seed data#31
sortakool merged 7 commits intomainfrom
feat/database-schema-drizzle

Conversation

@sortakool
Copy link
Copy Markdown
Contributor

Closes #27

Summary

Implements the complete data model using Drizzle ORM inside apps/api, with SQLite for local development, migration tooling, and a seed script with realistic sample data.

Schema (apps/api/src/db/schema/)

  • Artist — id (uuid), name, email, preferences (json), rider_template, timestamps
  • Tour — id, artist_id (FK → Artist), name, start/end dates, budget, status enum (planning | confirmed | in_progress | completed), timestamps
  • Gig — id, tour_id (FK → Tour), venue_name, city, state, date, promoter info, fee, rider_status enum (draft | sent | signed), timestamps
  • Booking — id, gig_id (FK → Gig), type enum (flight | hotel), provider, confirmation_number, cost, check_in/out, details (json), created_at
  • Rider — id, gig_id (FK → Gig, unique), content (json), pdf_url, status enum (draft | sent | signed), timestamps
  • Cascade deletes enforced: delete tour → deletes gigs → deletes bookings/riders

Tooling

  • Drizzle ORM + drizzle-kit installed and configured (drizzle.config.ts)
  • bun run db:generate — generates SQL migration files from schema changes
  • bun run db:migrate — applies pending migrations to SQLite
  • bun run db:studio — launches Drizzle Studio for local debugging
  • bun run db:seed — populates sample data
  • SQLite database stored at apps/api/local.db (gitignored)

Database client (apps/api/src/db/index.ts)

  • Drizzle client exported with bun:sqlite driver
  • Uses DATABASE_URL env var with fallback to ./local.db
  • Type-safe schema and DbClient type exported for route handlers

Seed data (apps/api/src/db/seed.ts)

  • 1 artist: Chic (with preferences and rider template)
  • 1 tour: "Spring Groove Tour 2026" with 5 gigs across NYC, Chicago, Austin, LA, Miami
  • Dates spread across 18 days (April 10–28, 2026)
  • 2 bookings on first gig: 1 flight (Delta) + 1 hotel (Williamsburg Hotel)
  • 1 draft rider with hospitality, technical, travel, and misc sections

Tests

  • 103 tests covering all 20 acceptance criteria (all passing)
  • Schema column verification, FK enforcement, cascade deletes, seed data validation

Ray Manaloto added 7 commits February 25, 2026 16:42
Add Gherkin feature spec (specs/features/database-schema-drizzle.feature)
covering all 20 acceptance criteria for the database schema.

Add comprehensive test suite (tests/database-schema.test.ts) with 103 tests:
- AC #7: Drizzle ORM and drizzle-kit installation verification
- AC #8-11: Database script existence checks
- AC #12: SQLite .db gitignore verification
- AC #1-5: Schema column and constraint verification via imports
- AC #6: Live in-memory SQLite cascade delete tests
- AC #13-17: Seed data verification against local.db
- AC #18-20: Database client export verification

All tests expected to fail until implementation is complete.
- Add drizzle-orm as dependency to apps/api and root package.json
- Add drizzle-kit as dev dependency to apps/api
- Add drizzle.config.ts targeting SQLite with schema at ./src/db/schema
- Add db:generate, db:migrate, db:studio, db:seed scripts
- Update .gitignore: add *.db-shm, *.db-wal, test-results/
- Remove apps/api/src/db/.gitkeep (replaced by actual db module)
Add schema files under apps/api/src/db/schema/:

- artists.ts: id (uuid), name, email, preferences (json),
  rider_template, created_at, updated_at
- tours.ts: FK → artists (cascade delete), status enum
  (planning/confirmed/in_progress/completed), budget (real), dates
- gigs.ts: FK → tours (cascade delete), state, rider_status enum
  (draft/sent/signed), fee (real), venue/promoter info
- bookings.ts: FK → gigs (cascade delete), type enum (flight/hotel),
  cost, check_in/check_out, details (json)
- riders.ts: FK → gigs (cascade delete, unique constraint on gig_id),
  content (json), status enum (draft/sent/signed)
- index.ts: barrel export of all tables, enums, and types

All foreign keys configured with ON DELETE CASCADE.
Rider gig_id has unique index for one-to-one relationship.
Add apps/api/src/db/index.ts:
- Create Drizzle client using bun:sqlite native driver
- Read DATABASE_URL env var with ./local.db fallback
- Enable WAL mode for better concurrent read performance
- Enable foreign key enforcement (off by default in SQLite)
- Export db client, schema, and DbClient type for route handlers
Add apps/api/src/db/migrate.ts:
- Programmatic migration runner using drizzle-orm/bun-sqlite/migrator
- Enables WAL mode and foreign keys before running migrations
- Reads DATABASE_URL with ./local.db fallback

Add apps/api/drizzle/0000_bouncy_fat_cobra.sql:
- Initial migration with CREATE TABLE for all 5 tables
- Foreign keys with ON DELETE CASCADE properly defined
- Unique index on riders.gig_id
- Generated by drizzle-kit generate from schema definitions
Add apps/api/src/db/seed.ts with:
- 1 artist: 'Chic' with preferences and rider template
- 1 tour: 'Spring Groove Tour 2026' (Apr 10-28, planning status, $15k budget)
- 5 gigs: NYC → Chicago → Austin → LA → Miami (18-day span)
- 2 bookings on first gig: 1 Delta flight ($320) + 1 hotel ($275)
- 1 rider in draft status with hospitality/technical/travel/misc sections

Seed runs migrations first, clears existing data in FK order,
then inserts all sample data. Exports seed() function and
auto-runs when executed directly.
@sortakool sortakool merged commit 0bfc7c3 into main Feb 26, 2026
@sortakool sortakool deleted the feat/database-schema-drizzle branch February 26, 2026 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Database schema with Drizzle ORM, migrations, and seed data

1 participant