You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

5.1 KiB

Phase 2: Database (Drizzle ORM)

Status: Todo Progress: 0/12 tasks (0%) Started: - Completed: - Assigned to: -


Overview

Setup Drizzle ORM, define complete database schema for all tables (users, products, carts, cart_items, orders, order_items), generate and apply migrations, and create database utilities.

Goal: Fully functional database with all MVP tables ready for use.


Dependencies

  • Phase 1: Foundation must be completed
  • PostgreSQL running in Docker (docker-compose.dev.yml)

Tasks

Drizzle Setup

  • Install Drizzle ORM & PostgreSQL driver

    pnpm add drizzle-orm postgres
    pnpm add -D drizzle-kit
    
  • Configure drizzle.config.ts

    import { defineConfig } from 'drizzle-kit'
    
    export default defineConfig({
      schema: './server/database/schema.ts',
      out: './server/database/migrations',
      dialect: 'postgresql',
      dbCredentials: {
        url: process.env.DATABASE_URL!,
      },
    })
    
  • Add database scripts to package.json

    {
      "scripts": {
        "db:generate": "drizzle-kit generate",
        "db:migrate": "drizzle-kit migrate",
        "db:studio": "drizzle-kit studio",
        "db:push": "drizzle-kit push"
      }
    }
    

Schema Definition

  • Create users table schema

    • File: server/database/schema.ts
    • Fields: id (UUID), experimenta_id (unique), email, first_name, last_name, salutation, date_of_birth, street, post_code, city, country_code, phone, created_at, updated_at
    • See: ARCHITECTURE.md Section 4.1
  • Create products table schema

    • Fields: id (UUID), nav_product_id (unique), name, description, price (decimal), stock_quantity, category, active, created_at, updated_at
    • Indexes: nav_product_id, active, category
  • Create carts table schema

    • Fields: id (UUID), user_id (FK to users, nullable), session_id, created_at, updated_at
    • Relations: hasMany cart_items
  • Create cart_items table schema

    • Fields: id (UUID), cart_id (FK to carts), product_id (FK to products), quantity, added_at
    • Relations: belongsTo cart, belongsTo product
  • Create orders table schema

    • Fields: id (UUID), order_number (unique), user_id (FK to users), total_amount, status, billing_address (JSON), payment_id, payment_completed_at, created_at, updated_at
    • Relations: hasMany order_items
    • Indexes: order_number, user_id, status
  • Create order_items table schema

    • Fields: id (UUID), order_id (FK to orders), product_id (FK to products), product_snapshot (JSON), quantity, price_snapshot, created_at
    • Relations: belongsTo order, belongsTo product

Migrations

  • Generate initial migration

    pnpm db:generate
    
    • Verify migration files in server/database/migrations/
  • Apply migrations to dev database

    pnpm db:migrate
    
    • Verify tables exist in PostgreSQL
    docker exec -it experimenta-db-dev psql -U dev -d experimenta_dev -c "\dt"
    

Database Utilities

  • Create database connection utility

    • File: server/utils/db.ts
    import { drizzle } from 'drizzle-orm/postgres-js'
    import postgres from 'postgres'
    import * as schema from '../database/schema'
    
    const config = useRuntimeConfig()
    const client = postgres(config.databaseUrl)
    export const db = drizzle(client, { schema })
    
  • Test CRUD operations

    • Create test endpoint: server/api/test/db.get.ts
    • Test insert, select, update, delete on users table
    • Verify relations work (e.g., fetch cart with items)
    • Remove test endpoint after verification

Tools

  • Setup Drizzle Studio

    pnpm db:studio
    
  • Document schema decisions

    • Add comments to schema.ts explaining design choices
    • Document why JSONB for billing_address
    • Document why UUID vs serial IDs

Acceptance Criteria

  • Drizzle ORM is installed and configured
  • All 6 tables are defined in schema.ts (users, products, carts, cart_items, orders, order_items)
  • Relations between tables are defined correctly
  • Initial migration is generated and applied
  • All tables exist in PostgreSQL database
  • Database connection utility (db.ts) is working
  • CRUD operations work as expected
  • Drizzle Studio can connect and display tables
  • Schema is documented with comments

Notes

  • UUID vs Serial: Using UUIDs for better distributed systems support and security
  • JSONB for billing_address: Flexible address storage, avoids complex normalized address tables
  • Decimal for prices: Using decimal(10,2) for accurate money calculations
  • created_at/updated_at: Timestamps for audit trail

Blockers

  • None currently