UNPKG

@golemio/cli

Version:

Collection of executables intended for use with Golemio services and modules

208 lines 9.94 kB
"use strict"; 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