Initial commit
This commit is contained in:
269
templates/DATABASE_SCHEMA.md
Normal file
269
templates/DATABASE_SCHEMA.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# Database Schema: [Project Name]
|
||||
|
||||
**Database**: Cloudflare D1 (SQLite)
|
||||
**Migrations**: `migrations/` directory
|
||||
**ORM**: [Drizzle ORM / Raw SQL / None]
|
||||
**Schema Version**: 1.0
|
||||
**Last Updated**: [Date]
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This document defines the complete database schema including tables, relationships, indexes, and migrations.
|
||||
|
||||
**Design Principles**:
|
||||
- Normalize data to reduce redundancy
|
||||
- Index frequently queried columns
|
||||
- Use foreign keys for referential integrity
|
||||
- Include timestamps for audit trail
|
||||
- Use INTEGER for IDs (SQLite auto-increment)
|
||||
- Use TEXT for strings (SQLite doesn't enforce varchar limits)
|
||||
- Use INTEGER for booleans (0 = false, 1 = true)
|
||||
- Use INTEGER for timestamps (Unix epoch)
|
||||
|
||||
---
|
||||
|
||||
## Tables
|
||||
|
||||
### `users`
|
||||
**Purpose**: User accounts and authentication data
|
||||
|
||||
| Column | Type | Constraints | Default | Notes |
|
||||
|--------|------|-------------|---------|-------|
|
||||
| `id` | INTEGER | PRIMARY KEY | AUTO | Auto-increment |
|
||||
| `email` | TEXT | UNIQUE, NOT NULL | - | Login identifier |
|
||||
| `clerk_id` | TEXT | UNIQUE, NOT NULL | - | Clerk user ID |
|
||||
| `display_name` | TEXT | NULL | - | User's display name |
|
||||
| `avatar_url` | TEXT | NULL | - | Profile picture URL (R2) |
|
||||
| `created_at` | INTEGER | NOT NULL | - | Unix timestamp |
|
||||
| `updated_at` | INTEGER | NOT NULL | - | Unix timestamp |
|
||||
|
||||
**Indexes**:
|
||||
- `idx_users_email` on `email` (for login lookups)
|
||||
- `idx_users_clerk_id` on `clerk_id` (for auth verification)
|
||||
|
||||
**Relationships**:
|
||||
- One-to-many with `[related_table]`
|
||||
|
||||
**Notes**:
|
||||
- `clerk_id` comes from Clerk authentication
|
||||
- `avatar_url` points to R2 storage if user uploads custom avatar
|
||||
- Emails are unique and used for account identification
|
||||
|
||||
---
|
||||
|
||||
### `[table_name]`
|
||||
**Purpose**: [Description of what this table stores]
|
||||
|
||||
| Column | Type | Constraints | Default | Notes |
|
||||
|--------|------|-------------|---------|-------|
|
||||
| `id` | INTEGER | PRIMARY KEY | AUTO | Auto-increment |
|
||||
| `user_id` | INTEGER | FOREIGN KEY, NOT NULL | - | References `users(id)` |
|
||||
| `[field]` | [TYPE] | [CONSTRAINTS] | [DEFAULT] | [Notes] |
|
||||
| `created_at` | INTEGER | NOT NULL | - | Unix timestamp |
|
||||
| `updated_at` | INTEGER | NOT NULL | - | Unix timestamp |
|
||||
|
||||
**Indexes**:
|
||||
- `idx_[table]_user_id` on `user_id` (for user-specific queries)
|
||||
- `idx_[table]_[field]` on `[field]` (if frequently queried)
|
||||
|
||||
**Relationships**:
|
||||
- Many-to-one with `users`
|
||||
- [Other relationships]
|
||||
|
||||
**Notes**:
|
||||
- [Important details about this table]
|
||||
|
||||
---
|
||||
|
||||
### `[junction_table]` (for many-to-many relationships)
|
||||
**Purpose**: Links [table_a] and [table_b] in many-to-many relationship
|
||||
|
||||
| Column | Type | Constraints | Default | Notes |
|
||||
|--------|------|-------------|---------|-------|
|
||||
| `id` | INTEGER | PRIMARY KEY | AUTO | Auto-increment |
|
||||
| `[table_a]_id` | INTEGER | FOREIGN KEY, NOT NULL | - | References `[table_a](id)` |
|
||||
| `[table_b]_id` | INTEGER | FOREIGN KEY, NOT NULL | - | References `[table_b](id)` |
|
||||
| `created_at` | INTEGER | NOT NULL | - | Unix timestamp |
|
||||
|
||||
**Indexes**:
|
||||
- `idx_[junction]_[table_a]_id` on `[table_a]_id`
|
||||
- `idx_[junction]_[table_b]_id` on `[table_b]_id`
|
||||
- `idx_[junction]_composite` on `([table_a]_id, [table_b]_id)` UNIQUE
|
||||
|
||||
**Relationships**:
|
||||
- Many-to-one with `[table_a]`
|
||||
- Many-to-one with `[table_b]`
|
||||
|
||||
**Notes**:
|
||||
- Composite unique index prevents duplicate associations
|
||||
|
||||
---
|
||||
|
||||
## Relationships Diagram
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ users │
|
||||
└──────┬──────┘
|
||||
│ 1
|
||||
│
|
||||
│ N
|
||||
┌──────┴──────────┐
|
||||
│ [child_table] │
|
||||
└─────────────────┘
|
||||
|
||||
[Add more relationships as needed]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migrations
|
||||
|
||||
### Migration 0001: Initial Schema
|
||||
**File**: `migrations/0001_initial_schema.sql`
|
||||
**Created**: [Date]
|
||||
**Purpose**: Create initial tables for [core entities]
|
||||
|
||||
**Creates**:
|
||||
- `users` table
|
||||
- `[other_tables]` tables
|
||||
|
||||
**Indexes**:
|
||||
- All primary indexes for frequently queried columns
|
||||
|
||||
**Run**:
|
||||
```bash
|
||||
npx wrangler d1 execute [DB_NAME] --local --file=migrations/0001_initial_schema.sql
|
||||
npx wrangler d1 execute [DB_NAME] --remote --file=migrations/0001_initial_schema.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Migration 0002: [Description]
|
||||
**File**: `migrations/0002_[name].sql`
|
||||
**Created**: [Date]
|
||||
**Purpose**: [What this migration does]
|
||||
|
||||
**Changes**:
|
||||
- Add `[column]` to `[table]`
|
||||
- Create `[new_table]` table
|
||||
- Add index `[index_name]`
|
||||
|
||||
**Run**:
|
||||
```bash
|
||||
npx wrangler d1 execute [DB_NAME] --local --file=migrations/0002_[name].sql
|
||||
npx wrangler d1 execute [DB_NAME] --remote --file=migrations/0002_[name].sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Seed Data
|
||||
|
||||
For development and testing, seed the database with sample data.
|
||||
|
||||
**File**: `migrations/seed.sql` (run manually, not in production)
|
||||
|
||||
**Sample Data**:
|
||||
- 3-5 test users
|
||||
- [Other sample data relevant to testing]
|
||||
|
||||
**Run**:
|
||||
```bash
|
||||
npx wrangler d1 execute [DB_NAME] --local --file=migrations/seed.sql
|
||||
```
|
||||
|
||||
**Sample Users**:
|
||||
```sql
|
||||
INSERT INTO users (email, clerk_id, display_name, created_at, updated_at)
|
||||
VALUES
|
||||
('test1@example.com', 'clerk_test_1', 'Test User 1', strftime('%s', 'now'), strftime('%s', 'now')),
|
||||
('test2@example.com', 'clerk_test_2', 'Test User 2', strftime('%s', 'now'), strftime('%s', 'now')),
|
||||
('test3@example.com', 'clerk_test_3', 'Test User 3', strftime('%s', 'now'), strftime('%s', 'now'));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Query Patterns
|
||||
|
||||
### Common Queries
|
||||
|
||||
**Get user by email**:
|
||||
```sql
|
||||
SELECT * FROM users WHERE email = ?;
|
||||
```
|
||||
|
||||
**Get all [items] for a user**:
|
||||
```sql
|
||||
SELECT * FROM [table] WHERE user_id = ? ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
**Get [item] with related data**:
|
||||
```sql
|
||||
SELECT
|
||||
[table].*,
|
||||
users.display_name,
|
||||
users.avatar_url
|
||||
FROM [table]
|
||||
JOIN users ON [table].user_id = users.id
|
||||
WHERE [table].id = ?;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Constraints and Validation
|
||||
|
||||
### Enforced at Database Level
|
||||
- Primary keys (unique, not null)
|
||||
- Foreign keys (referential integrity)
|
||||
- Unique constraints (email, composite indexes)
|
||||
- Not null constraints (required fields)
|
||||
|
||||
### Enforced at Application Level (Zod)
|
||||
- Email format validation
|
||||
- String length limits
|
||||
- Enum values
|
||||
- Complex business logic
|
||||
|
||||
**Why split?**: Database enforces data integrity, application provides user-friendly error messages.
|
||||
|
||||
---
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
### Export Database
|
||||
```bash
|
||||
npx wrangler d1 export [DB_NAME] --local --output=backup.sql
|
||||
npx wrangler d1 export [DB_NAME] --remote --output=backup.sql
|
||||
```
|
||||
|
||||
### Import Database
|
||||
```bash
|
||||
npx wrangler d1 execute [DB_NAME] --local --file=backup.sql
|
||||
npx wrangler d1 execute [DB_NAME] --remote --file=backup.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
**Indexes**: All frequently queried columns are indexed
|
||||
**Query Optimization**: Use `EXPLAIN QUERY PLAN` to check query performance
|
||||
**Pagination**: Use `LIMIT` and `OFFSET` for large result sets
|
||||
**Caching**: Consider Workers KV for frequently accessed, rarely changed data
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential schema changes to consider:
|
||||
- [ ] [Feature requiring schema change]
|
||||
- [ ] [Another potential enhancement]
|
||||
|
||||
---
|
||||
|
||||
## Revision History
|
||||
|
||||
**v1.0** ([Date]): Initial schema design
|
||||
**v1.1** ([Date]): [Changes made]
|
||||
Reference in New Issue
Block a user