diff --git a/src/Engine.ts b/src/Engine.ts index 3dbce67..f028c36 100644 --- a/src/Engine.ts +++ b/src/Engine.ts @@ -26,10 +26,7 @@ export class Engine { } private createModelFromMetadata(databaseModel: DatabaseModel) { - Handlebars.registerHelper("curly", (open) => {return open ? "{" : "}";}); - Handlebars.registerHelper("toEntityName", str => {return this.Options.convertCase ? changeCase.pascalCase(str) : str;}); - Handlebars.registerHelper("toFileName", str => {return this.Options.convertCase ? changeCase.paramCase(str) : str;}); - Handlebars.registerHelper("toPropertyName", str => {return this.Options.convertCase ? changeCase.camelCase(str) : str;}); + this.createHandlebarsHelpers(); let templatePath = path.resolve(__dirname, '../../src/entity.mst') let template = fs.readFileSync(templatePath, 'UTF-8'); let resultPath = this.Options.resultsPath @@ -43,28 +40,94 @@ export class Engine { if (!fs.existsSync(entitesPath)) fs.mkdirSync(entitesPath); } - Handlebars.registerHelper('toLowerCase', function (str) { - return str.toLowerCase(); - }); let compliedTemplate = Handlebars.compile(template, { noEscape: true }) databaseModel.entities.forEach(element => { element.Imports = []; element.Columns.forEach((column) => { column.relations.forEach( (relation) => { - if (element.EntityName !== relation.relatedTable) - {element.Imports.push(relation.relatedTable);} + if (element.EntityName !== relation.relatedTable) { element.Imports.push(relation.relatedTable); } } ); }); element.Imports.filter(function (elem, index, self) { return index === self.indexOf(elem); }); - let resultFilePath = path.resolve(entitesPath, (this.Options.convertCase ? changeCase.paramCase(element.EntityName) : element.EntityName) + '.ts'); - let rendered =compliedTemplate(element) + let casedFileName = '' + switch (this.Options.convertCaseFile) { + case 'camel': + casedFileName = changeCase.camelCase(element.EntityName); + break; + case 'param': + casedFileName = changeCase.paramCase(element.EntityName); + break; + case 'pascal': + casedFileName = changeCase.pascalCase(element.EntityName); + break; + case 'none': + casedFileName = element.EntityName; + break; + } + let resultFilePath = path.resolve(entitesPath, (casedFileName) + '.ts'); + let rendered = compliedTemplate(element) fs.writeFileSync(resultFilePath, rendered, { encoding: 'UTF-8', flag: 'w' }) }); } + private createHandlebarsHelpers() { + Handlebars.registerHelper("curly", (open) => { return open ? "{" : "}"; }); + Handlebars.registerHelper("toEntityName", str => { + let retStr = '' + switch (this.Options.convertCaseEntity) { + case 'camel': + retStr = changeCase.camelCase(str); + break; + case 'pascal': + retStr = changeCase.pascalCase(str); + break; + case 'none': + retStr = str; + break; + } + return retStr; + }); + Handlebars.registerHelper("toFileName", str => { + let retStr = '' + switch (this.Options.convertCaseFile) { + case 'camel': + retStr = changeCase.camelCase(str); + break; + case 'param': + retStr = changeCase.paramCase(str); + break; + case 'pascal': + retStr = changeCase.pascalCase(str); + break; + case 'none': + retStr = str; + break; + } + return retStr; + }); + Handlebars.registerHelper("toPropertyName", str => { + let retStr = '' + switch (this.Options.convertCaseProperty) { + case 'camel': + retStr = changeCase.camelCase(str); + break; + case 'pascal': + retStr = changeCase.pascalCase(str); + break; + case 'none': + retStr = str; + break; + } + return retStr; + }); + Handlebars.registerHelper('toLowerCase', str => { + return str.toLowerCase(); + }); + } + //TODO:Move to mustache template file private createTsConfigFile(resultPath) { fs.writeFileSync(path.resolve(resultPath, 'tsconfig.json'), `{"compilerOptions": { @@ -129,5 +192,8 @@ export interface EngineOptions { schemaName: string, ssl: boolean, noConfigs: boolean, - convertCase: boolean + convertCaseFile: 'pascal' | 'param' | 'camel' | 'none', + convertCaseEntity: 'pascal' | 'camel' | 'none', + convertCaseProperty: 'pascal' | 'camel' | 'none', } + diff --git a/src/entity.mst b/src/entity.mst index 90ebe73..a2d1f2c 100644 --- a/src/entity.mst +++ b/src/entity.mst @@ -3,12 +3,11 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi {{/each}} -@Entity("{{toEntityName EntityName}}") +@Entity("{{EntityName}}") {{#Indexes}}{{^isPrimaryKey}}@Index("{{name}}",[{{#columns}}"{{name}}",{{/columns}}]{{#isUnique}},{unique:true}{{/isUnique}}) {{/isPrimaryKey}}{{/Indexes}}export class {{toEntityName EntityName}} { {{#Columns}} - {{^relations}} @Column("{{sql_type}}",{ {{#is_generated}} generated:true,{{/is_generated}}{{#is_nullable}} nullable:true,{{/is_nullable}}{{^is_nullable}} @@ -18,14 +17,14 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi precision:{{.}},{{/numericPrecision}}{{#numericScale}} scale:{{.}},{{/numericScale}}{{#isPrimary}} primary:{{isPrimary}},{{/isPrimary}} + name:"{{name}}" }) {{toPropertyName name}}:{{ts_type}}; {{/relations}}{{#relations}} @{{relationType}}(type=>{{toEntityName relatedTable}}, {{toPropertyName ../name}}=>{{toPropertyName ../name}}.{{#if isOwner}}{{toPropertyName ownerColumn}}{{else}}{{toPropertyName relatedColumn}}{{/if}}){{#isOwner}} - @JoinColumn({ name:'{{toPropertyName ../name}}'}){{/isOwner}} + @JoinColumn({ name:'{{ ../name}}'}){{/isOwner}} {{#if isOneToMany}}{{toPropertyName ../name}}:{{toEntityName relatedTable}}[]; {{else}}{{toPropertyName ../name}}:{{toEntityName relatedTable}}; {{/if}}{{/relations}} - {{"\n"}} {{/Columns}} } diff --git a/src/index.ts b/src/index.ts index 5a15798..52ca469 100644 --- a/src/index.ts +++ b/src/index.ts @@ -61,9 +61,23 @@ var argv = Yargs describe: `Doesn't create tsconfig.json and ormconfig.json`, default: false }) - .option('c', { - alias: 'case', - describe: 'Convert snake_case tables names to PascalCase entities and snake_case columns to camelCase properties' + .option('cf', { + alias: 'case-file', + describe: 'Convert file names to specified case', + choices: ['pascal', 'param', 'camel', 'none'], + default: 'none' + }) + .option('ce', { + alias: 'case-entity', + describe: 'Convert class names to specified case', + choices: ['pascal', 'camel', 'none'], + default: 'none' + }) + .option('cp', { + alias: 'case-property', + describe: 'Convert property names to specified case', + choices: ['pascal', 'camel', 'none'], + default: 'none' }) .argv; @@ -111,7 +125,9 @@ let engine = new Engine( schemaName: argv.s || standardSchema, ssl: argv.ssl, noConfigs: argv.noConfig, - convertCase: !!argv.c + convertCaseFile: argv.cf, + convertCaseEntity: argv.ce, + convertCaseProperty: argv.cp, }); console.log(`[${new Date().toLocaleTimeString()}] Starting creation of model classes.`); diff --git a/test/utils/GeneralTestUtils.ts b/test/utils/GeneralTestUtils.ts index 26e1fa6..0c1f224 100644 --- a/test/utils/GeneralTestUtils.ts +++ b/test/utils/GeneralTestUtils.ts @@ -9,6 +9,7 @@ import { Engine } from "../../src/Engine"; import { createConnection, ConnectionOptions, Connection } from "typeorm"; import * as yn from "yn" import path = require('path') +import { noCase } from "change-case"; export async function createMSSQLModels(filesOrgPath: string, resultsPath: string): Promise { @@ -51,7 +52,9 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin schemaName: 'dbo', ssl: yn(process.env.MSSQL_SSL), noConfigs: false, - convertCase:false + convertCaseEntity: 'none', + convertCaseFile: 'none', + convertCaseProperty: 'none', }); @@ -96,7 +99,9 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st schemaName: 'public', ssl: yn(process.env.POSTGRES_SSL), noConfigs: false, - convertCase: false + convertCaseEntity: 'none', + convertCaseFile: 'none', + convertCaseProperty: 'none', }); @@ -142,7 +147,9 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin schemaName: 'ignored', ssl: yn(process.env.MYSQL_SSL), noConfigs: false, - convertCase: false + convertCaseEntity: 'none', + convertCaseFile: 'none', + convertCaseProperty: 'none', }); @@ -188,7 +195,9 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str schemaName: 'ignored', ssl: yn(process.env.MARIADB_SSL), noConfigs: false, - convertCase: false + convertCaseEntity: 'none', + convertCaseFile: 'none', + convertCaseProperty: 'none', }); @@ -236,7 +245,10 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st schemaName: String(process.env.ORACLE_Username), ssl: yn(process.env.ORACLE_SSL), noConfigs: false, - convertCase: false + convertCaseEntity: 'none', + convertCaseFile: 'none', + convertCaseProperty: 'none', + });