hades-cli
Version:
Hades CLI developer tool
197 lines (196 loc) • 11.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
const tsyringe_1 = require("tsyringe");
const command_1 = require("@oclif/command");
const types_1 = require("./../@cliter/types");
const utils_1 = require("./../@cliter/utils");
const state_service_1 = require("./../@cliter/services/state.service");
const file_manager_1 = require("./../@cliter/utils/file-manager");
const logSymbols = require("log-symbols");
const chalk = require("chalk");
const emoji = require("node-emoji");
const path = require("path");
const fs = require("fs");
const yaml = require("js-yaml");
const shell = require("shelljs");
const _ = require("lodash");
class Load extends command_1.Command {
async run() {
const { args, flags } = this.parse(Load);
const stateService = tsyringe_1.container.resolve(state_service_1.StateService);
if (args.elementType === 'b')
args.elementType = 'bounded-context';
if (args.elementType === 'm')
args.elementType = 'module';
// ser operations object
const operations = new utils_1.Operations();
if (args.elementType === types_1.TemplateElement.MODULE) {
let moduleFlag = {};
if (flags.module)
moduleFlag = utils_1.Operations.parseFlagOfBoundedContextAndModule(this, flags.module);
const { boundedContextName, moduleName } = await utils_1.Prompter.promptForLoadModule(moduleFlag === null || moduleFlag === void 0 ? void 0 : moduleFlag.boundedContextName, moduleFlag === null || moduleFlag === void 0 ? void 0 : moduleFlag.moduleName);
// create yaml file
const schema = this.loadYamlConfigFile(boundedContextName, moduleName);
const currentLockFiles = this.loadJsonLockFile(boundedContextName, moduleName);
// set stateService
stateService.command = this;
stateService.schema = schema;
stateService.lockFiles = currentLockFiles;
stateService.flags = flags;
// generate module files
await operations.generateModule();
await this.reviewOverwrites(operations, stateService);
}
if (args.elementType.toSnakeCase() === types_1.TemplateElement.BOUNDED_CONTEXT) {
const { boundedContextName } = await utils_1.Prompter.promptForLoadBoundedContext(flags.boundedContext);
const yamlFiles = fs.readdirSync(path.join(process.cwd(), 'cliter', boundedContextName.toKebabCase()));
for (const yamlFile of yamlFiles.filter(files => files.endsWith('.yml'))) {
// create yaml file
const schema = this.loadYamlConfigFile(boundedContextName, yamlFile.replace('.yml', ''));
const currentLockFiles = this.loadJsonLockFile(boundedContextName, schema.moduleName);
// set stateService
stateService.command = this;
stateService.schema = schema;
stateService.lockFiles = currentLockFiles;
stateService.flags = flags;
// generate module files
await operations.generateModule();
}
// generate graphql files
await this.reviewOverwrites(operations, stateService);
}
}
async reviewOverwrites(operations, stateService) {
// generate graphql files
await operations.generateGraphqlTypes();
if (stateService.originFiles.length > 0) {
stateService.command.log(`
********************************************
*** ATTENTION! ***
********************************************`);
stateService.command.log(`%s %s %s There are files that have not been overwritten because they were modified, the following origin files have been created.`, logSymbols.warning, chalk.yellow.bold('WARNING'), emoji.get('small_red_triangle'));
for (const originFile of stateService.originFiles) {
stateService.command.log(`%s ${originFile}`, emoji.get('question'));
}
let deleteOriginFiles = true;
let fileToCompare = '';
let actionResponse = '';
if ((await utils_1.Prompter.promptForCompareOriginFile()).hasCompareOriginFile) {
// list all origin files
fileToCompare = (await utils_1.Prompter.promptSelectOriginToCompare(stateService.originFiles)).fileToCompare;
shell.exec(`code --diff ${fileToCompare} ${fileToCompare.replace('.origin', '')}`, { silent: true, async: true }, () => { });
while (actionResponse !== stateService.cliterConfig.compareActions.finish) {
if (stateService.originFiles.length > 0) {
actionResponse = (await utils_1.Prompter.promptSelectCompareAction()).compareAction;
switch (actionResponse) {
case stateService.cliterConfig.compareActions.deleteOrigin:
fs.unlinkSync(fileToCompare); // delete origin file
fileToCompare = _.head(stateService.originFiles.slice()); // get next file
if (fileToCompare)
shell.exec(`code --diff ${fileToCompare} ${fileToCompare.replace('.origin', '')}`, { silent: true, async: true }, () => { });
break;
case stateService.cliterConfig.compareActions.selectFile:
console.log('selectFile ', fileToCompare);
fileToCompare = (await utils_1.Prompter.promptSelectOriginToCompare(stateService.originFiles)).fileToCompare;
shell.exec(`code --diff ${fileToCompare} ${fileToCompare.replace('.origin', '')}`, { silent: true, async: true }, () => { });
break;
}
}
else {
stateService.command.log(`[INFO] All files have been reviewed`);
deleteOriginFiles = false;
break;
}
}
}
if (deleteOriginFiles) {
file_manager_1.FileManager.deleteOriginFiles(process.cwd());
stateService.command.log(chalk.redBright.bold('[INFO] Origin files deleted!'));
}
}
}
loadJsonLockFile(boundedContextName, moduleName) {
const jsonPath = path.join(process.cwd(), 'cliter', boundedContextName.toKebabCase(), moduleName.toKebabCase() + '-lock.json');
if (!fs.existsSync(jsonPath))
return [];
return (JSON.parse(fs.readFileSync(jsonPath, 'utf8')).files);
}
loadYamlConfigFile(boundedContextName, moduleName) {
var _a;
const yamlPath = path.join(process.cwd(), 'cliter', boundedContextName.toKebabCase(), moduleName.toKebabCase() + '.yml');
// read yaml file
const yamlObj = yaml.load(fs.readFileSync(yamlPath, 'utf8'));
this.parseModuleDefinitionSchema(yamlObj);
const properties = new utils_1.Properties();
for (const property of yamlObj.aggregateProperties) {
properties.add(new utils_1.Property({
name: property.name,
type: property.type,
primaryKey: property === null || property === void 0 ? void 0 : property.primaryKey,
enumOptions: (_a = property === null || property === void 0 ? void 0 : property.enumOptions) === null || _a === void 0 ? void 0 : _a.join(),
decimals: property === null || property === void 0 ? void 0 : property.decimals,
length: property === null || property === void 0 ? void 0 : property.length,
minLength: property === null || property === void 0 ? void 0 : property.minLength,
maxLength: property === null || property === void 0 ? void 0 : property.maxLength,
nullable: property === null || property === void 0 ? void 0 : property.nullable,
defaultValue: property === null || property === void 0 ? void 0 : property.defaultValue,
relationship: property === null || property === void 0 ? void 0 : property.relationship,
relationshipSingularName: property === null || property === void 0 ? void 0 : property.relationshipSingularName,
relationshipAggregate: property === null || property === void 0 ? void 0 : property.relationshipAggregate,
relationshipModulePath: property === null || property === void 0 ? void 0 : property.relationshipModulePath,
relationshipKey: property === null || property === void 0 ? void 0 : property.relationshipKey,
relationshipField: property === null || property === void 0 ? void 0 : property.relationshipField,
intermediateTable: property === null || property === void 0 ? void 0 : property.intermediateTable,
intermediateModel: property === null || property === void 0 ? void 0 : property.intermediateModel,
intermediateModelModuleSection: property === null || property === void 0 ? void 0 : property.intermediateModelModuleSection,
intermediateModelFile: property === null || property === void 0 ? void 0 : property.intermediateModelFile,
index: property === null || property === void 0 ? void 0 : property.index,
example: property === null || property === void 0 ? void 0 : property.example,
faker: property === null || property === void 0 ? void 0 : property.faker,
}));
}
return {
boundedContextName: yamlObj.boundedContextName,
moduleName: yamlObj.moduleName,
moduleNames: yamlObj.moduleNames,
aggregateName: yamlObj.aggregateName,
hasOAuth: yamlObj.hasOAuth,
hasTenant: yamlObj.hasTenant,
properties: properties,
excluded: yamlObj.excluded,
};
}
parseModuleDefinitionSchema(yamlObj) {
if (typeof yamlObj.boundedContextName !== 'string')
throw new Error(`Yaml file structure error, boundedContextName field missing`);
if (typeof yamlObj.moduleName !== 'string')
throw new Error(`Yaml file structure error, moduleName field missing`);
if (typeof yamlObj.moduleNames !== 'string')
throw new Error(`Yaml file structure error, moduleNames field missing`);
if (typeof yamlObj.aggregateName !== 'string')
throw new Error(`Yaml file structure error, aggregateName field missing`);
if (typeof yamlObj.hasOAuth !== 'boolean')
throw new Error(`Yaml file structure error, hasOAuth field missing`);
if (typeof yamlObj.hasTenant !== 'boolean')
throw new Error(`Yaml file structure error, hasTenant field missing`);
}
}
exports.default = Load;
Load.description = 'Load hades elements [bounded-context, module] from yaml file, located in the cliter folder';
Load.flags = {
help: command_1.flags.help({ char: 'h' }),
module: command_1.flags.string({ char: 'm' }),
boundedContext: command_1.flags.string({ char: 'b' }),
force: command_1.flags.boolean({ char: 'f' }),
verbose: command_1.flags.boolean({ char: 'v' }),
tests: command_1.flags.boolean({ char: 't' }),
};
Load.args = [
{
name: 'elementType',
required: true,
description: 'Type element to create',
options: ['bounded-context', 'b', 'module', 'm']
}
];