Skip to content

Database Schema

Skema database yang digunakan di project ini.

🗄️ Entity Relationship Diagram

┌─────────────────┐       ┌─────────────────┐       ┌─────────────────┐
│      users      │       │    sessions     │       │  posts          │
├─────────────────┤       ├─────────────────┤       ├─────────────────┤
│ id (PK)         │◄──────│ user_id (FK)    │       │ id (PK)         │
│ email (unique)  │       │ id (PK)         │       │ title           │
│ name            │       │ expires_at      │       │ content         │
│ bio             │       └─────────────────┘       │ published       │
│ location        │                                 │ author_id (FK)  │──┐
│ website         │                                 │ created_at      │  │
│ password_hash   │                                 └─────────────────┘  │
│ provider        │                                                    │
│ google_id       │       ┌─────────────────────────┐                   │
│ avatar          │       │ password_reset_tokens   │                   │
│ email_verified  │       ├─────────────────────────┤                   │
│ created_at      │       │ id (PK)                 │                   │
│ updated_at      │       │ user_id (FK)            │◄──────────────────┘
└─────────────────┘       │ token_hash              │
                          │ expires_at              │
                          │ used                    │
                          │ created_at              │
                          └─────────────────────────┘

┌─────────────────────────────┐
│ email_verification_tokens   │
├─────────────────────────────┤
│ id (PK)                     │
│ user_id (FK)                │
│ token_hash                  │
│ expires_at                  │
│ used                        │
│ created_at                  │
└─────────────────────────────┘

📋 Table Details

users

Tabel utama untuk menyimpan data user.

sql
CREATE TABLE users (
  id TEXT PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  name TEXT NOT NULL,
  bio TEXT,
  location TEXT,
  website TEXT,
  password_hash TEXT,
  provider TEXT DEFAULT 'email',
  google_id TEXT,
  avatar TEXT,
  email_verified BOOLEAN DEFAULT FALSE,
  created_at INTEGER DEFAULT (unixepoch()),
  updated_at INTEGER DEFAULT (unixepoch())
);
ColumnTypeDescription
idTEXTUUID primary key
emailTEXTUnique email address
nameTEXTFull name
bioTEXTUser bio/description
locationTEXTUser location
websiteTEXTPersonal website URL
password_hashTEXTHashed password (null untuk OAuth)
providerTEXT'email' atau 'google'
google_idTEXTGoogle OAuth ID
avatarTEXTAvatar URL
email_verifiedBOOLEANEmail verification status
created_atINTEGERTimestamp creation
updated_atINTEGERTimestamp last update

sessions

Tabel session untuk authentication (Lucia Auth).

sql
CREATE TABLE sessions (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  expires_at INTEGER NOT NULL
);

password_reset_tokens

Tabel untuk password reset functionality.

sql
CREATE TABLE password_reset_tokens (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  token_hash TEXT NOT NULL,
  expires_at INTEGER NOT NULL,
  used BOOLEAN DEFAULT FALSE,
  created_at INTEGER DEFAULT (unixepoch())
);

email_verification_tokens

Tabel untuk email verification.

sql
CREATE TABLE email_verification_tokens (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  token_hash TEXT NOT NULL,
  expires_at INTEGER NOT NULL,
  used BOOLEAN DEFAULT FALSE,
  created_at INTEGER DEFAULT (unixepoch())
);

posts

Tabel contoh untuk posts/articles.

sql
CREATE TABLE posts (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  published BOOLEAN DEFAULT FALSE,
  author_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  created_at INTEGER DEFAULT (unixepoch())
);

🔗 Relations

One-to-Many Relations

users ||--o{ sessions : has
users ||--o{ posts : writes
users ||--o{ password_reset_tokens : has
users ||--o{ email_verification_tokens : has

📊 Indexes

sql
-- Users
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_google_id ON users(google_id);

-- Sessions
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_expires ON sessions(expires_at);

-- Tokens
CREATE INDEX idx_reset_tokens_user ON password_reset_tokens(user_id);
CREATE INDEX idx_verify_tokens_user ON email_verification_tokens(user_id);

-- Posts
CREATE INDEX idx_posts_author ON posts(author_id);
CREATE INDEX idx_posts_published ON posts(published);

📝 Drizzle Schema Definition

Contoh definisi schema di Drizzle ORM:

typescript
// src/lib/db/schema.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';

export const users = sqliteTable('users', {
  id: text('id').primaryKey(),
  email: text('email').notNull().unique(),
  name: text('name').notNull(),
  bio: text('bio'),
  location: text('location'),
  website: text('website'),
  passwordHash: text('password_hash'),
  provider: text('provider', { enum: ['email', 'google'] }).default('email'),
  googleId: text('google_id'),
  avatar: text('avatar'),
  emailVerified: integer('email_verified', { mode: 'boolean' }).default(false),
  createdAt: integer('created_at', { mode: 'number' })
    .$defaultFn(() => Date.now()),
  updatedAt: integer('updated_at', { mode: 'number' })
    .$defaultFn(() => Date.now()),
});

📖 Resources

SvelteKit Cloudflare Starter - Build Fast, Deploy Everywhere 🚀