strapi-plugin-config-sync/server/cli.js

231 lines
6.7 KiB
JavaScript
Raw Normal View History

2021-11-02 19:03:58 +01:00
#!/usr/bin/env node
const { Command } = require('commander');
const Table = require('cli-table');
const chalk = require('chalk');
const inquirer = require('inquirer');
2021-11-10 16:22:52 +01:00
const { isEmpty } = require('lodash');
const strapi = require('@strapi/strapi');
2021-11-02 19:03:58 +01:00
const warnings = require('./warnings');
2021-11-02 19:03:58 +01:00
const packageJSON = require('../package.json');
const program = new Command();
2021-11-10 16:22:52 +01:00
const initTable = (head) => {
2021-11-02 19:03:58 +01:00
return new Table({
2021-11-10 16:22:52 +01:00
head: [chalk.green('Name'), chalk.green(head || 'State')],
colWidths: [65, 20],
2021-11-02 19:03:58 +01:00
chars: { top: '═',
'top-mid': '╤',
'top-left': '╔',
'top-right': '╗',
bottom: '═',
'bottom-mid': '╧',
'bottom-left': '╚',
'bottom-right': '╝',
left: '║',
'left-mid': '╟',
mid: '─',
'mid-mid': '┼',
right: '║',
'right-mid': '╢',
middle: '│',
},
});
};
2021-11-10 16:22:52 +01:00
const getConfigState = (diff, configName, syncType) => {
if (
diff.fileConfig[configName]
&& diff.databaseConfig[configName]
) {
return chalk.yellow(syncType ? 'Update' : 'Different');
} else if (
diff.fileConfig[configName]
&& !diff.databaseConfig[configName]
) {
if (syncType === 'import') {
return chalk.green('Create');
} else if (syncType === 'export') {
return chalk.red('Delete');
} else {
return chalk.red('Only in sync dir');
}
} else if (
!diff.fileConfig[configName]
&& diff.databaseConfig[configName]
) {
if (syncType === 'import') {
return chalk.red('Delete');
} else if (syncType === 'export') {
return chalk.green('Create');
} else {
return chalk.green('Only in DB');
}
}
};
2021-11-18 22:45:20 +01:00
const handleAction = async (syncType, skipConfirm, configType, partials) => {
2021-11-10 16:22:52 +01:00
const app = await strapi().load();
const diff = await app.plugin('config-sync').service('main').getFormattedDiff();
// No changes.
if (isEmpty(diff.diff)) {
2021-12-28 23:50:25 +01:00
console.log(`${chalk.cyan.bold('[notice]')} There are no changes to ${syncType}.`);
2021-11-10 16:22:52 +01:00
process.exit(0);
}
// Init table.
const table = initTable('Action');
2021-11-18 22:45:20 +01:00
const configNames = partials && partials.split(',');
const partialDiff = {};
// Fill partialDiff with arguments.
if (configNames) {
configNames.map((name) => {
if (diff.diff[name]) partialDiff[name] = diff.diff[name];
});
}
if (configType) {
Object.keys(diff.diff).map((name) => {
if (configType === name.split('.')[0]) {
partialDiff[name] = diff.diff[name];
}
});
}
// No changes for partial diff.
if ((partials || configType) && isEmpty(partialDiff)) {
2021-12-28 23:50:25 +01:00
console.log(`${chalk.cyan.bold('[notice]')} There are no changes for the specified config.`);
2021-11-18 22:45:20 +01:00
process.exit(0);
}
const finalDiff = (partials || configType) && partialDiff ? partialDiff : diff.diff;
2021-11-10 16:22:52 +01:00
// Add diff to table.
2021-11-18 22:45:20 +01:00
Object.keys(finalDiff).map((configName) => {
table.push([configName, getConfigState(diff, configName, syncType)]);
2021-11-10 16:22:52 +01:00
});
// Print table.
console.log(table.toString(), '\n');
// Prompt to confirm.
let answer = {};
if (!skipConfirm) {
answer = await inquirer.prompt([{
type: 'confirm',
name: 'confirm',
2021-11-18 22:45:20 +01:00
message: `Are you sure you want to ${syncType} the config changes?`,
2021-11-10 16:22:52 +01:00
}]);
console.log('');
}
// Preform the action.
if (skipConfirm || answer.confirm) {
2021-11-18 22:45:20 +01:00
if (syncType === 'import') {
const onSuccess = (name) => console.log(`${chalk.green.bold('[success]')} Imported ${name} (${getConfigState(diff, name, syncType)})`);
2021-11-10 16:22:52 +01:00
try {
2021-11-18 22:45:20 +01:00
await Promise.all(Object.keys(finalDiff).map(async (name) => {
let warning;
if (
getConfigState(diff, name, syncType) === chalk.red('Delete')
&& warnings.delete[name]
) warning = warnings.delete[name];
2021-11-18 22:45:20 +01:00
await app.plugin('config-sync').service('main').importSingleConfig(name, onSuccess);
if (warning) console.log(`${chalk.yellow.bold('[warning]')} ${warning}`);
2021-11-18 22:45:20 +01:00
}));
2021-11-10 16:22:52 +01:00
} catch (e) {
console.log(`${chalk.red.bold('[error]')} Something went wrong during the import. ${e}`);
2021-11-10 16:22:52 +01:00
}
}
2021-11-18 22:45:20 +01:00
if (syncType === 'export') {
const onSuccess = (name) => console.log(`${chalk.green.bold('[success]')} Exported ${name} (${getConfigState(diff, name, syncType)})`);
2021-11-20 14:28:17 +01:00
2021-11-10 16:22:52 +01:00
try {
2021-11-20 14:28:17 +01:00
await Promise.all(Object.keys(finalDiff).map(async (name) => {
await app.plugin('config-sync').service('main').exportSingleConfig(name, onSuccess);
}));
2021-11-10 16:22:52 +01:00
} catch (e) {
console.log(`${chalk.red.bold('[error]')} Something went wrong during the export. ${e}`);
2021-11-10 16:22:52 +01:00
}
}
}
process.exit(0);
};
2021-11-02 19:03:58 +01:00
// Initial program setup
program.storeOptionsAsProperties(false).allowUnknownOption(true);
program.helpOption('-h, --help', 'Display help for command');
program.addHelpCommand('help [command]', 'Display help for command');
// `$ config-sync version` (--version synonym)
program.version(packageJSON.version, '-v, --version', 'Output the version number');
program
.command('version')
.description('Output your version of the config-sync plugin')
.action(() => {
process.stdout.write(`${packageJSON.version}\n`);
process.exit(0);
});
// `$ config-sync import`
program
.command('import')
2021-11-10 16:48:17 +01:00
.alias('i')
2021-11-20 14:28:17 +01:00
.option('-t, --type <type>', 'The type of config')
.option('-p, --partial <partials>', 'A comma separated string of configs')
.option('-y, --yes', 'Skip the confirm prompt')
2021-11-02 19:03:58 +01:00
.description('Import the config')
.action(async ({ yes, type, partial }) => {
return handleAction('import', yes, type, partial);
2021-11-02 19:03:58 +01:00
});
// `$ config-sync export`
program
.command('export')
2021-11-10 16:48:17 +01:00
.alias('e')
2021-11-20 14:28:17 +01:00
.option('-t, --type <type>', 'The type of config')
.option('-p, --partial <partials>', 'A comma separated string of configs')
.option('-y, --yes', 'Skip the confirm prompt')
2021-11-02 19:03:58 +01:00
.description('Export the config')
.action(async ({ yes, type, partial }) => {
return handleAction('export', yes, type, partial);
2021-11-10 16:22:52 +01:00
});
// `$ config-sync diff`
program
.command('diff')
2021-11-10 16:48:17 +01:00
.alias('d')
2021-11-10 16:22:52 +01:00
// .option('-t, --type <type>', 'The type of config') // TODO: partial diff
.description('The config diff')
.action(async ({ type }) => {
const app = await strapi().load();
const diff = await app.plugin('config-sync').service('main').getFormattedDiff();
2021-11-02 19:03:58 +01:00
2021-11-10 16:36:30 +01:00
// No changes.
if (isEmpty(diff.diff)) {
2021-12-28 23:50:25 +01:00
console.log(`${chalk.cyan.bold('[notice]')} No differences between DB and sync directory.`);
2021-11-10 16:36:30 +01:00
process.exit(0);
}
2021-11-02 19:03:58 +01:00
// Init table.
const table = initTable();
2021-11-10 16:22:52 +01:00
// Add diff to table.
Object.keys(diff.diff).map((configName) => {
table.push([configName, getConfigState(diff, configName)]);
});
2021-11-02 19:03:58 +01:00
// Print table.
console.log(table.toString());
2021-11-10 16:22:52 +01:00
process.exit(0);
2021-11-02 19:03:58 +01:00
});
program.parseAsync(process.argv);