code cleanup, introducing tslint

This commit is contained in:
Kononnable 2018-12-08 10:46:18 +01:00
parent 69a2362890
commit a4592ffb4d
26 changed files with 857 additions and 670 deletions

View File

@ -23,3 +23,4 @@ codecov.yml
tsconfig.json
typings.json
dist/test/
src/tslint.json

117
package-lock.json generated
View File

@ -338,6 +338,59 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
},
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
"requires": {
"chalk": "^1.1.3",
"esutils": "^2.0.2",
"js-tokens": "^3.0.2"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
},
"chalk": {
"version": "1.1.3",
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
}
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@ -2147,6 +2200,12 @@
"resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
"integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8="
},
"js-tokens": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
"dev": true
},
"js-yaml": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
@ -3510,6 +3569,12 @@
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
},
"path-to-regexp": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
@ -4889,6 +4954,58 @@
"integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==",
"dev": true
},
"tslint": {
"version": "5.11.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz",
"integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=",
"dev": true,
"requires": {
"babel-code-frame": "^6.22.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
"commander": "^2.12.1",
"diff": "^3.2.0",
"glob": "^7.1.1",
"js-yaml": "^3.7.0",
"minimatch": "^3.0.4",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.8.0",
"tsutils": "^2.27.2"
},
"dependencies": {
"resolve": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
"integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
"dev": true,
"requires": {
"path-parse": "^1.0.5"
}
},
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
"dev": true
}
}
},
"tslint-config-prettier": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.17.0.tgz",
"integrity": "sha512-NKWNkThwqE4Snn4Cm6SZB7lV5RMDDFsBwz6fWUkTxOKGjMx8ycOHnjIbhn7dZd5XmssW3CwqUjlANR6EhP9YQw==",
"dev": true
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",

View File

@ -65,6 +65,8 @@
"remap-istanbul": "^0.12.0",
"rimraf": "^2.6.2",
"sinon": "^6.0.0",
"sinon-chai": "^3.0.0"
"sinon-chai": "^3.0.0",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.17.0"
}
}

View File

