Merge branch 'master' into greenkeeper/mocha-5.0.5

This commit is contained in:
Kononnable 2018-04-01 18:40:30 +02:00 committed by GitHub
commit 615f094cb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 368 additions and 180 deletions

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "typeorm-model-generator",
"version": "0.2.11",
"version": "0.2.12",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "typeorm-model-generator",
"version": "0.2.11",
"version": "0.2.12",
"description": "Generates models for TypeORM from existing databases.",
"bin": "bin/typeorm-model-generator",
"scripts": {

View File

@ -27,7 +27,7 @@ export class Engine {
if (dbModel.entities.length > 0) {
this.createModelFromMetadata(dbModel);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
"Tables not found in selected database. Skipping creation of typeorm model.",
false
);
@ -160,6 +160,32 @@ export class Engine {
Handlebars.registerHelper("toLowerCase", str => {
return str.toLowerCase();
});
Handlebars.registerHelper({
eq: function(v1, v2) {
return v1 === v2;
},
ne: function(v1, v2) {
return v1 !== v2;
},
lt: function(v1, v2) {
return v1 < v2;
},
gt: function(v1, v2) {
return v1 > v2;
},
lte: function(v1, v2) {
return v1 <= v2;
},
gte: function(v1, v2) {
return v1 >= v2;
},
and: function(v1, v2) {
return v1 && v2;
},
or: function(v1, v2) {
return v1 || v2;
}
});
}
//TODO:Move to mustache template file

View File

@ -1,20 +1,19 @@
import * as data from "./../../package.json";
export function LogFatalError(
export function LogError(
errText: string,
isABug: boolean = true,
errObject?: any
) {
let x = <any>data;
console.error(errText);
console.error(`Fatal error occured.`);
console.error(`Error occured in typeorm-model-generator.`);
console.error(`${x.name}@${x.version} node@${process.version}`);
console.error(`Fatal error occured in typeorm-model-generator.`);
console.error(
`If this is a bug please open an issue including this log on ${
`If you think this is a bug please open an issue including this log on ${
x.bugs.url
}`
);
if (isABug && !errObject) errObject = new Error().stack;
if (!!errObject) console.error(errObject);
process.abort();
// process.abort();
}

View File

@ -1,9 +1,71 @@
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 { ManyToMany } from "typeorm";
/**
* AbstractDriver
*/
export abstract class AbstractDriver {
FindManyToManyRelations(dbModel: DatabaseModel) {
let manyToManyEntities = dbModel.entities.filter(entity => {
return (
entity.Columns.filter(column => {
return (
column.relations.length == 1 &&
!column.relations[0].isOneToMany &&
column.relations[0].isOwner
);
}).length == entity.Columns.length
);
});
manyToManyEntities.map(entity => {
let relations: RelationInfo[] = [];
relations = entity.Columns.reduce((prev: RelationInfo[], curr) => {
return prev.concat(curr.relations);
}, relations);
//TODO: Composed keys
if (relations.length == 2) {
let relatedTable1 = dbModel.entities.filter(
v => v.EntityName == relations[0].relatedTable
)[0];
relatedTable1.Columns = relatedTable1.Columns.filter(
v => v.name.toLowerCase() != entity.EntityName.toLowerCase()
);
let relatedTable2 = dbModel.entities.filter(
v => v.EntityName == relations[1].relatedTable
)[0];
relatedTable2.Columns = relatedTable2.Columns.filter(
v => v.name.toLowerCase() != entity.EntityName.toLowerCase()
);
dbModel.entities = dbModel.entities.filter(ent => {
return ent.EntityName != entity.EntityName;
});
let column1 = new ColumnInfo();
column1.name = relations[1].relatedTable;
let col1Rel = new RelationInfo();
col1Rel.relatedTable = relations[1].relatedTable;
col1Rel.relatedColumn = relations[1].relatedTable;
col1Rel.relationType = "ManyToMany";
col1Rel.isOwner = true;
col1Rel.ownerColumn = relations[0].relatedTable;
column1.relations.push(col1Rel);
relatedTable1.Columns.push(column1);
let column2 = new ColumnInfo();
column2.name = relations[0].relatedTable;
let col2Rel = new RelationInfo();
col2Rel.relatedTable = relations[0].relatedTable;
col2Rel.relatedColumn = relations[1].relatedTable;
col2Rel.relationType = "ManyToMany";
col2Rel.isOwner = false;
column2.relations.push(col2Rel);
relatedTable2.Columns.push(column2);
}
});
}
async GetDataFromServer(
database: string,
server: string,
@ -24,6 +86,7 @@ export abstract class AbstractDriver {
sqlEscapedSchema
);
await this.DisconnectFromServer();
this.FindManyToManyRelations(dbModel);
this.FindPrimaryColumnsFromIndexes(dbModel);
return dbModel;
}
@ -48,7 +111,27 @@ export abstract class AbstractDriver {
entities: EntityInfo[],
schema: string
): Promise<EntityInfo[]>;
abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel);
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
TomgUtils.LogError(
`Table ${entity.EntityName} has no PK.`,
false
);
return;
}
entity.Columns.forEach(col => {
if (
primaryIndex!.columns.some(
cIndex => cIndex.name == col.name
)
)
col.isPrimary = true;
});
});
}
abstract async DisconnectFromServer();
abstract async CreateDB(dbName: string);

View File

@ -10,27 +10,6 @@ import * as TomgUtils from "./../Utils";
* MssqlDriver
*/
export class MssqlDriver extends AbstractDriver {
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
TomgUtils.LogFatalError(
`Table ${entity.EntityName} has no PK.`,
false
);
return;
}
entity.Columns.forEach(col => {
if (
primaryIndex!.columns.some(
cIndex => cIndex.name == col.name
)
)
col.isPrimary = true;
});
});
}
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection);
let response: {
@ -238,7 +217,7 @@ export class MssqlDriver extends AbstractDriver {
colInfo.ts_type = "string";
break;
default:
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Unknown column type: ${
resp.DATA_TYPE
} table name: ${
@ -384,7 +363,7 @@ order by
return entitity.EntityName == relationTmp.ownerTable;
});
if (!ownerEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.ownerTable}.`
@ -395,7 +374,7 @@ order by
return entitity.EntityName == relationTmp.referencedTable;
});
if (!referencedEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.referencedTable}.`
@ -406,7 +385,7 @@ order by
return column.name == relationTmp.ownerColumnsNames[0];
});
if (!ownerColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -419,7 +398,7 @@ order by
return column.name == relationTmp.referencedColumnsNames[0];
});
if (!relatedColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -538,7 +517,7 @@ order by
//Connection successfull
resolve(true);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
"Error connecting to MSSQL Server.",
false,
err.message

View File

@ -11,27 +11,6 @@ import * as TomgUtils from "./../Utils";
export class MysqlDriver extends AbstractDriver {
readonly EngineName: string = "MySQL";
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
TomgUtils.LogFatalError(
`Table ${entity.EntityName} has no PK.`,
false
);
return;
}
entity.Columns.forEach(col => {
if (
primaryIndex!.columns.some(
cIndex => cIndex.name == col.name
)
)
col.isPrimary = true;
});
});
}
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TABLE_SCHEMA: string;
@ -231,7 +210,7 @@ export class MysqlDriver extends AbstractDriver {
.replace(/\'/gi, '"');
break;
default:
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Unknown column type: ${
resp.DATA_TYPE
} table name: ${
@ -347,7 +326,7 @@ export class MysqlDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.ownerTable;
});
if (!ownerEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.ownerTable}.`
@ -358,7 +337,7 @@ export class MysqlDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.referencedTable;
});
if (!referencedEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.referencedTable}.`
@ -369,7 +348,7 @@ export class MysqlDriver extends AbstractDriver {
return column.name == relationTmp.ownerColumnsNames[0];
});
if (!ownerColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -382,7 +361,7 @@ export class MysqlDriver extends AbstractDriver {
return column.name == relationTmp.referencedColumnsNames[0];
});
if (!relatedColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -477,7 +456,7 @@ export class MysqlDriver extends AbstractDriver {
//Connection successfull
resolve(true);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Error disconnecting to ${this.EngineName} Server.`,
false,
err.message
@ -529,7 +508,7 @@ export class MysqlDriver extends AbstractDriver {
//Connection successfull
resolve(true);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Error connecting to ${this.EngineName} Server.`,
false,
err.message

View File

@ -17,32 +17,11 @@ export class OracleDriver extends AbstractDriver {
try {
this.Oracle = require("oracledb");
} catch (error) {
TomgUtils.LogFatalError("", false, error);
TomgUtils.LogError("", false, error);
throw error;
}
}
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
TomgUtils.LogFatalError(
`Table ${entity.EntityName} has no PK.`,
false
);
return;
}
entity.Columns.forEach(col => {
if (
primaryIndex!.columns.some(
cIndex => cIndex.name == col.name
)
)
col.isPrimary = true;
});
});
}
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response: any[][] = (await this.Connection.execute(
` SELECT TABLE_NAME FROM all_tables WHERE owner = (select user from dual)`
@ -91,7 +70,7 @@ export class OracleDriver extends AbstractDriver {
resp[5] > 0 ? resp[5] : null;
break;
default:
TomgUtils.LogFatalError(
TomgUtils.LogError(
"Unknown column type:" + resp[4]
);
break;
@ -185,7 +164,7 @@ export class OracleDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.ownerTable;
});
if (!ownerEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.ownerTable}.`
@ -196,7 +175,7 @@ export class OracleDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.referencedTable;
});
if (!referencedEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.referencedTable}.`
@ -207,7 +186,7 @@ export class OracleDriver extends AbstractDriver {
return column.name == relationTmp.ownerColumnsNames[0];
});
if (!ownerColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -220,7 +199,7 @@ export class OracleDriver extends AbstractDriver {
return column.name == relationTmp.referencedColumnsNames[0];
});
if (!relatedColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -337,7 +316,7 @@ export class OracleDriver extends AbstractDriver {
that.Connection = connection;
resolve(true);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
"Error connecting to Oracle Server.",
false,
err.message

View File

@ -11,27 +11,6 @@ import * as TomgUtils from "./../Utils";
export class PostgresDriver extends AbstractDriver {
private Connection: PG.Client;
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
TomgUtils.LogFatalError(
`Table ${entity.EntityName} has no PK.`,
false
);
return;
}
entity.Columns.forEach(col => {
if (
primaryIndex!.columns.some(
cIndex => cIndex.name == col.name
)
)
col.isPrimary = true;
});
});
}
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response: {
table_schema: string;
@ -209,7 +188,7 @@ export class PostgresDriver extends AbstractDriver {
colInfo.ts_type = "string";
break;
default:
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Unknown column type: ${
resp.data_type
} table name: ${
@ -235,33 +214,31 @@ export class PostgresDriver extends AbstractDriver {
is_unique: number;
is_primary_key: number; //, is_descending_key: number//, is_included_column: number
}[] = (await this.Connection.query(`SELECT
c.relname AS tablename,
i.relname as indexname,
f.attname AS columnname,
CASE
WHEN ix.indisunique = true THEN '1'
ELSE '0'
END AS is_unique,
CASE
WHEN p.contype = 'p' THEN '1'
ELSE '0'
END AS is_primary_key
FROM pg_attribute f
JOIN pg_class c ON c.oid = f.attrelid
JOIN pg_type t ON t.oid = f.atttypid
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
LEFT JOIN pg_class AS g ON p.confrelid = g.oid
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
c.relname AS tablename,
i.relname as indexname,
f.attname AS columnname,
CASE
WHEN ix.indisunique = true THEN '1'
ELSE '0'
END AS is_unique,
CASE
WHEN ix.indisprimary='true' THEN '1'
ELSE '0'
END AS is_primary_key
FROM pg_attribute f
JOIN pg_class c ON c.oid = f.attrelid
JOIN pg_type t ON t.oid = f.atttypid
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
WHERE c.relkind = 'r'::char
AND n.nspname in (${schema})
--AND c.relname = 'nodes' -- Replace with table name, or Comment this for get all tables
AND f.attnum > 0
AND i.oid<>0
ORDER BY c.relname,f.attname;`)).rows;
WHERE c.relkind = 'r'::char
AND n.nspname in (${schema})
--AND c.relname = 'nodes' -- Replace with table name, or Comment this for get all tables
AND f.attnum > 0
AND i.oid<>0
ORDER BY c.relname,f.attname;`)).rows;
entities.forEach(ent => {
response
.filter(filterVal => {
@ -373,7 +350,7 @@ export class PostgresDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.ownerTable;
});
if (!ownerEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.ownerTable}.`
@ -384,7 +361,7 @@ export class PostgresDriver extends AbstractDriver {
return entitity.EntityName == relationTmp.referencedTable;
});
if (!referencedEntity) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity model ${relationTmp.referencedTable}.`
@ -395,7 +372,7 @@ export class PostgresDriver extends AbstractDriver {
return column.name == relationTmp.ownerColumnsNames[0];
});
if (!ownerColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -408,7 +385,7 @@ export class PostgresDriver extends AbstractDriver {
return column.name == relationTmp.referencedColumnsNames[0];
});
if (!relatedColumn) {
TomgUtils.LogFatalError(
TomgUtils.LogError(
`Relation between tables ${relationTmp.ownerTable} and ${
relationTmp.referencedTable
} didn't found entity column ${
@ -504,7 +481,7 @@ export class PostgresDriver extends AbstractDriver {
//Connection successfull
resolve(true);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
"Error connecting to Postgres Server.",
false,
err.message
@ -540,7 +517,7 @@ export class PostgresDriver extends AbstractDriver {
//Connection successfull
resolve(true);
} else {
TomgUtils.LogFatalError(
TomgUtils.LogError(
"Error connecting to Postgres Server.",
false,
err.message

View File

@ -1,4 +1,4 @@
import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm";
import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable} from "typeorm";
{{relationImports}}{{#each UniqueImports}}import {{curly true}}{{toEntityName this}}{{curly false}} from "./{{toFileName this}}";
{{/each}}
@ -23,8 +23,8 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi
{{toPropertyName name}}:{{ts_type}};
{{/relations}}{{#relations}}
@{{relationType}}(type=>{{toEntityName relatedTable}}, {{toPropertyName ../name}}=>{{toPropertyName ../name}}.{{#if isOwner}}{{toPropertyName ownerColumn}}{{else}}{{toPropertyName relatedColumn}}{{/if}}){{#isOwner}}
@JoinColumn({ name:'{{ ../name}}'}){{/isOwner}}
{{#if isOneToMany}}{{toPropertyName ../name}}:{{toEntityName relatedTable}}[];
{{#if isManyToMany}}@JoinTable(){{else}}@JoinColumn({ name:'{{ ../name}}'}){{/if}}{{/isOwner}}
{{#if (or isOneToMany isManyToMany)}}{{toPropertyName ../name}}:{{toEntityName relatedTable}}[];
{{else}}{{toPropertyName ../name}}:{{toEntityName relatedTable}};
{{/if}}{{/relations}}
{{/Columns}}

View File

@ -107,7 +107,7 @@ switch (argv.e) {
standardPort = 1521;
break;
default:
TomgUtils.LogFatalError("Database engine not recognized.", false);
TomgUtils.LogError("Database engine not recognized.", false);
throw new Error("Database engine not recognized.");
}

View File

@ -1,23 +1,4 @@
import { EntityInfo } from "./EntityInfo";
export class DatabaseModel {
entities: EntityInfo[];
config: {
cascadeInsert: boolean;
cascadeUpdate: boolean;
cascadeRemove: boolean;
};
//TODO:check if unused
relationImports(): any {
let that = this;
return function(text, render) {
if ("l" != render(text))
return `import {{curly true}}{{toEntityName ${render(
text
)}}}{{curly false}} from "./{{ ${render(
"toFileName" + text
)}}}`;
else return "";
};
}
}

View File

@ -2,7 +2,7 @@ export class RelationInfo {
[x: string]: any;
isOwner: boolean;
relationType: "OneToOne" | "OneToMany" | "ManyToOne";
relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany";
relatedTable: string;
relatedColumn: string;
ownerTable: string;
@ -13,4 +13,7 @@ export class RelationInfo {
get isOneToMany(): boolean {
return this.relationType == "OneToMany";
}
get isManyToMany(): boolean {
return this.relationType == "ManyToMany";
}
}

View File

@ -0,0 +1,62 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
import {PostDetails} from "./PostDetails";
import {PostCategory} from "./PostCategory";
import {PostAuthor} from "./PostAuthor";
import {PostInformation} from "./PostInformation";
import {PostImage} from "./PostImage";
import {PostMetadata} from "./PostMetadata";
@Entity("Post")
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
text: string;
// post has relation with category, however inverse relation is not set (category does not have relation with post set)
@ManyToMany(type => PostCategory, {
cascade: true
})
@JoinTable()
PostCategory: PostCategory[];
// post has relation with details. cascade inserts here means if new PostDetails instance will be set to this
// relation it will be inserted automatically to the db when you save this Post entity
@ManyToMany(type => PostDetails, details => details.Post, {
cascade: true
})
@JoinTable()
PostDetails: PostDetails[];
// post has relation with details. cascade update here means if new PostDetail instance will be set to this relation
// it will be inserted automatically to the db when you save this Post entity
@ManyToMany(type => PostImage, image => image.Post, {
cascade: true
})
@JoinTable()
PostImage: PostImage[];
// post has relation with details. cascade update here means if new PostDetail instance will be set to this relation
// it will be inserted automatically to the db when you save this Post entity
@ManyToMany(type => PostMetadata, metadata => metadata.Post)
@JoinTable()
PostMetadata: PostMetadata[];
// post has relation with details. full cascades here
@ManyToMany(type => PostInformation, information => information.Post, {
cascade: true
})
@JoinTable()
PostInformation: PostInformation[];
// post has relation with details. not cascades here. means cannot be persisted, updated or removed
@ManyToMany(type => PostAuthor, author => author.Post)
@JoinTable()
PostAuthor: PostAuthor[];
}

View File

@ -0,0 +1,16 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
import {Post} from "./Post";
@Entity("PostAuthor")
export class PostAuthor {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => Post, post => post.PostAuthor)
Post: Post[];
}

View File

@ -0,0 +1,12 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
@Entity("PostCategory")
export class PostCategory {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}

View File

@ -0,0 +1,22 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
import {Post} from "./Post";
@Entity("PostDetails")
export class PostDetails {
@PrimaryGeneratedColumn()
id: number;
@Column()
authorName: string;
@Column()
comment: string;
@Column()
metadata: string;
@ManyToMany(type => Post, post => post.PostDetails)
Post: Post[];
}

View File

@ -0,0 +1,16 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
import {Post} from "./Post";
@Entity("PostImage")
export class PostImage {
@PrimaryGeneratedColumn()
id: number;
@Column()
url: string;
@ManyToMany(type => Post, post => post.PostImage)
Post: Post[];
}

View File

@ -0,0 +1,16 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
import {Post} from "./Post";
@Entity("PostInformation")
export class PostInformation {
@PrimaryGeneratedColumn()
id: number;
@Column()
text: string;
@ManyToMany(type => Post, post => post.PostInformation)
Post: Post[];
}

View File

@ -0,0 +1,16 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm";
import {Post} from "./Post";
@Entity("PostMetadata")
export class PostMetadata {
@PrimaryGeneratedColumn()
id: number;
@Column()
description: string;
@ManyToMany(type => Post, post => post.PostMetadata)
Post: Post[];
}

View File

@ -5,15 +5,15 @@ export class EntityFileToJson {
let decoratorParameters = trimmedLine.slice(trimmedLine.indexOf('(') + 1, trimmedLine.lastIndexOf(')'))
if (decoratorParameters.length > 0) {
if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) {
if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) {
} else {
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
if (badJSON.lastIndexOf(',') == badJSON.length - 3) {
badJSON = badJSON.slice(0, badJSON.length - 3) + badJSON[badJSON.length - 2] + badJSON[badJSON.length - 1]
}
ent.entityOptions = JSON.parse(badJSON.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
} else {
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
if (badJSON.lastIndexOf(',') == badJSON.length - 3) {
badJSON = badJSON.slice(0, badJSON.length - 3) + badJSON[badJSON.length - 2] + badJSON[badJSON.length - 1]
}
ent.entityOptions = JSON.parse(badJSON.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
}
}
}
getColumnOptionsAndType(trimmedLine: string, col: EntityColumn) {
@ -126,8 +126,8 @@ export class EntityFileToJson {
priorPartOfMultilineStatement = trimmedLine;
continue;
} else {
let options = trimmedLine.substring(trimmedLine.lastIndexOf('{'), trimmedLine.lastIndexOf('}')+1).trim().toLowerCase()
this.getEntityOptions(trimmedLine,retVal);
let options = trimmedLine.substring(trimmedLine.lastIndexOf('{'), trimmedLine.lastIndexOf('}') + 1).trim().toLowerCase()
this.getEntityOptions(trimmedLine, retVal);
continue;
}
} else if (trimmedLine.startsWith('export class')) {
@ -225,6 +225,18 @@ export class EntityFileToJson {
column.relationType = "OneToMany"
continue;
}
} else if (trimmedLine.startsWith('@ManyToMany')) {
if (this.isPartOfMultilineStatement(trimmedLine)) {
isMultilineStatement = true;
priorPartOfMultilineStatement = trimmedLine;
continue;
} else {
isMultilineStatement = false;
let column = new EntityColumn()
retVal.columns.push(column)
column.relationType = "ManyToMany"
continue;
}
} else if (trimmedLine.startsWith('@OneToOne')) {
if (this.isPartOfMultilineStatement(trimmedLine)) {
isMultilineStatement = true;
@ -247,6 +259,16 @@ export class EntityFileToJson {
retVal.columns[retVal.columns.length - 1].isOwnerOfRelation = true;
continue;
}
} else if (trimmedLine.startsWith('@JoinTable')) {
if (this.isPartOfMultilineStatement(trimmedLine)) {
isMultilineStatement = true;
priorPartOfMultilineStatement = trimmedLine;
continue;
} else {
isMultilineStatement = false;
retVal.columns[retVal.columns.length - 1].isOwnerOfRelation = true;
continue;
}
} else if (trimmedLine.startsWith('@Index')) {
if (this.isPartOfMultilineStatement(trimmedLine)) {
isMultilineStatement = true;
@ -332,7 +354,7 @@ class EntityColumn {
columnName: string
columnTypes: string[] = []
columnOptions: any = {}
relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "None" = "None"
relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany" | "None" = "None"
isOwnerOfRelation: boolean = false;
}
class EntityIndex {