UNPKG

pg-diff-cli

Version:

PostgreSQL schema and data comparing tool

180 lines (171 loc) 8.4 kB
const chalk = require("chalk"); const figlet = require("figlet"); const path = require("path"); const inquirer = require("@inquirer/prompts"); const log = console.log; const fs = require("fs"); class CLI { /** * Print initial CLI information * @param {Object} pjson The package json */ static PrintIntro(pjson) { log(chalk.yellow(figlet.textSync(pjson.name, { horizontalLayout: "full" }))); log(); log(chalk.blue(" Author: ") + chalk.green(pjson.author)); log(chalk.blue(" Version: ") + chalk.green(pjson.version)); log(chalk.blue(" PostgreSQL: ") + chalk.green(pjson.pgver)); log(chalk.blue(" License: ") + chalk.green(pjson.license)); log(chalk.blue("Description: ") + chalk.green(pjson.description)); log(); } /** * Print help documentation */ static PrintHelp() { log(); log(); log(chalk.magenta("==============================")); log(chalk.magenta("=== pg-diff-cli HELP ===")); log(chalk.magenta("==============================")); log(); log(chalk.gray("OPTION \t\tDESCRIPTION")); log(chalk.green("-h, --help \t\t") + chalk.blue("To show this help.")); log(chalk.green("-c, --compare \t\t") + chalk.blue("To run compare and generate a patch file.")); log(chalk.green("-ms, --migrate-to-source \t\t") + chalk.blue("To run migration applying all missing patch files to SOURCE CLIENT.")); log(chalk.green("-mt, --migrate-to-target \t\t") + chalk.blue("To run migration applying all missing patch files to TARGET CLIENT.")); log( chalk.green("-f, --config-file \t\t") + chalk.blue("To specify where to find config file, otherwise looks for 'pg-diff-config.json' on current working directory.") ); log( chalk.green("-p, --patch-folder \t\t") + chalk.blue("To set patch folder where save\\retrieve patches (it will override configuration).") ); log( chalk.green("-s, --save \t\t") + chalk.blue("To save\\register patch on migration history table without executing the script.") ); log(chalk.green("-g, --generate-config \t\t") + chalk.blue("To generate a new config file.")); log(); log(); log(chalk.gray("TO GENERATE CONFIG FILE: ") + chalk.yellow("pg-diff ") + chalk.gray("-g ") + chalk.cyan("[configuration-file-name]")); log(chalk.gray(" EXAMPLE: ") + chalk.yellow("pg-diff ") + chalk.gray("-g ")); log(chalk.gray(" EXAMPLE: ") + chalk.yellow("pg-diff ") + chalk.gray("-g ") + chalk.cyan("my-config")); log(); log(chalk.gray(" TO COMPARE: ") + chalk.yellow("pg-diff ") + chalk.gray("-c ") + chalk.cyan("configuration-name script-name")); log(chalk.gray(" EXAMPLE: ") + chalk.yellow("pg-diff ") + chalk.gray("-c ") + chalk.cyan("development my-script")); log(); log(chalk.gray(" TO MIGRATE: ") + chalk.yellow("pg-diff ") + chalk.gray("[-ms | -mt] ") + chalk.cyan("configuration-name")); log(chalk.gray(" EXAMPLE: ") + chalk.yellow("pg-diff ") + chalk.gray("-ms ") + chalk.cyan("development")); log(chalk.gray(" EXAMPLE: ") + chalk.yellow("pg-diff ") + chalk.gray("-mt ") + chalk.cyan("development")); log(); log( chalk.gray(" TO REGISTER: ") + chalk.yellow("pg-diff ") + chalk.gray("-s ") + chalk.cyan("configuration-name patch-file-name") ); log( chalk.gray(" EXAMPLE: ") + chalk.yellow("pg-diff ") + chalk.gray("-s ") + chalk.cyan("development 20182808103040999_my-script.sql") ); log(); log(); } /** * Print configuration options * * @param {Object} config The configuration */ static PrintOptions(config) { log(); log(chalk.gray("CONFIGURED OPTIONS")); log(chalk.yellow(" Script Author: ") + chalk.green(config.compareOptions.author)); log(chalk.yellow(" Output Directory: ") + chalk.green(path.resolve(process.cwd(), config.compareOptions.outputDirectory))); let schemasMessage = config.compareOptions.schemaCompare.namespaces && config.compareOptions.schemaCompare.namespaces.length ? config.compareOptions.schemaCompare.namespaces : "will be retrieve dynamically from database"; log(chalk.yellow(" Schema Namespaces: ") + chalk.green(schemasMessage)); log(chalk.yellow(" Data Compare: ") + chalk.green(config.compareOptions.dataCompare.enable ? "ENABLED" : "DISABLED")); log(); } static async GenerateConfig(filename = "pg-diff-config") { const configName = await inquirer.input({ message: "Type a name for this configuration:", required: true, }); const patchesFolderName = await inquirer.input({ message: "Type the patches folder name:", default: "db_migration", required: true }); let configGenerated = {}; configGenerated[configName] = { sourceClient: { host: await inquirer.input({ message: "Type the SOURCE host name:", default: "localhost", required: true }), port: await inquirer.number({ message: "Type the SOURCE port number:", default: 5432, required: true }), database: await inquirer.input({ message: "Type the SOURCE database name:", required: true }), user: await inquirer.input({ message: "Type the SOURCE username:", default: "postgres", required: true }), password: await inquirer.password({ message: "Type the SOURCE password:", required: true, mask: true }), applicationName: await inquirer.input({ message: "Type the SOURCE application name:", default: "pg-diff-cli", required: true }), ssl: await inquirer.confirm({ message: "Does connection to SOURCE require SSL?", required: true }), }, targetClient: { host: await inquirer.input({ message: "Type the TARGET host name:", default: "localhost", required: true }), port: await inquirer.number({ message: "Type the TARGET port number:", default: 5432, required: true }), database: await inquirer.input({ message: "Type the TARGET database name:", required: true }), user: await inquirer.input({ message: "Type the TARGET username:", default: "postgres", required: true }), password: await inquirer.password({ message: "Type the TARGET password:", required: true, mask: true }), applicationName: await inquirer.input({ message: "Type the TARGET application name:", default: "pg-diff-cli", required: true }), ssl: await inquirer.confirm({ message: "Does connection to TARGET require SSL?", required: true }), }, compareOptions: { author: await inquirer.input({ message: "Type the author of sql patches:" }), getAuthorFromGit: await inquirer.confirm({ message: "Do you like to get the author from GIT user?" }), outputDirectory: patchesFolderName, schemaCompare: { namespaces: [], dropMissingTable: await inquirer.confirm({ message: "Do you want to enable DROP TABLE when exists on TARGET only?", required: true, }), dropMissingView: await inquirer.confirm({ message: "Do you want to enable DROP VIEW when exists on TARGET only?", required: true, }), dropMissingFunction: await inquirer.confirm({ message: "Do you want to enable DROP FUNCTION when exists on TARGET only?", required: true, }), dropMissingAggregate: await inquirer.confirm({ message: "Do you want to enable DROP AGGREGATE when exists on TARGET only?", required: true, }), roles: [], }, dataCompare: { enable: await inquirer.confirm({ message: "Do you want to enable data compare?", required: true }), tables: [ { tableName: "my_table_example", tableSchema: "public", tableKeyFields: ["id"], }, ], }, }, migrationOptions: { patchesDirectory: patchesFolderName, historyTableName: await inquirer.input({ message: "Type the table name will persist the patches applied:", default: "migrations", required: true, }), historyTableSchema: await inquirer.input({ message: "Type the schema name for the table will persist the patches applied:", default: "public", required: true, }), }, }; fs.writeFileSync(`${filename}.json`, JSON.stringify(configGenerated, null, 4), "utf-8"); } } module.exports.CLI = CLI;