summaryrefslogtreecommitdiff
path: root/src/db.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'src/db.mjs')
-rw-r--r--src/db.mjs87
1 files changed, 48 insertions, 39 deletions
diff --git a/src/db.mjs b/src/db.mjs
index 59d6a0e..fdfd899 100644
--- a/src/db.mjs
+++ b/src/db.mjs
@@ -3,47 +3,56 @@ import fs from "node:fs";
import path from "node:path";
import url from "node:url";
-import { difference, log } from "./utils.mjs";
+import sqlite from "./sqlite.cjs";
+import { runMigrations } from "./accretion.mjs";
-const DIRNAME = path.dirname(url.fileURLToPath(import.meta.url));
-const MIGRATIONS_DIR = DIRNAME + "/sql/migrations/";
-const MIGRATION_FILENAMES = fs.readdirSync(MIGRATIONS_DIR, "UTF-8");
-let db = null;
+export const promisify = nativeFn => (...args) =>
+ new Promise((resolve, reject) =>
+ nativeFn(...args, (err, data) => err ? reject(err) : resolve(data)));
+
+export const promisifyDb = dbHandle => ({
+ ref: dbHandle,
+ all: promisify((...args) => dbHandle.all(...args)),
+ exec: promisify((...args) => dbHandle.exec(...args)),
+ run: promisify((...args) => dbHandle.run(...args)),
+ each: (...args) =>
+ new Promise((resolve, reject) => {
+ const cb = args[args.length - 1];
+ dbHandle.each(
+ ...args.slice(0, args.length - 1),
+ (err, row) => err ? reject(err) : cb(row),
+ (err, data) => err ? reject(err) : resolve(data),
+ );
+ }),
+ prepare: (...args) =>
+ new Promise((resolve, reject) => {
+ const mkStmt = stmtRef => ({
+ ref: stmtRef,
+ run: promisify((...args) => stmtRef.run(...args)),
+ finalize: promisify((...args) => stmtRef.finalize(...args)),
+ });
+ const ref = dbHandle.prepare(
+ ...args,
+ err => err ? reject(err) : resolve(mkStmt(ref)),
+ );
+ }),
+});
+
+export const open = (...args) =>
+ new Promise((resolve, reject) => {
+ const dbName = args[0];
+ assert(dbName);
+ const ref = promisifyDb(new sqlite.Database(
+ ...args,
+ err => err ? reject(err) : resolve(ref),
+ ));
+ });
+
+export let db = null;
+
export const init = async (dbName = process.env.PAPO_DB_PATH || ":memory:") => {
- assert(dbName);
-
- db = await sqlite.open(dbName);
- await db.exec(`
- BEGIN TRANSACTION;
- CREATE TABLE IF NOT EXISTS migrations (
- filename TEXT PRIMARY KEY
- );
- COMMIT TRANSACTION;
- `);
-
- const done = await db.all(`
- SELECT filename FROM migrations;
- `).map(row => row.filename);
- const pending = difference(
- new Set(MIGRATION_FILENAMES),
- new Set(done)
- );
- const sortedPending = [...pending].sort((a, b) => a.localeCompare(b));
-
- await db.exec("BEGIN TRANSACTION;");
- for (const filename of sortedPending) {
- log({
- log: "exec-migration",
- filename,
- });
- const sql = fs.readFileSync(MIGRATIONS_DIR + filename, "UTF-8");
- await db.exec(sql);
- await db.run(
- `INSERT INTO migrations (filename) VALUES ($filename);`,
- { filename },
- );
- }
- await db.exec("COMMIT TRANSACTION;");
+ db = await open(dbName);
+ await runMigrations(db);
};