UNPKG

@adinsure-ops/ops-cli

Version:

Operations CLI for working with AdInsure

340 lines (339 loc) 15.3 kB
import { __awaiter } from "tslib"; import { Args, Flags } from '@oclif/core'; import axios from 'axios'; import chalk from 'chalk'; import fs from 'fs-extra'; import inquirer from 'inquirer'; import _ from 'lodash'; import path from 'path'; import semver from 'semver'; import CommandBase from '../command.base.js'; import { capitalizeFirstLetter } from '../lib/helper.js'; class Sql extends CommandBase { constructor() { super(...arguments); // eslint-disable-next-line @typescript-eslint/no-explicit-any this._moduleTypes = { acc: 'Accounting', claims: 'Claims', core: 'Core', pas: 'PAS', reins: 'Reinsurance', shared: 'Shared', }; this._dbmsTypes = [ { name: 'sql', scriptLocation: undefined, extendGenerator: this.sqlExtendScriptGeneration }, { name: 'oradc', scriptLocation: undefined, extendGenerator: this.oradcExtendScriptGeneration }, { name: 'postgres', scriptLocation: undefined, extendGenerator: this.postgresExtendScriptGeneration } ]; } /** * Get unique Script ID zip by specified version * @param {string} version The version of Identity Server * @returns {Promise<AxiosResponse<any, any>>} */ // eslint-disable-next-line @typescript-eslint/no-explicit-any getScriptId(version) { return __awaiter(this, void 0, void 0, function* () { return axios.get(`https://ops.adinsure.com/api/script/next?version=${version}`, { headers: { Authorization: 'Bearer ' + (yield this.security.getToken()), }, }); }); } /** * Get unique scriptID by specified version * @param {string} version Specified version * @param {string} description Description * @returns {Promise<string>} Promise to scriptID */ getOfflineScriptId(version, description) { return __awaiter(this, void 0, void 0, function* () { const prefix = '8.50'; const date = new Date(); const timestamp = date.getUTCFullYear() + ('0' + (date.getUTCMonth() + 1)).slice(-2) + ('0' + (date.getUTCDate())).slice(-2) + ('0' + (date.getUTCHours())).slice(-2) + ('0' + (date.getUTCMinutes())).slice(-2) + ('0' + (date.getUTCSeconds())).slice(-2); const versionSplit = version.split('.'); let scriptId = prefix + '_' + ('00' + versionSplit[0]).slice(-3) + '.' + ('00' + versionSplit[1]).slice(-3) + '.' + ('00' + versionSplit[2]).slice(-3) + '_' + timestamp; if (description) { scriptId = scriptId + '_' + _.snakeCase(description).slice(0, 100); } return scriptId; }); } handleLayer(scriptDbmsFolder, scriptLayer, scriptType, dbmsFormat) { return __awaiter(this, void 0, void 0, function* () { const scriptFolder = path.resolve(scriptDbmsFolder, scriptLayer, scriptType); const layerFolder = path.resolve(scriptDbmsFolder, scriptLayer); if (!(yield fs.pathExists(layerFolder))) { let layers = ''; // printout only layer folders for (const layer of fs.readdirSync(scriptDbmsFolder)) { if (layer.toLowerCase() !== 'schema' && layer.toLowerCase() !== 'data') { layers = layers + '\n' + layer; } } if (layers.length > 0) { this.log(`Layer ${scriptLayer} for ${dbmsFormat} does not exist, did you mean: ${layers}`); } else { this.log(`Layer ${scriptLayer} for ${dbmsFormat} does not exist.`); } } return scriptFolder; }); } sqlExtendScriptGeneration(tableSchema, tableName, columnName, columnType) { return __awaiter(this, void 0, void 0, function* () { return `if exists (select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = '${tableSchema}' and TABLE_NAME = '${tableName}') begin if not exists (select * from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = '${tableSchema}' and TABLE_NAME = '${tableName}' and COLUMN_NAME = '${columnName}') begin alter table ${tableSchema}.${tableName} add ${columnName} ${columnType}; end end`; }); } oradcExtendScriptGeneration(tableSchema, tableName, columnName, columnType) { return __awaiter(this, void 0, void 0, function* () { return `DECLARE v_column_exists number := 0; v_table_exists number := 0; BEGIN Select count(*) into v_table_exists from ALL_TAB_COLS where upper(OWNER) = '${tableSchema}' and upper(table_name) = '${tableName}'; if (v_table_exists > 0) then select count(*) into v_column_exists from ALL_TAB_COLS where upper(OWNER) = ${tableSchema} and upper(table_name) = '${tableName}'; and upper(column_name) = '${columnName}' if (v_column_exists = 0) then execute immediate alter table ${tableSchema}.${tableName} add ${columnName} ${columnType}; end if; end if; end;`; }); } postgresExtendScriptGeneration(tableSchema, tableName, columnName, columnType) { return __awaiter(this, void 0, void 0, function* () { return `ALTER TABLE IF EXISTS ${tableSchema}.${tableName} ADD COLUMN IF NOT EXISTS ${columnName} ${columnType}; `; }); } checkExtendParameters() { return __awaiter(this, void 0, void 0, function* () { const { flags } = yield this.parse(Sql); const arrayOfParameters = []; if (flags['table-schema'] === undefined) { arrayOfParameters.push('table-schema'); } if (flags['table-name'] === undefined) { arrayOfParameters.push('table-name'); } if (flags['column-name'] === undefined) { arrayOfParameters.push('column-name'); } if (flags['column-type'] === undefined) { arrayOfParameters.push('column-type'); } return arrayOfParameters; }); } // eslint-disable-next-line complexity run() { const _super = Object.create(null, { run: { get: () => super.run } }); return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; _super.run.call(this); const { args, flags } = yield this.parse(Sql); const fullVersion = (_a = flags.version) !== null && _a !== void 0 ? _a : yield this.getVersion('SQL_SCRIPTS_VERSION', 'PLATFORM_VERSION', 'VERSION'); let version = semver.parse(fullVersion); if (!version) { this.error(`Version in incorrect format. Got version: '${fullVersion}'`); } else if (flags.major) { version = semver.parse(`${version.major}.0.0`); this.error(`--major flag used. Got version: '${version === null || version === void 0 ? void 0 : version.version}'`); } else if (((_b = version === null || version === void 0 ? void 0 : version.prerelease) === null || _b === void 0 ? void 0 : _b.length) && ((_c = version === null || version === void 0 ? void 0 : version.prerelease) === null || _c === void 0 ? void 0 : _c.length) > 0) { this.warn(`Using prerelease version is not allowed. Got version: '${fullVersion}'.`); // eslint-disable-next-line @typescript-eslint/no-explicit-any const responses = yield inquirer.prompt([{ name: 'version', message: 'write version you want to use or write "yes" to revert to latest latest patch.', type: 'input', }]); if (responses.version === 'yes' || responses.version === '') { version = semver.parse(`${version.major}.0.0`); if (!version) { this.error(`Version in incorrect format. Got version: '${responses.version}'`); } } else { version = semver.parse(responses.version); if (!version) { this.error(`Version in incorrect format. Got version: '${responses.version}'`); } } this.warn(`${version === null || version === void 0 ? void 0 : version.version} version will be used.`); } // Validation of input parameters let scriptType = args.type; if (!scriptType) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const responses = yield inquirer.prompt([{ name: 'type', message: 'select a sql type', type: 'list', choices: [{ name: 'Schema' }, { name: 'Data' }, { name: 'Migration' }, { name: 'Extend' }], }]); scriptType = responses.type; } scriptType = scriptType === 'Migration' ? scriptType.toLowerCase() : capitalizeFirstLetter(scriptType); let scriptModule = args.module; if (!scriptModule && scriptType === 'data') { // eslint-disable-next-line @typescript-eslint/no-explicit-any const responses = yield inquirer.prompt([{ name: 'module', message: 'select a sql module for data type', type: 'list', choices: [{ name: 'acc' }, { name: 'claims' }, { name: 'core' }, { name: 'pas' }, { name: 'reins' }, { name: 'shared' }], }]); scriptModule = responses.module; } // If scriptType is Extend, then check input parameters for extending the db columns if (scriptType === 'Extend') { const arrayOfMissingParameters = yield this.checkExtendParameters(); if (arrayOfMissingParameters.length > 0) { this.error(`The script type Extend requires the following parameters to be specified: ${arrayOfMissingParameters.join(', ')}`); } } const scriptLayer = flags.layer; this.log(`Generating on SQL script layer:'${scriptLayer}'`); const scriptsRootFolder = path.resolve(yield this.getGitRoot(), 'database'); if (!(yield fs.pathExists(scriptsRootFolder))) { this.error(`Could not resolve database scripts folder: ${scriptsRootFolder}`); } for (const dbmsFormat of this._dbmsTypes) { const scriptDbmsFolder = path.resolve(scriptsRootFolder, dbmsFormat.name); if (yield fs.pathExists(scriptDbmsFolder)) { let scriptFolder = path.resolve(scriptDbmsFolder, scriptType); if (scriptLayer !== undefined) { scriptFolder = yield this.handleLayer(scriptDbmsFolder, scriptLayer, scriptType, dbmsFormat.name); } if (scriptModule !== undefined) { scriptFolder = path.resolve(scriptFolder, this._moduleTypes[scriptModule]); } if (!(yield fs.pathExists(scriptFolder))) { this.warn(`Could not resolve existing database scripts folder. Creating folder: ${scriptFolder}`); yield fs.mkdir(scriptFolder); } dbmsFormat.scriptLocation = scriptFolder; } } // Validation of parameters succeed. Requesting new SQL script ID and creating file. this.log(`Requesting new id for '${version}'`); let scriptId = ''; if (flags.offline) { scriptId = yield this.getOfflineScriptId(version.version, flags.description); this.log(`Generation script: '${chalk.green(scriptId + '.sql')}'`); } else { scriptId = (yield this.getScriptId(version.version)).data; this.log(`Got: '${chalk.green(scriptId)}'`); } const usedDbmsTypes = this._dbmsTypes.filter(it => it.scriptLocation !== undefined); for (const usedDbmsType of usedDbmsTypes) { const scriptsFilePath = path.resolve(usedDbmsType.scriptLocation, `${scriptId}.sql`); const content = scriptType === 'Extend' ? yield usedDbmsType.extendGenerator(flags['table-schema'], flags['table-name'], flags['column-name'], flags['column-type']) : ''; yield fs.writeFile(scriptsFilePath, content); this.log(`${chalk.yellow(scriptsFilePath)}`); } }); } } Sql.description = 'creates a new database script'; Sql.usage = 'sql <type> <module> [flags]'; Sql.examples = [ `$ ops sql schema `, `$ ops sql data shared --layer basic`, `$ ops sql data shared --major`, `$ ops sql data shared --offline --description "this is script description"`, ]; Sql.args = { type: Args.string({ description: 'Type of database scripts', required: true, options: ['schema', 'data', 'migration', 'extend', 'Schema', 'Data', 'Migration', 'Extend'], }), module: Args.string({ description: 'Module of data database scripts', options: ['acc', 'claims', 'core', 'pas', 'reins', 'shared'], }), }; Sql.flags = { version: Flags.string({ char: 'v', description: 'version for which you\'re generating database script', }), layer: Flags.string({ char: 'l', description: 'name of the configuration layer for which you are generating database script', }), offline: Flags.boolean({ char: 'o', description: 'generate database script with timestamp', default: false, }), description: Flags.string({ char: 'd', description: 'description of script to be used in filename for offline', dependsOn: ['offline'], }), major: Flags.boolean({ char: 'm', description: 'generate script for major version', default: false, }), // Used only for generating scripts to extend existing db tables with new column 'table-schema': Flags.string({ description: 'name of the existing table schema', }), 'table-name': Flags.string({ description: 'name of the existing table', }), 'column-name': Flags.string({ description: 'name the new column to be added', }), 'column-type': Flags.string({ description: 'type of the new column to be added', }), }; export default Sql;