hades-cli
Version:
Hades CLI developer tool
448 lines (447 loc) • 20 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Prompter = void 0;
const types_1 = require("./../types");
const operations_1 = require("./operations");
const property_1 = require("./property");
const cliter_config_1 = require("./../config/cliter.config");
const new_command_config_1 = require("./../config/new-command.config");
const inquirer = require("inquirer");
const Table = require("cli-table3");
class Prompter {
static async promptForNewApplication() {
const questions = [];
questions.push({
name: 'branch',
message: `Choose with which branch do you want to create your application?`,
type: 'list',
choices: new_command_config_1.newCommandConfig.branches
});
return await inquirer.prompt(questions);
}
static async promptForGithubCredentials() {
const questions = [];
questions.push({
name: 'githubUsername',
message: `Type your github username`,
type: 'input'
});
questions.push({
name: 'githubPassword',
message: `Type your github password`,
type: 'password'
});
return await inquirer.prompt(questions);
}
static async promptForLoadModule(boundedContextName, moduleName) {
const questions = [];
questions.push({
name: 'boundedContextName',
message: `Input the name of bonded context where will be created your module`,
type: 'input',
when: (answers) => {
if (!!boundedContextName) {
answers.boundedContextName = boundedContextName;
return false;
}
return true;
}
});
questions.push({
name: 'moduleName',
message: `Input the name of module`,
type: 'input',
when: (answers) => {
if (!!moduleName) {
answers.moduleName = moduleName;
return false;
}
return true;
}
});
const response = await inquirer.prompt(questions);
return {
boundedContextName: response.boundedContextName.toKebabCase(),
moduleName: response.moduleName.toKebabCase(),
};
}
static async promptForLoadBoundedContext(boundedContextName) {
const questions = [];
questions.push({
name: 'boundedContextName',
message: `Input the name of bonded context where will be created your module`,
type: 'input',
when: (answers) => {
if (!!boundedContextName) {
answers.boundedContextName = boundedContextName;
return false;
}
return true;
}
});
const response = await inquirer.prompt(questions);
return {
boundedContextName: response.boundedContextName.toKebabCase()
};
}
static async promptForGenerateModule(boundedContextName, moduleName) {
const questions = [];
questions.push({
name: 'boundedContextName',
message: `Input the name of bonded context where will be created your module`,
type: 'input',
when: (answers) => {
if (!!boundedContextName) {
answers.boundedContextName = boundedContextName;
return false;
}
return true;
}
});
questions.push({
name: 'moduleName',
message: `Input the name of module`,
type: 'input',
when: (answers) => {
if (!!moduleName) {
answers.moduleName = moduleName;
return false;
}
return true;
}
});
questions.push({
name: 'moduleNames',
message: `Input the plural of the module name in kebab case format`,
type: 'input',
});
questions.push({
name: 'hasOAuth',
message: `do you want to protect this module with OAuth?`,
type: 'confirm',
});
const response = await inquirer.prompt(questions);
return {
boundedContextName: response.boundedContextName.toKebabCase(),
moduleName: response.moduleName.toKebabCase(),
moduleNames: response.moduleNames.toKebabCase(),
hasOAuth: response.hasOAuth,
hasTenant: response.hasOAuth,
};
}
static async promptForGenerateAggregate() {
const questions = [];
questions.push({
name: 'hasValueObject',
message: `Do you want to define a property?`,
type: 'confirm'
});
return await inquirer.prompt(questions);
}
static async promptSelectOriginToCompare(files) {
const questions = [];
questions.push({
name: 'fileToCompare',
message: `Select file to compare`,
type: 'list',
choices: files
});
return await inquirer.prompt(questions);
}
static async promptSelectCompareAction() {
const questions = [];
questions.push({
name: 'compareAction',
message: `Select an action`,
type: 'list',
choices: Object.values(cliter_config_1.cliterConfig.compareActions)
});
return await inquirer.prompt(questions);
}
static async promptForCompareOriginFile() {
const questions = [];
questions.push({
name: 'hasCompareOriginFile',
message: `Do you want compare any origin file?`,
type: 'confirm'
});
return await inquirer.prompt(questions);
}
static async promptForSeedModule(boundedContextName, moduleName) {
const questions = [];
questions.push({
name: 'boundedContextName',
message: `Input the name of bonded context where is the module to run seed`,
type: 'input',
when: (answers) => {
if (!!boundedContextName) {
answers.boundedContextName = boundedContextName;
return false;
}
return true;
}
});
questions.push({
name: 'moduleName',
message: `Input the name of module`,
type: 'input',
when: (answers) => {
if (!!moduleName) {
answers.moduleName = moduleName;
return false;
}
return true;
}
});
const response = await inquirer.prompt(questions);
return {
boundedContextName: response.boundedContextName.toKebabCase(),
moduleName: response.moduleName.toKebabCase(),
};
}
static async promptForSeedBoundedContext(boundedContextName) {
const questions = [];
questions.push({
name: 'boundedContextName',
message: `Input the name of bonded context where are the modules for run seeds`,
type: 'input',
when: (answers) => {
if (!!boundedContextName) {
answers.boundedContextName = boundedContextName;
return false;
}
return true;
}
});
const response = await inquirer.prompt(questions);
return {
boundedContextName: response.boundedContextName.toKebabCase()
};
}
static async promptDefineAggregateProperty(command, boundedContextName, moduleName, moduleNames) {
const questions = [];
let name = '';
questions.push({
name: 'name',
message: `What's the name of property (type in snake case)`,
type: 'input',
validate: (input, answers) => {
name = input;
return true;
}
});
// only if filed end with _id
questions.push({
name: 'relationship',
message: `What kind of relationship do you want to create?`,
type: 'list',
choices: Object.values(types_1.SqlRelationship).filter(item => ['none', 'one-to-one', 'many-to-one'].includes(item)),
when: (answers) => {
if (answers.name.endsWith('_id')) {
answers.type = 'id';
answers.length = 36;
return true;
}
return false;
}
});
questions.push({
name: 'type',
message: `What's the type of property?`,
type: 'list',
choices: Object.values(types_1.SqlType),
when: (answers) => !answers.type
});
questions.push({
name: 'enumOptions',
message: `Set comma separated enumeration options, example: ONE,TWO,THREE,FOUR`,
type: 'input',
when: (answers) => answers.type === types_1.SqlType.ENUM
});
questions.push({
name: 'relationship',
message: `What kind of relationship do you want to create?`,
type: 'list',
choices: Object.values(types_1.SqlRelationship).filter(item => !['many-to-one'].includes(item)),
when: (answers) => answers.type === types_1.SqlType.RELATIONSHIP
});
questions.push({
name: 'relationshipSingularName',
message: `The property name will be plural, type its singular`,
type: 'input',
when: (answers) => answers.relationship === types_1.SqlRelationship.ONE_TO_MANY || answers.relationship === types_1.SqlRelationship.MANY_TO_MANY
});
questions.push({
name: 'relationshipAggregate',
message: `What is the aggregate which you want to relate this property? (example: AdminLang)`,
type: 'input',
when: (answers) => answers.relationship === types_1.SqlRelationship.ONE_TO_ONE || answers.relationship === types_1.SqlRelationship.MANY_TO_ONE || answers.relationship === types_1.SqlRelationship.ONE_TO_MANY || answers.relationship === types_1.SqlRelationship.MANY_TO_MANY
});
questions.push({
name: 'relationshipModulePath',
message: `Type path to module where to find the aggregate with which you want to relate this property? Type with format: bounded-context/module`,
type: 'input',
when: (answers) => {
if (answers.relationship === types_1.SqlRelationship.ONE_TO_MANY || (answers.relationship === types_1.SqlRelationship.ONE_TO_ONE && !answers.name.endsWith('_id')))
answers.type = answers.relationshipAggregate;
if (answers.relationship === types_1.SqlRelationship.ONE_TO_ONE && answers.name.endsWith('_id')) {
answers.type = 'id';
answers.length = 36;
}
// by default all many to many relationship will be nullable
if (answers.relationship === types_1.SqlRelationship.MANY_TO_MANY)
answers.nullable = true;
return answers.relationship === types_1.SqlRelationship.ONE_TO_ONE || answers.relationship === types_1.SqlRelationship.MANY_TO_ONE || answers.relationship === types_1.SqlRelationship.ONE_TO_MANY || answers.relationship === types_1.SqlRelationship.MANY_TO_MANY;
}
});
questions.push({
name: 'hasIntermediateTable',
message: () => `You want to create the intermediate table of your many to many relationship with name: ${boundedContextName.toSnakeCase()}_${moduleNames.toSnakeCase()}_${name.toSnakeCase()}?`,
type: 'confirm',
when: (answers) => {
return answers.relationship === types_1.SqlRelationship.MANY_TO_MANY;
}
});
questions.push({
name: 'decimals',
message: `Set total digits and decimals comma separated, example: 10,2`,
type: 'input',
when: (answers) => answers.type === types_1.SqlType.DECIMAL,
filter: (answers) => answers.split(',').map(item => parseInt(item.trim()))
});
questions.push({
name: 'length',
message: `What's the length of property? Push enter to use the default length`,
type: 'number',
when: (answers) => {
// avoid length for decimal values
if (answers.type === types_1.SqlType.DECIMAL || answers.type === types_1.SqlType.FLOAT)
return false;
// set intermediateTable value
if (answers.hasIntermediateTable)
answers.intermediateTable = `${boundedContextName.toSnakeCase()}_${moduleNames.toSnakeCase()}_${name.toSnakeCase()}`;
// set intermediateModel value
if (answers.hasIntermediateTable) {
answers.intermediateModel = `${boundedContextName.toPascalCase()}${moduleNames.toPascalCase()}${name.toPascalCase()}Model`;
answers.intermediateModelModuleSection = `${boundedContextName}/${moduleName}`;
answers.intermediateModelFile = `${moduleNames.toKebabCase()}-${name.toKebabCase()}`;
}
if (!answers.hasIntermediateTable && answers.relationship === types_1.SqlRelationship.MANY_TO_MANY) {
const relationshipModulePath = operations_1.Operations.parseFlagOfBoundedContextAndModule(command, answers.relationshipModulePath);
answers.intermediateModel = `${relationshipModulePath.boundedContextName.toPascalCase()}${name.toPascalCase()}${moduleNames.toPascalCase()}Model`;
answers.intermediateModelModuleSection = answers.relationshipModulePath;
answers.intermediateModelFile = `${name.toKebabCase()}-${moduleNames.toKebabCase()}`;
}
if (answers.relationship || answers.relationship)
return false;
return Object.keys(cliter_config_1.cliterConfig.defaultTypeLength).includes(answers.type) && !answers.length;
}
});
questions.push({
name: 'nullable',
message: `This property will be nullable?`,
type: 'confirm',
when: (answers) => {
if (answers.relationship === types_1.SqlRelationship.ONE_TO_MANY) {
// a field with relation one-to-many always will be nullable
answers.nullable = true;
return false;
}
if (answers.relationship === types_1.SqlRelationship.MANY_TO_MANY) {
// answers.nullable = true;
return false;
}
return true;
}
});
const response = await inquirer.prompt(questions);
// add default length
if (Object.keys(cliter_config_1.cliterConfig.defaultTypeLength).includes(response.type) && !response.length)
response.length = cliter_config_1.cliterConfig.defaultTypeLength[response.type];
// delete relationship none value
if (response.relationship === types_1.SqlRelationship.NONE)
delete response.relationship;
return new property_1.Property({
name: response.name,
type: response.type,
primaryKey: response.name === 'id' ? true : undefined,
enumOptions: response.enumOptions,
decimals: response.decimals,
length: response.length,
minLength: response.minLength,
maxLength: response.maxLength,
nullable: response.nullable,
defaultValue: response.defaultValue,
relationship: response.relationship,
relationshipSingularName: response.relationshipSingularName,
relationshipAggregate: response.relationshipAggregate,
relationshipModulePath: response.relationshipModulePath,
relationshipKey: response.relationship === types_1.SqlRelationship.MANY_TO_ONE ? 'id' : undefined,
relationshipField: response.relationship === types_1.SqlRelationship.MANY_TO_ONE || (response.relationship === types_1.SqlRelationship.ONE_TO_ONE && response.name.endsWith('_id')) ? response.name.replace(new RegExp('_id$'), '').toCamelCase() : undefined,
intermediateTable: response.intermediateTable,
intermediateModel: response.intermediateModel,
intermediateModelModuleSection: response.intermediateModelModuleSection,
intermediateModelFile: response.intermediateModelFile,
index: response.index
});
}
static printValueObjectsTable(command, items) {
const headers = [];
const excludeHeaders = ['config', 'id', 'intermediateModel', 'intermediateModelModuleSection', 'intermediateModelFile'];
const aliases = [
{ origin: '_name', alias: 'Name' },
{ origin: 'type', alias: 'Type' },
{ origin: 'primaryKey', alias: 'PK' },
{ origin: 'enumOptions', alias: 'Enums' },
{ origin: 'decimals', alias: 'Decimals' },
{ origin: 'length', alias: 'Length' },
{ origin: 'minLength', alias: 'MinL.' },
{ origin: 'maxLength', alias: 'MaxL.' },
{ origin: 'nullable', alias: 'Nullable' },
{ origin: 'relationship', alias: 'SqlRelationship' },
{ origin: 'relationshipSingularName', alias: 'Singular' },
{ origin: 'relationshipAggregate', alias: 'R. Aggregate' },
{ origin: 'relationshipModulePath', alias: 'R. Module Path' },
{ origin: 'relationshipKey', alias: 'R. Key' },
{ origin: 'relationshipField', alias: 'R. Field' },
{ origin: 'intermediateTable', alias: 'Intermediate Table' },
{ origin: 'index', alias: 'Index' },
];
const rows = [];
// set headers
for (const item of items) {
for (const key in item) {
if (item[key]) {
const alias = aliases.find(alias => alias.origin === key);
if (!headers.includes(alias ? alias.alias : key) && !excludeHeaders.includes(key))
headers.push(alias ? alias.alias : key);
}
}
}
// set rows in headers order
for (const item of items) {
const row = [];
for (const header of headers) {
const alias = aliases.find(alias => alias.alias === header);
// get value for each header
const value = header === 'Decimals' && Array.isArray(item['decimals']) ?
item['decimals'].join() :
item[alias ?
alias.origin :
header] ?
item[alias ?
alias.origin :
header] : '';
row.push(value);
}
rows.push(row);
}
var table = new Table({
head: headers,
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': '│' }
});
table.push(...rows);
command.log(table.toString());
}
}
exports.Prompter = Prompter;