added relation tests - problems with distinguishing OneTwoMany from OneToOne without indexes
This commit is contained in:
parent
3ca6707a80
commit
642e57bf74
@ -1,22 +1,23 @@
|
||||
import { AbstractDriver } from './AbstractDriver'
|
||||
import * as MSSQL from 'mssql'
|
||||
import {ColumnInfo} from './../models/ColumnInfo'
|
||||
import {EntityInfo} from './../models/EntityInfo'
|
||||
import {DatabaseModel} from './../models/DatabaseModel'
|
||||
import { ColumnInfo } from './../models/ColumnInfo'
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { RelationInfo } from './../models/RelationInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
/**
|
||||
* MssqlDriver
|
||||
*/
|
||||
export class MssqlDriver extends AbstractDriver {
|
||||
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
|
||||
dbModel.entities.forEach(entity => {
|
||||
let primaryIndex = entity.Indexes.find(v=>v.isPrimaryKey);
|
||||
if (!primaryIndex){
|
||||
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
|
||||
if (!primaryIndex) {
|
||||
console.error(`Table ${entity.EntityName} has no PK.`)
|
||||
return;
|
||||
}
|
||||
let pIndex=primaryIndex //typescript error? pIndex:IndexInfo; primaryIndex:IndexInfo|undefined
|
||||
entity.Columns.forEach(col=>{
|
||||
if(pIndex.columns.some( cIndex=> cIndex.name==col.name)) col.isPrimary=true
|
||||
let pIndex = primaryIndex //typescript error? pIndex:IndexInfo; primaryIndex:IndexInfo|undefined
|
||||
entity.Columns.forEach(col => {
|
||||
if (pIndex.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
|
||||
})
|
||||
});
|
||||
}
|
||||
@ -37,9 +38,11 @@ export class MssqlDriver extends AbstractDriver {
|
||||
}
|
||||
async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection)
|
||||
let response: { TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
|
||||
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
|
||||
NUMERIC_PRECISION:number,NUMERIC_SCALE:number,IsIdentity:number }[]
|
||||
let response: {
|
||||
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
|
||||
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
|
||||
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity: number
|
||||
}[]
|
||||
= await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
|
||||
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
|
||||
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS`);
|
||||
@ -116,8 +119,8 @@ export class MssqlDriver extends AbstractDriver {
|
||||
case "decimal":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "decimal"
|
||||
colInfo.numericPrecision=resp.NUMERIC_PRECISION
|
||||
colInfo.numericScale=resp.NUMERIC_SCALE
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string"
|
||||
@ -127,7 +130,7 @@ export class MssqlDriver extends AbstractDriver {
|
||||
console.error("Unknown column type:" + resp.DATA_TYPE);
|
||||
break;
|
||||
}
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH>0?resp.CHARACTER_MAXIMUM_LENGTH:null;
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
})
|
||||
})
|
||||
@ -192,7 +195,8 @@ ORDER BY
|
||||
let response: {
|
||||
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
|
||||
TableReferenced: string, ForeignKeyColumnReferenced: string,
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET NULL", object_id: number
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: number
|
||||
}[]
|
||||
= await request.query(`select
|
||||
parentTable.name as TableWithForeignKey,
|
||||
@ -201,6 +205,7 @@ ORDER BY
|
||||
referencedTable.name as TableReferenced,
|
||||
referencedColumn.name as ForeignKeyColumnReferenced,
|
||||
fk.delete_referential_action_desc as onDelete,
|
||||
fk.update_referential_action_desc as onUpdate,
|
||||
fk.object_id
|
||||
from
|
||||
sys.foreign_keys fk
|
||||
@ -228,6 +233,7 @@ order by
|
||||
rels.ownerColumnsNames = [];
|
||||
rels.referencedColumnsNames = [];
|
||||
rels.actionOnDelete = resp.onDelete;
|
||||
rels.actionOnUpdate = resp.onUpdate;
|
||||
rels.object_id = resp.object_id;
|
||||
rels.ownerTable = resp.TableWithForeignKey;
|
||||
rels.referencedTable = resp.TableReferenced;
|
||||
@ -236,66 +242,84 @@ order by
|
||||
rels.ownerColumnsNames.push(resp.ForeignKeyColumn);
|
||||
rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced);
|
||||
})
|
||||
relationsTemp.forEach( (relationTmp)=>{
|
||||
let ownerEntity = entities.find((entitity)=>{
|
||||
return entitity.EntityName==relationTmp.ownerTable;
|
||||
relationsTemp.forEach((relationTmp) => {
|
||||
let ownerEntity = entities.find((entitity) => {
|
||||
return entitity.EntityName == relationTmp.ownerTable;
|
||||
})
|
||||
if (!ownerEntity){
|
||||
if (!ownerEntity) {
|
||||
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
|
||||
return;
|
||||
}
|
||||
let referencedEntity = entities.find((entitity)=>{
|
||||
return entitity.EntityName==relationTmp.referencedTable;
|
||||
let referencedEntity = entities.find((entitity) => {
|
||||
return entitity.EntityName == relationTmp.referencedTable;
|
||||
})
|
||||
if (!referencedEntity){
|
||||
if (!referencedEntity) {
|
||||
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
|
||||
return;
|
||||
}
|
||||
let ownerColumn = ownerEntity.Columns.find((column)=>{
|
||||
return column.name==relationTmp.ownerColumnsNames[0];
|
||||
let ownerColumn = ownerEntity.Columns.find((column) => {
|
||||
return column.name == relationTmp.ownerColumnsNames[0];
|
||||
})
|
||||
if(!ownerColumn){
|
||||
if (!ownerColumn) {
|
||||
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
|
||||
return;
|
||||
}
|
||||
let relatedColumn = referencedEntity.Columns.find((column)=>{
|
||||
return column.name==relationTmp.referencedColumnsNames[0];
|
||||
let relatedColumn = referencedEntity.Columns.find((column) => {
|
||||
return column.name == relationTmp.referencedColumnsNames[0];
|
||||
})
|
||||
if(!relatedColumn){
|
||||
if (!relatedColumn) {
|
||||
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
|
||||
return;
|
||||
}
|
||||
let ownColumn:ColumnInfo = ownerColumn;
|
||||
let isOneToMany:boolean;
|
||||
isOneToMany=false;
|
||||
let ownColumn: ColumnInfo = ownerColumn;
|
||||
let isOneToMany: boolean;
|
||||
isOneToMany = false;
|
||||
let index = ownerEntity.Indexes.find(
|
||||
(index)=>{
|
||||
return index.isUnique && index.columns.some(col=>{
|
||||
return col.name==ownColumn.name
|
||||
(index) => {
|
||||
return index.isUnique && index.columns.some(col => {
|
||||
return col.name == ownColumn.name
|
||||
})
|
||||
}
|
||||
)
|
||||
if (!index){
|
||||
isOneToMany=true;
|
||||
}else{
|
||||
isOneToMany=false;
|
||||
if (!index) {
|
||||
isOneToMany = true;
|
||||
} else {
|
||||
isOneToMany = false;
|
||||
}
|
||||
let ownerRelation=new RelationInfo()
|
||||
ownerRelation.actionOnDelete= relationTmp.actionOnDelete
|
||||
ownerRelation.actionOnUpdate= relationTmp.actionOnUpdate
|
||||
ownerRelation.isOwner= true
|
||||
ownerRelation.relatedColumn= relatedColumn.name.toLowerCase()
|
||||
ownerRelation.relatedTable= relationTmp.referencedTable
|
||||
ownerRelation.relationType= isOneToMany ? "OneToMany" : "OneToOne"
|
||||
ownerColumn.relations.push(ownerRelation)
|
||||
if (isOneToMany) {
|
||||
let col = new ColumnInfo()
|
||||
col.name = ownerEntity.EntityName.toLowerCase() //+ 's'
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete= relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate= relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner= false
|
||||
referencedRelation.relatedColumn= ownerColumn.name
|
||||
referencedRelation.relatedTable= relationTmp.ownerTable
|
||||
referencedRelation.relationType= "ManyToOne"
|
||||
referencedEntity.Columns.push(col)
|
||||
} else {
|
||||
let col = new ColumnInfo()
|
||||
col.name = ownerEntity.EntityName.toLowerCase()
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete= relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate= relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner= false
|
||||
referencedRelation.relatedColumn= ownerColumn.name
|
||||
referencedRelation.relatedTable= relationTmp.ownerTable
|
||||
referencedRelation.relationType= "OneToOne"
|
||||
|
||||
referencedEntity.Columns.push(col)
|
||||
}
|
||||
|
||||
ownerColumn.relations.push(<RelationInfo>{
|
||||
actionOnDelete:relationTmp.actionOnDelete,
|
||||
isOwner:true,
|
||||
relatedColumn:relatedColumn.name,
|
||||
relatedTable:relationTmp.referencedTable,
|
||||
relationType:isOneToMany?"OneToMany":"OneToOne"
|
||||
})
|
||||
relatedColumn.relations.push(<RelationInfo>{
|
||||
actionOnDelete:relationTmp.actionOnDelete,
|
||||
isOwner:false,
|
||||
relatedColumn:ownerColumn.name,
|
||||
relatedTable:relationTmp.ownerTable,
|
||||
relationType:isOneToMany?"ManyToOne":"OneToOne"
|
||||
})
|
||||
|
||||
})
|
||||
return entities;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinTable} from "typeorm";
|
||||
import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm";
|
||||
{{relationImports}}
|
||||
|
||||
@Entity()
|
||||
@ -7,7 +7,7 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi
|
||||
|
||||
{{#Columns}}
|
||||
|
||||
@Column("{{sql_type}}",{ {{#is_generated}}
|
||||
{{^relations}} @Column("{{sql_type}}",{ {{#is_generated}}
|
||||
generated:true,{{/is_generated}}{{#is_nullable}}
|
||||
nullable:true,{{/is_nullable}}{{^is_nullable}}
|
||||
nullable:false,{{/is_nullable}}{{#char_max_lenght}}
|
||||
@ -16,9 +16,13 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Joi
|
||||
precision:{{numericPrecision}},{{/numericPrecision}}{{#numericScale}}
|
||||
scale:{{numericScale}},{{/numericScale}}{{#isPrimary}}
|
||||
primary:{{isPrimary}},{{/isPrimary}}
|
||||
}){{#relations}}
|
||||
@{{relationType}}(type=>{{relatedTable}},x=>x.{{relatedColumn}}){{#isOwner}}
|
||||
@JoinTable(){{/isOwner}}{{/relations}}
|
||||
})
|
||||
{{name}}:{{ts_type}};
|
||||
{{/relations}}{{#relations}}
|
||||
@{{relationType}}(type=>{{relatedTable}},x=>x.{{relatedColumn}}){{#isOwner}}
|
||||
@JoinColumn(){{/isOwner}}
|
||||
{{#if isOneToMany}}{{../name}}:{{relatedTable}}[];
|
||||
{{else}}{{../name}}:{{relatedTable}};
|
||||
{{/if}}{{/relations}}
|
||||
{{/Columns}}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import {RelationInfo} from './RelationInfo'
|
||||
/**
|
||||
* ColumnInfo
|
||||
*/
|
||||
|
@ -1,7 +1,13 @@
|
||||
interface RelationInfo {
|
||||
isOwner: boolean,
|
||||
relationType: "OneToOne", "OneToMany", "ManyToOne"
|
||||
relatedTable: string,
|
||||
relatedColumn: string,
|
||||
actionOnDelete:"RESTRICT"|"CASCADE"|"SET NULL",
|
||||
export class RelationInfo {
|
||||
isOwner: boolean
|
||||
relationType: "OneToOne" | "OneToMany" | "ManyToOne"
|
||||
relatedTable: string
|
||||
relatedColumn: string
|
||||
actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL"
|
||||
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL"
|
||||
|
||||
get isOneToMany(): boolean {
|
||||
return this.relationType == "OneToMany"
|
||||
}
|
||||
|
||||
}
|
@ -4,5 +4,6 @@ interface RelationTempInfo{
|
||||
referencedTable:string,
|
||||
referencedColumnsNames:string[],
|
||||
actionOnDelete:"RESTRICT"|"CASCADE"|"SET NULL",
|
||||
actionOnUpdate:"RESTRICT"|"CASCADE"|"SET NULL",
|
||||
object_id:number
|
||||
}
|
@ -4,6 +4,7 @@ import * as Sinon from 'sinon'
|
||||
import * as MSSQL from 'mssql'
|
||||
import { EntityInfo } from './../../src/models/EntityInfo'
|
||||
import { ColumnInfo } from './../../src/models/ColumnInfo'
|
||||
import { RelationInfo } from './../../src/models/RelationInfo'
|
||||
|
||||
|
||||
describe('MssqlDriver', function () {
|
||||
|
68
test/integration/examples/sample2-one-to-one/entity/Post.ts
Normal file
68
test/integration/examples/sample2-one-to-one/entity/Post.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} 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)
|
||||
@OneToOne(type => PostCategory, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
@JoinColumn()
|
||||
category: 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
|
||||
@OneToOne(type => PostDetails, details => details.post, {
|
||||
cascadeInsert: true
|
||||
})
|
||||
@JoinColumn()
|
||||
details: 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
|
||||
@OneToOne(type => PostImage, image => image.post, {
|
||||
cascadeUpdate: true
|
||||
})
|
||||
@JoinColumn()
|
||||
image: 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
|
||||
@OneToOne(type => PostMetadata, metadata => metadata.post, {
|
||||
cascadeRemove: true
|
||||
})
|
||||
@JoinColumn()
|
||||
metadata: PostMetadata|null;
|
||||
|
||||
// post has relation with details. full cascades here
|
||||
@OneToOne(type => PostInformation, information => information.post, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
@JoinColumn()
|
||||
information: PostInformation;
|
||||
|
||||
// post has relation with details. not cascades here. means cannot be persisted, updated or removed
|
||||
@OneToOne(type => PostAuthor, author => author.post)
|
||||
@JoinColumn()
|
||||
author: PostAuthor;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity("PostAuthor")
|
||||
export class PostAuthor {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.author)
|
||||
post: Post;
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
|
||||
|
||||
@Entity("PostCategory")
|
||||
export class PostCategory {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity("PostDetails")
|
||||
export class PostDetails {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
authorName: string;
|
||||
|
||||
@Column()
|
||||
comment: string;
|
||||
|
||||
@Column()
|
||||
metadata: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.details, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
post: Post;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity("PostImage")
|
||||
export class PostImage {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
url: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.image)
|
||||
post: Post;
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity("PostInformation")
|
||||
export class PostInformation {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
text: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.information, {
|
||||
cascadeUpdate: true,
|
||||
})
|
||||
post: Post;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import {PrimaryGeneratedColumn, Column, Entity, OneToOne,JoinColumn} from "typeorm";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity("PostMetadata")
|
||||
export class PostMetadata {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
description: string;
|
||||
|
||||
@OneToOne(type => Post, post => post.metadata)
|
||||
post: Post;
|
||||
|
||||
}
|
@ -80,7 +80,7 @@ describe("integration tests", async function () {
|
||||
let entftj = new EntityFileToJson();
|
||||
let jsonEntityOrg= entftj.convert(fs.readFileSync(path.resolve(filesOrgPath, file)))
|
||||
let jsonEntityGen= entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
|
||||
expect(jsonEntityGen).to.containSubset(jsonEntityOrg)
|
||||
expect(jsonEntityGen,`Error in file ${file}`).to.containSubset(jsonEntityOrg)
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4,7 +4,12 @@ export class EntityFileToJson {
|
||||
|
||||
if (decoratorParameters.length > 0) {
|
||||
if (decoratorParameters.search(',') > 0) {
|
||||
col.columnType = decoratorParameters.substring(0, decoratorParameters.indexOf(',')).trim()
|
||||
col.columnTypes = decoratorParameters.substring(0, decoratorParameters.indexOf(',')).trim().split('|').map(function (x) {
|
||||
if (!x.endsWith('[]')) {
|
||||
x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes
|
||||
}
|
||||
return x;
|
||||
});
|
||||
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
|
||||
if (badJSON.lastIndexOf(',') == badJSON.length - 3) {
|
||||
badJSON = badJSON.slice(0, badJSON.length - 3) + badJSON[badJSON.length - 2] + badJSON[badJSON.length - 1]
|
||||
@ -12,7 +17,12 @@ export class EntityFileToJson {
|
||||
col.columnOptions = JSON.parse(badJSON.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
|
||||
} else {
|
||||
if (decoratorParameters[0] == '"' && decoratorParameters.endsWith('"')) {
|
||||
col.columnType = decoratorParameters
|
||||
col.columnTypes = decoratorParameters.split('|').map(function (x) {
|
||||
if (!x.endsWith('[]')) {
|
||||
x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes
|
||||
}
|
||||
return x;
|
||||
});
|
||||
} else {
|
||||
let badJSON = decoratorParameters.substring(decoratorParameters.indexOf(',') + 1).trim()
|
||||
if (badJSON.lastIndexOf(',') == badJSON.length - 3) {
|
||||
@ -34,6 +44,9 @@ export class EntityFileToJson {
|
||||
let lines = entityFile.toString().replace('\r', '').split('\n');
|
||||
for (let line of lines) {
|
||||
let trimmedLine = line.trim();
|
||||
if (trimmedLine.startsWith('//')) {
|
||||
continue; //commented line
|
||||
}
|
||||
if (isMultilineStatement)
|
||||
trimmedLine = priorPartOfMultilineStatement + ' ' + trimmedLine
|
||||
if (trimmedLine.length == 0)
|
||||
@ -97,8 +110,9 @@ export class EntityFileToJson {
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
retVal.columns.push(new EntityColumn())
|
||||
//TODO:Options,relation options if declared
|
||||
let column = new EntityColumn()
|
||||
retVal.columns.push(column)
|
||||
column.relationType = "OneToMany"//"ManyToOne" - can't distinguish OneTwoMany from OneToOne without indexes
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.startsWith('@OneToMany')) {
|
||||
@ -108,13 +122,47 @@ export class EntityFileToJson {
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
retVal.columns.push(new EntityColumn())
|
||||
//TODO:Options, relation options if declared
|
||||
let column = new EntityColumn()
|
||||
retVal.columns.push(column)
|
||||
column.relationType = "OneToMany"
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.startsWith('@OneToOne')) {
|
||||
if (this.isPartOfMultilineStatement(trimmedLine)) {
|
||||
isMultilineStatement = true;
|
||||
priorPartOfMultilineStatement = trimmedLine;
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
let column = new EntityColumn()
|
||||
retVal.columns.push(column)
|
||||
column.relationType = "OneToMany"//"OneToOne" - can't distinguish OneTwoMany from OneToOne without indexes
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.startsWith('@JoinColumn')) {
|
||||
if (this.isPartOfMultilineStatement(trimmedLine)) {
|
||||
isMultilineStatement = true;
|
||||
priorPartOfMultilineStatement = trimmedLine;
|
||||
continue;
|
||||
} else {
|
||||
isMultilineStatement = false;
|
||||
retVal.columns[retVal.columns.length - 1].isOwnerOfRelation = true;
|
||||
continue;
|
||||
}
|
||||
} else if (trimmedLine.split(':').length - 1 > 0) {
|
||||
retVal.columns[retVal.columns.length - 1].columnName = trimmedLine.split(':')[0].trim();
|
||||
retVal.columns[retVal.columns.length - 1].columnType = trimmedLine.split(':')[1].split(';')[0].trim();
|
||||
//TODO:Should check if null only column is nullable?
|
||||
retVal.columns[retVal.columns.length - 1].columnTypes = trimmedLine.split(':')[1].split(';')[0].trim().split('|').map(function (x) {
|
||||
if (!x.endsWith('[]')) {
|
||||
x = x + '[]'// can't distinguish OneTwoMany from OneToOne without indexes
|
||||
}
|
||||
return x;
|
||||
});
|
||||
|
||||
if (!retVal.columns[retVal.columns.length - 1].columnTypes.some(function (this, val, ind, arr) {
|
||||
return val == "null" ? true : false;
|
||||
})) retVal.columns[retVal.columns.length - 1].columnTypes.push('null[]')
|
||||
|
||||
continue
|
||||
} else if (trimmedLine = '}') {
|
||||
isInClassBody = false;
|
||||
@ -122,7 +170,8 @@ export class EntityFileToJson {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[EntityFileToJson:convert] Line not recognized: ${trimmedLine}`)
|
||||
console.log(`[EntityFileToJson:convert] Line not recognized in entity ${retVal.entityName}:`)
|
||||
console.log(`${trimmedLine}`)
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
@ -141,6 +190,8 @@ class EntityJson {
|
||||
}
|
||||
class EntityColumn {
|
||||
columnName: string
|
||||
columnType: string
|
||||
columnTypes: string[]
|
||||
columnOptions: any = {}
|
||||
relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "None" = "None"
|
||||
isOwnerOfRelation: boolean = false;
|
||||
}
|
Loading…
Reference in New Issue
Block a user