diff --git a/src/Engine.ts b/src/Engine.ts index df5b3d2..799f321 100644 --- a/src/Engine.ts +++ b/src/Engine.ts @@ -5,9 +5,7 @@ import fs = require("fs"); import path = require("path"); import * as TomgUtils from "./Utils"; import changeCase = require("change-case"); -/** - * Engine - */ + export class Engine { constructor( private driver: AbstractDriver, diff --git a/src/Utils.ts b/src/Utils.ts index 72c601a..d6ba713 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,19 +1,21 @@ -import * as data from "./../../package.json"; +import * as packagejson from "./../../package.json"; export function LogError( errText: string, isABug: boolean = true, errObject?: any ) { - let x = data; console.error(errText); console.error(`Error occured in typeorm-model-generator.`); - console.error(`${x.name}@${x.version} node@${process.version}`); + console.error(`${packageVersion()} node@${process.version}`); console.error( `If you think this is a bug please open an issue including this log on ${ - x.bugs.url + (packagejson).bugs.url }` ); if (isABug && !errObject) errObject = new Error().stack; if (!!errObject) console.error(errObject); // process.abort(); } +export function packageVersion() { + return `${(packagejson).name}@${(packagejson).version}`; +} diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index 95986c8..b3d6103 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -9,9 +9,6 @@ import { WithLengthColumnType } from "./../../node_modules/typeorm/driver/types/ColumnTypes"; -/** - * AbstractDriver - */ export abstract class AbstractDriver { ColumnTypesWithWidth: WithWidthColumnType[] = [ "tinyint", @@ -154,7 +151,180 @@ export abstract class AbstractDriver { password: string, ssl: boolean ); - abstract async GetAllTables(schema: string): Promise; + + abstract GetAllTablesQuery: ( + schema: string + ) => Promise< + { + TABLE_SCHEMA: string; + TABLE_NAME: string; + }[] + >; + + async GetAllTables(schema: string): Promise { + let response = await this.GetAllTablesQuery(schema); + let ret: EntityInfo[] = []; + response.forEach(val => { + let ent: EntityInfo = new EntityInfo(); + ent.EntityName = val.TABLE_NAME; + ent.Schema = val.TABLE_SCHEMA; + ent.Columns = []; + ent.Indexes = []; + ret.push(ent); + }); + return ret; + } + + GetRelationsFromRelationTempInfo( + relationsTemp: RelationTempInfo[], + entities: EntityInfo[] + ) { + relationsTemp.forEach(relationTmp => { + let ownerEntity = entities.find(entitity => { + return entitity.EntityName == relationTmp.ownerTable; + }); + if (!ownerEntity) { + TomgUtils.LogError( + `Relation between tables ${relationTmp.ownerTable} and ${ + relationTmp.referencedTable + } didn't found entity model ${relationTmp.ownerTable}.` + ); + return; + } + let referencedEntity = entities.find(entitity => { + return entitity.EntityName == relationTmp.referencedTable; + }); + if (!referencedEntity) { + TomgUtils.LogError( + `Relation between tables ${relationTmp.ownerTable} and ${ + relationTmp.referencedTable + } didn't found entity model ${relationTmp.referencedTable}.` + ); + return; + } + for ( + let relationColumnIndex = 0; + relationColumnIndex < relationTmp.ownerColumnsNames.length; + relationColumnIndex++ + ) { + let ownerColumn = ownerEntity.Columns.find(column => { + return ( + column.name == + relationTmp.ownerColumnsNames[relationColumnIndex] + ); + }); + if (!ownerColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.ownerTable + }.${ownerColumn}.` + ); + return; + } + let relatedColumn = referencedEntity.Columns.find(column => { + return ( + column.name == + relationTmp.referencedColumnsNames[relationColumnIndex] + ); + }); + if (!relatedColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.referencedTable + }.${relatedColumn}.` + ); + return; + } + let isOneToMany: boolean; + isOneToMany = false; + let index = ownerEntity.Indexes.find(index => { + return ( + index.isUnique && + index.columns.some(col => { + return col.name == ownerColumn!.name; + }) + ); + }); + isOneToMany = !index; + + let ownerRelation = new RelationInfo(); + let columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : ""); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length > 0 + ) { + for (let i = 2; i <= ownerEntity.Columns.length; i++) { + columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : "") + + i.toString(); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length == 0 + ) + break; + } + } + ownerRelation.actionOnDelete = relationTmp.actionOnDelete; + ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; + ownerRelation.isOwner = true; + ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); + ownerRelation.relatedTable = relationTmp.referencedTable; + ownerRelation.ownerTable = relationTmp.ownerTable; + ownerRelation.ownerColumn = columnName; + ownerRelation.relationType = isOneToMany + ? "ManyToOne" + : "OneToOne"; + ownerColumn.relations.push(ownerRelation); + if (isOneToMany) { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToMany"; + referencedEntity.Columns.push(col); + } else { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToOne"; + referencedEntity.Columns.push(col); + } + } + }); + return entities; + } abstract async GetCoulmnsFromEntity( entities: EntityInfo[], schema: string @@ -171,7 +341,6 @@ export abstract class AbstractDriver { FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) { dbModel.entities.forEach(entity => { let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey); - entity.Columns.forEach(col => { if ( primaryIndex && @@ -193,7 +362,6 @@ export abstract class AbstractDriver { }); } abstract async DisconnectFromServer(); - abstract async CreateDB(dbName: string); abstract async DropDB(dbName: string); abstract async UseDB(dbName: string); diff --git a/src/drivers/MariaDbDriver.ts b/src/drivers/MariaDbDriver.ts index 52309f8..e0633a7 100644 --- a/src/drivers/MariaDbDriver.ts +++ b/src/drivers/MariaDbDriver.ts @@ -1,13 +1,5 @@ -import { AbstractDriver } from "./AbstractDriver"; -import * as MariaDb from "mysql"; -import { ColumnInfo } from "./../models/ColumnInfo"; -import { EntityInfo } from "./../models/EntityInfo"; -import { RelationInfo } from "./../models/RelationInfo"; -import { DatabaseModel } from "./../models/DatabaseModel"; import { MysqlDriver } from "./MysqlDriver"; -/** - * MariaDb - */ + export class MariaDbDriver extends MysqlDriver { readonly EngineName: string = "MariaDb"; } diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 4f9605f..0b03735 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -2,15 +2,10 @@ import { AbstractDriver } from "./AbstractDriver"; import * as MSSQL from "mssql"; import { ColumnInfo } from "./../models/ColumnInfo"; import { EntityInfo } from "./../models/EntityInfo"; -import { RelationInfo } from "./../models/RelationInfo"; -import { DatabaseModel } from "./../models/DatabaseModel"; import * as TomgUtils from "./../Utils"; -/** - * MssqlDriver - */ export class MssqlDriver extends AbstractDriver { - async GetAllTables(schema: string): Promise { + GetAllTablesQuery = async (schema: string) => { let request = new MSSQL.Request(this.Connection); let response: { TABLE_SCHEMA: string; @@ -18,17 +13,9 @@ export class MssqlDriver extends AbstractDriver { }[] = (await request.query( `SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema})` )).recordset; - let ret: EntityInfo[] = []; - response.forEach(val => { - let ent: EntityInfo = new EntityInfo(); - ent.EntityName = val.TABLE_NAME; - ent.Schema = val.TABLE_SCHEMA; - ent.Columns = []; - ent.Indexes = []; - ret.push(ent); - }); - return ret; - } + return response; + }; + async GetCoulmnsFromEntity( entities: EntityInfo[], schema: string @@ -217,15 +204,13 @@ export class MssqlDriver extends AbstractDriver { IndexName: string; ColumnName: string; is_unique: number; - is_primary_key: number; //, is_descending_key: number//, is_included_column: number + is_primary_key: number; }[] = (await request.query(`SELECT TableName = t.name, IndexName = ind.name, ColumnName = col.name, ind.is_unique, ind.is_primary_key - -- ,ic.is_descending_key, - -- ic.is_included_column FROM sys.indexes ind INNER JOIN @@ -259,14 +244,11 @@ ORDER BY } else { indexInfo.columns = []; indexInfo.name = resp.IndexName; - indexInfo.isUnique = resp.is_unique == 1 ? true : false; - indexInfo.isPrimaryKey = - resp.is_primary_key == 1 ? true : false; + indexInfo.isUnique = resp.is_unique == 1; + indexInfo.isPrimaryKey = resp.is_primary_key == 1; ent.Indexes.push(indexInfo); } indexColumnInfo.name = resp.ColumnName; - // indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false; - // indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false; indexInfo.columns.push(indexColumnInfo); }); }); @@ -355,155 +337,10 @@ order by rels.ownerColumnsNames.push(resp.ForeignKeyColumn); rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced); }); - relationsTemp.forEach(relationTmp => { - let ownerEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.ownerTable; - }); - if (!ownerEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.ownerTable}.` - ); - return; - } - let referencedEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.referencedTable; - }); - if (!referencedEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.referencedTable}.` - ); - return; - } - for ( - let relationColumnIndex = 0; - relationColumnIndex < relationTmp.ownerColumnsNames.length; - relationColumnIndex++ - ) { - let ownerColumn = ownerEntity.Columns.find(column => { - return ( - column.name == - relationTmp.ownerColumnsNames[relationColumnIndex] - ); - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return ( - column.name == - relationTmp.referencedColumnsNames[relationColumnIndex] - ); - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 - ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; - } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany - ? "ManyToOne" - : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; - - referencedEntity.Columns.push(col); - } - } - }); + entities = this.GetRelationsFromRelationTempInfo( + relationsTemp, + entities + ); return entities; } async DisconnectFromServer() { @@ -526,7 +363,7 @@ order by user: user, password: password, options: { - encrypt: ssl, // Use this if you're on Windows Azure + encrypt: ssl, appName: "typeorm-model-generator" } }; @@ -534,7 +371,6 @@ order by let promise = new Promise((resolve, reject) => { this.Connection = new MSSQL.ConnectionPool(config, err => { if (!err) { - //Connection successfull resolve(true); } else { TomgUtils.LogError( @@ -551,15 +387,15 @@ order by } async CreateDB(dbName: string) { let request = new MSSQL.Request(this.Connection); - let resp = await request.query(`CREATE DATABASE ${dbName}; `); + await request.query(`CREATE DATABASE ${dbName}; `); } async UseDB(dbName: string) { let request = new MSSQL.Request(this.Connection); - let resp = await request.query(`USE ${dbName}; `); + await request.query(`USE ${dbName}; `); } async DropDB(dbName: string) { let request = new MSSQL.Request(this.Connection); - let resp = await request.query(`DROP DATABASE ${dbName}; `); + await request.query(`DROP DATABASE ${dbName}; `); } async CheckIfDBExists(dbName: string): Promise { let request = new MSSQL.Request(this.Connection); diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 6c7ab16..d091150 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -2,33 +2,22 @@ import { AbstractDriver } from "./AbstractDriver"; import * as MYSQL from "mysql"; import { ColumnInfo } from "./../models/ColumnInfo"; import { EntityInfo } from "./../models/EntityInfo"; -import { RelationInfo } from "./../models/RelationInfo"; -import { DatabaseModel } from "./../models/DatabaseModel"; import * as TomgUtils from "./../Utils"; -/** - * MysqlDriver - */ + export class MysqlDriver extends AbstractDriver { readonly EngineName: string = "MySQL"; - async GetAllTables(schema: string): Promise { - let response = await this.ExecQuery<{ + GetAllTablesQuery = async (schema: string) => { + let response = this.ExecQuery<{ TABLE_SCHEMA: string; TABLE_NAME: string; }>(`SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema like DATABASE()`); - let ret: EntityInfo[] = []; - response.forEach(val => { - let ent: EntityInfo = new EntityInfo(); - ent.EntityName = val.TABLE_NAME; - ent.Columns = []; - ent.Indexes = []; - ret.push(ent); - }); - return ret; - } + return response; + }; + async GetCoulmnsFromEntity( entities: EntityInfo[], schema: string @@ -228,7 +217,7 @@ export class MysqlDriver extends AbstractDriver { IndexName: string; ColumnName: string; is_unique: number; - is_primary_key: number; //, is_descending_key: number//, is_included_column: number + is_primary_key: number; }>(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique, CASE WHEN INDEX_NAME='PRIMARY' THEN 1 ELSE 0 END is_primary_key FROM information_schema.statistics sta @@ -253,14 +242,11 @@ export class MysqlDriver extends AbstractDriver { } else { indexInfo.columns = []; indexInfo.name = resp.IndexName; - indexInfo.isUnique = resp.is_unique == 1 ? true : false; - indexInfo.isPrimaryKey = - resp.is_primary_key == 1 ? true : false; + indexInfo.isUnique = resp.is_unique == 1; + indexInfo.isPrimaryKey = resp.is_primary_key == 1; ent.Indexes.push(indexInfo); } indexColumnInfo.name = resp.ColumnName; - // indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false; - // indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false; indexInfo.columns.push(indexColumnInfo); }); }); @@ -318,162 +304,16 @@ export class MysqlDriver extends AbstractDriver { rels.ownerColumnsNames.push(resp.ForeignKeyColumn); rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced); }); - relationsTemp.forEach(relationTmp => { - let ownerEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.ownerTable; - }); - if (!ownerEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.ownerTable}.` - ); - return; - } - let referencedEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.referencedTable; - }); - if (!referencedEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.referencedTable}.` - ); - return; - } - for ( - let relationColumnIndex = 0; - relationColumnIndex < relationTmp.ownerColumnsNames.length; - relationColumnIndex++ - ) { - let ownerColumn = ownerEntity.Columns.find(column => { - return ( - column.name == - relationTmp.ownerColumnsNames[relationColumnIndex] - ); - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return ( - column.name == - relationTmp.referencedColumnsNames[relationColumnIndex] - ); - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 - ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; - } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany - ? "ManyToOne" - : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; - - referencedEntity.Columns.push(col); - } - } - }); + entities = this.GetRelationsFromRelationTempInfo( + relationsTemp, + entities + ); return entities; } async DisconnectFromServer() { let promise = new Promise((resolve, reject) => { this.Connection.end(err => { if (!err) { - //Connection successfull resolve(true); } else { TomgUtils.LogError( @@ -485,7 +325,6 @@ export class MysqlDriver extends AbstractDriver { } }); }); - if (this.Connection) await promise; } @@ -525,7 +364,6 @@ export class MysqlDriver extends AbstractDriver { this.Connection.connect(err => { if (!err) { - //Connection successfull resolve(true); } else { TomgUtils.LogError( @@ -541,13 +379,13 @@ export class MysqlDriver extends AbstractDriver { await promise; } async CreateDB(dbName: string) { - let resp = await this.ExecQuery(`CREATE DATABASE ${dbName}; `); + await this.ExecQuery(`CREATE DATABASE ${dbName}; `); } async UseDB(dbName: string) { - let resp = await this.ExecQuery(`USE ${dbName}; `); + await this.ExecQuery(`USE ${dbName}; `); } async DropDB(dbName: string) { - let resp = await this.ExecQuery(`DROP DATABASE ${dbName}; `); + await this.ExecQuery(`DROP DATABASE ${dbName}; `); } async CheckIfDBExists(dbName: string): Promise { let resp = await this.ExecQuery( @@ -557,13 +395,13 @@ export class MysqlDriver extends AbstractDriver { } async ExecQuery(sql: string): Promise> { let ret: Array = []; - let that = this; let query = this.Connection.query(sql); let stream = query.stream({}); let promise = new Promise((resolve, reject) => { stream.on("data", chunk => { ret.push((chunk)); }); + stream.on("error", err => reject(err)); stream.on("end", () => resolve(true)); }); await promise; diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index 903dd53..563ef7e 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -1,15 +1,8 @@ import { AbstractDriver } from "./AbstractDriver"; import { ColumnInfo } from "./../models/ColumnInfo"; import { EntityInfo } from "./../models/EntityInfo"; -import { RelationInfo } from "./../models/RelationInfo"; -import { DatabaseModel } from "./../models/DatabaseModel"; -import { promisify } from "util"; -import { request } from "https"; import * as TomgUtils from "./../Utils"; -/** - * OracleDriver - */ export class OracleDriver extends AbstractDriver { Oracle: any; constructor() { @@ -22,20 +15,16 @@ export class OracleDriver extends AbstractDriver { } } - async GetAllTables(schema: string): Promise { - let response: { TABLE_NAME: string }[] = (await this.Connection.execute( - ` SELECT TABLE_NAME FROM all_tables WHERE owner = (select user from dual)` + GetAllTablesQuery = async (schema: string) => { + let response: { + TABLE_SCHEMA: string; + TABLE_NAME: string; + }[] = (await this.Connection.execute( + ` SELECT NULL AS TABLE_SCHEMA, TABLE_NAME FROM all_tables WHERE owner = (select user from dual)` )).rows!; - let ret: EntityInfo[] = []; - response.forEach(val => { - let ent: EntityInfo = new EntityInfo(); - ent.EntityName = val.TABLE_NAME; - ent.Columns = []; - ent.Indexes = []; - ret.push(ent); - }); - return ret; - } + return response; + }; + async GetCoulmnsFromEntity( entities: EntityInfo[], schema: string @@ -67,9 +56,8 @@ export class OracleDriver extends AbstractDriver { .forEach(resp => { let colInfo: ColumnInfo = new ColumnInfo(); colInfo.name = resp.COLUMN_NAME; - colInfo.is_nullable = resp.NULLABLE == "Y" ? true : false; - colInfo.is_generated = - resp.IDENTITY_COLUMN == "YES" ? true : false; + colInfo.is_nullable = resp.NULLABLE == "Y"; + colInfo.is_generated = resp.IDENTITY_COLUMN == "YES"; colInfo.default = !resp.DATA_DEFAULT || resp.DATA_DEFAULT.includes('"') ? null @@ -284,155 +272,10 @@ export class OracleDriver extends AbstractDriver { rels.ownerColumnsNames.push(resp.OWNER_COLUMN_NAME); rels.referencedColumnsNames.push(resp.CHILD_COLUMN_NAME); }); - relationsTemp.forEach(relationTmp => { - let ownerEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.ownerTable; - }); - if (!ownerEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.ownerTable}.` - ); - return; - } - let referencedEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.referencedTable; - }); - if (!referencedEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.referencedTable}.` - ); - return; - } - for ( - let relationColumnIndex = 0; - relationColumnIndex < relationTmp.ownerColumnsNames.length; - relationColumnIndex++ - ) { - let ownerColumn = ownerEntity.Columns.find(column => { - return ( - column.name == - relationTmp.ownerColumnsNames[relationColumnIndex] - ); - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return ( - column.name == - relationTmp.referencedColumnsNames[relationColumnIndex] - ); - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 - ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; - } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany - ? "ManyToOne" - : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; - - referencedEntity.Columns.push(col); - } - } - }); + entities = this.GetRelationsFromRelationTempInfo( + relationsTemp, + entities + ); return entities; } async DisconnectFromServer() { @@ -453,7 +296,6 @@ export class OracleDriver extends AbstractDriver { config /*Oracle.IConnectionAttributes*/ = { user: user, password: password, - // connectString: `${server}:${port}/ORCLCDB.localdomain/${database}`, connectString: `${server}:${port}/${database}`, externalAuth: ssl, privilege: this.Oracle.SYSDBA @@ -462,7 +304,6 @@ export class OracleDriver extends AbstractDriver { config /*Oracle.IConnectionAttributes*/ = { user: user, password: password, - // connectString: `${server}:${port}/ORCLCDB.localdomain/${database}`, connectString: `${server}:${port}/${database}`, externalAuth: ssl }; @@ -471,9 +312,7 @@ export class OracleDriver extends AbstractDriver { let promise = new Promise((resolve, reject) => { this.Oracle.getConnection(config, function(err, connection) { if (!err) { - //Connection successfull that.Connection = connection; - resolve(true); } else { TomgUtils.LogError( @@ -490,17 +329,16 @@ export class OracleDriver extends AbstractDriver { } async CreateDB(dbName: string) { - var x = await this.Connection.execute( + await this.Connection.execute( `CREATE USER ${dbName} IDENTIFIED BY ${String( process.env.ORACLE_Password )}` ); - - var y = await this.Connection.execute(`GRANT CONNECT TO ${dbName}`); + await this.Connection.execute(`GRANT CONNECT TO ${dbName}`); } async UseDB(dbName: string) {} async DropDB(dbName: string) { - var x = await this.Connection.execute(`DROP USER ${dbName} CASCADE`); + await this.Connection.execute(`DROP USER ${dbName} CASCADE`); } async CheckIfDBExists(dbName: string): Promise { var x = await this.Connection.execute( diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index 2ff41d7..5f9e9d2 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -2,34 +2,21 @@ import { AbstractDriver } from "./AbstractDriver"; import * as PG from "pg"; import { ColumnInfo } from "./../models/ColumnInfo"; import { EntityInfo } from "./../models/EntityInfo"; -import { RelationInfo } from "./../models/RelationInfo"; -import { DatabaseModel } from "./../models/DatabaseModel"; import * as TomgUtils from "./../Utils"; -/** - * PostgresDriver - */ + export class PostgresDriver extends AbstractDriver { private Connection: PG.Client; - async GetAllTables(schema: string): Promise { + GetAllTablesQuery = async (schema: string) => { let response: { - table_schema: string; - table_name: string; + TABLE_SCHEMA: string; + TABLE_NAME: string; }[] = (await this.Connection.query( - `SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) ` + `SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) ` )).rows; + return response; + }; - let ret: EntityInfo[] = []; - response.forEach(val => { - let ent: EntityInfo = new EntityInfo(); - ent.EntityName = val.table_name; - ent.Schema = val.table_schema; - ent.Columns = []; - ent.Indexes = []; - ret.push(ent); - }); - return ret; - } async GetCoulmnsFromEntity( entities: EntityInfo[], schema: string @@ -187,11 +174,9 @@ export class PostgresDriver extends AbstractDriver { case "boolean": colInfo.ts_type = "boolean"; break; - /* */ case "enum": colInfo.ts_type = "string"; break; - /* */ case "point": colInfo.ts_type = "string | Object"; break; @@ -222,7 +207,6 @@ export class PostgresDriver extends AbstractDriver { case "macaddr": colInfo.ts_type = "string"; break; - case "tsvector": colInfo.ts_type = "string"; break; @@ -297,7 +281,6 @@ export class PostgresDriver extends AbstractDriver { ? resp.character_maximum_length : null; } - if (colInfo.sql_type) ent.Columns.push(colInfo); }); }); @@ -312,7 +295,7 @@ export class PostgresDriver extends AbstractDriver { indexname: string; columnname: string; is_unique: number; - is_primary_key: number; //, is_descending_key: number//, is_included_column: number + is_primary_key: number; }[] = (await this.Connection.query(`SELECT c.relname AS tablename, i.relname as indexname, @@ -332,10 +315,8 @@ export class PostgresDriver extends AbstractDriver { LEFT JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid - WHERE c.relkind = 'r'::char AND n.nspname in (${schema}) - --AND c.relname = 'nodes' -- Replace with table name, or Comment this for get all tables AND f.attnum > 0 AND i.oid<>0 ORDER BY c.relname,f.attname;`)).rows; @@ -358,17 +339,14 @@ export class PostgresDriver extends AbstractDriver { } else { indexInfo.columns = []; indexInfo.name = resp.indexname; - indexInfo.isUnique = resp.is_unique == 1 ? true : false; - indexInfo.isPrimaryKey = - resp.is_primary_key == 1 ? true : false; + indexInfo.isUnique = resp.is_unique == 1; + indexInfo.isPrimaryKey = resp.is_primary_key == 1; ent.Indexes.push(indexInfo); } indexColumnInfo.name = resp.columnname; if (resp.is_primary_key == 0) { indexInfo.isPrimaryKey = false; } - // indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false; - //indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false; indexInfo.columns.push(indexColumnInfo); }); }); @@ -447,155 +425,10 @@ export class PostgresDriver extends AbstractDriver { rels.ownerColumnsNames.push(resp.foreignkeycolumn); rels.referencedColumnsNames.push(resp.foreignkeycolumnreferenced); }); - relationsTemp.forEach(relationTmp => { - let ownerEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.ownerTable; - }); - if (!ownerEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.ownerTable}.` - ); - return; - } - let referencedEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.referencedTable; - }); - if (!referencedEntity) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.referencedTable}.` - ); - return; - } - for ( - let relationColumnIndex = 0; - relationColumnIndex < relationTmp.ownerColumnsNames.length; - relationColumnIndex++ - ) { - let ownerColumn = ownerEntity.Columns.find(column => { - return ( - column.name == - relationTmp.ownerColumnsNames[relationColumnIndex] - ); - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return ( - column.name == - relationTmp.referencedColumnsNames[relationColumnIndex] - ); - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 - ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; - } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany - ? "ManyToOne" - : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionondelete = - relationTmp.actionOnDelete; - referencedRelation.actiononupdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionondelete = - relationTmp.actionOnDelete; - referencedRelation.actiononupdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; - - referencedEntity.Columns.push(col); - } - } - }); + entities = this.GetRelationsFromRelationTempInfo( + relationsTemp, + entities + ); return entities; } async DisconnectFromServer() { @@ -603,7 +436,6 @@ export class PostgresDriver extends AbstractDriver { let promise = new Promise((resolve, reject) => { this.Connection.end(err => { if (!err) { - //Connection successfull resolve(true); } else { TomgUtils.LogError( @@ -639,7 +471,6 @@ export class PostgresDriver extends AbstractDriver { let promise = new Promise((resolve, reject) => { this.Connection.connect(err => { if (!err) { - //Connection successfull resolve(true); } else { TomgUtils.LogError( @@ -656,13 +487,13 @@ export class PostgresDriver extends AbstractDriver { } async CreateDB(dbName: string) { - let resp = await this.Connection.query(`CREATE DATABASE ${dbName}; `); + await this.Connection.query(`CREATE DATABASE ${dbName}; `); } async UseDB(dbName: string) { - let resp = await this.Connection.query(`USE ${dbName}; `); + await this.Connection.query(`USE ${dbName}; `); } async DropDB(dbName: string) { - let resp = await this.Connection.query(`DROP DATABASE ${dbName}; `); + await this.Connection.query(`DROP DATABASE ${dbName}; `); } async CheckIfDBExists(dbName: string): Promise { let resp = await this.Connection.query( diff --git a/src/drivers/SqliteDriver.ts b/src/drivers/SqliteDriver.ts index 3e4d6f5..563d40e 100644 --- a/src/drivers/SqliteDriver.ts +++ b/src/drivers/SqliteDriver.ts @@ -1,19 +1,16 @@ import { AbstractDriver } from "./AbstractDriver"; import { ColumnInfo } from "./../models/ColumnInfo"; import { EntityInfo } from "./../models/EntityInfo"; -import { RelationInfo } from "./../models/RelationInfo"; -import { DatabaseModel } from "./../models/DatabaseModel"; import * as TomgUtils from "./../Utils"; -/** - * SqlLiteDriver - */ + export class SqliteDriver extends AbstractDriver { sqlite = require("sqlite3").verbose(); db: any; tablesWithGeneratedPrimaryKey: String[] = new Array(); + GetAllTablesQuery: any; + async GetAllTables(schema: string): Promise { let ret: EntityInfo[] = []; - let rows = await this.ExecQuery<{ tbl_name: string; sql: string }>( `SELECT tbl_name, sql FROM "sqlite_master" WHERE "type" = 'table' AND name NOT LIKE 'sqlite_%'` ); @@ -27,7 +24,6 @@ export class SqliteDriver extends AbstractDriver { } ret.push(ent); }); - return ret; } async GetCoulmnsFromEntity( @@ -56,7 +52,6 @@ export class SqliteDriver extends AbstractDriver { colInfo.is_generated = colInfo.isPrimary && this.tablesWithGeneratedPrimaryKey.includes(ent.EntityName); - switch (colInfo.sql_type) { case "int": colInfo.ts_type = "number"; @@ -228,11 +223,8 @@ export class SqliteDriver extends AbstractDriver { indexInfo.columns = []; indexInfo.name = resp.name; indexInfo.isUnique = resp.unique == 1; - // indexInfo.isPrimaryKey = - // resp.is_primary_key == 1 ? true : false; ent.Indexes.push(indexInfo); } - indexColumnInfo.name = element.name; if ( indexColumnsResponse.length == 1 && @@ -279,149 +271,10 @@ export class SqliteDriver extends AbstractDriver { rels.ownerColumnsNames.push(resp.from); rels.referencedColumnsNames.push(resp.to); }); - relationsTemp.forEach(relationTmp => { - let ownerEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.ownerTable; - }); - if (!ownerEntity) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.ownerTable}.` - ); - return; - } - let referencedEntity = entities.find(entitity => { - return entitity.EntityName == relationTmp.referencedTable; - }); - if (!referencedEntity) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity model ${ - relationTmp.referencedTable - }.` - ); - return; - } - let ownerColumn = ownerEntity.Columns.find(column => { - return column.name == relationTmp.ownerColumnsNames[0]; - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return column.name == relationTmp.referencedColumnsNames[0]; - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 - ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; - } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany - ? "ManyToOne" - : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; - - referencedEntity.Columns.push(col); - } - }); + entities = this.GetRelationsFromRelationTempInfo( + relationsTemp, + entities + ); } return entities; } @@ -465,7 +318,6 @@ export class SqliteDriver extends AbstractDriver { this.db.serialize(() => { this.db.all(sql, [], function(err, row) { if (!err) { - //Connection successfull ret = row; resolve(true); } else { @@ -479,8 +331,7 @@ export class SqliteDriver extends AbstractDriver { }); }); }); - - let x = await promise; + await promise; return ret; } } diff --git a/src/index.ts b/src/index.ts index 967fd3f..c334bce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -149,6 +149,7 @@ let engine = new Engine(driver, { constructor: argv.constructor }); +console.log(TomgUtils.packageVersion()); console.log( `[${new Date().toLocaleTimeString()}] Starting creation of model classes.` ); diff --git a/src/models/ColumnInfo.ts b/src/models/ColumnInfo.ts index 6abea04..1507011 100644 --- a/src/models/ColumnInfo.ts +++ b/src/models/ColumnInfo.ts @@ -1,8 +1,5 @@ import { RelationInfo } from "./RelationInfo"; -import { ColumnType } from "typeorm"; -/** - * ColumnInfo - */ + export class ColumnInfo { name: string = ""; default: string | null = null; diff --git a/src/models/EntityInfo.ts b/src/models/EntityInfo.ts index 8e511f4..024a0e0 100644 --- a/src/models/EntityInfo.ts +++ b/src/models/EntityInfo.ts @@ -1,9 +1,5 @@ import { ColumnInfo } from "./ColumnInfo"; -import * as Handlebars from "handlebars"; -/** - * EntityInfo - */ export class EntityInfo { EntityName: string; Columns: ColumnInfo[]; @@ -14,7 +10,6 @@ export class EntityInfo { GenerateConstructor: boolean; relationImports(): any { - var returnString = ""; var imports: string[] = []; this.Columns.forEach(column => { column.relations.forEach(relation => { diff --git a/src/models/IndexColumnInfo.ts b/src/models/IndexColumnInfo.ts index 7e21e55..c0a130d 100644 --- a/src/models/IndexColumnInfo.ts +++ b/src/models/IndexColumnInfo.ts @@ -1,5 +1,3 @@ interface IndexColumnInfo { name: string; - //isDescending:boolean, - // isIncludedColumn:boolean } diff --git a/src/models/IndexInfo.ts b/src/models/IndexInfo.ts index 53d13a4..df35175 100644 --- a/src/models/IndexInfo.ts +++ b/src/models/IndexInfo.ts @@ -1,6 +1,3 @@ -/** - * IndexInfo - */ interface IndexInfo { name: string; columns: IndexColumnInfo[]; diff --git a/src/models/RelationInfo.ts b/src/models/RelationInfo.ts index a239d10..3a39f87 100644 --- a/src/models/RelationInfo.ts +++ b/src/models/RelationInfo.ts @@ -1,6 +1,4 @@ export class RelationInfo { - [x: string]: any; - isOwner: boolean; relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany"; relatedTable: string; diff --git a/test/drivers/MssqlDriver.test.ts b/test/drivers/MssqlDriver.test.ts index 7ca892a..9649ce1 100644 --- a/test/drivers/MssqlDriver.test.ts +++ b/test/drivers/MssqlDriver.test.ts @@ -12,8 +12,8 @@ class fakeResponse implements MSSQL.IResult { recordset: MSSQL.IRecordSet; rowsAffected: number[]; output: { [key: string]: any; }; - } + class fakeRecordset extends Array implements MSSQL.IRecordSet{ columns: IColumnMetadata; toTable(): Table { @@ -27,16 +27,6 @@ describe('MssqlDriver', function () { beforeEach(() => { driver = new MssqlDriver(); - // sandbox.mock() - // sandbox.stub( (driver).Connection,) - // driver = Sinon.createStubInstance(MssqlDriver); - - // sandbox.stub(MSSQL,'Connection') - // .callsFake( (a,b)=>{ - // console.log(a) - // b({message:'a'}) - // }) - // sandbox.stub(MSSQL.) }) afterEach(() => { @@ -48,15 +38,12 @@ describe('MssqlDriver', function () { .returns( { query: (q) => { - let response = new fakeResponse(); - response.recordset = new fakeRecordset(); response.recordset.push({ TABLE_SCHEMA: 'schema', TABLE_NAME: 'name' }) return response; } - } - ) + }) let result = await driver.GetAllTables('schema') let expectedResult = []; let y = new EntityInfo(); @@ -82,9 +69,7 @@ describe('MssqlDriver', function () { }) return response; } - } - ) - + }) let entities = []; let y = new EntityInfo(); diff --git a/test/integration/entityTypes.test.ts b/test/integration/entityTypes.test.ts index 6e37a8a..a4ffab0 100644 --- a/test/integration/entityTypes.test.ts +++ b/test/integration/entityTypes.test.ts @@ -1,10 +1,8 @@ require('dotenv').config() import "reflect-metadata"; -import { createConnection, ConnectionOptions, Connection } from "typeorm"; import fs = require('fs-extra'); import path = require('path') import { expect } from "chai"; -import * as Sinon from 'sinon' import { EntityFileToJson } from "../utils/EntityFileToJson"; var chai = require('chai'); var chaiSubset = require('chai-subset'); @@ -14,7 +12,6 @@ import { Engine } from "./../../src/Engine"; chai.use(chaiSubset); - describe("Platform specyfic types", async function () { this.timeout(30000) this.slow(5000)//compiling created models takes time @@ -27,13 +24,11 @@ describe("Platform specyfic types", async function () { if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql') if (process.env.ORACLE_Skip == '0') dbDrivers.push('oracle') - let examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/entityTypes') let examplesPathTS = path.resolve(process.cwd(), 'test/integration/entityTypes') let files = fs.readdirSync(examplesPathTS) for (let dbDriver of dbDrivers) { - for (let folder of files) { if (dbDriver == folder) { it(dbDriver, async function () { @@ -63,16 +58,13 @@ describe("Platform specyfic types", async function () { case 'oracle': engine = await GTU.createOracleDBModels(filesOrgPathJS, resultsPath) break; - default: console.log(`Unknown engine type`); engine = {} break; } - - let result = await engine.createModelFromDatabase() - + await engine.createModelFromDatabase() let filesGenPath = path.resolve(resultsPath, 'entities') let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') }) @@ -91,7 +83,6 @@ describe("Platform specyfic types", async function () { return path.resolve(filesGenPath, v) }) let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, { - experimentalDecorators: true, sourceMap: false, emitDecoratorMetadata: true, diff --git a/test/integration/githubIssues.test.ts b/test/integration/githubIssues.test.ts index ef912d7..02edcc0 100644 --- a/test/integration/githubIssues.test.ts +++ b/test/integration/githubIssues.test.ts @@ -9,7 +9,6 @@ import * as Sinon from 'sinon' import { EntityFileToJson } from "../utils/EntityFileToJson"; var chai = require('chai'); var chaiSubset = require('chai-subset'); -import * as yn from "yn" import * as ts from "typescript"; import * as GTU from "../utils/GeneralTestUtils" @@ -79,13 +78,11 @@ describe("GitHub issues", async function () { break; } - - let result = await engine.createModelFromDatabase() - + await engine.createModelFromDatabase() let filesGenPath = path.resolve(resultsPath, 'entities') - let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') }) - let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') }) + let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val) { return val.toString().endsWith('.ts') }) + let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val) { return val.toString().endsWith('.ts') }) expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen) @@ -100,7 +97,6 @@ describe("GitHub issues", async function () { return path.resolve(filesGenPath, v) }) let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, { - experimentalDecorators: true, sourceMap: false, emitDecoratorMetadata: true, diff --git a/test/integration/integration.test.ts b/test/integration/integration.test.ts index 98ed100..1900d8e 100644 --- a/test/integration/integration.test.ts +++ b/test/integration/integration.test.ts @@ -1,21 +1,17 @@ require('dotenv').config() import "reflect-metadata"; -import { createConnection, ConnectionOptions, Connection } from "typeorm"; import fs = require('fs-extra'); import path = require('path') import { Engine } from "./../../src/Engine"; import { expect } from "chai"; -import * as Sinon from 'sinon' import { EntityFileToJson } from "../utils/EntityFileToJson"; var chai = require('chai'); var chaiSubset = require('chai-subset'); -import * as yn from "yn" import * as ts from "typescript"; import * as GTU from "../utils/GeneralTestUtils" chai.use(chaiSubset); - describe("TypeOrm examples", async function () { this.timeout(30000) this.slow(5000)//compiling created models takes time @@ -33,11 +29,9 @@ describe("TypeOrm examples", async function () { let files = fs.readdirSync(examplesPathTS) for (let folder of files) { - describe(folder, async function () { for (let dbDriver of dbDrivers) { it(dbDriver, async function () { - let filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity') let filesOrgPathTS = path.resolve(examplesPathTS, folder, 'entity') let resultsPath = path.resolve(process.cwd(), `output`) @@ -63,7 +57,6 @@ describe("TypeOrm examples", async function () { case 'oracle': engine = await GTU.createOracleDBModels(filesOrgPathJS, resultsPath) break; - default: console.log(`Unknown engine type`); engine = {} @@ -73,12 +66,11 @@ describe("TypeOrm examples", async function () { engine.Options.lazy = true; } - let result = await engine.createModelFromDatabase() - + await engine.createModelFromDatabase() let filesGenPath = path.resolve(resultsPath, 'entities') - let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') }) - let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') }) + let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val) { return val.toString().endsWith('.ts') }) + let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val) { return val.toString().endsWith('.ts') }) expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen) @@ -93,7 +85,6 @@ describe("TypeOrm examples", async function () { return path.resolve(filesGenPath, v) }) let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, { - experimentalDecorators: true, sourceMap: false, emitDecoratorMetadata: true, diff --git a/test/utils/EntityFileToJson.ts b/test/utils/EntityFileToJson.ts index 15da64e..3b91d7c 100644 --- a/test/utils/EntityFileToJson.ts +++ b/test/utils/EntityFileToJson.ts @@ -1,10 +1,7 @@ -import { debug } from "util"; -import { param } from "change-case"; export class EntityFileToJson { getEntityOptions(trimmedLine: string, ent: EntityJson) { let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')')) - if (decoratorParameters.length > 0) { if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) { @@ -19,13 +16,9 @@ export class EntityFileToJson { } getColumnOptionsAndType(trimmedLine: string, col: EntityColumn) { let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')')) - if (decoratorParameters.length > 0) { if (decoratorParameters.search(',') > 0) { col.columnTypes = decoratorParameters.substring(0, decoratorParameters.indexOf(',')).trim().split('|').map(function (x) { - // if (!x.endsWith('[]')) { - // x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes - // } return x; }); let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim() @@ -36,9 +29,6 @@ export class EntityFileToJson { } else { if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) { col.columnTypes = decoratorParameters.split('|').map(function (x) { - // if (!x.endsWith('[]')) { - // x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes - // } x = x.trim(); return x; }); @@ -75,7 +65,6 @@ export class EntityFileToJson { let containsOptions = decoratorParameters.search('{') > -1 let containsName = decoratorParameters.search('"') > -1//TODO:no name, but fields as string[] if (containsName) { - ind.indexName = decoratorParameters.slice(decoratorParameters.indexOf('"') + 1, decoratorParameters.substr(decoratorParameters.indexOf('"') + 1).indexOf('"')) } if (containsTables) { @@ -91,7 +80,6 @@ export class EntityFileToJson { }).filter(v => { return v.length > 0 })) - } if (containsOptions) { let optionsStr = decoratorParameters.slice(decoratorParameters.indexOf('{') + 1, decoratorParameters.indexOf('}')) @@ -101,7 +89,6 @@ export class EntityFileToJson { case "unique": ind.isUnique = optionsStr.split(':')[1].trim() == 'true' ? true : false; break; - default: console.log(`[EntityFileToJson:convert] Index option not recognized ${ind.indexName}:`) console.log(`${optionsStr}`) @@ -109,9 +96,7 @@ export class EntityFileToJson { } } }) - } - } } @@ -126,23 +111,21 @@ export class EntityFileToJson { for (let line of lines) { let trimmedLine = line.trim(); if (trimmedLine.startsWith('//')) { - continue; //commented line + continue; } if (isMultilineStatement) trimmedLine = priorPartOfMultilineStatement + ' ' + trimmedLine if (trimmedLine.length == 0) - continue;//empty line - + continue; else if (!isInClassBody) { if (trimmedLine.startsWith('import')) { - continue; //import statement is not part of entity definition + continue; } else if (trimmedLine.startsWith('@Entity')) { if (this.isPartOfMultilineStatement(trimmedLine)) { isMultilineStatement = true; priorPartOfMultilineStatement = trimmedLine; continue; } else { - let options = trimmedLine.substring(trimmedLine.lastIndexOf('{'), trimmedLine.lastIndexOf('}') + 1).trim().toLowerCase() this.getEntityOptions(trimmedLine, retVal); continue; } @@ -176,7 +159,6 @@ export class EntityFileToJson { retVal.columns.push(col); continue; } - } else if (trimmedLine.startsWith('@PrimaryColumn')) { if (this.isPartOfMultilineStatement(trimmedLine)) { isMultilineStatement = true; @@ -319,9 +301,6 @@ export class EntityFileToJson { if (x == 'any') { x = 'string' //for json columns } - // if (!x.endsWith('[]')) { - // x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes - // } x = x.trim(); return x; }); @@ -335,14 +314,13 @@ export class EntityFileToJson { continue } else if (trimmedLine == '}') { isInClassBody = false; - continue; //class declaration end + continue; } else { console.log(`[EntityFileToJson:convert] Line not recognized in entity ${retVal.entityName}:`) console.log(`${trimmedLine}`) } } - console.log(`[EntityFileToJson:convert] Line not recognized in entity ${retVal.entityName}:`) console.log(`${trimmedLine}`) } @@ -365,14 +343,12 @@ export class EntityFileToJson { isPartOfMultilineStatement(statement: string) { let matchStarting = statement.split('(').length+statement.split('{').length let matchEnding = statement.split(')').length+statement.split('}').length - return !(matchStarting == matchEnding) } } class EntityJson { entityName: string entityOptions: any = {} - columns: EntityColumn[] = []; indicies: EntityIndex[] = []; } diff --git a/test/utils/GeneralTestUtils.ts b/test/utils/GeneralTestUtils.ts index 83012ad..b9b9d0f 100644 --- a/test/utils/GeneralTestUtils.ts +++ b/test/utils/GeneralTestUtils.ts @@ -7,10 +7,9 @@ import { MariaDbDriver } from "../../src/drivers/MariaDbDriver"; import { OracleDriver } from "../../src/drivers/OracleDriver"; import { SqliteDriver } from "../../src/drivers/SqliteDriver"; import { Engine } from "../../src/Engine"; -import { createConnection, ConnectionOptions, Connection } from "typeorm"; +import { createConnection, ConnectionOptions } 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 { @@ -24,7 +23,6 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin await driver.DisconnectFromServer(); let connOpt: ConnectionOptions = { - database: String(process.env.MSSQL_Database), host: String(process.env.MSSQL_Host), password: String(process.env.MSSQL_Password), @@ -245,8 +243,6 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin constructor:false }); - - return engine; } export async function createMariaDBModels(filesOrgPath: string, resultsPath: string): Promise { @@ -260,7 +256,6 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str await driver.DisconnectFromServer(); let connOpt: ConnectionOptions = { - database: String(process.env.MARIADB_Database), host: String(process.env.MARIADB_Host), password: String(process.env.MARIADB_Password), @@ -312,7 +307,6 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st await driver.DisconnectFromServer(); let connOpt: ConnectionOptions = { - database: String(process.env.ORACLE_Database), sid: String(process.env.ORACLE_Database), host: String(process.env.ORACLE_Host), @@ -320,7 +314,6 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st type: 'oracle', username: String(process.env.ORACLE_Username), port: Number(process.env.ORACLE_Port), - // dropSchema: true, synchronize: true, entities: [path.resolve(filesOrgPath, '*.js')], }