we-superapp / apps /api /src /core /db.js
nenbuj
Initial deploy: «МЫ» супер-апп
c562e21
Raw History Blame Contribute Delete
3.21 kB
// Ядро: база данных + миграции. Ведёт Claude.
// Кодекс импортирует { db } и работает через него (API: prepare().get/run/all, exec).
// Используется встроенный node:sqlite (Node >= 22.5), нативная сборка не нужна.
import { DatabaseSync } from 'node:sqlite';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
export const db = new DatabaseSync(join(__dirname, '../../data.sqlite'));
db.exec('PRAGMA journal_mode = WAL');
db.exec('PRAGMA foreign_keys = ON');
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE, -- null для Telegram-юзеров
password_hash TEXT, -- null для Telegram-юзеров
telegram_id INTEGER UNIQUE, -- null для email-юзеров
name TEXT NOT NULL,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS spaces (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('couple','family','friends','flat')),
owner_id TEXT NOT NULL REFERENCES users(id),
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS space_members (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL REFERENCES spaces(id),
user_id TEXT NOT NULL REFERENCES users(id),
role TEXT NOT NULL CHECK (role IN ('owner','member')),
joined_at INTEGER NOT NULL,
UNIQUE (space_id, user_id)
);
CREATE TABLE IF NOT EXISTS transactions (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL REFERENCES spaces(id),
author_id TEXT NOT NULL REFERENCES users(id),
title TEXT NOT NULL,
amount INTEGER NOT NULL CHECK (amount > 0),
paid_by TEXT NOT NULL REFERENCES users(id),
split TEXT NOT NULL,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL REFERENCES spaces(id),
title TEXT NOT NULL,
assignee_id TEXT REFERENCES users(id),
done INTEGER NOT NULL DEFAULT 0,
due_at INTEGER,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS posts (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL REFERENCES spaces(id),
author_id TEXT NOT NULL REFERENCES users(id),
text TEXT NOT NULL,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS events (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL REFERENCES spaces(id),
title TEXT NOT NULL,
start_at INTEGER NOT NULL,
created_at INTEGER NOT NULL
);
`);
// Миграция: БД, созданные до появления telegram_id, не имеют этой колонки
// (CREATE TABLE IF NOT EXISTS существующую таблицу не меняет). Добавляем на лету.
const userColumns = db.prepare('PRAGMA table_info(users)').all();
if (!userColumns.some((c) => c.name === 'telegram_id')) {
db.exec('ALTER TABLE users ADD COLUMN telegram_id INTEGER');
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_users_telegram_id ON users(telegram_id)');
}