diff options
Diffstat (limited to 'src/db.mjs')
-rw-r--r-- | src/db.mjs | 87 |
1 files changed, 48 insertions, 39 deletions
@@ -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); }; |