@golemio/cli
Version:
Collection of executables intended for use with Golemio services and modules
208 lines • 9.94 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.printSummaryMatrix = exports.printCommandHelp = exports.getPostgresMigrateInstances = exports.readLockfile = exports.getDefaultModulePgSchemas = exports.runCommandShim = void 0;
const cross_spawn_1 = require("cross-spawn");
const db_migrate_1 = __importDefault(require("db-migrate"));
const fs_1 = __importDefault(require("fs"));
const gluegun_1 = require("gluegun");
const promises_1 = require("node:fs/promises");
const path_1 = __importDefault(require("path"));
const pg_connection_string_1 = require("pg-connection-string");
const DEFAULT_MODULE_PG_SCHEMA_PLACEHOLDER = "$DEFAULT_MODULE_PG_SCHEMA";
const SUPPORTED_LOCKFILE_VERSIONS = [3];
/**
* Run command shim (node_modules/.bin/)
*/
const runCommandShim = (binaryName, command) => {
const chProcess = (0, cross_spawn_1.spawn)(binaryName, [binaryName === "yarn" ? "run" : "exec", ...command.split(" ")], { stdio: "inherit" });
return new Promise((resolve, reject) => {
chProcess.on("error", reject);
chProcess.on("exit", (code) => (code === 0 ? resolve() : reject("Command exited with non-zero code")));
});
};
exports.runCommandShim = runCommandShim;
async function getDefaultModulePgSchemas(migrationDirs) {
const defaultModulePgSchemas = new Map();
const promises = migrationDirs.map(getDefaultModulePgSchema);
const results = await Promise.all(promises);
for (const res of results) {
if (res === null)
continue;
defaultModulePgSchemas.set(res.modulePath, res.schema);
}
return defaultModulePgSchemas;
}
exports.getDefaultModulePgSchemas = getDefaultModulePgSchemas;
async function getDefaultModulePgSchema(migrationDir) {
const migrationConfigLocation = path_1.default.resolve(migrationDir, ".config.json");
if (!fs_1.default.existsSync(migrationConfigLocation)) {
gluegun_1.print.warning(`Local config ${migrationConfigLocation} not found.`);
return null;
}
const dbmConfig = JSON.parse(await (0, promises_1.readFile)(migrationConfigLocation, "utf-8"));
if (!dbmConfig.isSchemaModuleDefault)
return null;
const modulePath = getModulePathFromAnyPath(migrationDir);
return { modulePath, schema: dbmConfig.schema };
}
function getModulePathFromAnyPath(path) {
const matches = [...path.matchAll(/.*?(node_modules\/(?:@.+?\/.+?|.+?))\//g)];
if (matches.length === 0)
return "";
const lastMatch = matches.at(-1);
if (typeof lastMatch.at(-1) !== "string")
throw new Error("Invalid match");
return lastMatch.at(1);
}
function readLockfile() {
if (fs_1.default.existsSync("./package-lock.json")) {
return JSON.parse(fs_1.default.readFileSync("./package-lock.json", "utf-8"));
}
if (fs_1.default.existsSync("./npm-shrinkwrap.json")) {
return JSON.parse(fs_1.default.readFileSync("./npm-shrinkwrap.json", "utf-8"));
}
throw new Error("No lockfile data provided. Check if the service image contains valid package-lock");
}
exports.readLockfile = readLockfile;
/**
* Create and return new db-migrate instances
*/
function getPostgresMigrateInstances({ connectionString, migrationDir, defaultModulePgSchemas, defaultSchema, includeLocalConfig, lockfileData, }) {
// Default config
let dbmConfig = { schema: "public" };
const migrationConfigLocation = path_1.default.resolve(migrationDir, ".config.json");
if (includeLocalConfig) {
if (fs_1.default.existsSync(migrationConfigLocation)) {
dbmConfig = Object.assign(Object.assign({}, dbmConfig), JSON.parse(fs_1.default.readFileSync(migrationConfigLocation).toString("utf8")));
}
else {
gluegun_1.print.warning(`Local config ${migrationConfigLocation} not found. ` +
`Using the default configuration\n${JSON.stringify(dbmConfig, null, 4)}`);
}
}
if (typeof defaultSchema === "string") {
dbmConfig.schema = defaultSchema;
}
const schemas = [];
if (dbmConfig.schema.includes(DEFAULT_MODULE_PG_SCHEMA_PLACEHOLDER) && lockfileData) {
if (!defaultModulePgSchemas) {
throw new Error("Default module schemas required for placeholder");
}
const modulePath = getModulePathFromAnyPath(migrationDir);
const dependantsPaths = getModuleDependants(lockfileData, modulePath);
for (const dependant of dependantsPaths) {
if (!defaultModulePgSchemas.has(dependant))
continue;
const schema = defaultModulePgSchemas.get(dependant);
schemas.push(dbmConfig.schema.replace(DEFAULT_MODULE_PG_SCHEMA_PLACEHOLDER, schema));
}
}
else {
schemas.push(dbmConfig.schema);
}
if ("isSchemaModuleDefault" in dbmConfig) {
const { isSchemaModuleDefault } = dbmConfig, rest = __rest(dbmConfig, ["isSchemaModuleDefault"]);
dbmConfig = rest;
}
const { user, password, host, database, port, ssl } = (0, pg_connection_string_1.parse)(connectionString);
const migrations = schemas.map((schema) => {
var _a;
return db_migrate_1.default.getInstance(true, {
config: {
postgres: Object.assign(Object.assign({}, dbmConfig), { schema, driver: "pg", user,
password,
host,
database, port: (_a = port === null || port === void 0 ? void 0 : port.toString()) !== null && _a !== void 0 ? _a : "5432", ssl: !!ssl }),
},
cmdOptions: {
"migrations-dir": migrationDir,
"sql-file": true,
},
env: "postgres",
});
});
return {
migrations,
schemas,
createLocalConfig: () => {
if (!fs_1.default.existsSync(migrationConfigLocation)) {
fs_1.default.writeFileSync(migrationConfigLocation, JSON.stringify(dbmConfig, null, 4));
gluegun_1.print.info("[INFO] Created local config at " + migrationConfigLocation);
}
},
};
}
exports.getPostgresMigrateInstances = getPostgresMigrateInstances;
function getModuleDependants(lockfileData, modulePath) {
var _a, _b, _c, _d;
if (!SUPPORTED_LOCKFILE_VERSIONS.includes(lockfileData.lockfileVersion)) {
throw new Error(`Unsupported lockfile version "${lockfileData.lockfileVersion}"`);
}
if (!lockfileData.packages)
return [];
const moduleName = modulePath.replace("node_modules/", "");
const dependantPkgs = [];
for (const pkgPath of Object.keys(lockfileData.packages)) {
const pkg = lockfileData.packages[pkgPath];
const allDependencies = Object.assign(Object.assign(Object.assign(Object.assign({}, ((_a = pkg.dependencies) !== null && _a !== void 0 ? _a : {})), ((_b = pkg.devDependencies) !== null && _b !== void 0 ? _b : {})), ((_c = pkg.peerDependencies) !== null && _c !== void 0 ? _c : {})), ((_d = pkg.optionalDependencies) !== null && _d !== void 0 ? _d : {}));
if (Object.keys(allDependencies).includes(moduleName)) {
dependantPkgs.push(pkgPath);
}
}
return dependantPkgs;
}
/**
* Print command help for migrate-db
*/
const printCommandHelp = () => {
gluegun_1.print.info(gluegun_1.print.colors.blue("\ngolemio migrate-db (mdb)"));
gluegun_1.print.info(" Commands\n");
gluegun_1.print.info(" create <name>\t\t Create new migration");
gluegun_1.print.info(" up\t\t\t Execute up migrations");
gluegun_1.print.info(" down\t\t\t Execute down migrations");
gluegun_1.print.info(" reset\t\t\t Reset all executed migrations");
gluegun_1.print.info(" help (h)\t\t -");
gluegun_1.print.info("\n Flags\n");
gluegun_1.print.info(" --postgres\t\t Set database to PostgreSQL (default)");
gluegun_1.print.info(" --path\t\t Set path to migration director(y/ies) (default db/migrations/postgresql)");
gluegun_1.print.info(" --schema <name>\t Set database schema (postgres only)");
gluegun_1.print.info(" --silent\t\t Ignore database driver stdout (postgres only)");
};
exports.printCommandHelp = printCommandHelp;
/**
* Transform command results and print summary matrix
*/
const printSummaryMatrix = (results) => {
const summaryMatrix = results.map(([dir, schema, isSuccess, info]) => {
var _a;
const migrationsPath = path_1.default.relative(process.cwd(), dir);
const isModule = migrationsPath.startsWith("node_modules");
return [
isModule ? `Module: ${(_a = migrationsPath.match(/node_modules\/([^\/]*\/[^\/]*)/s)) === null || _a === void 0 ? void 0 : _a[1]}` : `Path: ${migrationsPath}`,
schema.replaceAll(/(,| )+(public)/g, ""),
isSuccess ? gluegun_1.print.colors.green("Success") : gluegun_1.print.colors.red("Fail"),
info !== null && info !== void 0 ? info : "\uD83E\uDD73",
];
});
gluegun_1.print.info(gluegun_1.print.colors.blue("\nSummary"));
gluegun_1.print.table([["Location", "Schema", "Result", "Info"], ...summaryMatrix], {
format: "lean",
style: { "padding-left": 0, "padding-right": 8 },
});
};
exports.printSummaryMatrix = printSummaryMatrix;
//# sourceMappingURL=migrate-db.utils.js.map