@ -1,14 +1,14 @@
import { RelationInfo } from "./models/RelationInfo";
import { DatabaseModel } from "./models/DatabaseModel";
import { RelationInfo } from "./models/RelationInfo";
export abstract class AbstractNamingStrategy {
abstract relationName(
public abstract relationName(
columnName: string,
relation: RelationInfo,
dbModel: DatabaseModel
): string;
abstract entityName(entityName: string): string;
public abstract entityName(entityName: string): string;
abstract columnName(columnName: string): string;
public abstract columnName(columnName: string): string;
}

View File

@ -1,11 +1,11 @@
import changeCase = require("change-case");
import fs = require("fs");
import * as Handlebars from "handlebars";
import path = require("path");
import { AbstractNamingStrategy } from "./AbstractNamingStrategy";
import { AbstractDriver } from "./drivers/AbstractDriver";
import { DatabaseModel } from "./models/DatabaseModel";
import * as Handlebars from "handlebars";
import fs = require("fs");
import path = require("path");
import * as TomgUtils from "./Utils";
import changeCase = require("change-case");
import { AbstractNamingStrategy } from "./AbstractNamingStrategy";
export class Engine {
constructor(
@ -14,7 +14,7 @@ export class Engine {
) {}
public async createModelFromDatabase(): Promise<boolean> {
let dbModel = await this.getEntitiesInfo(
const dbModel = await this.getEntitiesInfo(
this.Options.databaseName,
this.Options.host,
this.Options.port,
@ -60,18 +60,24 @@ export class Engine {
}
private createModelFromMetadata(databaseModel: DatabaseModel) {
this.createHandlebarsHelpers();
let templatePath = path.resolve(__dirname, "../../src/entity.mst");
let template = fs.readFileSync(templatePath, "UTF-8");
let resultPath = this.Options.resultsPath;
if (!fs.existsSync(resultPath)) fs.mkdirSync(resultPath);
const templatePath = path.resolve(__dirname, "../../src/entity.mst");
const template = fs.readFileSync(templatePath, "UTF-8");
const resultPath = this.Options.resultsPath;
if (!fs.existsSync(resultPath)) {
fs.mkdirSync(resultPath);
}
let entitesPath = resultPath;
if (!this.Options.noConfigs) {
this.createTsConfigFile(resultPath);
this.createTypeOrmConfig(resultPath);
entitesPath = path.resolve(resultPath, "./entities");
if (!fs.existsSync(entitesPath)) fs.mkdirSync(entitesPath);
if (!fs.existsSync(entitesPath)) {
fs.mkdirSync(entitesPath);
}
}
let compliedTemplate = Handlebars.compile(template, { noEscape: true });
const compliedTemplate = Handlebars.compile(template, {
noEscape: true
});
databaseModel.entities.forEach(element => {
element.Imports = [];
element.Columns.forEach(column => {
@ -100,11 +106,11 @@ export class Engine {
casedFileName = element.EntityName;
break;
}
let resultFilePath = path.resolve(
const resultFilePath = path.resolve(
entitesPath,
casedFileName + ".ts"
);
let rendered = compliedTemplate(element);
const rendered = compliedTemplate(element);
fs.writeFileSync(resultFilePath, rendered, {
encoding: "UTF-8",
flag: "w"
@ -173,8 +179,11 @@ export class Engine {
});
Handlebars.registerHelper("toLowerCase", str => str.toLowerCase());
Handlebars.registerHelper("toLazy", str => {
if (this.Options.lazy) return `Promise<${str}>`;
else return str;
if (this.Options.lazy) {
return `Promise<${str}>`;
} else {
return str;
}
});
Handlebars.registerHelper({
eq: (v1, v2) => v1 === v2,
@ -188,7 +197,7 @@ export class Engine {
});
}
//TODO:Move to mustache template file
// TODO:Move to mustache template file
private createTsConfigFile(resultPath) {
fs.writeFileSync(
path.resolve(resultPath, "tsconfig.json"),

View File

@ -1,15 +1,15 @@
import { AbstractNamingStrategy } from "./AbstractNamingStrategy";
import { RelationInfo } from "./models/RelationInfo";
import { DatabaseModel } from "./models/DatabaseModel";
import { RelationInfo } from "./models/RelationInfo";
export class NamingStrategy extends AbstractNamingStrategy {
relationName(
public relationName(
columnOldName: string,
relation: RelationInfo,
dbModel: DatabaseModel
): string {
let isRelationToMany = relation.isOneToMany || relation.isManyToMany;
let ownerEntity = dbModel.entities.find(
const isRelationToMany = relation.isOneToMany || relation.isManyToMany;
const ownerEntity = dbModel.entities.find(
v => v.EntityName == relation.ownerTable
)!;
@ -51,8 +51,9 @@ export class NamingStrategy extends AbstractNamingStrategy {
v.tsName != columnName ||
columnName == columnOldName
)
)
) {
break;
}
}
}
}
@ -60,11 +61,11 @@ export class NamingStrategy extends AbstractNamingStrategy {
return columnName;
}
entityName(entityName: string): string {
public entityName(entityName: string): string {
return entityName;
}
columnName(columnName: string): string {
public columnName(columnName: string): string {
return columnName;
}
}

View File

@ -9,12 +9,16 @@ export function LogError(
console.error(`${packageVersion()} node@${process.version}`);
console.error(
`If you think this is a bug please open an issue including this log on ${
(<any>packagejson).bugs.url
(packagejson as any).bugs.url
}`
);
if (isABug && !errObject) errObject = new Error().stack;
if (!!errObject) console.error(errObject);
if (isABug && !errObject) {
errObject = new Error().stack;
}
if (!!errObject) {
console.error(errObject);
}
}
export function packageVersion() {
return `${(<any>packagejson).name}@${(<any>packagejson).version}`;
return `${(packagejson as any).name}@${(packagejson as any).version}`;
}

View File

@ -1,119 +1,24 @@
import { EntityInfo } from "../models/EntityInfo";
import { DatabaseModel } from "../models/DatabaseModel";
import * as TomgUtils from "../Utils";
import { RelationInfo } from "../models/RelationInfo";
import { ColumnInfo } from "../models/ColumnInfo";
import {
WithWidthColumnType,
WithLengthColumnType,
WithPrecisionColumnType,
WithLengthColumnType
WithWidthColumnType
} from "typeorm/driver/types/ColumnTypes";
import { AbstractNamingStrategy } from "../AbstractNamingStrategy";
import { ColumnInfo } from "../models/ColumnInfo";
import { DatabaseModel } from "../models/DatabaseModel";
import { EntityInfo } from "../models/EntityInfo";
import { RelationInfo } from "../models/RelationInfo";
import * as TomgUtils from "../Utils";
export abstract class AbstractDriver {
changeColumnNames(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
entity.Columns.forEach(column => {
let newName = this.namingStrategy.columnName(column.tsName);
entity.Indexes.forEach(index => {
index.columns
.filter(column2 => column2.name == column.tsName)
.forEach(column2 => (column2.name = newName));
});
dbModel.entities.forEach(entity2 => {
entity2.Columns.forEach(column2 => {
column2.relations
.filter(
relation =>
relation.relatedTable ==
entity.EntityName &&
relation.relatedColumn == column.tsName
)
.map(v => (v.relatedColumn = newName));
column2.relations
.filter(
relation =>
relation.relatedTable ==
entity.EntityName &&
relation.ownerColumn == column.tsName
)
.map(v => (v.ownerColumn = newName));
});
});
column.tsName = newName;
});
});
}
changeEntityNames(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let newName = this.namingStrategy.entityName(entity.EntityName);
dbModel.entities.forEach(entity2 => {
entity2.Columns.forEach(column => {
column.relations.forEach(relation => {
if (relation.ownerTable == entity.EntityName)
relation.ownerTable = newName;
if (relation.relatedTable == entity.EntityName)
relation.relatedTable = newName;
});
});
});
entity.EntityName = newName;
});
}
changeRelationNames(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
entity.Columns.forEach(column => {
column.relations.forEach(relation => {
let newName = this.namingStrategy.relationName(
column.tsName,
relation,
dbModel
);
dbModel.entities.forEach(entity2 => {
entity2.Columns.forEach(column2 => {
column2.relations.forEach(relation2 => {
if (
relation2.relatedTable ==
entity.EntityName &&
relation2.ownerColumn == column.tsName
) {
relation2.ownerColumn = newName;
}
if (
relation2.relatedTable ==
entity.EntityName &&
relation2.relatedColumn == column.tsName
) {
relation2.relatedColumn = newName;
}
if (relation.isOwner) {
entity.Indexes.forEach(ind => {
ind.columns
.filter(
col => col.name == column.tsName
)
.forEach(
col => (col.name = newName)
);
});
}
});
});
});
column.tsName = newName;
});
});
});
}
ColumnTypesWithWidth: WithWidthColumnType[] = [
public ColumnTypesWithWidth: WithWidthColumnType[] = [
"tinyint",
"smallint",
"mediumint",
"int",
"bigint"
];
ColumnTypesWithPrecision: WithPrecisionColumnType[] = [
public ColumnTypesWithPrecision: WithPrecisionColumnType[] = [
"float",
"double",
"dec",
@ -133,7 +38,7 @@ export abstract class AbstractDriver {
"timestamp with time zone",
"timestamp with local time zone"
];
ColumnTypesWithLength: WithLengthColumnType[] = [
public ColumnTypesWithLength: WithLengthColumnType[] = [
"character varying",
"varying character",
"nvarchar",
@ -148,19 +53,126 @@ export abstract class AbstractDriver {
"binary",
"varbinary"
];
namingStrategy: AbstractNamingStrategy;
generateRelationsIds: boolean;
public namingStrategy: AbstractNamingStrategy;
public generateRelationsIds: boolean;
FindManyToManyRelations(dbModel: DatabaseModel) {
let manyToManyEntities = dbModel.entities.filter(
public abstract GetAllTablesQuery: (
schema: string
) => Promise<
Array<{
TABLE_SCHEMA: string;
TABLE_NAME: string;
}>
>;
public changeColumnNames(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
entity.Columns.forEach(column => {
const newName = this.namingStrategy.columnName(column.tsName);
entity.Indexes.forEach(index => {
index.columns
.filter(column2 => column2.name === column.tsName)
.forEach(column2 => (column2.name = newName));
});
dbModel.entities.forEach(entity2 => {
entity2.Columns.forEach(column2 => {
column2.relations
.filter(
relation =>
relation.relatedTable ===
entity.EntityName &&
relation.relatedColumn === column.tsName
)
.map(v => (v.relatedColumn = newName));
column2.relations
.filter(
relation =>
relation.relatedTable ===
entity.EntityName &&
relation.ownerColumn === column.tsName
)
.map(v => (v.ownerColumn = newName));
});
});
column.tsName = newName;
});
});
}
public changeEntityNames(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
const newName = this.namingStrategy.entityName(entity.EntityName);
dbModel.entities.forEach(entity2 => {
entity2.Columns.forEach(column => {
column.relations.forEach(relation => {
if (relation.ownerTable === entity.EntityName) {
relation.ownerTable = newName;
}
if (relation.relatedTable === entity.EntityName) {
relation.relatedTable = newName;
}
});
});
});
entity.EntityName = newName;
});
}
public changeRelationNames(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
entity.Columns.forEach(column => {
column.relations.forEach(relation => {
const newName = this.namingStrategy.relationName(
column.tsName,
relation,
dbModel
);
dbModel.entities.forEach(entity2 => {
entity2.Columns.forEach(column2 => {
column2.relations.forEach(relation2 => {
if (
relation2.relatedTable ===
entity.EntityName &&
relation2.ownerColumn === column.tsName
) {
relation2.ownerColumn = newName;
}
if (
relation2.relatedTable ===
entity.EntityName &&
relation2.relatedColumn === column.tsName
) {
relation2.relatedColumn = newName;
}
if (relation.isOwner) {
entity.Indexes.forEach(ind => {
ind.columns
.filter(
col =>
col.name === column.tsName
)
.forEach(
col => (col.name = newName)
);
});
}
});
});
});
column.tsName = newName;
});
});
});
}
public FindManyToManyRelations(dbModel: DatabaseModel) {
const manyToManyEntities = dbModel.entities.filter(
entity =>
entity.Columns.filter(column => {
return (
column.relations.length == 1 &&
column.relations.length === 1 &&
!column.relations[0].isOneToMany &&
column.relations[0].isOwner
);
}).length == entity.Columns.length
}).length === entity.Columns.length
);
manyToManyEntities.map(entity => {
let relations: RelationInfo[] = [];
@ -168,12 +180,12 @@ export abstract class AbstractDriver {
(prev: RelationInfo[], curr) => prev.concat(curr.relations),
relations
);
let namesOfRelatedTables = relations
const namesOfRelatedTables = relations
.map(v => v.relatedTable)
.filter((v, i, s) => s.indexOf(v) == i);
if (namesOfRelatedTables.length == 2) {
let relatedTable1 = dbModel.entities.find(
v => v.EntityName == namesOfRelatedTables[0]
.filter((v, i, s) => s.indexOf(v) === i);
if (namesOfRelatedTables.length === 2) {
const relatedTable1 = dbModel.entities.find(
v => v.EntityName === namesOfRelatedTables[0]
)!;
relatedTable1.Columns = relatedTable1.Columns.filter(
v =>
@ -181,8 +193,8 @@ export abstract class AbstractDriver {
.toLowerCase()
.startsWith(entity.EntityName.toLowerCase())
);
let relatedTable2 = dbModel.entities.find(
v => v.EntityName == namesOfRelatedTables[1]
const relatedTable2 = dbModel.entities.find(
v => v.EntityName === namesOfRelatedTables[1]
)!;
relatedTable2.Columns = relatedTable2.Columns.filter(
v =>
@ -191,13 +203,13 @@ export abstract class AbstractDriver {
.startsWith(entity.EntityName.toLowerCase())
);
dbModel.entities = dbModel.entities.filter(ent => {
return ent.EntityName != entity.EntityName;
return ent.EntityName !== entity.EntityName;
});
let column1 = new ColumnInfo();
const column1 = new ColumnInfo();
column1.tsName = namesOfRelatedTables[1];
let col1Rel = new RelationInfo();
const col1Rel = new RelationInfo();
col1Rel.relatedTable = namesOfRelatedTables[1];
col1Rel.relatedColumn = namesOfRelatedTables[1];
@ -208,10 +220,10 @@ export abstract class AbstractDriver {
column1.relations.push(col1Rel);
relatedTable1.Columns.push(column1);
let column2 = new ColumnInfo();
const column2 = new ColumnInfo();
column2.tsName = namesOfRelatedTables[0];
let col2Rel = new RelationInfo();
const col2Rel = new RelationInfo();
col2Rel.relatedTable = namesOfRelatedTables[0];
col2Rel.relatedColumn = namesOfRelatedTables[1];
@ -222,7 +234,7 @@ export abstract class AbstractDriver {
}
});
}
async GetDataFromServer(
public async GetDataFromServer(
database: string,
server: string,
port: number,
@ -234,10 +246,10 @@ export abstract class AbstractDriver {
relationIds: boolean
): Promise<DatabaseModel> {
this.generateRelationsIds = relationIds;
let dbModel = <DatabaseModel>{};
const dbModel = {} as DatabaseModel;
this.namingStrategy = namingStrategy;
await this.ConnectToServer(database, server, port, user, password, ssl);
let sqlEscapedSchema = "'" + schema.split(",").join("','") + "'";
const sqlEscapedSchema = "'" + schema.split(",").join("','") + "'";
dbModel.entities = await this.GetAllTables(sqlEscapedSchema);
await this.GetCoulmnsFromEntity(dbModel.entities, sqlEscapedSchema);
await this.GetIndexesFromEntity(dbModel.entities, sqlEscapedSchema);
@ -252,13 +264,7 @@ export abstract class AbstractDriver {
return dbModel;
}
private ApplyNamingStrategy(dbModel: DatabaseModel) {
this.changeRelationNames(dbModel);
this.changeEntityNames(dbModel);
this.changeColumnNames(dbModel);
}
abstract async ConnectToServer(
public abstract async ConnectToServer(
database: string,
server: string,
port: number,
@ -267,36 +273,27 @@ export abstract class AbstractDriver {
ssl: boolean
);
abstract GetAllTablesQuery: (
schema: string
) => Promise<
{
TABLE_SCHEMA: string;
TABLE_NAME: string;
}[]
>;
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response = await this.GetAllTablesQuery(schema);
let ret: EntityInfo[] = <EntityInfo[]>[];
public async GetAllTables(schema: string): Promise<EntityInfo[]> {
const response = await this.GetAllTablesQuery(schema);
const ret: EntityInfo[] = [] as EntityInfo[];
response.forEach(val => {
let ent: EntityInfo = new EntityInfo();
const ent: EntityInfo = new EntityInfo();
ent.EntityName = val.TABLE_NAME;
ent.Schema = val.TABLE_SCHEMA;
ent.Columns = <ColumnInfo[]>[];
ent.Indexes = <IndexInfo[]>[];
ent.Columns = [] as ColumnInfo[];
ent.Indexes = [] as IndexInfo[];
ret.push(ent);
});
return ret;
}
GetRelationsFromRelationTempInfo(
public GetRelationsFromRelationTempInfo(
relationsTemp: RelationTempInfo[],
entities: EntityInfo[]
) {
relationsTemp.forEach(relationTmp => {
let ownerEntity = entities.find(
entitity => entitity.EntityName == relationTmp.ownerTable
const ownerEntity = entities.find(
entitity => entitity.EntityName === relationTmp.ownerTable
);
if (!ownerEntity) {
TomgUtils.LogError(
@ -306,8 +303,8 @@ export abstract class AbstractDriver {
);
return;
}
let referencedEntity = entities.find(
entitity => entitity.EntityName == relationTmp.referencedTable
const referencedEntity = entities.find(
entitity => entitity.EntityName === relationTmp.referencedTable
);
if (!referencedEntity) {
TomgUtils.LogError(
@ -322,9 +319,9 @@ export abstract class AbstractDriver {
relationColumnIndex < relationTmp.ownerColumnsNames.length;
relationColumnIndex++
) {
let ownerColumn = ownerEntity.Columns.find(
const ownerColumn = ownerEntity.Columns.find(
column =>
column.tsName ==
column.tsName ===
relationTmp.ownerColumnsNames[relationColumnIndex]
);
if (!ownerColumn) {
@ -339,9 +336,9 @@ export abstract class AbstractDriver {
);
return;
}
let relatedColumn = referencedEntity.Columns.find(
const relatedColumn = referencedEntity.Columns.find(
column =>
column.tsName ==
column.tsName ===
relationTmp.referencedColumnsNames[relationColumnIndex]
);
if (!relatedColumn) {
@ -358,16 +355,16 @@ export abstract class AbstractDriver {
}
let isOneToMany: boolean;
isOneToMany = false;
let index = ownerEntity.Indexes.find(
const index = ownerEntity.Indexes.find(
index =>
index.isUnique &&
index.columns.some(
col => col.name == ownerColumn!.tsName
col => col.name === ownerColumn!.tsName
)
);
isOneToMany = !index;
let ownerRelation = new RelationInfo();
const ownerRelation = new RelationInfo();
ownerRelation.actionOnDelete = relationTmp.actionOnDelete;
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate;
ownerRelation.isOwner = true;
@ -381,7 +378,7 @@ export abstract class AbstractDriver {
let columnName = ownerEntity.EntityName;
if (
referencedEntity.Columns.some(v => v.tsName == columnName)
referencedEntity.Columns.some(v => v.tsName === columnName)
) {
columnName = columnName + "_";
for (let i = 2; i <= referencedEntity.Columns.length; i++) {
@ -392,19 +389,20 @@ export abstract class AbstractDriver {
) + i.toString();
if (
referencedEntity.Columns.every(
v => v.tsName != columnName
v => v.tsName !== columnName
)
)
) {
break;
}
}
}
ownerRelation.ownerColumn = columnName;
ownerColumn.relations.push(ownerRelation);
if (isOneToMany) {
let col = new ColumnInfo();
const col = new ColumnInfo();
col.tsName = columnName;
let referencedRelation = new RelationInfo();
const referencedRelation = new RelationInfo();
col.relations.push(referencedRelation);
referencedRelation.actionOnDelete =
relationTmp.actionOnDelete;
@ -418,9 +416,9 @@ export abstract class AbstractDriver {
referencedRelation.relationType = "OneToMany";
referencedEntity.Columns.push(col);
} else {
let col = new ColumnInfo();
const col = new ColumnInfo();
col.tsName = columnName;
let referencedRelation = new RelationInfo();
const referencedRelation = new RelationInfo();
col.relations.push(referencedRelation);
referencedRelation.actionOnDelete =
relationTmp.actionOnDelete;
@ -438,27 +436,27 @@ export abstract class AbstractDriver {
});
return entities;
}
abstract async GetCoulmnsFromEntity(
public abstract async GetCoulmnsFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(
public abstract async GetIndexesFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]>;
abstract async GetRelations(
public abstract async GetRelations(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]>;
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
public FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
const primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
entity.Columns.filter(
col =>
primaryIndex &&
primaryIndex.columns.some(
cIndex => cIndex.name == col.tsName
cIndex => cIndex.name === col.tsName
)
).forEach(col => (col.isPrimary = true));
if (
@ -474,9 +472,15 @@ export abstract class AbstractDriver {
}
});
}
abstract async DisconnectFromServer();
abstract async CreateDB(dbName: string);
abstract async DropDB(dbName: string);
abstract async UseDB(dbName: string);
abstract async CheckIfDBExists(dbName: string): Promise<boolean>;
public abstract async DisconnectFromServer();
public abstract async CreateDB(dbName: string);
public abstract async DropDB(dbName: string);
public abstract async UseDB(dbName: string);
public abstract async CheckIfDBExists(dbName: string): Promise<boolean>;
private ApplyNamingStrategy(dbModel: DatabaseModel) {
this.changeRelationNames(dbModel);
this.changeEntityNames(dbModel);
this.changeColumnNames(dbModel);
}
}

View File

@ -1,5 +1,5 @@
import { MysqlDriver } from "./MysqlDriver";
export class MariaDbDriver extends MysqlDriver {
readonly EngineName: string = "MariaDb";
public readonly EngineName: string = "MariaDb";
}

View File

@ -6,8 +6,8 @@ import * as TomgUtils from "../Utils";
export class MssqlDriver extends AbstractDriver {
GetAllTablesQuery = async (schema: string) => {
let request = new MSSQL.Request(this.Connection);
let response: {
const request = new MSSQL.Request(this.Connection);
const response: {
TABLE_SCHEMA: string;
TABLE_NAME: string;
}[] = (await request.query(
@ -20,8 +20,8 @@ export class MssqlDriver extends AbstractDriver {
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection);
let response: {
const request = new MSSQL.Request(this.Connection);
const response: {
TABLE_NAME: string;
COLUMN_NAME: string;
COLUMN_DEFAULT: string;
@ -199,8 +199,8 @@ export class MssqlDriver extends AbstractDriver {
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection);
let response: {
const request = new MSSQL.Request(this.Connection);
const response: {
TableName: string;
IndexName: string;
ColumnName: string;
@ -258,8 +258,8 @@ ORDER BY
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection);
let response: {
const request = new MSSQL.Request(this.Connection);
const response: {
TableWithForeignKey: string;
FK_PartNo: number;
ForeignKeyColumn: string;
@ -365,7 +365,7 @@ order by
}
};
let promise = new Promise<boolean>((resolve, reject) => {
const promise = new Promise<boolean>((resolve, reject) => {
this.Connection = new MSSQL.ConnectionPool(config, err => {
if (!err) {
resolve(true);
@ -383,20 +383,20 @@ order by
await promise;
}
async CreateDB(dbName: string) {
let request = new MSSQL.Request(this.Connection);
const request = new MSSQL.Request(this.Connection);
await request.query(`CREATE DATABASE ${dbName}; `);
}
async UseDB(dbName: string) {
let request = new MSSQL.Request(this.Connection);
const request = new MSSQL.Request(this.Connection);
await request.query(`USE ${dbName}; `);
}
async DropDB(dbName: string) {
let request = new MSSQL.Request(this.Connection);
const request = new MSSQL.Request(this.Connection);
await request.query(`DROP DATABASE ${dbName}; `);
}
async CheckIfDBExists(dbName: string): Promise<boolean> {
let request = new MSSQL.Request(this.Connection);
let resp = await request.query(
const request = new MSSQL.Request(this.Connection);
const resp = await request.query(
`SELECT name FROM master.sys.databases WHERE name = N'${dbName}' `
);
return resp.recordset.length > 0;

View File

@ -1,14 +1,16 @@
import { AbstractDriver } from "./AbstractDriver";
import * as MYSQL from "mysql";
import { ColumnInfo } from "../models/ColumnInfo";
import { EntityInfo } from "../models/EntityInfo";
import * as TomgUtils from "../Utils";
import { AbstractDriver } from "./AbstractDriver";
export class MysqlDriver extends AbstractDriver {
readonly EngineName: string = "MySQL";
public readonly EngineName: string = "MySQL";
GetAllTablesQuery = async (schema: string) => {
let response = this.ExecQuery<{
private Connection: MYSQL.Connection;
public GetAllTablesQuery = async (schema: string) => {
const response = this.ExecQuery<{
TABLE_SCHEMA: string;
TABLE_NAME: string;
}>(`SELECT TABLE_SCHEMA, TABLE_NAME
@ -18,11 +20,11 @@ export class MysqlDriver extends AbstractDriver {
return response;
};
async GetCoulmnsFromEntity(
public async GetCoulmnsFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
const response = await this.ExecQuery<{
TABLE_NAME: string;
COLUMN_NAME: string;
COLUMN_DEFAULT: string;
@ -40,14 +42,14 @@ export class MysqlDriver extends AbstractDriver {
FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA like DATABASE()`);
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TABLE_NAME == ent.EntityName)
.filter(filterVal => filterVal.TABLE_NAME === ent.EntityName)
.forEach(resp => {
let colInfo: ColumnInfo = new ColumnInfo();
const colInfo: ColumnInfo = new ColumnInfo();
colInfo.tsName = resp.COLUMN_NAME;
colInfo.sqlName = resp.COLUMN_NAME;
colInfo.is_nullable = resp.IS_NULLABLE == "YES";
colInfo.is_generated = resp.IsIdentity == 1;
colInfo.is_unique = resp.column_key == "UNI";
colInfo.is_nullable = resp.IS_NULLABLE === "YES";
colInfo.is_generated = resp.IsIdentity === 1;
colInfo.is_unique = resp.column_key === "UNI";
colInfo.default = resp.COLUMN_DEFAULT;
colInfo.sql_type = resp.DATA_TYPE;
switch (resp.DATA_TYPE) {
@ -55,7 +57,7 @@ export class MysqlDriver extends AbstractDriver {
colInfo.ts_type = "number";
break;
case "tinyint":
if (resp.column_type == "tinyint(1)") {
if (resp.column_type === "tinyint(1)") {
colInfo.width = 1;
colInfo.ts_type = "boolean";
} else {
@ -173,7 +175,7 @@ export class MysqlDriver extends AbstractDriver {
}
if (
this.ColumnTypesWithPrecision.some(
v => v == colInfo.sql_type
v => v === colInfo.sql_type
)
) {
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
@ -181,7 +183,7 @@ export class MysqlDriver extends AbstractDriver {
}
if (
this.ColumnTypesWithLength.some(
v => v == colInfo.sql_type
v => v === colInfo.sql_type
)
) {
colInfo.lenght =
@ -192,8 +194,8 @@ export class MysqlDriver extends AbstractDriver {
if (
this.ColumnTypesWithWidth.some(
v =>
v == colInfo.sql_type &&
colInfo.ts_type != "boolean"
v === colInfo.sql_type &&
colInfo.ts_type !== "boolean"
)
) {
colInfo.width =
@ -202,16 +204,18 @@ export class MysqlDriver extends AbstractDriver {
: null;
}
if (colInfo.sql_type) ent.Columns.push(colInfo);
if (colInfo.sql_type) {
ent.Columns.push(colInfo);
}
});
});
return entities;
}
async GetIndexesFromEntity(
public async GetIndexesFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
const response = await this.ExecQuery<{
TableName: string;
IndexName: string;
ColumnName: string;
@ -224,23 +228,23 @@ export class MysqlDriver extends AbstractDriver {
`);
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TableName == ent.EntityName)
.filter(filterVal => filterVal.TableName === ent.EntityName)
.forEach(resp => {
let indexInfo: IndexInfo = <IndexInfo>{};
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(
filterVal => filterVal.name == resp.IndexName
filterVal => filterVal.name === resp.IndexName
).length > 0
) {
indexInfo = ent.Indexes.find(
filterVal => filterVal.name == resp.IndexName
filterVal => filterVal.name === resp.IndexName
)!;
} else {
indexInfo.columns = <IndexColumnInfo[]>[];
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.IndexName;
indexInfo.isUnique = resp.is_unique == 1;
indexInfo.isPrimaryKey = resp.is_primary_key == 1;
indexInfo.isUnique = resp.is_unique === 1;
indexInfo.isPrimaryKey = resp.is_primary_key === 1;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.ColumnName;
@ -250,11 +254,11 @@ export class MysqlDriver extends AbstractDriver {
return entities;
}
async GetRelations(
public async GetRelations(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
const response = await this.ExecQuery<{
TableWithForeignKey: string;
FK_PartNo: number;
ForeignKeyColumn: string;
@ -280,19 +284,19 @@ export class MysqlDriver extends AbstractDriver {
TABLE_SCHEMA = SCHEMA()
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
`);
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[];
response.forEach(resp => {
let rels = relationsTemp.find(
val => val.object_id == resp.object_id
val => val.object_id === resp.object_id
);
if (rels == undefined) {
rels = <RelationTempInfo>{};
if (rels === undefined) {
rels = {} as RelationTempInfo;
rels.ownerColumnsNames = [];
rels.referencedColumnsNames = [];
rels.actionOnDelete =
resp.onDelete == "NO_ACTION" ? null : resp.onDelete;
resp.onDelete === "NO_ACTION" ? null : resp.onDelete;
rels.actionOnUpdate =
resp.onUpdate == "NO_ACTION" ? null : resp.onUpdate;
resp.onUpdate === "NO_ACTION" ? null : resp.onUpdate;
rels.object_id = resp.object_id;
rels.ownerTable = resp.TableWithForeignKey;
rels.referencedTable = resp.TableReferenced;
@ -307,8 +311,8 @@ export class MysqlDriver extends AbstractDriver {
);
return entities;
}
async DisconnectFromServer() {
let promise = new Promise<boolean>((resolve, reject) => {
public async DisconnectFromServer() {
const promise = new Promise<boolean>((resolve, reject) => {
this.Connection.end(err => {
if (!err) {
resolve(true);
@ -322,11 +326,11 @@ export class MysqlDriver extends AbstractDriver {
}
});
});
if (this.Connection) await promise;
if (this.Connection) {
await promise;
}
}
private Connection: MYSQL.Connection;
async ConnectToServer(
public async ConnectToServer(
database: string,
server: string,
port: number,
@ -337,26 +341,26 @@ export class MysqlDriver extends AbstractDriver {
let config: MYSQL.ConnectionConfig;
if (ssl) {
config = {
database: database,
database,
host: server,
port: port,
user: user,
password: password,
port,
user,
password,
ssl: {
rejectUnauthorized: false
}
};
} else {
config = {
database: database,
database,
host: server,
port: port,
user: user,
password: password
port,
user,
password
};
}
let promise = new Promise<boolean>((resolve, reject) => {
const promise = new Promise<boolean>((resolve, reject) => {
this.Connection = MYSQL.createConnection(config);
this.Connection.connect(err => {
@ -375,28 +379,28 @@ export class MysqlDriver extends AbstractDriver {
await promise;
}
async CreateDB(dbName: string) {
public async CreateDB(dbName: string) {
await this.ExecQuery<any>(`CREATE DATABASE ${dbName}; `);
}
async UseDB(dbName: string) {
public async UseDB(dbName: string) {
await this.ExecQuery<any>(`USE ${dbName}; `);
}
async DropDB(dbName: string) {
public async DropDB(dbName: string) {
await this.ExecQuery<any>(`DROP DATABASE ${dbName}; `);
}
async CheckIfDBExists(dbName: string): Promise<boolean> {
let resp = await this.ExecQuery<any>(
public async CheckIfDBExists(dbName: string): Promise<boolean> {
const resp = await this.ExecQuery<any>(
`SHOW DATABASES LIKE '${dbName}' `
);
return resp.length > 0;
}
async ExecQuery<T>(sql: string): Promise<Array<T>> {
let ret: Array<T> = [];
let query = this.Connection.query(sql);
let stream = query.stream({});
let promise = new Promise<boolean>((resolve, reject) => {
public async ExecQuery<T>(sql: string): Promise<T[]> {
const ret: T[] = [];
const query = this.Connection.query(sql);
const stream = query.stream({});
const promise = new Promise<boolean>((resolve, reject) => {
stream.on("data", chunk => {
ret.push(<T>(<any>chunk));
ret.push((chunk as any) as T);
});
stream.on("error", err => reject(err));
stream.on("end", () => resolve(true));

View File

@ -1,10 +1,12 @@
import { AbstractDriver } from "./AbstractDriver";
import { ColumnInfo } from "../models/ColumnInfo";
import { EntityInfo } from "../models/EntityInfo";
import * as TomgUtils from "../Utils";
import { AbstractDriver } from "./AbstractDriver";
export class OracleDriver extends AbstractDriver {
Oracle: any;
public Oracle: any;
private Connection: any /*Oracle.IConnection*/;
constructor() {
super();
try {
@ -16,21 +18,21 @@ export class OracleDriver extends AbstractDriver {
}
}
GetAllTablesQuery = async (schema: string) => {
let response: {
public GetAllTablesQuery = async (schema: string) => {
const response: Array<{
TABLE_SCHEMA: string;
TABLE_NAME: string;
}[] = (await this.Connection.execute(
}> = (await this.Connection.execute(
` SELECT NULL AS TABLE_SCHEMA, TABLE_NAME FROM all_tables WHERE owner = (select user from dual)`
)).rows!;
return response;
};
async GetCoulmnsFromEntity(
public async GetCoulmnsFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response: {
const response: Array<{
TABLE_NAME: string;
COLUMN_NAME: string;
DATA_DEFAULT: string;
@ -41,7 +43,7 @@ export class OracleDriver extends AbstractDriver {
DATA_SCALE: number;
IDENTITY_COLUMN: string;
IS_UNIQUE: Number;
}[] = (await this.Connection
}> = (await this.Connection
.execute(`SELECT utc.TABLE_NAME, utc.COLUMN_NAME, DATA_DEFAULT, NULLABLE, DATA_TYPE, DATA_LENGTH,
DATA_PRECISION, DATA_SCALE, IDENTITY_COLUMN,
(select count(*) from USER_CONS_COLUMNS ucc
@ -51,13 +53,13 @@ export class OracleDriver extends AbstractDriver {
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TABLE_NAME == ent.EntityName)
.filter(filterVal => filterVal.TABLE_NAME === ent.EntityName)
.forEach(resp => {
let colInfo: ColumnInfo = new ColumnInfo();
const colInfo: ColumnInfo = new ColumnInfo();
colInfo.tsName = resp.COLUMN_NAME;
colInfo.sqlName = resp.COLUMN_NAME;
colInfo.is_nullable = resp.NULLABLE == "Y";
colInfo.is_generated = resp.IDENTITY_COLUMN == "YES";
colInfo.is_nullable = resp.NULLABLE === "Y";
colInfo.is_generated = resp.IDENTITY_COLUMN === "YES";
colInfo.default =
!resp.DATA_DEFAULT || resp.DATA_DEFAULT.includes('"')
? null
@ -161,7 +163,7 @@ export class OracleDriver extends AbstractDriver {
}
if (
this.ColumnTypesWithPrecision.some(
v => v == colInfo.sql_type
v => v === colInfo.sql_type
)
) {
colInfo.numericPrecision = resp.DATA_PRECISION;
@ -169,29 +171,31 @@ export class OracleDriver extends AbstractDriver {
}
if (
this.ColumnTypesWithLength.some(
v => v == colInfo.sql_type
v => v === colInfo.sql_type
)
) {
colInfo.lenght =
resp.DATA_LENGTH > 0 ? resp.DATA_LENGTH : null;
}
if (colInfo.sql_type) ent.Columns.push(colInfo);
if (colInfo.sql_type) {
ent.Columns.push(colInfo);
}
});
});
return entities;
}
async GetIndexesFromEntity(
public async GetIndexesFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response: {
const response: Array<{
COLUMN_NAME: string;
TABLE_NAME: string;
INDEX_NAME: string;
UNIQUENESS: string;
ISPRIMARYKEY: number;
}[] = (await this.Connection
}> = (await this.Connection
.execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY
FROM USER_INDEXES ind
JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME
@ -200,23 +204,23 @@ export class OracleDriver extends AbstractDriver {
entities.forEach(ent => {
response
.filter(filterVal => filterVal.TABLE_NAME == ent.EntityName)
.filter(filterVal => filterVal.TABLE_NAME === ent.EntityName)
.forEach(resp => {
let indexInfo: IndexInfo = <IndexInfo>{};
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(
filterVal => filterVal.name == resp.INDEX_NAME
filterVal => filterVal.name === resp.INDEX_NAME
).length > 0
) {
indexInfo = ent.Indexes.find(
filterVal => filterVal.name == resp.INDEX_NAME
filterVal => filterVal.name === resp.INDEX_NAME
)!;
} else {
indexInfo.columns = <IndexColumnInfo[]>[];
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.INDEX_NAME;
indexInfo.isUnique = resp.UNIQUENESS == "UNIQUE";
indexInfo.isPrimaryKey = resp.ISPRIMARYKEY == 1;
indexInfo.isUnique = resp.UNIQUENESS === "UNIQUE";
indexInfo.isPrimaryKey = resp.ISPRIMARYKEY === 1;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.COLUMN_NAME;
@ -226,11 +230,11 @@ export class OracleDriver extends AbstractDriver {
return entities;
}
async GetRelations(
public async GetRelations(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response: {
const response: Array<{
OWNER_TABLE_NAME: string;
OWNER_POSITION: string;
OWNER_COLUMN_NAME: string;
@ -238,7 +242,7 @@ export class OracleDriver extends AbstractDriver {
CHILD_COLUMN_NAME: string;
DELETE_RULE: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
CONSTRAINT_NAME: string;
}[] = (await this.Connection
}> = (await this.Connection
.execute(`select owner.TABLE_NAME OWNER_TABLE_NAME,ownCol.POSITION OWNER_POSITION,ownCol.COLUMN_NAME OWNER_COLUMN_NAME,
child.TABLE_NAME CHILD_TABLE_NAME ,childCol.COLUMN_NAME CHILD_COLUMN_NAME,
owner.DELETE_RULE,
@ -250,17 +254,17 @@ export class OracleDriver extends AbstractDriver {
ORDER BY OWNER_TABLE_NAME ASC, owner.CONSTRAINT_NAME ASC, OWNER_POSITION ASC`))
.rows!;
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[];
response.forEach(resp => {
let rels = relationsTemp.find(
val => val.object_id == resp.CONSTRAINT_NAME
val => val.object_id === resp.CONSTRAINT_NAME
);
if (rels == undefined) {
rels = <RelationTempInfo>{};
if (rels === undefined) {
rels = {} as RelationTempInfo;
rels.ownerColumnsNames = [];
rels.referencedColumnsNames = [];
rels.actionOnDelete =
resp.DELETE_RULE == "NO ACTION" ? null : resp.DELETE_RULE;
resp.DELETE_RULE === "NO ACTION" ? null : resp.DELETE_RULE;
rels.actionOnUpdate = null;
rels.object_id = resp.CONSTRAINT_NAME;
rels.ownerTable = resp.OWNER_TABLE_NAME;
@ -276,12 +280,12 @@ export class OracleDriver extends AbstractDriver {
);
return entities;
}
async DisconnectFromServer() {
if (this.Connection) await this.Connection.close();
public async DisconnectFromServer() {
if (this.Connection) {
await this.Connection.close();
}
}
private Connection: any /*Oracle.IConnection*/;
async ConnectToServer(
public async ConnectToServer(
database: string,
server: string,
port: number,
@ -290,24 +294,24 @@ export class OracleDriver extends AbstractDriver {
ssl: boolean
) {
let config: any;
if (user == String(process.env.ORACLE_UsernameSys)) {
if (user === String(process.env.ORACLE_UsernameSys)) {
config /*Oracle.IConnectionAttributes*/ = {
user: user,
password: password,
user,
password,
connectString: `${server}:${port}/${database}`,
externalAuth: ssl,
privilege: this.Oracle.SYSDBA
};
} else {
config /*Oracle.IConnectionAttributes*/ = {
user: user,
password: password,
user,
password,
connectString: `${server}:${port}/${database}`,
externalAuth: ssl
};
}
let that = this;
let promise = new Promise<boolean>((resolve, reject) => {
const that = this;
const promise = new Promise<boolean>((resolve, reject) => {
this.Oracle.getConnection(config, function(err, connection) {
if (!err) {
that.Connection = connection;
@ -326,7 +330,7 @@ export class OracleDriver extends AbstractDriver {
await promise;
}
async CreateDB(dbName: string) {
public async CreateDB(dbName: string) {
await this.Connection.execute(
`CREATE USER ${dbName} IDENTIFIED BY ${String(
process.env.ORACLE_Password
@ -334,12 +338,12 @@ export class OracleDriver extends AbstractDriver {
);
await this.Connection.execute(`GRANT CONNECT TO ${dbName}`);
}
async UseDB(dbName: string) {}
async DropDB(dbName: string) {
public async UseDB(dbName: string) {}
public async DropDB(dbName: string) {
await this.Connection.execute(`DROP USER ${dbName} CASCADE`);
}
async CheckIfDBExists(dbName: string): Promise<boolean> {
var x = await this.Connection.execute(
public async CheckIfDBExists(dbName: string): Promise<boolean> {
const x = await this.Connection.execute(
`select count(*) as CNT from dba_users where username='${dbName.toUpperCase()}'`
);
return x.rows[0][0] > 0 || x.rows[0].CNT;

View File

@ -8,7 +8,7 @@ export class PostgresDriver extends AbstractDriver {
private Connection: PG.Client;
GetAllTablesQuery = async (schema: string) => {
let response: {
const response: {
TABLE_SCHEMA: string;
TABLE_NAME: string;
}[] = (await this.Connection.query(
@ -21,7 +21,7 @@ export class PostgresDriver extends AbstractDriver {
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response: {
const response: {
table_name: string;
column_name: string;
udt_name: string;
@ -62,7 +62,7 @@ export class PostgresDriver extends AbstractDriver {
? null
: resp.column_default;
var columnTypes = this.MatchColumnTypes(
const columnTypes = this.MatchColumnTypes(
resp.data_type,
resp.udt_name
);
@ -338,7 +338,10 @@ export class PostgresDriver extends AbstractDriver {
ret.ts_type = "string";
break;
case "ARRAY":
let z = this.MatchColumnTypes(udt_name.substring(1), udt_name);
const z = this.MatchColumnTypes(
udt_name.substring(1),
udt_name
);
ret.ts_type = z.ts_type;
ret.sql_type = z.sql_type;
ret.is_array = true;
@ -368,7 +371,7 @@ export class PostgresDriver extends AbstractDriver {
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response: {
const response: {
tablename: string;
indexname: string;
columnname: string;
@ -433,7 +436,7 @@ export class PostgresDriver extends AbstractDriver {
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
let response: {
const response: {
tablewithforeignkey: string;
fk_partno: number;
foreignkeycolumn: string;
@ -509,7 +512,7 @@ export class PostgresDriver extends AbstractDriver {
}
async DisconnectFromServer() {
if (this.Connection) {
let promise = new Promise<boolean>((resolve, reject) => {
const promise = new Promise<boolean>((resolve, reject) => {
this.Connection.end(err => {
if (!err) {
resolve(true);
@ -544,7 +547,7 @@ export class PostgresDriver extends AbstractDriver {
ssl: ssl
});
let promise = new Promise<boolean>((resolve, reject) => {
const promise = new Promise<boolean>((resolve, reject) => {
this.Connection.connect(err => {
if (!err) {
resolve(true);
@ -572,7 +575,7 @@ export class PostgresDriver extends AbstractDriver {
await this.Connection.query(`DROP DATABASE ${dbName}; `);
}
async CheckIfDBExists(dbName: string): Promise<boolean> {
let resp = await this.Connection.query(
const resp = await this.Connection.query(
`SELECT datname FROM pg_database WHERE datname ='${dbName}' `
);
return resp.rowCount > 0;

View File

@ -1,24 +1,24 @@
import { AbstractDriver } from "./AbstractDriver";
import { ColumnInfo } from "../models/ColumnInfo";
import { EntityInfo } from "../models/EntityInfo";
import * as TomgUtils from "../Utils";
import { AbstractDriver } from "./AbstractDriver";
export class SqliteDriver extends AbstractDriver {
sqlite = require("sqlite3").verbose();
db: any;
tablesWithGeneratedPrimaryKey: String[] = new Array<String>();
GetAllTablesQuery: any;
public sqlite = require("sqlite3").verbose();
public db: any;
public tablesWithGeneratedPrimaryKey: String[] = new Array<String>();
public GetAllTablesQuery: any;
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let ret: EntityInfo[] = <EntityInfo[]>[];
let rows = await this.ExecQuery<{ tbl_name: string; sql: string }>(
public async GetAllTables(schema: string): Promise<EntityInfo[]> {
const ret: EntityInfo[] = [] as EntityInfo[];
const rows = await this.ExecQuery<{ tbl_name: string; sql: string }>(
`SELECT tbl_name, sql FROM "sqlite_master" WHERE "type" = 'table' AND name NOT LIKE 'sqlite_%'`
);
rows.forEach(val => {
let ent: EntityInfo = new EntityInfo();
const ent: EntityInfo = new EntityInfo();
ent.EntityName = val.tbl_name;
ent.Columns = <ColumnInfo[]>[];
ent.Indexes = <IndexInfo[]>[];
ent.Columns = [] as ColumnInfo[];
ent.Indexes = [] as IndexInfo[];
if (val.sql.includes("AUTOINCREMENT")) {
this.tablesWithGeneratedPrimaryKey.push(ent.EntityName);
}
@ -26,12 +26,12 @@ export class SqliteDriver extends AbstractDriver {
});
return ret;
}
async GetCoulmnsFromEntity(
public async GetCoulmnsFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
for (const ent of entities) {
let response = await this.ExecQuery<{
const response = await this.ExecQuery<{
cid: number;
name: string;
type: string;
@ -40,7 +40,7 @@ export class SqliteDriver extends AbstractDriver {
pk: number;
}>(`PRAGMA table_info('${ent.EntityName}');`);
response.forEach(resp => {
let colInfo: ColumnInfo = new ColumnInfo();
const colInfo: ColumnInfo = new ColumnInfo();
colInfo.tsName = resp.name;
colInfo.sqlName = resp.name;
colInfo.is_nullable = resp.notnull == 0;
@ -146,19 +146,19 @@ export class SqliteDriver extends AbstractDriver {
);
break;
}
let options = resp.type.match(/\([0-9 ,]+\)/g);
const options = resp.type.match(/\([0-9 ,]+\)/g);
if (
this.ColumnTypesWithPrecision.some(
v => v == colInfo.sql_type
) &&
options
) {
colInfo.numericPrecision = <any>options[0]
colInfo.numericPrecision = options[0]
.substring(1, options[0].length - 1)
.split(",")[0];
colInfo.numericScale = <any>options[0]
.split(",")[0] as any;
colInfo.numericScale = options[0]
.substring(1, options[0].length - 1)
.split(",")[1];
.split(",")[1] as any;
}
if (
this.ColumnTypesWithLength.some(
@ -166,10 +166,10 @@ export class SqliteDriver extends AbstractDriver {
) &&
options
) {
colInfo.lenght = <any>options[0].substring(
colInfo.lenght = options[0].substring(
1,
options[0].length - 1
);
) as any;
}
if (
this.ColumnTypesWithWidth.some(
@ -179,24 +179,26 @@ export class SqliteDriver extends AbstractDriver {
) &&
options
) {
colInfo.width = <any>options[0].substring(
colInfo.width = options[0].substring(
1,
options[0].length - 1
);
) as any;
}
if (colInfo.sql_type) ent.Columns.push(colInfo);
if (colInfo.sql_type) {
ent.Columns.push(colInfo);
}
});
}
return entities;
}
async GetIndexesFromEntity(
public async GetIndexesFromEntity(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
for (const ent of entities) {
let response = await this.ExecQuery<{
const response = await this.ExecQuery<{
seq: number;
name: string;
unique: number;
@ -204,14 +206,14 @@ export class SqliteDriver extends AbstractDriver {
partial: number;
}>(`PRAGMA index_list('${ent.EntityName}');`);
for (const resp of response) {
let indexColumnsResponse = await this.ExecQuery<{
const indexColumnsResponse = await this.ExecQuery<{
seqno: number;
cid: number;
name: string;
}>(`PRAGMA index_info('${resp.name}');`);
indexColumnsResponse.forEach(element => {
let indexInfo: IndexInfo = <IndexInfo>{};
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
let indexInfo: IndexInfo = {} as IndexInfo;
const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo;
if (
ent.Indexes.filter(filterVal => {
return filterVal.name == resp.name;
@ -221,7 +223,7 @@ export class SqliteDriver extends AbstractDriver {
filterVal => filterVal.name == resp.name
)!;
} else {
indexInfo.columns = <IndexColumnInfo[]>[];
indexInfo.columns = [] as IndexColumnInfo[];
indexInfo.name = resp.name;
indexInfo.isUnique = resp.unique == 1;
ent.Indexes.push(indexInfo);
@ -242,12 +244,12 @@ export class SqliteDriver extends AbstractDriver {
return entities;
}
async GetRelations(
public async GetRelations(
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]> {
for (const entity of entities) {
let response = await this.ExecQuery<{
const response = await this.ExecQuery<{
id: number;
seq: number;
table: string;
@ -257,9 +259,9 @@ export class SqliteDriver extends AbstractDriver {
on_delete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
match: string;
}>(`PRAGMA foreign_key_list('${entity.EntityName}');`);
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[];
response.forEach(resp => {
let rels = <RelationTempInfo>{};
const rels = {} as RelationTempInfo;
rels.ownerColumnsNames = [];
rels.referencedColumnsNames = [];
rels.actionOnDelete =
@ -279,11 +281,11 @@ export class SqliteDriver extends AbstractDriver {
}
return entities;
}
async DisconnectFromServer() {
public async DisconnectFromServer() {
this.db.close();
}
async ConnectToServer(
public async ConnectToServer(
database: string,
server: string,
port: number,
@ -294,9 +296,9 @@ export class SqliteDriver extends AbstractDriver {
await this.UseDB(database);
}
async CreateDB(dbName: string) {}
async UseDB(dbName: string) {
let promise = new Promise<boolean>((resolve, reject) => {
public async CreateDB(dbName: string) {}
public async UseDB(dbName: string) {
const promise = new Promise<boolean>((resolve, reject) => {
this.db = new this.sqlite.Database(dbName, err => {
if (err) {
console.error(err.message);
@ -308,14 +310,14 @@ export class SqliteDriver extends AbstractDriver {
});
return promise;
}
async DropDB(dbName: string) {}
async CheckIfDBExists(dbName: string): Promise<boolean> {
public async DropDB(dbName: string) {}
public async CheckIfDBExists(dbName: string): Promise<boolean> {
return true;
}
async ExecQuery<T>(sql: string): Promise<Array<T>> {
public async ExecQuery<T>(sql: string): Promise<T[]> {
let ret: any;
let promise = new Promise<boolean>((resolve, reject) => {
const promise = new Promise<boolean>((resolve, reject) => {
this.db.serialize(() => {
this.db.all(sql, [], function(err, row) {
if (!err) {

View File

@ -1,18 +1,18 @@
import path = require("path");
import * as Yargs from "yargs";
import { AbstractNamingStrategy } from "./AbstractNamingStrategy";
import { AbstractDriver } from "./drivers/AbstractDriver";
import { MariaDbDriver } from "./drivers/MariaDbDriver";
import { MssqlDriver } from "./drivers/MssqlDriver";
import { MysqlDriver } from "./drivers/MysqlDriver";
import { OracleDriver } from "./drivers/OracleDriver";
import { PostgresDriver } from "./drivers/PostgresDriver";
import { SqliteDriver } from "./drivers/SqliteDriver";
import { MysqlDriver } from "./drivers/MysqlDriver";
import { MariaDbDriver } from "./drivers/MariaDbDriver";
import { OracleDriver } from "./drivers/OracleDriver";
import { Engine } from "./Engine";
import * as Yargs from "yargs";
import * as TomgUtils from "./Utils";
import path = require("path");
import { AbstractNamingStrategy } from "./AbstractNamingStrategy";
import { NamingStrategy } from "./NamingStrategy";
import * as TomgUtils from "./Utils";
var argv = Yargs.usage(
const argv = Yargs.usage(
"Usage: typeorm-model-generator -h <host> -d <database> -p [port] -u <user> -x [password] -e [engine]"
)
.option("h", {
@ -148,13 +148,13 @@ switch (argv.e) {
}
let namingStrategy: AbstractNamingStrategy;
if (argv.namingStrategy && argv.namingStrategy != "") {
let req = require(argv.namingStrategy);
const req = require(argv.namingStrategy);
namingStrategy = new req.NamingStrategy();
} else {
namingStrategy = new NamingStrategy();
}
let engine = new Engine(driver, {
const engine = new Engine(driver, {
host: argv.h,
port: parseInt(argv.p) || standardPort,
databaseName: argv.d ? argv.d.toString() : null,
@ -172,7 +172,7 @@ let engine = new Engine(driver, {
lazy: argv.lazy,
constructor: argv.generateConstructor,
relationIds: argv.relationIds,
namingStrategy: namingStrategy
namingStrategy
});
console.log(TomgUtils.packageVersion());

View File

@ -1,12 +1,12 @@
import { RelationInfo } from "./RelationInfo";
export class ColumnInfo {
tsName: string = "";
sqlName: string = "";
default: string | null = null;
is_nullable: boolean = false;
is_unique: boolean = false;
ts_type:
public tsName: string = "";
public sqlName: string = "";
public default: string | null = null;
public is_nullable: boolean = false;
public is_unique: boolean = false;
public ts_type:
| "number"
| "string"
| "boolean"
@ -16,16 +16,16 @@ export class ColumnInfo {
| "string | Object"
| "string | string[]"
| "any";
sql_type: string;
lenght: number | null = null;
width: number | null = null;
isPrimary: boolean = false;
is_generated: boolean = false;
is_array: boolean = false;
numericPrecision: number | null = null;
numericScale: number | null = null;
enumOptions: string | null = null;
relations: RelationInfo[];
public sql_type: string;
public lenght: number | null = null;
public width: number | null = null;
public isPrimary: boolean = false;
public is_generated: boolean = false;
public is_array: boolean = false;
public numericPrecision: number | null = null;
public numericScale: number | null = null;
public enumOptions: string | null = null;
public relations: RelationInfo[];
constructor() {
this.relations = [];
}

View File

@ -1,4 +1,4 @@
import { EntityInfo } from "./EntityInfo";
export class DatabaseModel {
entities: EntityInfo[];
public entities: EntityInfo[];
}

View File

@ -1,20 +1,21 @@
import { ColumnInfo } from "./ColumnInfo";
export class EntityInfo {
EntityName: string;
Columns: ColumnInfo[];
Imports: string[];
UniqueImports: string[];
Indexes: IndexInfo[];
Schema: string;
GenerateConstructor: boolean;
public EntityName: string;
public Columns: ColumnInfo[];
public Imports: string[];
public UniqueImports: string[];
public Indexes: IndexInfo[];
public Schema: string;
public GenerateConstructor: boolean;
relationImports() {
var imports: string[] = [];
public relationImports() {
const imports: string[] = [];
this.Columns.forEach(column => {
column.relations.forEach(relation => {
if (this.EntityName != relation.relatedTable)
if (this.EntityName != relation.relatedTable) {
imports.push(relation.relatedTable);
}
});
});
this.UniqueImports = imports.filter(

View File

@ -1,19 +1,24 @@
export class RelationInfo {
isOwner: boolean;
relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany";
relatedTable: string;
relatedColumn: string;
ownerTable: string;
ownerColumn: string;
actionOnDelete:
public isOwner: boolean;
public relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany";
public relatedTable: string;
public relatedColumn: string;
public ownerTable: string;
public ownerColumn: string;
public actionOnDelete:
| "RESTRICT"
| "CASCADE"
| "SET NULL"
| "DEFAULT"
| "NO ACTION"
| null;
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "DEFAULT" | null;
relationIdField: boolean = false;
public actionOnUpdate:
| "RESTRICT"
| "CASCADE"
| "SET NULL"
| "DEFAULT"
| null;
public relationIdField: boolean = false;
get isOneToMany(): boolean {
return this.relationType == "OneToMany";

9
src/tslint.json Normal file
View File

@ -0,0 +1,9 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended", "tslint-config-prettier"
],
"jsRules": {},
"rules": {},
"rulesDirectory": []
}

View File

@ -1,30 +1,30 @@
import { expect } from "chai";
import { MssqlDriver } from '../../src/drivers/MssqlDriver'
import * as Sinon from 'sinon'
import * as MSSQL from 'mssql'
import { EntityInfo } from '../../src/models/EntityInfo'
import { IColumnMetadata, Table } from "mssql";
import * as Sinon from 'sinon'
import { MssqlDriver } from '../../src/drivers/MssqlDriver'
import { ColumnInfo } from '../../src/models/ColumnInfo'
import { EntityInfo } from '../../src/models/EntityInfo'
import { RelationInfo } from '../../src/models/RelationInfo'
import { Table, IColumnMetadata } from "mssql";
import { NamingStrategy } from "../../src/NamingStrategy";
class fakeResponse implements MSSQL.IResult<any> {
recordsets: MSSQL.IRecordSet<any>[];
recordset: MSSQL.IRecordSet<any>;
rowsAffected: number[];
output: { [key: string]: any; };
public recordsets: Array<MSSQL.IRecordSet<any>>;
public recordset: MSSQL.IRecordSet<any>;
public rowsAffected: number[];
public output: { [key: string]: any; };
}
class fakeRecordset extends Array<any> implements MSSQL.IRecordSet<any>{
columns: IColumnMetadata;
toTable(): Table {
public columns: IColumnMetadata;
public toTable(): Table {
return new Table();
}
}
describe('MssqlDriver', function () {
let driver: MssqlDriver
let sandbox = Sinon.sandbox.create()
const sandbox = Sinon.sandbox.create()
beforeEach(() => {
driver = new MssqlDriver();
@ -40,19 +40,19 @@ describe('MssqlDriver', function () {
.returns(
{
query: (q) => {
let response = new fakeResponse();
const 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 = <EntityInfo[]>[];
let y = new EntityInfo();
const result = await driver.GetAllTables('schema')
const expectedResult = [] as EntityInfo[];
const y = new EntityInfo();
y.EntityName = 'name'
y.Schema='schema'
y.Columns = <ColumnInfo[]>[];
y.Indexes = <IndexInfo[]>[];
y.Columns = [] as ColumnInfo[];
y.Indexes = [] as IndexInfo[];
expectedResult.push(y)
expect(result).to.be.deep.equal(expectedResult)
})
@ -61,7 +61,7 @@ describe('MssqlDriver', function () {
.returns(
{
query: (q) => {
let response = new fakeResponse();
const response = new fakeResponse();
response.recordset = new fakeRecordset();
response.recordset.push({
TABLE_NAME: 'name', CHARACTER_MAXIMUM_LENGTH: 0,
@ -73,13 +73,13 @@ describe('MssqlDriver', function () {
}
})
let entities = <EntityInfo[]>[];
let y = new EntityInfo();
const entities = [] as EntityInfo[];
const y = new EntityInfo();
y.EntityName = 'name'
y.Columns = <ColumnInfo[]>[];
y.Indexes = <IndexInfo[]>[];
y.Columns = [] as ColumnInfo[];
y.Indexes = [] as IndexInfo[];
entities.push(y)
var expected: EntityInfo[] = JSON.parse(JSON.stringify(entities));
const expected: EntityInfo[] = JSON.parse(JSON.stringify(entities));
expected[0].Columns.push({
lenght: null,
default: 'a',
@ -96,9 +96,9 @@ describe('MssqlDriver', function () {
enumOptions: null,
is_unique:false,
is_array:false,
relations: <RelationInfo[]>[],
relations: [] as RelationInfo[],
})
let result = await driver.GetCoulmnsFromEntity(entities, 'schema');
const result = await driver.GetCoulmnsFromEntity(entities, 'schema');
expect(result).to.be.deep.equal(expected)
})
it('should find primary indexes')

View File

@ -1,41 +1,41 @@
require('dotenv').config()
import "reflect-metadata";
import { expect } from "chai";
import fs = require('fs-extra');
import path = require('path')
import { expect } from "chai";
import "reflect-metadata";
import { EntityFileToJson } from "../utils/EntityFileToJson";
var chai = require('chai');
var chaiSubset = require('chai-subset');
const chai = require('chai');
const chaiSubset = require('chai-subset');
import * as ts from "typescript";
import * as GTU from "../utils/GeneralTestUtils"
import { Engine } from "../../src/Engine";
import * as GTU from "../utils/GeneralTestUtils"
chai.use(chaiSubset);
describe("Platform specyfic types", async function () {
this.timeout(30000)
this.slow(5000)//compiling created models takes time
this.slow(5000)// compiling created models takes time
let dbDrivers: string[] = []
if (process.env.SQLITE_Skip == '0') dbDrivers.push('sqlite')
if (process.env.POSTGRES_Skip == '0') dbDrivers.push('postgres')
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
if (process.env.ORACLE_Skip == '0') dbDrivers.push('oracle')
const dbDrivers: string[] = []
if (process.env.SQLITE_Skip == '0') { dbDrivers.push('sqlite') }
if (process.env.POSTGRES_Skip == '0') { dbDrivers.push('postgres') }
if (process.env.MYSQL_Skip == '0') { dbDrivers.push('mysql') }
if (process.env.MARIADB_Skip == '0') { dbDrivers.push('mariadb') }
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)
const examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/entityTypes')
const examplesPathTS = path.resolve(process.cwd(), 'test/integration/entityTypes')
const files = fs.readdirSync(examplesPathTS)
for (let dbDriver of dbDrivers) {
for (let folder of files) {
for (const dbDriver of dbDrivers) {
for (const folder of files) {
if (dbDriver == folder) {
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`)
const filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity')
const filesOrgPathTS = path.resolve(examplesPathTS, folder, 'entity')
const resultsPath = path.resolve(process.cwd(), `output`)
fs.removeSync(resultsPath)
let engine: Engine;
@ -60,27 +60,27 @@ describe("Platform specyfic types", async function () {
break;
default:
console.log(`Unknown engine type`);
engine = <Engine>{}
engine = {} as Engine
break;
}
await engine.createModelFromDatabase()
let filesGenPath = path.resolve(resultsPath, 'entities')
const filesGenPath = path.resolve(resultsPath, 'entities')
let filesOrg = fs.readdirSync(filesOrgPathTS).filter((val) => val.toString().endsWith('.ts'))
let filesGen = fs.readdirSync(filesGenPath).filter((val) => val.toString().endsWith('.ts'))
const filesOrg = fs.readdirSync(filesOrgPathTS).filter((val) => val.toString().endsWith('.ts'))
const filesGen = fs.readdirSync(filesGenPath).filter((val) => val.toString().endsWith('.ts'))
expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen)
for (let file of filesOrg) {
let entftj = new EntityFileToJson();
let jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
let jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
for (const file of filesOrg) {
const entftj = new EntityFileToJson();
const jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
const jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
expect(jsonEntityGen, `Error in file ${file}`).to.containSubset(jsonEntityOrg)
}
const currentDirectoryFiles = fs.readdirSync(filesGenPath).
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => path.resolve(filesGenPath, v))
let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
const compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
experimentalDecorators: true,
sourceMap: false,
emitDecoratorMetadata: true,

View File

@ -1,14 +1,14 @@
require('dotenv').config()
import "reflect-metadata";
import { createConnection, ConnectionOptions, Connection } from "typeorm";
import { expect } from "chai";
import fs = require('fs-extra');
import path = require('path')
import { Engine } from "../../src/Engine";
import { expect } from "chai";
import "reflect-metadata";
import * as Sinon from 'sinon'
import { Connection, ConnectionOptions, createConnection } from "typeorm";
import { Engine } from "../../src/Engine";
import { EntityFileToJson } from "../utils/EntityFileToJson";
var chai = require('chai');
var chaiSubset = require('chai-subset');
const chai = require('chai');
const chaiSubset = require('chai-subset');
import * as ts from "typescript";
import * as GTU from "../utils/GeneralTestUtils"
@ -17,29 +17,30 @@ chai.use(chaiSubset);
describe("GitHub issues", async function () {
this.timeout(30000)
this.slow(5000)//compiling created models takes time
this.slow(5000)// compiling created models takes time
let dbDrivers: string[] = []
if (process.env.SQLITE_Skip == '0') dbDrivers.push('sqlite')
if (process.env.POSTGRES_Skip == '0') dbDrivers.push('postgres')
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
if (process.env.ORACLE_Skip == '0') dbDrivers.push('oracle')
const dbDrivers: string[] = []
if (process.env.SQLITE_Skip == '0') { dbDrivers.push('sqlite') }
if (process.env.POSTGRES_Skip == '0') { dbDrivers.push('postgres') }
if (process.env.MYSQL_Skip == '0') { dbDrivers.push('mysql') }
if (process.env.MARIADB_Skip == '0') { dbDrivers.push('mariadb') }
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/github-issues')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/github-issues')
let files = fs.readdirSync(examplesPathTS)
const examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/github-issues')
const examplesPathTS = path.resolve(process.cwd(), 'test/integration/github-issues')
const files = fs.readdirSync(examplesPathTS)
for (let folder of files) {
for (const folder of files) {
describe(`#${folder}`, async function () {
for (let dbDriver of dbDrivers) {
for (const dbDriver of dbDrivers) {
switch (folder) {
case '39':
if (dbDriver == 'mysql' || dbDriver == 'mariadb' || dbDriver == 'oracle' || dbDriver == 'sqlite')
if (dbDriver == 'mysql' || dbDriver == 'mariadb' || dbDriver == 'oracle' || dbDriver == 'sqlite') {
continue;
}
break;
default:
break;
@ -47,9 +48,9 @@ describe("GitHub issues", async function () {
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`)
const filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity')
const filesOrgPathTS = path.resolve(examplesPathTS, folder, 'entity')
const resultsPath = path.resolve(process.cwd(), `output`)
fs.removeSync(resultsPath)
let engine: Engine;
@ -74,7 +75,7 @@ describe("GitHub issues", async function () {
break;
default:
console.log(`Unknown engine type`);
engine = <Engine>{}
engine = {} as Engine
break;
}
@ -87,22 +88,22 @@ describe("GitHub issues", async function () {
}
await engine.createModelFromDatabase()
let filesGenPath = path.resolve(resultsPath, 'entities')
const filesGenPath = path.resolve(resultsPath, 'entities')
let filesOrg = fs.readdirSync(filesOrgPathTS).filter((val) => val.toString().endsWith('.ts'))
let filesGen = fs.readdirSync(filesGenPath).filter((val) => val.toString().endsWith('.ts'))
const filesOrg = fs.readdirSync(filesOrgPathTS).filter((val) => val.toString().endsWith('.ts'))
const filesGen = fs.readdirSync(filesGenPath).filter((val) => val.toString().endsWith('.ts'))
expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen)
for (let file of filesOrg) {
let entftj = new EntityFileToJson();
let jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
let jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
for (const file of filesOrg) {
const entftj = new EntityFileToJson();
const jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
const jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
expect(jsonEntityGen, `Error in file ${file}`).to.containSubset(jsonEntityOrg)
}
const currentDirectoryFiles = fs.readdirSync(filesGenPath).
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => path.resolve(filesGenPath, v))
let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
const compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
experimentalDecorators: true,
sourceMap: false,
emitDecoratorMetadata: true,

View File

@ -1,12 +1,12 @@
require('dotenv').config()
import "reflect-metadata";
import { expect } from "chai";
import fs = require('fs-extra');
import path = require('path')
import "reflect-metadata";
import { Engine } from "../../src/Engine";
import { expect } from "chai";
import { EntityFileToJson } from "../utils/EntityFileToJson";
var chai = require('chai');
var chaiSubset = require('chai-subset');
const chai = require('chai');
const chaiSubset = require('chai-subset');
import * as ts from "typescript";
import * as GTU from "../utils/GeneralTestUtils"
@ -14,27 +14,27 @@ chai.use(chaiSubset);
describe("TypeOrm examples", async function () {
this.timeout(30000)
this.slow(5000)//compiling created models takes time
this.slow(5000)// compiling created models takes time
let dbDrivers: string[] = []
if (process.env.SQLITE_Skip == '0') dbDrivers.push('sqlite')
if (process.env.POSTGRES_Skip == '0') dbDrivers.push('postgres')
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
if (process.env.ORACLE_Skip == '0') dbDrivers.push('oracle')
const dbDrivers: string[] = []
if (process.env.SQLITE_Skip == '0') { dbDrivers.push('sqlite') }
if (process.env.POSTGRES_Skip == '0') { dbDrivers.push('postgres') }
if (process.env.MYSQL_Skip == '0') { dbDrivers.push('mysql') }
if (process.env.MARIADB_Skip == '0') { dbDrivers.push('mariadb') }
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/examples')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/examples')
let files = fs.readdirSync(examplesPathTS)
const examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/examples')
const examplesPathTS = path.resolve(process.cwd(), 'test/integration/examples')
const files = fs.readdirSync(examplesPathTS)
for (let folder of files) {
for (const folder of files) {
describe(folder, async function () {
for (let dbDriver of dbDrivers) {
for (const 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`)
const filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity')
const filesOrgPathTS = path.resolve(examplesPathTS, folder, 'entity')
const resultsPath = path.resolve(process.cwd(), `output`)
fs.removeSync(resultsPath)
let engine: Engine;
@ -59,7 +59,7 @@ describe("TypeOrm examples", async function () {
break;
default:
console.log(`Unknown engine type`);
engine = <Engine>{}
engine = {} as Engine
break;
}
if (folder == 'sample18-lazy-relations') {
@ -67,22 +67,22 @@ describe("TypeOrm examples", async function () {
}
await engine.createModelFromDatabase()
let filesGenPath = path.resolve(resultsPath, 'entities')
const filesGenPath = path.resolve(resultsPath, 'entities')
let filesOrg = fs.readdirSync(filesOrgPathTS).filter((val) => val.toString().endsWith('.ts'))
let filesGen = fs.readdirSync(filesGenPath).filter((val) => val.toString().endsWith('.ts'))
const filesOrg = fs.readdirSync(filesOrgPathTS).filter((val) => val.toString().endsWith('.ts'))
const filesGen = fs.readdirSync(filesGenPath).filter((val) => val.toString().endsWith('.ts'))
expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen)
for (let file of filesOrg) {
let entftj = new EntityFileToJson();
let jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
let jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
for (const file of filesOrg) {
const entftj = new EntityFileToJson();
const jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
const jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
expect(jsonEntityGen, `Error in file ${file}`).to.containSubset(jsonEntityOrg)
}
const currentDirectoryFiles = fs.readdirSync(filesGenPath).
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => path.resolve(filesGenPath, v))
let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
const compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
experimentalDecorators: true,
sourceMap: false,
emitDecoratorMetadata: true,

View File

@ -1,7 +1,7 @@
export class EntityFileToJson {
getEntityOptions(trimmedLine: string, ent: EntityJson) {
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
public getEntityOptions(trimmedLine: string, ent: EntityJson) {
const decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
if (decoratorParameters.length > 0) {
if (decoratorParameters[0] != '"' || !decoratorParameters.endsWith('"')) {
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
@ -12,9 +12,9 @@ export class EntityFileToJson {
}
}
}
getColumnOptionsAndType(trimmedLine: string, col: EntityColumn) {
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
let primaryGeneratedColumn = trimmedLine.substring(0, trimmedLine.indexOf('('))=='@PrimaryGeneratedColumn'
public getColumnOptionsAndType(trimmedLine: string, col: EntityColumn) {
const decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
const primaryGeneratedColumn = trimmedLine.substring(0, trimmedLine.indexOf('('))=='@PrimaryGeneratedColumn'
if (decoratorParameters.length > 0) {
if (decoratorParameters.search(',') > 0 && !primaryGeneratedColumn) {
col.columnTypes = decoratorParameters.substring(0, decoratorParameters.indexOf(',')).trim().split('|');
@ -37,10 +37,10 @@ export class EntityFileToJson {
}
}
}
getRelationOptions(trimmedLine:string, col:EntityColumn){
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
public getRelationOptions(trimmedLine:string, col:EntityColumn){
const decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
if (decoratorParameters.length > 0) {
let params = decoratorParameters.match(/(,)(?!([^{]*}))/g)
const params = decoratorParameters.match(/(,)(?!([^{]*}))/g)
if ( params && params.length == 2) {
let badJSON = decoratorParameters.substring( decoratorParameters.lastIndexOf('{'),decoratorParameters.lastIndexOf('}')+1).trim()
if (badJSON.lastIndexOf(',') == badJSON.length - 3) {
@ -50,18 +50,18 @@ export class EntityFileToJson {
}
}
}
getIndexOptions(trimmedLine: string, ind: EntityIndex) {
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
public getIndexOptions(trimmedLine: string, ind: EntityIndex) {
const decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
if (decoratorParameters.length > 0) {
let containsTables = decoratorParameters.search('\\[') > -1
let containsOptions = decoratorParameters.search('{') > -1
let containsName = decoratorParameters.search('"') > -1
const containsTables = decoratorParameters.search('\\[') > -1
const containsOptions = decoratorParameters.search('{') > -1
const containsName = decoratorParameters.search('"') > -1
if (containsName) {
ind.indexName = decoratorParameters.slice(decoratorParameters.indexOf('"') + 1, decoratorParameters.substr(decoratorParameters.indexOf('"') + 1).indexOf('"'))
}
if (containsTables) {
let columnsStr = decoratorParameters.slice(decoratorParameters.indexOf('[') + 1, decoratorParameters.indexOf(']'))
const columnsStr = decoratorParameters.slice(decoratorParameters.indexOf('[') + 1, decoratorParameters.indexOf(']'))
ind.columnNames.push(...columnsStr.split(',').map((val) => {
let colName = ''
if (val.search('\\.') > -1) {
@ -73,7 +73,7 @@ export class EntityFileToJson {
}).filter(v => v.length > 0))
}
if (containsOptions) {
let optionsStr = decoratorParameters.slice(decoratorParameters.indexOf('{') + 1, decoratorParameters.indexOf('}'))
const optionsStr = decoratorParameters.slice(decoratorParameters.indexOf('{') + 1, decoratorParameters.indexOf('}'))
optionsStr.split(',').forEach((v) => {
if (v.split(':').length - 1 > 0) {
switch (optionsStr.split(':')[0].trim()) {
@ -91,23 +91,25 @@ export class EntityFileToJson {
}
}
convert(entityFile: Buffer): EntityJson {
let retVal = new EntityJson();
public convert(entityFile: Buffer): EntityJson {
const retVal = new EntityJson();
let isInClassBody = false;
let isMultilineStatement = false;
let priorPartOfMultilineStatement = '';
let lines = entityFile.toString().replace('\r', '').split('\n');
for (let line of lines) {
const lines = entityFile.toString().replace('\r', '').split('\n');
for (const line of lines) {
let trimmedLine = line.trim();
if (trimmedLine.startsWith('//')) {
continue;
}
if (isMultilineStatement)
if (isMultilineStatement) {
trimmedLine = priorPartOfMultilineStatement + ' ' + trimmedLine
if (trimmedLine.length == 0)
}
if (trimmedLine.length == 0) {
continue;
}
else if (!isInClassBody) {
if (trimmedLine.startsWith('import')) {
continue;
@ -131,7 +133,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let ind = new EntityIndex()
const ind = new EntityIndex()
this.getIndexOptions(trimmedLine, ind)
retVal.indicies.push(ind);
continue;
@ -145,7 +147,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let col = new EntityColumn()
const col = new EntityColumn()
this.getColumnOptionsAndType(trimmedLine, col)
retVal.columns.push(col);
continue;
@ -157,9 +159,9 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let col = new EntityColumn()
const col = new EntityColumn()
this.getColumnOptionsAndType(trimmedLine, col)
col.columnOptions['primary'] = true
col.columnOptions.primary = true
retVal.columns.push(col);
continue;
}
@ -170,7 +172,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let col = new EntityColumn()
const col = new EntityColumn()
this.getColumnOptionsAndType(trimmedLine, col)
retVal.columns.push(col);
continue;
@ -182,10 +184,10 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let col = new EntityColumn()
const col = new EntityColumn()
this.getColumnOptionsAndType(trimmedLine, col)
col.columnOptions['primary'] = true
col.columnOptions['generated'] = true
col.columnOptions.primary = true
col.columnOptions.generated = true
retVal.columns.push(col);
continue;
}
@ -196,7 +198,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let column = new EntityColumn()
const column = new EntityColumn()
retVal.columns.push(column)
column.relationType = "ManyToOne"
column.isOwnerOfRelation = true;
@ -209,7 +211,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let column = new EntityColumn()
const column = new EntityColumn()
retVal.columns.push(column)
column.relationType = "OneToMany"
continue;
@ -221,7 +223,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let column = new EntityColumn()
const column = new EntityColumn()
retVal.columns.push(column)
column.relationType = "ManyToMany"
continue;
@ -233,7 +235,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let column = new EntityColumn()
const column = new EntityColumn()
retVal.columns.push(column)
column.relationType = "OneToOne"
this.getRelationOptions(trimmedLine,column);
@ -266,7 +268,7 @@ export class EntityFileToJson {
continue;
} else {
isMultilineStatement = false;
let ind = new EntityIndex()
const ind = new EntityIndex()
this.getIndexOptions(trimmedLine, ind)
retVal.indicies.push(ind);
continue;
@ -282,7 +284,7 @@ export class EntityFileToJson {
}
} else if (trimmedLine.split(':').length - 1 > 0) {
retVal.columns[retVal.columns.length - 1].columnName = trimmedLine.split(':')[0].trim();
//TODO:Should check if null only column is nullable?
// TODO:Should check if null only column is nullable?
let colTypes=trimmedLine.split(':')[1].split(';')[0].trim();
if (colTypes.startsWith('Promise<')) {
colTypes=colTypes.substring(8,colTypes.length-1)
@ -290,14 +292,15 @@ export class EntityFileToJson {
}
retVal.columns[retVal.columns.length - 1].columnTypes = colTypes.split('|').map(function (x) {
if (x == 'any') {
x = 'string' //for json columns
x = 'string' // for json columns
}
x = x.trim();
return x;
});
if (!retVal.columns[retVal.columns.length - 1].columnTypes.some( (val) => val == "null" ? true : false))
if (!retVal.columns[retVal.columns.length - 1].columnTypes.some( (val) => val == "null" ? true : false)) {
retVal.columns[retVal.columns.length - 1].columnTypes.push('null')
}
if (retVal.indicies.length > 0 && retVal.indicies[retVal.indicies.length - 1].columnNames.length == 0) {
retVal.indicies[retVal.indicies.length - 1].columnNames.push(retVal.columns[retVal.columns.length - 1].columnName)
}
@ -316,41 +319,43 @@ export class EntityFileToJson {
}
retVal.columns = retVal.columns.map(col => {
if (col.columnName.endsWith('Id'))
if (col.columnName.endsWith('Id')) {
col.columnName = col.columnName.substr(0, col.columnName.length - 2)
}
return col;
})
retVal.indicies = retVal.indicies.map(ind => {
ind.columnNames = ind.columnNames.map(colName => {
if (colName.endsWith('Id'))
if (colName.endsWith('Id')) {
colName = colName.substr(0, colName.length - 2)
}
return colName;
})
return ind;
})
return retVal;
}
isPartOfMultilineStatement(statement: string) {
let matchStarting = statement.split('(').length+statement.split('{').length
let matchEnding = statement.split(')').length+statement.split('}').length
public isPartOfMultilineStatement(statement: string) {
const matchStarting = statement.split('(').length+statement.split('{').length
const matchEnding = statement.split(')').length+statement.split('}').length
return !(matchStarting == matchEnding)
}
}
class EntityJson {
entityName: string
entityOptions: any = {}
columns: EntityColumn[] = <EntityColumn[]>[];
indicies: EntityIndex[] = <EntityIndex[]>[];
public entityName: string
public entityOptions: any = {}
public columns: EntityColumn[] = [] as EntityColumn[];
public indicies: EntityIndex[] = [] as EntityIndex[];
}
class EntityColumn {
columnName: string
columnTypes: string[] = []
columnOptions: any = {}
relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany" | "None" = "None"
isOwnerOfRelation: boolean = false;
public columnName: string
public columnTypes: string[] = []
public columnOptions: any = {}
public relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany" | "None" = "None"
public isOwnerOfRelation: boolean = false;
}
class EntityIndex {
indexName: string
columnNames: string[] = []
isUnique: boolean = false
public indexName: string
public columnNames: string[] = []
public isUnique: boolean = false
}

View File

@ -1,16 +1,16 @@
import path = require('path')
import { ConnectionOptions, createConnection } from "typeorm";
import * as ts from "typescript";
import * as yn from "yn"
import { AbstractNamingStrategy } from "../../src/AbstractNamingStrategy";
import { AbstractDriver } from "../../src/drivers/AbstractDriver";
import { MssqlDriver } from "../../src/drivers/MssqlDriver";
import { PostgresDriver } from "../../src/drivers/PostgresDriver";
import { MysqlDriver } from "../../src/drivers/MysqlDriver";
import { MariaDbDriver } from "../../src/drivers/MariaDbDriver";
import { MssqlDriver } from "../../src/drivers/MssqlDriver";
import { MysqlDriver } from "../../src/drivers/MysqlDriver";
import { OracleDriver } from "../../src/drivers/OracleDriver";
import { PostgresDriver } from "../../src/drivers/PostgresDriver";
import { SqliteDriver } from "../../src/drivers/SqliteDriver";
import { Engine } from "../../src/Engine";
import { createConnection, ConnectionOptions } from "typeorm";
import * as yn from "yn"
import path = require('path')
import { AbstractNamingStrategy } from "../../src/AbstractNamingStrategy";
import { NamingStrategy } from "../../src/NamingStrategy";
export async function createMSSQLModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
@ -19,12 +19,13 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
driver = new MssqlDriver();
await driver.ConnectToServer(`master`, String(process.env.MSSQL_Host), Number(process.env.MSSQL_Port), String(process.env.MSSQL_Username), String(process.env.MSSQL_Password), yn(process.env.MSSQL_SSL));
if (await driver.CheckIfDBExists(String(process.env.MSSQL_Database)))
if (await driver.CheckIfDBExists(String(process.env.MSSQL_Database))) {
await driver.DropDB(String(process.env.MSSQL_Database));
}
await driver.CreateDB(String(process.env.MSSQL_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
const connOpt: ConnectionOptions = {
database: String(process.env.MSSQL_Database),
host: String(process.env.MSSQL_Host),
password: String(process.env.MSSQL_Password),
@ -36,7 +37,7 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
entities: [path.resolve(filesOrgPath, '*.js')],
}
let schemas = 'dbo,sch1,sch2'
const schemas = 'dbo,sch1,sch2'
let conn = await createConnection(connOpt)
let queryRunner = conn.createQueryRunner()
for (const sch of schemas.split(',')) {
@ -44,13 +45,14 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
}
await conn.synchronize();
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
}
let namingStrategy: AbstractNamingStrategy = new NamingStrategy();
const namingStrategy: AbstractNamingStrategy = new NamingStrategy();
driver = new MssqlDriver();
let engine = new Engine(
const engine = new Engine(
driver, {
host: String(process.env.MSSQL_Host),
port: Number(process.env.MSSQL_Port),
@ -58,7 +60,7 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
user: String(process.env.MSSQL_Username),
password: String(process.env.MSSQL_Password),
databaseType: 'mssql',
resultsPath: resultsPath,
resultsPath,
schemaName: 'dbo,sch1,sch2',
ssl: yn(process.env.MSSQL_SSL),
noConfigs: false,
@ -68,7 +70,7 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
propertyVisibility: 'none',
lazy: false,
constructor: false,
namingStrategy: namingStrategy,
namingStrategy,
relationIds: false
});
@ -78,8 +80,9 @@ export async function createMSSQLModels(filesOrgPath: string, resultsPath: strin
await queryRunner.createSchema(sch, true);
}
await conn.synchronize();
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
}
return engine;
}
@ -89,12 +92,13 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
driver = new PostgresDriver();
await driver.ConnectToServer(`postgres`, String(process.env.POSTGRES_Host), Number(process.env.POSTGRES_Port), String(process.env.POSTGRES_Username), String(process.env.POSTGRES_Password), yn(process.env.POSTGRES_SSL));
if (await driver.CheckIfDBExists(String(process.env.POSTGRES_Database)))
if (await driver.CheckIfDBExists(String(process.env.POSTGRES_Database))) {
await driver.DropDB(String(process.env.POSTGRES_Database));
}
await driver.CreateDB(String(process.env.POSTGRES_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
const connOpt: ConnectionOptions = {
database: String(process.env.POSTGRES_Database),
host: String(process.env.POSTGRES_Host),
password: String(process.env.POSTGRES_Password),
@ -106,7 +110,7 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
entities: [path.resolve(filesOrgPath, '*.js')],
}
let schemas = 'public,sch1,sch2'
const schemas = 'public,sch1,sch2'
let conn = await createConnection(connOpt)
let queryRunner = conn.createQueryRunner()
for (const sch of schemas.split(',')) {
@ -114,12 +118,13 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
}
await conn.synchronize();
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
let namingStrategy: AbstractNamingStrategy = new NamingStrategy();
}
const namingStrategy: AbstractNamingStrategy = new NamingStrategy();
driver = new PostgresDriver();
let engine = new Engine(
const engine = new Engine(
driver, {
host: String(process.env.POSTGRES_Host),
port: Number(process.env.POSTGRES_Port),
@ -127,7 +132,7 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
user: String(process.env.POSTGRES_Username),
password: String(process.env.POSTGRES_Password),
databaseType: 'postgres',
resultsPath: resultsPath,
resultsPath,
schemaName: 'public,sch1,sch2',
ssl: yn(process.env.POSTGRES_SSL),
noConfigs: false,
@ -137,7 +142,7 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
propertyVisibility: 'none',
lazy: false,
constructor: false,
namingStrategy: namingStrategy,
namingStrategy,
relationIds: false
});
@ -147,8 +152,9 @@ export async function createPostgresModels(filesOrgPath: string, resultsPath: st
await queryRunner.createSchema(sch, true);
}
await conn.synchronize();
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
}
return engine;
}
@ -158,12 +164,13 @@ export async function createSQLiteModels(filesOrgPath: string, resultsPath: stri
driver = new SqliteDriver();
await driver.ConnectToServer(String(process.env.SQLITE_Database), '', 0, '', '', false);
if (await driver.CheckIfDBExists(String(process.env.SQLITE_Database)))
if (await driver.CheckIfDBExists(String(process.env.SQLITE_Database))) {
await driver.DropDB(String(process.env.SQLITE_Database));
}
await driver.CreateDB(String(process.env.SQLITE_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
const connOpt: ConnectionOptions = {
database: String(process.env.SQLITE_Database),
type: 'sqlite',
dropSchema: true,
@ -175,12 +182,13 @@ export async function createSQLiteModels(filesOrgPath: string, resultsPath: stri
let queryRunner = conn.createQueryRunner()
await conn.synchronize();
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
let namingStrategy: AbstractNamingStrategy = new NamingStrategy();
}
const namingStrategy: AbstractNamingStrategy = new NamingStrategy();
driver = new SqliteDriver();
let engine = new Engine(
const engine = new Engine(
driver, {
host: '',
port: 0,
@ -188,7 +196,7 @@ export async function createSQLiteModels(filesOrgPath: string, resultsPath: stri
user: '',
password: '',
databaseType: 'sqlite',
resultsPath: resultsPath,
resultsPath,
schemaName: '',
ssl: false,
noConfigs: false,
@ -198,15 +206,16 @@ export async function createSQLiteModels(filesOrgPath: string, resultsPath: stri
propertyVisibility: 'none',
lazy: false,
constructor: false,
namingStrategy: namingStrategy,
namingStrategy,
relationIds: false
});
conn = await createConnection(connOpt)
queryRunner = conn.createQueryRunner()
await conn.synchronize();
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
}
return engine;
}
@ -216,12 +225,13 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin
driver = new MysqlDriver();
await driver.ConnectToServer(`mysql`, String(process.env.MYSQL_Host), Number(process.env.MYSQL_Port), String(process.env.MYSQL_Username), String(process.env.MYSQL_Password), yn(process.env.MYSQL_SSL));
if (await driver.CheckIfDBExists(String(process.env.MYSQL_Database)))
if (await driver.CheckIfDBExists(String(process.env.MYSQL_Database))) {
await driver.DropDB(String(process.env.MYSQL_Database));
}
await driver.CreateDB(String(process.env.MYSQL_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
const connOpt: ConnectionOptions = {
database: String(process.env.MYSQL_Database),
host: String(process.env.MYSQL_Host),
password: String(process.env.MYSQL_Password),
@ -232,14 +242,15 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
const conn = await createConnection(connOpt)
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
let namingStrategy: AbstractNamingStrategy = new NamingStrategy();
}
const namingStrategy: AbstractNamingStrategy = new NamingStrategy();
driver = new MysqlDriver();
let engine = new Engine(
const engine = new Engine(
driver, {
host: String(process.env.MYSQL_Host),
port: Number(process.env.MYSQL_Port),
@ -247,7 +258,7 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin
user: String(process.env.MYSQL_Username),
password: String(process.env.MYSQL_Password),
databaseType: 'mysql',
resultsPath: resultsPath,
resultsPath,
schemaName: 'ignored',
ssl: yn(process.env.MYSQL_SSL),
noConfigs: false,
@ -257,7 +268,7 @@ export async function createMysqlModels(filesOrgPath: string, resultsPath: strin
propertyVisibility: 'none',
lazy: false,
constructor: false,
namingStrategy: namingStrategy,
namingStrategy,
relationIds: false
});
@ -268,12 +279,13 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str
driver = new MariaDbDriver();
await driver.ConnectToServer(`mysql`, String(process.env.MARIADB_Host), Number(process.env.MARIADB_Port), String(process.env.MARIADB_Username), String(process.env.MARIADB_Password), yn(process.env.MARIADB_SSL));
if (await driver.CheckIfDBExists(String(process.env.MARIADB_Database)))
if (await driver.CheckIfDBExists(String(process.env.MARIADB_Database))) {
await driver.DropDB(String(process.env.MARIADB_Database));
}
await driver.CreateDB(String(process.env.MARIADB_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
const connOpt: ConnectionOptions = {
database: String(process.env.MARIADB_Database),
host: String(process.env.MARIADB_Host),
password: String(process.env.MARIADB_Password),
@ -284,14 +296,15 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
const conn = await createConnection(connOpt)
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
let namingStrategy: AbstractNamingStrategy = new NamingStrategy();
}
const namingStrategy: AbstractNamingStrategy = new NamingStrategy();
driver = new MariaDbDriver();
let engine = new Engine(
const engine = new Engine(
driver, {
host: String(process.env.MARIADB_Host),
port: Number(process.env.MARIADB_Port),
@ -299,7 +312,7 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str
user: String(process.env.MARIADB_Username),
password: String(process.env.MARIADB_Password),
databaseType: 'mariadb',
resultsPath: resultsPath,
resultsPath,
schemaName: 'ignored',
ssl: yn(process.env.MARIADB_SSL),
noConfigs: false,
@ -309,7 +322,7 @@ export async function createMariaDBModels(filesOrgPath: string, resultsPath: str
propertyVisibility: 'none',
lazy: false,
constructor: false,
namingStrategy: namingStrategy,
namingStrategy,
relationIds: false
});
@ -323,12 +336,13 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st
driver = new OracleDriver();
await driver.ConnectToServer(String(process.env.ORACLE_Database), String(process.env.ORACLE_Host), Number(process.env.ORACLE_Port), String(process.env.ORACLE_UsernameSys), String(process.env.ORACLE_PasswordSys), yn(process.env.ORACLE_SSL));
if (await driver.CheckIfDBExists(String(process.env.ORACLE_Username)))
if (await driver.CheckIfDBExists(String(process.env.ORACLE_Username))) {
await driver.DropDB(String(process.env.ORACLE_Username));
}
await driver.CreateDB(String(process.env.ORACLE_Username));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
const connOpt: ConnectionOptions = {
database: String(process.env.ORACLE_Database),
sid: String(process.env.ORACLE_Database),
host: String(process.env.ORACLE_Host),
@ -339,14 +353,15 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
const conn = await createConnection(connOpt)
if (conn.isConnected)
if (conn.isConnected) {
await conn.close()
let namingStrategy: AbstractNamingStrategy = new NamingStrategy();
}
const namingStrategy: AbstractNamingStrategy = new NamingStrategy();
driver = new OracleDriver();
let engine = new Engine(
const engine = new Engine(
driver, {
host: String(process.env.ORACLE_Host),
port: Number(process.env.ORACLE_Port),
@ -354,7 +369,7 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st
user: String(process.env.ORACLE_Username),
password: String(process.env.ORACLE_Password),
databaseType: 'oracle',
resultsPath: resultsPath,
resultsPath,
schemaName: String(process.env.ORACLE_Username),
ssl: yn(process.env.ORACLE_SSL),
noConfigs: false,
@ -364,7 +379,7 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st
propertyVisibility: 'none',
lazy: false,
constructor: false,
namingStrategy: namingStrategy,
namingStrategy,
relationIds: false
});
@ -372,16 +387,16 @@ export async function createOracleDBModels(filesOrgPath: string, resultsPath: st
}
export function compileTsFiles(fileNames: string[], options: ts.CompilerOptions): boolean {
let program = ts.createProgram(fileNames, options);
let emitResult = program.emit();
const program = ts.createProgram(fileNames, options);
const emitResult = program.emit();
let compileErrors = false;
let preDiagnostics = ts.getPreEmitDiagnostics(program);
const preDiagnostics = ts.getPreEmitDiagnostics(program);
let allDiagnostics = [...preDiagnostics, ...emitResult.diagnostics];
const allDiagnostics = [...preDiagnostics, ...emitResult.diagnostics];
allDiagnostics.forEach(diagnostic => {
let lineAndCharacter = diagnostic.file!.getLineAndCharacterOfPosition(diagnostic.start!);
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
const lineAndCharacter = diagnostic.file!.getLineAndCharacterOfPosition(diagnostic.start!);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.log(`${diagnostic.file!.fileName} (${lineAndCharacter.line + 1},${lineAndCharacter.character + 1}): ${message}`);
compileErrors = true;
});