af1a8e4bed
- Next.js 15 + TypeScript + Tailwind, standalone output - SQLite schema: users, clients, projects, quotes, quote_items - HMAC-signed sessie-cookie auth - Dockerfile (Node 22 Alpine, multi-stage) - create-admin script - Doel: portal.rikxplatform.nl Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
75 lines
2.2 KiB
TypeScript
75 lines
2.2 KiB
TypeScript
import { DatabaseSync } from "node:sqlite";
|
|
import path from "path";
|
|
|
|
const DB_PATH =
|
|
process.env.DB_PATH || path.join(process.cwd(), "data", "app.db");
|
|
|
|
let _db: DatabaseSync | null = null;
|
|
|
|
export function getDb(): DatabaseSync {
|
|
if (!_db) {
|
|
_db = new DatabaseSync(DB_PATH);
|
|
_db.exec("PRAGMA journal_mode = WAL");
|
|
_db.exec("PRAGMA foreign_keys = ON");
|
|
migrate(_db);
|
|
}
|
|
return _db;
|
|
}
|
|
|
|
function migrate(db: DatabaseSync) {
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
email TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'admin',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS clients (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
email TEXT,
|
|
phone TEXT,
|
|
address TEXT,
|
|
notes TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS projects (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
client_id INTEGER NOT NULL REFERENCES clients(id),
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quotes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
project_id INTEGER NOT NULL REFERENCES projects(id),
|
|
title TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
notes TEXT,
|
|
sent_at TEXT,
|
|
accepted_at TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quote_items (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
quote_id INTEGER NOT NULL REFERENCES quotes(id) ON DELETE CASCADE,
|
|
description TEXT NOT NULL,
|
|
quantity REAL NOT NULL DEFAULT 1,
|
|
unit TEXT,
|
|
unit_price REAL NOT NULL DEFAULT 0,
|
|
total REAL GENERATED ALWAYS AS (quantity * unit_price) VIRTUAL,
|
|
sort_order INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
`);
|
|
}
|