From 76c049537814fd988270d6383ea65e79d127da10 Mon Sep 17 00:00:00 2001 From: Viktor Podzigun Date: Mon, 17 Jun 2024 20:10:50 +0200 Subject: [PATCH] Added readBundle --- index.d.mts | 3 +++ index.mjs | 10 ++++++++++ src/bundler.mjs | 6 +++++- src/runner.mjs | 14 ++++++++++++++ test/runner.test.mjs | 38 +++++++++++++++++++++++++++++++++++++- 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/index.d.mts b/index.d.mts index b8caf64..48a31dd 100644 --- a/index.d.mts +++ b/index.d.mts @@ -1,3 +1,4 @@ +import { URL } from "node:url"; import Database from "@farjs/better-sqlite3-wrapper"; export interface MigrationBundleItem { @@ -7,6 +8,8 @@ export interface MigrationBundleItem { export type MigrationBundle = MigrationBundleItem[]; +export function readBundle(url: URL): Promise; + export function runBundle(db: Database, bundle: MigrationBundle): Promise; export function createBundle(args: string[]): Promise; diff --git a/index.mjs b/index.mjs index d421b8d..7112ce1 100644 --- a/index.mjs +++ b/index.mjs @@ -1,8 +1,18 @@ /** + * @typedef {import("node:url").URL} URL * @typedef {import("@farjs/better-sqlite3-wrapper").Database} Database * @typedef {import("./index.mjs").MigrationBundle} MigrationBundle */ +/** + * @param {URL} url + * @returns {Promise} + */ +export async function readBundle(url) { + const { readBundle } = await import("./src/runner.mjs"); + return readBundle(url); +} + /** * @param {Database} db * @param {MigrationBundle} bundle diff --git a/src/bundler.mjs b/src/bundler.mjs index 544a9f3..6ee21ec 100644 --- a/src/bundler.mjs +++ b/src/bundler.mjs @@ -53,7 +53,11 @@ export async function createBundle(args) { }; }); - fs.writeFileSync(migrationsBundle, JSON.stringify(bundleObj, undefined, 2)); + fs.writeFileSync( + migrationsBundle, + JSON.stringify(bundleObj, undefined, 2), + { encoding: "utf8" } + ); console.log(`Generated SQL bundle file: ${migrationsBundle}`); return; } diff --git a/src/runner.mjs b/src/runner.mjs index 1f6bb5b..b4ca8a7 100644 --- a/src/runner.mjs +++ b/src/runner.mjs @@ -1,7 +1,9 @@ /** + * @typedef {import("node:url").URL} URL * @typedef {import("@farjs/better-sqlite3-wrapper").Database} Database * @typedef {import("../index.mjs").MigrationBundle} MigrationBundle */ +import fs from "fs"; import Database from "@farjs/better-sqlite3-wrapper"; /** @@ -16,6 +18,18 @@ const dbTable = "schema_versions"; const versionAndNameRegex = /V(\d+)__(.+).sql/i; const underscoreRegex = /_/g; +/** + * @param {URL} url + * @returns {Promise} + */ +export async function readBundle(url) { + const json = fs.readFileSync(url, { encoding: "utf8" }); + + /** @type {MigrationBundle} */ + const bundle = JSON.parse(json); + return bundle; +} + /** * @param {Database} db * @param {MigrationBundle} bundle diff --git a/test/runner.test.mjs b/test/runner.test.mjs index ba2d17f..572ae82 100644 --- a/test/runner.test.mjs +++ b/test/runner.test.mjs @@ -2,10 +2,11 @@ * @typedef {import("@farjs/better-sqlite3-wrapper").Database} Database * @typedef {import("../index.mjs").MigrationBundleItem} MigrationBundleItem */ +import { URL } from "node:url"; import assert from "node:assert/strict"; import mockFunction from "mock-fn"; import Database from "@farjs/better-sqlite3-wrapper"; -import { runBundle } from "../index.mjs"; +import { readBundle, runBundle } from "../index.mjs"; const { describe, it } = await (async () => { // @ts-ignore @@ -351,6 +352,41 @@ describe("runner.test.mjs", () => { assertSchema(db, [{ version: 1, name: "non-transactional migration" }]); }); + it("should run migrations from bundle.json", async () => { + //given + const db = new Database(":memory:"); + const logs = /** @type {string[]} */ ([]); + const logMock = mockFunction((msg) => { + logs.push(msg); + }); + const savedLog = console.log; + console.log = logMock; + + //when & then + const bundleUrl = new URL("./migrations/bundle.json", import.meta.url); + const bundle = await readBundle(bundleUrl); + + //when + await runBundle(db, bundle); + + //then + console.log = savedLog; + assert.deepEqual(logMock.times, 3); + assert.deepEqual(logs, [ + "DB: migrating to version 1 - initial db structure", + "DB: migrating to version 2 - rename db field", + "DB: 2 migration(s) were applied successfully", + ]); + assertDb(db, [ + { id: 1, name: "test 1" }, + { id: 2, name: "test 2" }, + ]); + assertSchema(db, [ + { version: 1, name: "initial db structure" }, + { version: 2, name: "rename db field" }, + ]); + }); + it("should fail if cannot parse migration version and name", async () => { //given const db = new Database(":memory:");