DocsSection 5
5Section 5 of 10

Database Layer

Database Layer

5.1 Connection Pattern

Single connection, shared across requests:

// lib/db/index.ts
import Database from 'better-sqlite3';

let db: Database | null = null;

export function getDatabase(): Database {
  if (!db) {
    db = new Database('database/maediia.db');
    db.pragma('journal_mode = WAL');  // Better concurrency
  }
  return db;
}

5.2 Query Pattern

Parameterized queries (prevents SQL injection):

// BAD - SQL injection risk
const query = `SELECT * FROM clients WHERE email = '${email}'`;

// GOOD - Parameterized
const stmt = db.prepare('SELECT * FROM clients WHERE email = ?');
const client = stmt.get(email);

5.3 Query Organization

Split by domain:

// lib/db/client-queries.ts
export const ClientQueries = {
  getById: (id: string) => { ... },
  getByEmail: (email: string) => { ... },
  create: (data: InsertClient) => { ... },
  update: (id: string, data: UpdateClient) => { ... },
  delete: (id: string) => { ... },
  list: (options: ListOptions) => { ... },
};

// lib/db/admin-queries.ts
export const AdminQueries = {
  getDashboardStats: () => { ... },
  getRevenueByMonth: () => { ... },
  // ...
};

5.4 Transactions

For multi-step operations:

export function transferService(clientId: string, newPlan: string) {
  const db = getDatabase();
  
  // Start transaction
  const transaction = db.transaction(() => {
    // Step 1: Update client
    const updateClient = db.prepare('UPDATE clients SET plan = ? WHERE id = ?');
    updateClient.run(newPlan, clientId);
    
    // Step 2: Create invoice
    const createInvoice = db.prepare('INSERT INTO invoices ...');
    createInvoice.run(...);
    
    // Step 3: Log activity
    const logActivity = db.prepare('INSERT INTO audit_logs ...');
    logActivity.run(...);
    
    // All succeed or all fail
  });
  
  transaction();
}