import { getConfig, setConfig } from "./mod.js"; import * as M from "../migrations.js"; import * as util from "../util.js"; import { EmVer } from "../emver-lite/mod.js"; import { Config } from "../config/mod.js"; /** * @param fn function making desired modifications to the config * @param configured whether or not the service should be considered "configured" * @param noRepeat (optional) supply the version and type of the migration * @param noFail (optional, default:false) whether or not to fail the migration if fn throws an error * @returns a migraion function */ export function updateConfig(fn, configured, noRepeat, noFail = false) { return M.migrationFn(async (effects) => { await noRepeatGuard(effects, noRepeat, async () => { let config = util.unwrapResultType(await getConfig(Config.of({}))(effects)).config; if (config) { try { config = await fn(config, effects); } catch (e) { if (!noFail) { throw e; } else { configured = false; } } util.unwrapResultType(await setConfig(effects, config)); } }); return { configured }; }); } export async function noRepeatGuard(effects, noRepeat, fn) { if (!noRepeat) { return fn(); } if (!(await util.exists(effects, { path: "start9/migrations", volumeId: "main", }))) { await effects.createDir({ path: "start9/migrations", volumeId: "main" }); } const migrationPath = { path: `start9/migrations/${noRepeat.version}.complete`, volumeId: "main", }; if (noRepeat.type === "up") { if (!(await util.exists(effects, migrationPath))) { await fn(); await effects.writeFile({ ...migrationPath, toWrite: "" }); } } else if (noRepeat.type === "down") { if (await util.exists(effects, migrationPath)) { await fn(); await effects.removeFile(migrationPath); } } } export async function initNoRepeat(effects, migrations, startingVersion) { if (!(await util.exists(effects, { path: "start9/migrations", volumeId: "main", }))) { const starting = EmVer.parse(startingVersion); await effects.createDir({ path: "start9/migrations", volumeId: "main" }); for (const version in migrations) { const migrationVersion = EmVer.parse(version); if (migrationVersion.lessThanOrEqual(starting)) { await effects.writeFile({ path: `start9/migrations/${version}.complete`, volumeId: "main", toWrite: "", }); } } } } export function fromMapping(migrations, currentVersion) { const inner = M.fromMapping(migrations, currentVersion); return async (effects, version, direction) => { await initNoRepeat(effects, migrations, direction === "from" ? version : currentVersion); return inner(effects, version, direction); }; }