feat(middleware): add SQLite DB init with WAL mode, FK support, and 9-table migration
- src/db/index.ts: initDb/getDb/closeDb using node-sqlite3-wasm (pure WASM, no VS build required) - src/db/migrations/001-initial.ts: creates all 9 tables with FK constraints and CHECK constraints - tests/db.test.ts: 10 tests verifying WAL mode, FK cascade, all table columns, and constraint enforcement - Switched from better-sqlite3 (requires Visual Studio on Windows) to node-sqlite3-wasm Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { Database } from 'node-sqlite3-wasm';
|
||||
|
||||
export function migrate001(db: Database): void {
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS mqtt_brokers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
host TEXT NOT NULL,
|
||||
port INTEGER DEFAULT 1883,
|
||||
username TEXT,
|
||||
password TEXT,
|
||||
use_tls INTEGER DEFAULT 0,
|
||||
enabled INTEGER DEFAULT 1,
|
||||
status TEXT DEFAULT 'disconnected',
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS mqtt_topics (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
broker_id INTEGER NOT NULL,
|
||||
topic TEXT NOT NULL,
|
||||
json_path TEXT,
|
||||
selected INTEGER DEFAULT 0,
|
||||
ignored INTEGER DEFAULT 0,
|
||||
last_payload TEXT,
|
||||
discovered_at TEXT DEFAULT (datetime('now')),
|
||||
FOREIGN KEY (broker_id) REFERENCES mqtt_brokers(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pg_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
host TEXT NOT NULL,
|
||||
port INTEGER DEFAULT 5432,
|
||||
database_name TEXT NOT NULL,
|
||||
username TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
use_tls INTEGER DEFAULT 0,
|
||||
enabled INTEGER DEFAULT 1,
|
||||
status TEXT DEFAULT 'disconnected',
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pg_queries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
query TEXT NOT NULL,
|
||||
interval_sec INTEGER DEFAULT 60,
|
||||
result_column TEXT NOT NULL,
|
||||
last_result TEXT,
|
||||
last_run_at TEXT,
|
||||
FOREIGN KEY (source_id) REFERENCES pg_sources(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS datapoints (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
label TEXT NOT NULL,
|
||||
unit TEXT,
|
||||
value TEXT,
|
||||
status TEXT DEFAULT 'unknown',
|
||||
source_type TEXT NOT NULL CHECK(source_type IN ('mqtt','postgresql')),
|
||||
source_id INTEGER NOT NULL,
|
||||
topic_id INTEGER,
|
||||
query_id INTEGER,
|
||||
transform TEXT,
|
||||
enabled INTEGER DEFAULT 1,
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
FOREIGN KEY (topic_id) REFERENCES mqtt_topics(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (query_id) REFERENCES pg_queries(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS layouts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT DEFAULT 'free' CHECK(type IN ('free','grid')),
|
||||
width INTEGER DEFAULT 800,
|
||||
height INTEGER DEFAULT 480,
|
||||
grid_cols INTEGER,
|
||||
grid_rows INTEGER,
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS layout_elements (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
layout_id INTEGER NOT NULL,
|
||||
datapoint_id INTEGER,
|
||||
type TEXT NOT NULL CHECK(type IN ('value','label','line','rect')),
|
||||
x INTEGER NOT NULL DEFAULT 0,
|
||||
y INTEGER NOT NULL DEFAULT 0,
|
||||
width INTEGER,
|
||||
height INTEGER,
|
||||
font_size INTEGER DEFAULT 24,
|
||||
font_weight TEXT DEFAULT 'normal',
|
||||
text_align TEXT DEFAULT 'left',
|
||||
icon TEXT,
|
||||
style TEXT DEFAULT 'plain' CHECK(style IN ('plain','card')),
|
||||
static_text TEXT,
|
||||
grid_col INTEGER,
|
||||
grid_row INTEGER,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (layout_id) REFERENCES layouts(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (datapoint_id) REFERENCES datapoints(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS displays (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
layout_id INTEGER,
|
||||
api_token TEXT,
|
||||
last_seen TEXT,
|
||||
refresh_sec INTEGER DEFAULT 300,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
FOREIGN KEY (layout_id) REFERENCES layouts(id) ON DELETE SET NULL
|
||||
);
|
||||
`);
|
||||
}
|
||||
Reference in New Issue
Block a user