first commit
This commit is contained in:
commit
0e1ce93def
12 files changed
+1693
No files matched your search
+19
@@ -0,0 +1,19 @@
|
||||
// Creates tachyon.db (if it doesn't exist) and applies schema.sql.
|
||||
// Safe to re-run: every statement uses CREATE TABLE IF NOT EXISTS.
|
||||
import Database from 'better-sqlite3';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const dbPath = path.join(__dirname, 'tachyon.db');
|
||||
const schemaPath = path.join(__dirname, 'schema.sql');
|
||||
|
||||
const db = new Database(dbPath);
|
||||
db.pragma('journal_mode = WAL');
|
||||
|
||||
const schema = readFileSync(schemaPath, 'utf8');
|
||||
db.exec(schema);
|
||||
|
||||
console.log(`Initialized database at ${dbPath}`);
|
||||
db.close();
|
||||
@@ -0,0 +1,52 @@
|
||||
-- TACHYON site schema
|
||||
-- SQLite. Timestamps stored as ISO-8601 strings (TEXT), sorted lexically = chronologically.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS news_posts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS media_items (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
media_type TEXT NOT NULL CHECK (media_type IN ('image', 'video')),
|
||||
url TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||
);
|
||||
|
||||
-- Registered/tracked users (distinct from "who is currently online" -- see sessions below)
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
joined_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||
last_seen_at TEXT
|
||||
);
|
||||
|
||||
-- One row per active session; presence of a row (or non-null ended_at) drives "current users"
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||
ended_at TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS activity_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
description TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||
);
|
||||
|
||||
-- Freeform key/value store for the "General Statistics" cards (build number, version, etc.)
|
||||
CREATE TABLE IF NOT EXISTS site_stats (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_news_created_at ON news_posts(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_created_at ON media_items(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_created_at ON activity_log(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_active ON sessions(ended_at);
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Populates the DB with placeholder rows so the API has something to return
|
||||
// immediately. Re-runnable: clears each table before inserting.
|
||||
import Database from 'better-sqlite3';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const db = new Database(path.join(__dirname, 'tachyon.db'));
|
||||
|
||||
db.exec(`
|
||||
DELETE FROM sessions;
|
||||
DELETE FROM users;
|
||||
DELETE FROM news_posts;
|
||||
DELETE FROM media_items;
|
||||
DELETE FROM activity_log;
|
||||
DELETE FROM site_stats;
|
||||
`);
|
||||
|
||||
const insertNews = db.prepare(
|
||||
'INSERT INTO news_posts (title, content, created_at) VALUES (?, ?, ?)'
|
||||
);
|
||||
insertNews.run('Placeholder announcement title', 'Short placeholder line describing an update or change.', '2026-07-06T12:00:00.000Z');
|
||||
insertNews.run('Placeholder announcement title', 'Short placeholder line describing an update or change.', '2026-07-02T12:00:00.000Z');
|
||||
insertNews.run('Placeholder announcement title', 'Short placeholder line describing an update or change.', '2026-06-27T12:00:00.000Z');
|
||||
|
||||
const insertMedia = db.prepare(
|
||||
'INSERT INTO media_items (title, media_type, url) VALUES (?, ?, ?)'
|
||||
);
|
||||
insertMedia.run('placeholder clip one', 'image', 'https://example.com/media/1.png');
|
||||
insertMedia.run('placeholder clip two', 'image', 'https://example.com/media/2.png');
|
||||
insertMedia.run('placeholder clip three', 'video', 'https://example.com/media/3.mp4');
|
||||
insertMedia.run('placeholder clip four', 'image', 'https://example.com/media/4.png');
|
||||
|
||||
const insertUser = db.prepare(
|
||||
'INSERT INTO users (username, joined_at, last_seen_at) VALUES (?, ?, ?)'
|
||||
);
|
||||
const u1 = insertUser.run('placeholder_user_01', '2025-01-10T00:00:00.000Z', '2026-07-08T18:00:00.000Z');
|
||||
const u2 = insertUser.run('placeholder_user_02', '2025-03-22T00:00:00.000Z', '2026-07-08T17:45:00.000Z');
|
||||
const u3 = insertUser.run('placeholder_user_03', '2025-05-01T00:00:00.000Z', '2026-07-08T17:30:00.000Z');
|
||||
|
||||
const insertSession = db.prepare(
|
||||
'INSERT INTO sessions (user_id, started_at) VALUES (?, ?)'
|
||||
);
|
||||
// open sessions (no ended_at) = "currently online" for the Current Users column
|
||||
insertSession.run(u1.lastInsertRowid, '2026-07-08T18:00:00.000Z');
|
||||
insertSession.run(u2.lastInsertRowid, '2026-07-08T17:45:00.000Z');
|
||||
insertSession.run(u3.lastInsertRowid, '2026-07-08T17:30:00.000Z');
|
||||
|
||||
const insertActivity = db.prepare(
|
||||
'INSERT INTO activity_log (description, created_at) VALUES (?, ?)'
|
||||
);
|
||||
insertActivity.run('placeholder event one', '2026-07-08T17:00:00.000Z');
|
||||
insertActivity.run('placeholder event two', '2026-07-08T15:00:00.000Z');
|
||||
insertActivity.run('placeholder event three', '2026-07-08T13:00:00.000Z');
|
||||
insertActivity.run('placeholder event four', '2026-07-08T09:00:00.000Z');
|
||||
|
||||
const upsertStat = db.prepare(
|
||||
'INSERT INTO site_stats (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = strftime(\'%Y-%m-%dT%H:%M:%fZ\', \'now\')'
|
||||
);
|
||||
upsertStat.run('build_pipeline', 'Completed');
|
||||
upsertStat.run('build_number', '00000000');
|
||||
upsertStat.run('version', '0.0.0');
|
||||
upsertStat.run('reports_named', '00');
|
||||
upsertStat.run('reports_associated', '00');
|
||||
upsertStat.run('reports_logged', '00');
|
||||
|
||||
console.log('Seeded placeholder data.');
|
||||
db.close();
|
||||
Reference in new issue
Block a user