2025-05-31 23:10:25 +02:00
|
|
|
import { readFile, unlink, writeFile } from "node:fs/promises";
|
2025-03-05 18:41:47 +01:00
|
|
|
import { Schedule } from "~/shared/types/schedule";
|
2025-06-09 16:51:05 +02:00
|
|
|
import { Account, Subscription } from "~/shared/types/account";
|
2025-03-07 12:41:57 +01:00
|
|
|
import { generateDemoSchedule, generateDemoAccounts } from "./generate-demo-schedule";
|
2025-03-05 18:41:47 +01:00
|
|
|
|
2025-06-09 16:51:05 +02:00
|
|
|
export interface ServerSession {
|
|
|
|
id: number,
|
|
|
|
accountId: number,
|
|
|
|
};
|
|
|
|
|
2025-03-05 18:41:47 +01:00
|
|
|
// For this demo I'm just storing the runtime data in JSON files. When making
|
|
|
|
// this into proper application this should be replaced with an actual database.
|
|
|
|
|
2025-03-07 12:25:10 +01:00
|
|
|
const schedulePath = "data/schedule.json";
|
|
|
|
const subscriptionsPath = "data/subscriptions.json";
|
2025-03-07 12:41:57 +01:00
|
|
|
const accountsPath = "data/accounts.json";
|
2025-03-07 23:53:57 +01:00
|
|
|
const nextAccountIdPath = "data/next-account-id.json";
|
2025-03-07 12:41:57 +01:00
|
|
|
const sessionsPath = "data/sessions.json";
|
|
|
|
const nextSessionIdPath = "data/next-session-id.json";
|
2025-03-05 18:41:47 +01:00
|
|
|
|
2025-05-31 23:10:25 +02:00
|
|
|
async function remove(path: string) {
|
|
|
|
try {
|
|
|
|
await unlink(path);
|
|
|
|
} catch (err: any) {
|
|
|
|
if (err.code !== "ENOENT") {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function deleteDatbase() {
|
|
|
|
await remove(schedulePath);
|
|
|
|
await remove(subscriptionsPath);
|
|
|
|
await remove(accountsPath);
|
|
|
|
await remove(sessionsPath);
|
|
|
|
}
|
|
|
|
|
2025-03-07 12:25:10 +01:00
|
|
|
async function readJson<T>(filePath: string, fallback: T) {
|
|
|
|
let data: T extends () => infer R ? R : T;
|
2025-03-05 18:41:47 +01:00
|
|
|
try {
|
2025-03-07 12:25:10 +01:00
|
|
|
data = JSON.parse(await readFile(filePath, "utf-8"));
|
2025-03-05 18:41:47 +01:00
|
|
|
} catch (err: any) {
|
|
|
|
if (err.code !== "ENOENT")
|
|
|
|
throw err;
|
2025-03-07 12:25:10 +01:00
|
|
|
data = typeof fallback === "function" ? fallback() : fallback;
|
2025-03-05 18:41:47 +01:00
|
|
|
}
|
2025-03-07 12:25:10 +01:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function readSchedule() {
|
|
|
|
return readJson(schedulePath, generateDemoSchedule);
|
2025-03-05 18:41:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function writeSchedule(schedule: Schedule) {
|
|
|
|
await writeFile(schedulePath, JSON.stringify(schedule, undefined, "\t") + "\n", "utf-8");
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function readSubscriptions() {
|
2025-03-07 12:30:39 +01:00
|
|
|
let subscriptions = await readJson<Subscription[]>(subscriptionsPath, []);
|
|
|
|
if (subscriptions.length && "keys" in subscriptions[0]) {
|
|
|
|
// Discard old format
|
|
|
|
subscriptions = [];
|
|
|
|
}
|
2025-03-07 12:25:10 +01:00
|
|
|
return subscriptions;
|
2025-03-05 18:41:47 +01:00
|
|
|
}
|
|
|
|
|
2025-03-07 12:30:39 +01:00
|
|
|
export async function writeSubscriptions(subscriptions: Subscription[]) {
|
2025-03-05 18:41:47 +01:00
|
|
|
await writeFile(subscriptionsPath, JSON.stringify(subscriptions, undefined, "\t") + "\n", "utf-8");
|
|
|
|
}
|
2025-03-07 12:41:57 +01:00
|
|
|
|
2025-03-07 23:53:57 +01:00
|
|
|
export async function nextAccountId() {
|
|
|
|
let nextId = await readJson(nextAccountIdPath, 0);
|
|
|
|
if (nextId === 0) {
|
|
|
|
nextId = Math.max(...(await readAccounts()).map(account => account.id), -1) + 1;
|
|
|
|
}
|
|
|
|
await writeFile(nextAccountIdPath, String(nextId + 1), "utf-8");
|
|
|
|
return nextId;
|
|
|
|
}
|
|
|
|
|
2025-03-07 12:41:57 +01:00
|
|
|
export async function readAccounts() {
|
|
|
|
return await readJson(accountsPath, generateDemoAccounts);
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function writeAccounts(accounts: Account[]) {
|
|
|
|
await writeFile(accountsPath, JSON.stringify(accounts, undefined, "\t") + "\n", "utf-8");
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function nextSessionId() {
|
|
|
|
const nextId = await readJson(nextSessionIdPath, 0);
|
|
|
|
await writeFile(nextSessionIdPath, String(nextId + 1), "utf-8");
|
|
|
|
return nextId;
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function readSessions() {
|
2025-06-09 16:51:05 +02:00
|
|
|
return await readJson<ServerSession[]>(sessionsPath, []);
|
2025-03-07 12:41:57 +01:00
|
|
|
}
|
|
|
|
|
2025-06-09 16:51:05 +02:00
|
|
|
export async function writeSessions(sessions: ServerSession[]) {
|
2025-03-07 12:41:57 +01:00
|
|
|
await writeFile(sessionsPath, JSON.stringify(sessions, undefined, "\t") + "\n", "utf-8");
|
|
|
|
}
|