X-Git-Url: http://git.squeep.com/?p=squeep-indie-auther;a=blobdiff_plain;f=src%2Fdb%2Fschema-version-helper.js;fp=src%2Fdb%2Fschema-version-helper.js;h=65a1e39f2c3cb64ceea5483f9dabf5606b35d736;hp=0000000000000000000000000000000000000000;hb=b0103b0d496262c438b40bc20304081dbfe41e73;hpb=8ed81748bce7cea7904cac7225b20a60cafdfc16 diff --git a/src/db/schema-version-helper.js b/src/db/schema-version-helper.js new file mode 100644 index 0000000..65a1e39 --- /dev/null +++ b/src/db/schema-version-helper.js @@ -0,0 +1,131 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +/** + * Utility functions for wrangling schema migrations. + * This mostly just deals with sorting and comparing 'x.y.z' version + * strings, with some presumptions about directory layouts and whatnot. + */ + +/** + * @typedef {Object} SchemaVersionObject + * @property {Number} major + * @property {Number} minor + * @property {Number} patch + */ + + +/** + * Split a dotted version string into parts. + * @param {String} v + * @returns {SchemaVersionObject} + */ +function schemaVersionStringToObject(v) { + const [ major, minor, patch ] = v.split('.', 3).map((x) => parseInt(x, 10)); + return { major, minor, patch }; +} + + +/** + * Render a version object numerically. + * @param {SchemaVersionObject} v + * @returns {Number} + */ +function schemaVersionObjectToNumber(v) { + const vScale = 1000; + return parseInt(v.major) * vScale * vScale + parseInt(v.minor) * vScale + parseInt(v.patch); +} + + +/** + * Convert dotted version string into number. + * @param {String} v + * @returns {Number} + */ +function schemaVersionStringToNumber(v) { + return schemaVersionObjectToNumber(schemaVersionStringToObject(v)); +} + + +/** + * Version string comparison, for sorting. + * @param {String} a + * @param {String} b + * @returns {Number} + */ +function schemaVersionStringCmp(a, b) { + return schemaVersionStringToNumber(a) - schemaVersionStringToNumber(b); +} + + +/** + * Check if an entry in a directory is a directory containing a migration file. + * @param {String} schemaDir + * @param {String} name + * @returns {Boolean} + */ +function isSchemaMigrationDirectory(schemaDir, name, migrationFile = 'apply.sql') { + // eslint-disable-next-line security/detect-non-literal-fs-filename + const nameStat = fs.statSync(path.join(schemaDir, name)); + if (nameStat.isDirectory()) { + let applyStat; + try { + // eslint-disable-next-line security/detect-non-literal-fs-filename + applyStat = fs.statSync(path.join(schemaDir, name, migrationFile)); + return applyStat.isFile(); + } catch (e) { + return false; + } + } + return false; +} + + +/** + * Return an array of schema migration directory names within engineDir, + * sorted in increasing order. + * @param {String} engineDir + * @returns {String[]} + */ +function allSchemaVersions(engineDir) { + const schemaDir = path.join(engineDir, 'sql', 'schema'); + // eslint-disable-next-line security/detect-non-literal-fs-filename + const availableVersions = fs.readdirSync(schemaDir).filter((d) => isSchemaMigrationDirectory(schemaDir, d)); + availableVersions.sort(schemaVersionStringCmp); + return availableVersions; +} + + +/** + * Return an array of schema migration directory names within engineDir, + * which are within supported range, and are greater than the current + * @param {String} engineDir + * @param {SchemaVersionObject} current + * @param {Object} supported + * @param {SchemaVersionObject} supported.min + * @param {SchemaVersionObject} supported.max + * @returns {String[]} + */ +function unappliedSchemaVersions(engineDir, current, supported) { + const min = schemaVersionObjectToNumber(supported.min); + const max = schemaVersionObjectToNumber(supported.max); + const cur = schemaVersionObjectToNumber(current); + const available = allSchemaVersions(engineDir); + return available.filter((a) => { + a = schemaVersionStringToNumber(a); + return a >= min && a <= max && a > cur; + }); +} + + +module.exports = { + schemaVersionStringToObject, + schemaVersionObjectToNumber, + schemaVersionStringToNumber, + schemaVersionStringCmp, + isSchemaMigrationDirectory, + allSchemaVersions, + unappliedSchemaVersions, +}; \ No newline at end of file