Loading db schema

This commit is contained in:
micialware committed 2026-09-13 18:55:12 +03:00
1 parent 4646dad2b8
commit 68c24dcec5
3 files changed
+231

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
// Числовые даты в БД JapLearn. Никаких TEXT/DATE-типов: всё — числа.
//
// Два формата:
// 1. «Дата-только» — число дней от 1970-01-01 (UTC).
// Поля: states.fsrs_opened, states.fsrs_open_day.
// Помощники: dateToEpochDay / epochDayToIso / isoToEpochDay.
// 2. Полный таймстамп — миллисекунды от 1970-01-01 (эпоха Unix, UTC).
// Поля: history.timestamp, states.last_opened.
// Помощники: dateToEpochMs / epochMsToIso / isoToEpochMs.
// (Предположение о единице измерения — см. ниже.)
/** Миллисекунд в одних сутках (UTC). */
export const DAY_MS = 86_400_000;
// ---------------------------------------------------------------------------
// Формат «дата-только»: число дней от 1970-01-01.
// ---------------------------------------------------------------------------
/** Количество дней от 1970-01-01 (UTC) до указанной даты. */
export function dateToEpochDay(date: Date): number {
return Math.floor(date.getTime() / DAY_MS);
}
/** Дата (полночь UTC) по номеру дня от 1970-01-01. */
export function epochDayToDate(day: number): Date {
return new Date(day * DAY_MS);
}
/** ISO-формат 'YYYY-MM-DD' по номеру дня от 1970-01-01. */
export function epochDayToIso(day: number): string {
return epochDayToDate(day).toISOString().slice(0, 10);
}
/** Номер дня от 1970-01-01 по ISO-дате 'YYYY-MM-DD'. */
export function isoToEpochDay(iso: string): number {
return Math.floor(Date.parse(`${iso}T00:00:00Z`) / DAY_MS);
}
// ---------------------------------------------------------------------------
// Полный таймстамп: миллисекунды от 1970-01-01.
//
// ВАЖНО: единица измерения не зафиксирована в схеме. Здесь приняты
// миллисекунды (нативный формат JS Date). Если десктопная версия хранит
// секунды — поправить достаточно в одном месте (умножение на 1000).
// ---------------------------------------------------------------------------
/** Таймстамп (мс) для даты. */
export function dateToEpochMs(date: Date): number {
return date.getTime();
}
/** Дата по таймстампу (мс). */
export function epochMsToDate(ms: number): Date {
return new Date(ms);
}
/** ISO-строка (UTC) по таймстампу (мс). */
export function epochMsToIso(ms: number): string {
return epochMsToDate(ms).toISOString();
}
/** Таймстамп (мс) по ISO-строке. */
export function isoToEpochMs(iso: string): number {
return Date.parse(iso);
}
+86
View File
@@ -0,0 +1,86 @@
-- Схема базы данных JapLearn.
-- Источник истины: /dbschema.sql (корень проекта).
-- Здесь та же схема, но идемпотентная (CREATE TABLE IF NOT EXISTS),
-- чтобы выполнять её при инициализации БД без ошибок на уже готовой базе.
-- Все даты и таймстампы — числа. Поля-«даты» (fsrs_opened, fsrs_open_day)
-- хранят число дней от 1970-01-01 (UTC), остальные — таймстампы.
create table if not exists custom_fields
(
id integer
primary key,
name text not null,
identifier text not null
);
create table if not exists decks
(
id INTEGER
primary key autoincrement,
name TEXT not null,
forward TEXT not null,
backward TEXT not null,
filter TEXT not null
);
create table if not exists settings
(
id text
primary key,
value text
);
create table if not exists word_groups
(
id INTEGER
primary key autoincrement,
name TEXT not null
);
create table if not exists words
(
id INTEGER
primary key autoincrement,
key TEXT not null,
value TEXT not null,
tags TEXT not null,
more TEXT,
group_id integer default 1 not null
constraint words_word_group_id_fk
references word_groups
on update cascade on delete cascade
);
create table if not exists history
(
id INTEGER
primary key autoincrement,
deck_id INTEGER not null
references decks
on delete cascade,
word_id INTEGER not null
references words
on delete cascade,
timestamp INTEGER not null,
answer INTEGER not null,
before INTEGER not null,
after INTEGER not null,
fsrs INTEGER not null
);
create table if not exists states
(
id INTEGER
primary key autoincrement,
word_id INTEGER not null
references words
on delete cascade,
deck_id INTEGER
references decks
on delete cascade,
score INTEGER default 1 not null,
last_opened integer not null,
fsrs_opened integer not null,
fsrs_memory integer not null,
fsrs_open_day integer not null
);