hades-cli
Version:
Hades CLI developer tool
196 lines (195 loc) • 13.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodeWriter = void 0;
const ts_morph_1 = require("ts-morph");
const typescript_1 = require("typescript");
const import_driver_1 = require("./import.driver");
const array_driver_1 = require("./array.driver");
const path = require("path");
const fs = require("fs");
class CodeWriter {
constructor(srcDirectory, appDirectory, frameworkDirectory, boundedContextName, moduleName, moduleNames) {
this.srcDirectory = srcDirectory;
this.appDirectory = appDirectory;
this.frameworkDirectory = frameworkDirectory;
this.boundedContextName = boundedContextName;
this.moduleName = moduleName;
this.moduleNames = moduleNames;
this.project = new ts_morph_1.Project({
tsConfigFilePath: path.join(process.cwd(), 'tsconfig.json'),
// these are the defaults
manipulationSettings: {
// TwoSpaces, FourSpaces, EightSpaces, or Tab
indentationText: ts_morph_1.IndentationText.FourSpaces,
// LineFeed or CarriageReturnLineFeed
newLineKind: typescript_1.NewLineKind.LineFeed,
// Single or Double
quoteKind: ts_morph_1.QuoteKind.Single,
// Whether to change shorthand property assignments to property assignments
// and add aliases to import & export specifiers (see more information in
// the renaming section of the documentation).
usePrefixAndSuffixTextForRename: false,
// Whether to use trailing commas in multi-line scenarios where trailing
// commas would be used.
useTrailingCommas: false
}
});
}
generateTestingForeignReferences(properties) {
// get foreign relationship
const foreignRelationships = properties.getForeignRelationship(this.boundedContextName);
// check that exist bounded context folder
if (!fs.existsSync(path.join(process.cwd(), 'cliter', this.boundedContextName.toKebabCase())))
return;
// get all yaml files to get all modules managed by cli
const yamlFiles = fs.readdirSync(path.join(process.cwd(), 'cliter', this.boundedContextName.toKebabCase()));
for (const foreignRelationship of foreignRelationships) {
if (!foreignRelationship.relationshipModulePath)
return;
const foreignBoundedContextName = foreignRelationship.relationshipModulePath.split('/')[0];
for (const yamlFile of yamlFiles) {
// get filename of e2e test
const e2eTestFile = yamlFile.replace('.yml', '').concat('.e2e-spec.ts');
const e2eTestPath = path.join(process.cwd(), 'test', 'acceptance', this.boundedContextName.toKebabCase(), e2eTestFile);
// check that exist e2e test file
if (fs.existsSync(e2eTestPath)) {
// get sourceFile of e2e test
const sourceFile = this.project.addSourceFileAtPath(e2eTestPath);
// register import in e2e test
import_driver_1.ImportDriver.createImportItems(sourceFile, [
`${foreignBoundedContextName.toPascalCase()}Module`
], `./../../../src/apps/${foreignBoundedContextName.toKebabCase()}/${foreignBoundedContextName.toKebabCase()}.module`);
// register import in import array
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `${foreignBoundedContextName.toPascalCase()}Module`, `importForeignModules`);
sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile.saveSync();
}
}
}
}
generateReferences(properties) {
const sourceFile = this.project.addSourceFileAtPath(path.join(process.cwd(), this.srcDirectory, this.appDirectory, this.boundedContextName.toKebabCase(), 'index.ts'));
// register import
import_driver_1.ImportDriver.createImportItems(sourceFile, [
`${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Handlers`,
`${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Services`,
`${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Model`,
`I${this.moduleName.toPascalCase()}Repository`,
`Sequelize${this.moduleName.toPascalCase()}Repository`,
`${this.moduleName.toPascalCase()}Sagas`
], `./${this.moduleName.toKebabCase()}`);
// handlers
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `...${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Handlers`, `${this.boundedContextName.toPascalCase()}Handlers`);
// services
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `...${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Services`, `${this.boundedContextName.toPascalCase()}Services`);
// models
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Model`, `${this.boundedContextName.toPascalCase()}Models`);
// intermediate table model
for (const intermediateModel of properties.withRelationshipIntermediateTable) {
import_driver_1.ImportDriver.createImportItems(sourceFile, [intermediateModel.intermediateModel], `./${this.moduleName.toKebabCase()}`);
array_driver_1.ArrayDriver.createArrayItem(sourceFile, intermediateModel.intermediateModel, `${this.boundedContextName.toPascalCase()}Models`);
}
// repositories
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `
{
provide: I${this.moduleName.toPascalCase()}Repository,
useClass: Sequelize${this.moduleName.toPascalCase()}Repository
}`, `${this.boundedContextName.toPascalCase()}Repositories`);
// sagas
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `${this.moduleName.toPascalCase()}Sagas`, `${this.boundedContextName.toPascalCase()}Sagas`);
sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile.saveSync();
}
declareFramework() {
// get decorator arguments
const sourceFile = this.project.addSourceFileAtPath(path.join(process.cwd(), this.srcDirectory, this.frameworkDirectory, this.boundedContextName.toKebabCase(), `${this.boundedContextName.toKebabCase()}.module.ts`));
const moduleDecoratorArguments = this.getModuleDecoratorArguments(sourceFile, `${this.boundedContextName.toPascalCase()}Module`);
const providers = moduleDecoratorArguments.getProperty('providers');
const providersArray = providers === null || providers === void 0 ? void 0 : providers.getInitializerIfKindOrThrow(typescript_1.SyntaxKind.ArrayLiteralExpression);
const controllers = moduleDecoratorArguments.getProperty('controllers');
const controllersArray = controllers === null || controllers === void 0 ? void 0 : controllers.getInitializerIfKindOrThrow(typescript_1.SyntaxKind.ArrayLiteralExpression);
// register imports from bounded context
import_driver_1.ImportDriver.createImportItems(sourceFile, [
`${this.boundedContextName.toPascalCase()}Models`,
`${this.boundedContextName.toPascalCase()}Handlers`,
`${this.boundedContextName.toPascalCase()}Services`,
`${this.boundedContextName.toPascalCase()}Repositories`,
`${this.boundedContextName.toPascalCase()}Sagas`,
], `/${this.boundedContextName.toKebabCase()}`);
// register import for controllers and providers
import_driver_1.ImportDriver.createImportItems(sourceFile, [
`${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Controllers`,
`${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Resolvers`
], `./${this.moduleName.toKebabCase()}`);
// add model to ORM array argument
const modelArrayArgument = this.getModelArrayArgument(moduleDecoratorArguments);
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `...${this.boundedContextName.toPascalCase()}Models`, modelArrayArgument);
// add handlers to providers
array_driver_1.ArrayDriver.createArrayItems(sourceFile, [
`...${this.boundedContextName.toPascalCase()}Handlers`,
`...${this.boundedContextName.toPascalCase()}Services`,
`...${this.boundedContextName.toPascalCase()}Repositories`,
`...${this.boundedContextName.toPascalCase()}Sagas`,
`...${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Resolvers`,
], providersArray);
// add controller to controllers array
array_driver_1.ArrayDriver.createArrayItem(sourceFile, `...${this.boundedContextName.toPascalCase()}${this.moduleName.toPascalCase()}Controllers`, controllersArray);
sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile.saveSync();
}
declareModule() {
const sourceFile = this.project.addSourceFileAtPath(path.join(process.cwd(), this.srcDirectory, 'app.module.ts'));
const moduleDecoratorArguments = this.getModuleDecoratorArguments(sourceFile, 'AppModule');
const modules = this.getImportedModules(sourceFile);
if (!modules.includes(`${this.boundedContextName.toPascalCase()}Module`)) {
// import module
import_driver_1.ImportDriver.createImportItems(sourceFile, [`${this.boundedContextName.toPascalCase()}Module`], `./apps/${this.boundedContextName.toKebabCase()}/${this.boundedContextName.toKebabCase()}.module`);
// register module
const importsArgument = moduleDecoratorArguments.getProperty('imports');
const importsArray = importsArgument === null || importsArgument === void 0 ? void 0 : importsArgument.getInitializerIfKindOrThrow(typescript_1.SyntaxKind.ArrayLiteralExpression);
importsArray.addElement(`${this.boundedContextName.toPascalCase()}Module`, { useNewLines: true });
}
sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile.saveSync();
}
declareAuthModuleInShareModule() {
const sourceFile = this.project.addSourceFileAtPath(path.join(process.cwd(), this.srcDirectory, path.join('apps', 'shared', 'shared.module.ts')));
const moduleDecoratorArguments = this.getModuleDecoratorArguments(sourceFile, 'SharedModule');
// register import auth module
import_driver_1.ImportDriver.createImportItems(sourceFile, [
`AuthModule`
], `/iam/shared/domain/modules/auth/auth.module.ts`);
// register auth module
const importsArgument = moduleDecoratorArguments.getProperty('imports');
const importsArray = importsArgument === null || importsArgument === void 0 ? void 0 : importsArgument.getInitializerIfKindOrThrow(typescript_1.SyntaxKind.ArrayLiteralExpression);
const importsElements = importsArray.getElements();
// check if AuthModule is imported
if (!importsElements.find(el => el.getText() === 'AuthModule'))
importsArray.addElement(`AuthModule`, { useNewLines: true });
// register auth module
const exportsArgument = moduleDecoratorArguments.getProperty('exports');
const exportsArray = exportsArgument === null || exportsArgument === void 0 ? void 0 : exportsArgument.getInitializerIfKindOrThrow(typescript_1.SyntaxKind.ArrayLiteralExpression);
const exportsElements = exportsArray.getElements();
// check if AuthModule is imported
if (!exportsElements.find(el => el.getText() === 'AuthModule'))
exportsArray.addElement(`AuthModule`, { useNewLines: true });
sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile.saveSync();
}
getModelArrayArgument(moduleDecoratorArguments) {
const importsArgument = moduleDecoratorArguments.getProperty('imports');
const importsArray = importsArgument.getInitializerIfKindOrThrow(typescript_1.SyntaxKind.ArrayLiteralExpression);
const importsElements = importsArray.getElements();
const SequelizeModuleElement = importsElements.find(el => el.getText().indexOf('SequelizeModule.forFeature') === 0);
return SequelizeModuleElement.getArguments()[0];
}
getImportedModules(sourceFile) {
const imports = sourceFile.getImportDeclarations();
let modules = [];
for (const importObj of imports) {
modules = modules.concat(importObj.getNamedImports().map(i => i.getName()));
}
return modules;
}
getModuleDecoratorArguments(sourceFile, className) {
const moduleClass = sourceFile.getClass(className);
const moduleDecorator = moduleClass === null || moduleClass === void 0 ? void 0 : moduleClass.getDecorator('Module');
return moduleDecorator.getArguments()[0];
}
}
exports.CodeWriter = CodeWriter;