From 2928faac644b40ea73d968c5c3b873050dd744e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kopeck=C3=BD?= Date: Thu, 29 Jul 2021 13:46:36 +0200 Subject: [PATCH] #41 Allow to specify custom folder for Enums --- packages/generator/README.md | 2 + .../generator/src/openapi/fileGenerator.ts | 6 ++- packages/generator/src/openapi/types.ts | 1 + .../src/openapi/writers/objectEntityWriter.ts | 51 +++++++++++++++++-- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/packages/generator/README.md b/packages/generator/README.md index 387bc2d9..b5da59c2 100644 --- a/packages/generator/README.md +++ b/packages/generator/README.md @@ -193,6 +193,8 @@ Custom configuration is expected to be a JSON file with the following structure: ```ts export interface IConfig { api: string; + entitiesPath?: string; + enumsPath?: string; observable?: ObservableConfig; enums?: "enum" | "string"; dates?: "native" | "date-fns"; diff --git a/packages/generator/src/openapi/fileGenerator.ts b/packages/generator/src/openapi/fileGenerator.ts index 7d7b6177..b1088ca5 100644 --- a/packages/generator/src/openapi/fileGenerator.ts +++ b/packages/generator/src/openapi/fileGenerator.ts @@ -56,8 +56,12 @@ export default class FileGenerator { Handlebars.registerPartial("generatedEntityHeader", await this.readTemplate("generatedEntityHeader")); const directory = this.project.createDirectory(this.config.entitiesPath); + let enumDirectory = directory; + if (this.config.enumsPath) { + enumDirectory = this.project.createDirectory(this.config.enumsPath); + } const enumWriter = - this.config.enums === "enum" ? new EnumWriter(directory, templates) : new StringLiteralWriter(directory, templates); + this.config.enums === "enum" ? new EnumWriter(enumDirectory, templates) : new StringLiteralWriter(enumDirectory, templates); const objectWriter = new ObjectEntityWriter(directory, this.config, templates); const unionWriter = new UnionEntityWriter(directory, templates); diff --git a/packages/generator/src/openapi/types.ts b/packages/generator/src/openapi/types.ts index d51d06bf..753052bf 100644 --- a/packages/generator/src/openapi/types.ts +++ b/packages/generator/src/openapi/types.ts @@ -31,6 +31,7 @@ export interface IConfig { entitiesPath: string; repositoriesPath: string; + enumsPath?: string; validation?: boolean; conversion?: boolean; diff --git a/packages/generator/src/openapi/writers/objectEntityWriter.ts b/packages/generator/src/openapi/writers/objectEntityWriter.ts index 9470e952..fada893c 100644 --- a/packages/generator/src/openapi/writers/objectEntityWriter.ts +++ b/packages/generator/src/openapi/writers/objectEntityWriter.ts @@ -1,5 +1,6 @@ import camelCase from "lodash/camelCase"; import uniq from "lodash/uniq"; +import path from "path"; import { Directory, SourceFile } from "ts-morph"; import GeneratorBase from "../../generatorBase"; import ObservableFormatter from "../formatters/observableFormatter"; @@ -47,7 +48,27 @@ export default class ObjectEntityWriter { private createFile(fileName: string, definition: ObjectEntity, baseClass: ObjectEntity | undefined) { const decoratorImports = this.getPropertyDecoratorsImports(definition.properties); - const entitiesToImport = definition.properties.filter(x => x.type.isImportRequired).map(x => x.type.getTypeName()); + const propertiesToImport = definition.properties.filter(x => x.type.isImportRequired); + + interface SplitImports { + enumsToImport: Array; + entitiesToImport: Array; + } + + const { entitiesToImport, enumsToImport } = propertiesToImport.reduce( + (accumulator: SplitImports, property) => { + const typeName = property.type.getTypeName(); + if (typeName) { + if (property.type.type instanceof Enum) { + accumulator.enumsToImport.push(typeName); + } else { + accumulator.entitiesToImport.push(typeName); + } + } + return accumulator; + }, + { entitiesToImport: [], enumsToImport: [] } + ); if (baseClass) { entitiesToImport.push(baseClass.name); @@ -55,10 +76,15 @@ export default class ObjectEntityWriter { const entityImports = uniq(entitiesToImport) .sort() - .map(x => `import ${x} from "./${camelCase(x)}";`); + .map((x: string) => `import ${x} from "./${camelCase(x)}";`); + + const pathToEnums = this.getPathToEnums(); + const enumsImports = uniq(enumsToImport) + .sort() + .map((x: string) => `import ${x} from "${pathToEnums}/${camelCase(x)}";`); const result = this.templates.objectEntityFile({ - imports: [...decoratorImports, ...entityImports], + imports: [...decoratorImports, ...entityImports, ...enumsImports], content: () => this.getEntityContent(definition, baseClass), entity: definition, baseClass, @@ -67,6 +93,25 @@ export default class ObjectEntityWriter { return this.parentDirectory.createSourceFile(fileName, result, { overwrite: true }); } + getPathToEnums() { + function convertPath(windowsPath: string) { + return windowsPath + .replace(/^\\\\\?\\/, "") + .replace(/\\/g, "/") + .replace(/\/\/+/g, "/"); + } + + if (this.config.enumsPath && this.config.entitiesPath) { + const relativePath = convertPath(path.relative(this.config.entitiesPath, this.config.enumsPath)); + if (!relativePath.startsWith(".")) { + return `./${relativePath}`; + } + return relativePath; + } + + return "."; + } + getPropertyDecoratorsImports(properties: EntityProperty[]) { const result = new Set();