mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
first interation of refactoring of metadata, metadata storage and builder
This commit is contained in:
parent
30775c3820
commit
c43c2faa43
@ -793,6 +793,7 @@ Feel free to contribute ;)
|
||||
* fixtures and migrations
|
||||
* lazy loading of properties throw promises? Property can have a Promise\<Entity\> type.
|
||||
* cover everything with tests
|
||||
* logging
|
||||
|
||||
|
||||
[1]: https://en.wikipedia.org/wiki/Object-relational_mapping
|
||||
|
||||
83
sample/sample13-everywhere-abstraction/app.ts
Normal file
83
sample/sample13-everywhere-abstraction/app.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/typeorm";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostCategory} from "./entity/PostCategory";
|
||||
import {PostAuthor} from "./entity/PostAuthor";
|
||||
import {Blog} from "./entity/Blog";
|
||||
|
||||
const options: CreateConnectionOptions = {
|
||||
driver: "mysql",
|
||||
connection: {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true,
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
}
|
||||
},
|
||||
entityDirectories: [__dirname + "/entity"]
|
||||
};
|
||||
|
||||
createConnection(options).then(connection => {
|
||||
|
||||
let category1 = new PostCategory();
|
||||
category1.name = "post category #1";
|
||||
|
||||
let category2 = new PostCategory();
|
||||
category2.name = "post category #2";
|
||||
|
||||
let author = new PostAuthor();
|
||||
author.name = "Umed";
|
||||
author.firstName = "Uma";
|
||||
author.secondName = "Edi";
|
||||
|
||||
let post = new Post();
|
||||
post.text = "Hello how are you?";
|
||||
post.title = "hello";
|
||||
post.author = author;
|
||||
post.title2312312 = "awesome title!";
|
||||
post.categories.push(category1, category2);
|
||||
|
||||
/*category1 = new PostCategory();
|
||||
category1.name = "post category #1";
|
||||
|
||||
category2 = new PostCategory();
|
||||
category2.name = "post category #2";
|
||||
|
||||
author = new PostAuthor();
|
||||
author.name = "Umed";*/
|
||||
|
||||
let blog = new Blog();
|
||||
blog.text = "Hello how are you?";
|
||||
blog.title = "hello";
|
||||
blog.author = author;
|
||||
blog.title2312312 = "awesome title!";
|
||||
blog.categories.push(category1, category2);
|
||||
|
||||
let postRepository = connection.getRepository(Post);
|
||||
let blogRepository = connection.getRepository(Blog);
|
||||
|
||||
postRepository
|
||||
.persist(post)
|
||||
.then(post => {
|
||||
console.log("Post has been saved");
|
||||
return postRepository.findById(post.id);
|
||||
})
|
||||
.then(loadedPost => {
|
||||
console.log("post is loaded: ", loadedPost);
|
||||
return blogRepository.persist(blog);
|
||||
})
|
||||
.then(blog => {
|
||||
console.log("Blog has been saved");
|
||||
return blogRepository.findById(blog.id);
|
||||
})
|
||||
.then(loadedBlog => {
|
||||
console.log("blog is loaded: ", loadedBlog);
|
||||
return blogRepository.persist(blog);
|
||||
})
|
||||
.catch(error => console.log("Cannot save. Error: ", error.stack ? error.stack : error));
|
||||
|
||||
}, error => console.log("Cannot connect: ", error.stack ? error.stack : error));
|
||||
14
sample/sample13-everywhere-abstraction/entity/BaseObject.ts
Normal file
14
sample/sample13-everywhere-abstraction/entity/BaseObject.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/columns";
|
||||
import {AbstractTable} from "../../../src/decorator/tables/AbstractTable";
|
||||
import {BasePost} from "./BasePost";
|
||||
|
||||
@AbstractTable()
|
||||
export class BaseObject extends BasePost {
|
||||
|
||||
@PrimaryColumn("double", { generated: true })
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
}
|
||||
16
sample/sample13-everywhere-abstraction/entity/BasePost.ts
Normal file
16
sample/sample13-everywhere-abstraction/entity/BasePost.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/columns";
|
||||
import {AbstractTable} from "../../../src/decorator/tables/AbstractTable";
|
||||
|
||||
@AbstractTable()
|
||||
export class BasePost {
|
||||
|
||||
@PrimaryColumn("int", { generated: true })
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Column()
|
||||
title2312312: string;
|
||||
|
||||
}
|
||||
31
sample/sample13-everywhere-abstraction/entity/Blog.ts
Normal file
31
sample/sample13-everywhere-abstraction/entity/Blog.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import {Column} from "../../../src/columns";
|
||||
import {Table} from "../../../src/tables";
|
||||
import {ManyToOne} from "../../../src/decorator/relations/ManyToOne";
|
||||
import {PostAuthor} from "./PostAuthor";
|
||||
import {ManyToMany} from "../../../src/decorator/relations/ManyToMany";
|
||||
import {PostCategory} from "./PostCategory";
|
||||
import {JoinTable} from "../../../src/decorator/relations/JoinTable";
|
||||
import {BaseObject} from "./BaseObject";
|
||||
|
||||
@Table("sample13_blog")
|
||||
export class Blog extends BaseObject {
|
||||
|
||||
@Column()
|
||||
text: string;
|
||||
|
||||
@ManyToOne(type => PostAuthor, post => post.posts, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
author: PostAuthor;
|
||||
|
||||
@ManyToMany(type => PostCategory, category => category.posts, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
@JoinTable()
|
||||
categories: PostCategory[] = [];
|
||||
|
||||
}
|
||||
31
sample/sample13-everywhere-abstraction/entity/Post.ts
Normal file
31
sample/sample13-everywhere-abstraction/entity/Post.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import {Column} from "../../../src/columns";
|
||||
import {Table} from "../../../src/tables";
|
||||
import {PostCategory} from "./PostCategory";
|
||||
import {ManyToMany} from "../../../src/decorator/relations/ManyToMany";
|
||||
import {PostAuthor} from "./PostAuthor";
|
||||
import {ManyToOne} from "../../../src/decorator/relations/ManyToOne";
|
||||
import {JoinTable} from "../../../src/decorator/relations/JoinTable";
|
||||
import {BaseObject} from "./BaseObject";
|
||||
|
||||
@Table("sample13_post")
|
||||
export class Post extends BaseObject {
|
||||
|
||||
@Column()
|
||||
text: string;
|
||||
|
||||
@ManyToOne(type => PostAuthor, post => post.posts, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
author: PostAuthor;
|
||||
|
||||
@ManyToMany(type => PostCategory, category => category.posts, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
@JoinTable()
|
||||
categories: PostCategory[] = [];
|
||||
|
||||
}
|
||||
19
sample/sample13-everywhere-abstraction/entity/PostAuthor.ts
Normal file
19
sample/sample13-everywhere-abstraction/entity/PostAuthor.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/columns";
|
||||
import {Table} from "../../../src/tables";
|
||||
import {Post} from "./Post";
|
||||
import {OneToMany} from "../../../src/decorator/relations/OneToMany";
|
||||
import {PostUser} from "./PostUser";
|
||||
|
||||
@Table("sample13_post_author")
|
||||
export class PostAuthor extends PostUser {
|
||||
|
||||
@PrimaryColumn("int", { generated: true })
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToMany(type => Post, post => post.author)
|
||||
posts: Post[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/columns";
|
||||
import {Table} from "../../../src/tables";
|
||||
import {Post} from "./Post";
|
||||
import {ManyToMany} from "../../../src/decorator/relations/ManyToMany";
|
||||
|
||||
@Table("sample13_post_category")
|
||||
export class PostCategory {
|
||||
|
||||
@PrimaryColumn("int", { generated: true })
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Post, post => post.categories, {
|
||||
cascadeInsert: true,
|
||||
cascadeUpdate: true,
|
||||
cascadeRemove: true
|
||||
})
|
||||
posts: Post[] = [];
|
||||
|
||||
}
|
||||
19
sample/sample13-everywhere-abstraction/entity/PostUser.ts
Normal file
19
sample/sample13-everywhere-abstraction/entity/PostUser.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/columns";
|
||||
import {Table} from "../../../src/tables";
|
||||
|
||||
@Table("sample13_post_user")
|
||||
export class PostUser {
|
||||
|
||||
@PrimaryColumn("int", { generated: true })
|
||||
id: number;
|
||||
|
||||
@Column("int")
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
firstName: string;
|
||||
|
||||
@Column()
|
||||
secondName: string;
|
||||
|
||||
}
|
||||
@ -1,9 +1,4 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/columns";
|
||||
import {Table} from "../../../src/tables";
|
||||
import {ManyToMany} from "../../../src/relations";
|
||||
import {PostCategory} from "./PostCategory";
|
||||
import {PostAuthor} from "./PostAuthor";
|
||||
import {ManyToOne} from "../../../src/decorator/relations/ManyToOne";
|
||||
import {AbstractTable} from "../../../src/decorator/tables/AbstractTable";
|
||||
|
||||
@AbstractTable()
|
||||
|
||||
@ -12,7 +12,7 @@ import {importClassesFromDirectories} from "../util/DirectoryExportedClassesLoad
|
||||
import {defaultMetadataStorage, getContainer} from "../typeorm";
|
||||
import {EntityMetadataBuilder} from "../metadata-storage/EntityMetadataBuilder";
|
||||
import {DefaultNamingStrategy} from "../naming-strategy/DefaultNamingStrategy";
|
||||
import {EntityMetadataArray} from "../metadata/EntityMetadataArray";
|
||||
import {EntityMetadataCollection} from "../metadata/collection/EntityMetadataCollection";
|
||||
import {NamingStrategyMetadata} from "../metadata/NamingStrategyMetadata";
|
||||
import {NoConnectionForRepositoryError} from "./error/NoConnectionForRepositoryError";
|
||||
import {CannotImportAlreadyConnectedError} from "./error/CannotImportAlreadyConnectedError";
|
||||
@ -76,7 +76,7 @@ export class Connection {
|
||||
/**
|
||||
* All entity metadatas that are registered for this connection.
|
||||
*/
|
||||
private readonly entityMetadatas = new EntityMetadataArray();
|
||||
private readonly entityMetadatas = new EntityMetadataCollection();
|
||||
|
||||
/**
|
||||
* All naming strategy metadatas that are registered for this connection.
|
||||
@ -255,19 +255,20 @@ export class Connection {
|
||||
private buildMetadatas() {
|
||||
|
||||
// first register naming strategies
|
||||
const metadatas = defaultMetadataStorage().findNamingStrategiesForClasses(this.namingStrategyClasses);
|
||||
const metadatas = defaultMetadataStorage().namingStrategyMetadatas.filterByClasses(this.namingStrategyClasses);
|
||||
this.namingStrategyMetadatas.push(...metadatas);
|
||||
|
||||
// second register subscriber metadatas
|
||||
const subscribers = defaultMetadataStorage()
|
||||
.findEventSubscribersForClasses(this.subscriberClasses)
|
||||
.eventSubscriberMetadatas
|
||||
.filterByClasses(this.subscriberClasses)
|
||||
.map(metadata => this.createContainerInstance(metadata.target));
|
||||
this.subscriberMetadatas.push(...subscribers);
|
||||
|
||||
// third register entity and entity listener metadatas
|
||||
const entityMetadataBuilder = new EntityMetadataBuilder(this.createNamingStrategy());
|
||||
const entityMetadatas = entityMetadataBuilder.build(this.entityClasses);
|
||||
const entityListenerMetadatas = defaultMetadataStorage().findEntityListenersForClasses(this.entityClasses);
|
||||
const entityListenerMetadatas = defaultMetadataStorage().entityListenerMetadatas.filterByClasses(this.entityClasses);
|
||||
|
||||
this.entityMetadatas.push(...entityMetadatas);
|
||||
this.entityListeners.push(...entityListenerMetadatas);
|
||||
|
||||
@ -8,6 +8,6 @@ import {defaultMetadataStorage} from "../typeorm";
|
||||
export function NamingStrategy(name?: string): Function {
|
||||
return function (target: Function) {
|
||||
const strategyName = name ? name : (<any> target).name;
|
||||
defaultMetadataStorage().addNamingStrategyMetadata(new NamingStrategyMetadata(target, strategyName));
|
||||
defaultMetadataStorage().namingStrategyMetadatas.add(new NamingStrategyMetadata(target, strategyName));
|
||||
};
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ export function Column(typeOrOptions?: ColumnType|ColumnOptions, options?: Colum
|
||||
throw new AutoIncrementOnlyForPrimaryError(object, propertyName);
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage().addColumnMetadata(new ColumnMetadata({
|
||||
defaultMetadataStorage().columnMetadatas.add(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
|
||||
@ -20,7 +20,7 @@ export function CreateDateColumn(options?: ColumnOptions): Function {
|
||||
options.type = ColumnTypes.DATETIME;
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage().addColumnMetadata(new ColumnMetadata({
|
||||
defaultMetadataStorage().columnMetadatas.add(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
|
||||
@ -56,7 +56,7 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
|
||||
throw new PrimaryColumnCannotBeNullableError(object, propertyName);
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage().addColumnMetadata(new ColumnMetadata({
|
||||
defaultMetadataStorage().columnMetadatas.add(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
|
||||
@ -20,7 +20,7 @@ export function UpdateDateColumn(options?: ColumnOptions): Function {
|
||||
options.type = ColumnTypes.DATETIME;
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage().addColumnMetadata(new ColumnMetadata({
|
||||
defaultMetadataStorage().columnMetadatas.add(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
|
||||
@ -6,6 +6,6 @@ import {defaultMetadataStorage} from "../../typeorm";
|
||||
*/
|
||||
export function CompoundIndex(fields: string[]) {
|
||||
return function (cls: Function) {
|
||||
defaultMetadataStorage().addCompoundIndexMetadata(new CompoundIndexMetadata(cls, fields));
|
||||
defaultMetadataStorage().compoundIndexMetadatas.add(new CompoundIndexMetadata(cls, fields));
|
||||
};
|
||||
}
|
||||
@ -6,6 +6,6 @@ import {IndexMetadata} from "../../metadata/IndexMetadata";
|
||||
*/
|
||||
export function Index(name?: string) {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addIndexMetadata(new IndexMetadata(object.constructor, propertyName, name));
|
||||
defaultMetadataStorage().indexMetadatas.add(new IndexMetadata(object.constructor, propertyName, name));
|
||||
};
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function AfterInsert() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.AFTER_INSERT
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function AfterLoad() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.AFTER_LOAD
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function AfterRemove() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.AFTER_REMOVE
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function AfterUpdate() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.AFTER_UPDATE
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function BeforeInsert() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.BEFORE_INSERT
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function BeforeRemove() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.BEFORE_REMOVE
|
||||
|
||||
@ -7,7 +7,7 @@ import {EntityListenerMetadata} from "../../metadata/EntityListenerMetadata";
|
||||
*/
|
||||
export function BeforeUpdate() {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage().addEntityListenerMetadata(new EntityListenerMetadata(
|
||||
defaultMetadataStorage().entityListenerMetadatas.add(new EntityListenerMetadata(
|
||||
object.constructor,
|
||||
propertyName,
|
||||
EventListenerTypes.BEFORE_UPDATE
|
||||
|
||||
@ -7,6 +7,6 @@ import {EventSubscriberMetadata} from "../../metadata/EventSubscriberMetadata";
|
||||
*/
|
||||
export function EventSubscriber() {
|
||||
return function (target: Function) {
|
||||
defaultMetadataStorage().addEventSubscriberMetadata(new EventSubscriberMetadata(target));
|
||||
defaultMetadataStorage().eventSubscriberMetadatas.add(new EventSubscriberMetadata(target));
|
||||
};
|
||||
}
|
||||
@ -1,14 +1,14 @@
|
||||
import {defaultMetadataStorage} from "../../typeorm";
|
||||
import {JoinTableOptions} from "../../metadata/options/JoinTableOptions";
|
||||
import {JoinColumnMetadata} from "../../metadata/JoinColumnMetadata";
|
||||
import {JoinColumnOptions} from "../../metadata/options/JoinColumnOptions";
|
||||
|
||||
/**
|
||||
*/
|
||||
export function JoinColumn(options?: JoinTableOptions): Function {
|
||||
export function JoinColumn(options?: JoinColumnOptions): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
options = options || {} as JoinTableOptions;
|
||||
options = options || {} as JoinColumnOptions;
|
||||
const metadata = new JoinColumnMetadata(object.constructor, propertyName, options);
|
||||
defaultMetadataStorage().addJoinColumnMetadata(metadata);
|
||||
defaultMetadataStorage().joinColumnMetadatas.add(metadata);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ export function JoinTable(options?: JoinTableOptions): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
options = options || {} as JoinTableOptions;
|
||||
const metadata = new JoinTableMetadata(object.constructor, propertyName, options);
|
||||
defaultMetadataStorage().addJoinTableMetadata(metadata);
|
||||
defaultMetadataStorage().joinTableMetadatas.add(metadata);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ export function ManyToMany<T>(typeFunction: (type?: any) => ConstructorFunction<
|
||||
return function (object: Object, propertyName: string) {
|
||||
if (!options) options = {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage().addRelationMetadata(new RelationMetadata({
|
||||
defaultMetadataStorage().relationMetadatas.add(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
relationType: RelationTypes.MANY_TO_MANY,
|
||||
|
||||
@ -38,7 +38,7 @@ export function ManyToOne<T>(typeFunction: (type?: any) => ConstructorFunction<T
|
||||
return function (object: Object, propertyName: string) {
|
||||
if (!options) options = {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage().addRelationMetadata(new RelationMetadata({
|
||||
defaultMetadataStorage().relationMetadatas.add(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
relationType: RelationTypes.MANY_TO_ONE,
|
||||
|
||||
@ -35,7 +35,7 @@ export function OneToMany<T>(typeFunction: (type?: any) => ConstructorFunction<T
|
||||
return function (object: Object, propertyName: string) {
|
||||
if (!options) options = {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage().addRelationMetadata(new RelationMetadata({
|
||||
defaultMetadataStorage().relationMetadatas.add(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
relationType: RelationTypes.ONE_TO_MANY,
|
||||
|
||||
@ -35,7 +35,7 @@ export function OneToOne<T>(typeFunction: (type?: any) => ConstructorFunction<T>
|
||||
return function (object: Object, propertyName: string) {
|
||||
if (!options) options = {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage().addRelationMetadata(new RelationMetadata({
|
||||
defaultMetadataStorage().relationMetadatas.add(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
relationType: RelationTypes.ONE_TO_ONE,
|
||||
|
||||
@ -6,6 +6,6 @@ import {defaultMetadataStorage} from "../../typeorm";
|
||||
*/
|
||||
export function AbstractTable() {
|
||||
return function (cls: Function) {
|
||||
defaultMetadataStorage().addTableMetadata(new TableMetadata(cls, true));
|
||||
defaultMetadataStorage().tableMetadatas.add(new TableMetadata(cls, true));
|
||||
};
|
||||
}
|
||||
@ -7,6 +7,6 @@ import {TableMetadata} from "../../metadata/TableMetadata";
|
||||
*/
|
||||
export function Table(name?: string) {
|
||||
return function (cls: Function) {
|
||||
defaultMetadataStorage().addTableMetadata(new TableMetadata(cls, name));
|
||||
defaultMetadataStorage().tableMetadatas.add(new TableMetadata(cls, name));
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import {MetadataStorage} from "./MetadataStorage";
|
||||
import {PropertyMetadata} from "../metadata/PropertyMetadata";
|
||||
import {TableMetadata} from "../metadata/TableMetadata";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategy";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
@ -8,6 +7,8 @@ import {ColumnOptions} from "../metadata/options/ColumnOptions";
|
||||
import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
|
||||
import {JunctionTableMetadata} from "../metadata/JunctionTableMetadata";
|
||||
import {defaultMetadataStorage} from "../typeorm";
|
||||
import {TableMetadata} from "../metadata/TableMetadata";
|
||||
import {TargetMetadataCollection} from "../metadata/collection/TargetMetadataCollection";
|
||||
|
||||
/**
|
||||
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
|
||||
@ -17,6 +18,9 @@ import {defaultMetadataStorage} from "../typeorm";
|
||||
export class EntityMetadataBuilder {
|
||||
|
||||
// todo: type in function validation, inverse side function validation
|
||||
// todo: check on build for duplicate names, since naming checking was removed from MetadataStorage
|
||||
|
||||
// todo: duplicate name checking for: table, relation, column, index, naming strategy, join tables/columns?
|
||||
|
||||
private metadataStorage: MetadataStorage = defaultMetadataStorage();
|
||||
|
||||
@ -35,70 +39,50 @@ export class EntityMetadataBuilder {
|
||||
* Builds a complete metadata aggregations for the given entity classes.
|
||||
*/
|
||||
build(entityClasses: Function[]): EntityMetadata[] {
|
||||
|
||||
const allMetadataStorage = defaultMetadataStorage();
|
||||
|
||||
// filter the metadata only we need - those which are bind to the given table classes
|
||||
const tableMetadatas = this.metadataStorage.findTableMetadatasForClasses(entityClasses);
|
||||
const abstractTableMetadatas = this.metadataStorage.findAbstractTableMetadatasForClasses(entityClasses);
|
||||
const columnMetadatas = this.metadataStorage.findFieldMetadatasForClasses(entityClasses);
|
||||
const relationMetadatas = this.metadataStorage.findRelationMetadatasForClasses(entityClasses);
|
||||
const joinTableMetadatas = this.metadataStorage.findJoinTableMetadatasForClasses(entityClasses);
|
||||
const joinColumnMetadatas = this.metadataStorage.findJoinColumnMetadatasForClasses(entityClasses);
|
||||
const indexMetadatas = this.metadataStorage.findIndexMetadatasForClasses(entityClasses);
|
||||
const compoundIndexMetadatas = this.metadataStorage.findCompoundIndexMetadatasForClasses(entityClasses);
|
||||
const allTableMetadatas = allMetadataStorage.tableMetadatas.filterByClasses(entityClasses);
|
||||
const tableMetadatas = allTableMetadatas.filterByClasses(entityClasses).filter(table => !table.isAbstract);
|
||||
|
||||
// const abstractTableMetadatas = allTableMetadatas.filterByClasses(entityClasses).filter(table => table.isAbstract);
|
||||
|
||||
const entityMetadatas = tableMetadatas.map(tableMetadata => {
|
||||
const mergedMetadata = allMetadataStorage.mergeWithAbstract(allTableMetadatas, tableMetadata);
|
||||
|
||||
const constructorChecker = (opm: PropertyMetadata) => opm.target === tableMetadata.target;
|
||||
const constructorChecker2 = (opm: { target: Function }) => opm.target === tableMetadata.target;
|
||||
|
||||
let entityColumns = columnMetadatas.filter(constructorChecker);
|
||||
let entityRelations = relationMetadatas.filter(constructorChecker);
|
||||
let entityCompoundIndices = compoundIndexMetadatas.filter(constructorChecker2);
|
||||
let entityIndices = indexMetadatas.filter(constructorChecker);
|
||||
let entityJoinTables = joinTableMetadatas.filter(constructorChecker);
|
||||
let entityJoinColumns = joinColumnMetadatas.filter(constructorChecker);
|
||||
|
||||
// merge all columns in the abstract table extendings of this table
|
||||
abstractTableMetadatas.forEach(abstractMetadata => {
|
||||
if (!this.isTableMetadataExtendsAbstractMetadata(tableMetadata, abstractMetadata)) return;
|
||||
const constructorChecker = (opm: PropertyMetadata) => opm.target === abstractMetadata.target;
|
||||
const constructorChecker2 = (opm: { target: Function }) => opm.target === abstractMetadata.target;
|
||||
|
||||
const abstractColumns = columnMetadatas.filter(constructorChecker);
|
||||
const abstractRelations = entityRelations.filter(constructorChecker);
|
||||
const abstractCompoundIndices = entityCompoundIndices.filter(constructorChecker2);
|
||||
const abstractIndices = indexMetadatas.filter(constructorChecker);
|
||||
|
||||
const inheritedFields = this.filterObjectPropertyMetadatasIfNotExist(abstractColumns, entityColumns);
|
||||
const inheritedRelations = this.filterObjectPropertyMetadatasIfNotExist(abstractRelations, entityRelations);
|
||||
const inheritedIndices = this.filterObjectPropertyMetadatasIfNotExist(abstractIndices, entityIndices);
|
||||
|
||||
entityCompoundIndices = entityCompoundIndices.concat(abstractCompoundIndices);
|
||||
entityColumns = entityColumns.concat(inheritedFields);
|
||||
entityRelations = entityRelations.concat(inheritedRelations);
|
||||
entityIndices = entityIndices.concat(inheritedIndices);
|
||||
});
|
||||
|
||||
const entityMetadata = new EntityMetadata(tableMetadata, entityColumns, entityRelations, entityIndices, entityCompoundIndices, []);
|
||||
const entityMetadata = new EntityMetadata(
|
||||
tableMetadata,
|
||||
mergedMetadata.columnMetadatas,
|
||||
mergedMetadata.relationMetadatas,
|
||||
mergedMetadata.indexMetadatas,
|
||||
mergedMetadata.compoundIndexMetadatas,
|
||||
[]
|
||||
);
|
||||
|
||||
// find entity's relations join tables
|
||||
entityRelations.forEach(relation => {
|
||||
const relationJoinTable = entityJoinTables.find(joinTable => joinTable.propertyName === relation.propertyName);
|
||||
entityMetadata.relations.forEach(relation => {
|
||||
const relationJoinTable = mergedMetadata.joinTableMetadatas.find(joinTable => joinTable.propertyName === relation.propertyName);
|
||||
if (relationJoinTable)
|
||||
relation.joinTable = relationJoinTable;
|
||||
});
|
||||
|
||||
// find entity's relations join columns
|
||||
entityRelations.forEach(relation => {
|
||||
const relationJoinColumn = entityJoinColumns.find(joinColumn => joinColumn.propertyName === relation.propertyName);
|
||||
entityMetadata.relations.forEach(relation => {
|
||||
const relationJoinColumn = mergedMetadata.joinColumnMetadatas.find(joinColumn => joinColumn.propertyName === relation.propertyName);
|
||||
if (relationJoinColumn)
|
||||
relation.joinColumn = relationJoinColumn;
|
||||
});
|
||||
|
||||
// set naming strategies
|
||||
tableMetadata.namingStrategy = this.namingStrategy;
|
||||
entityColumns.forEach(column => column.namingStrategy = this.namingStrategy);
|
||||
entityRelations.forEach(relation => relation.namingStrategy = this.namingStrategy);
|
||||
entityMetadata.columns.forEach(column => column.namingStrategy = this.namingStrategy);
|
||||
entityMetadata.relations.forEach(relation => relation.namingStrategy = this.namingStrategy);
|
||||
|
||||
|
||||
// check if table metadata has an id
|
||||
if (!entityMetadata.primaryColumn)
|
||||
throw new Error(`Entity "${entityMetadata.name}" (table "${tableMetadata.name}") does not have a primary column. Primary column is required to have in all your entities. Use @PrimaryColumn decorator to add a primary column to your entity.`);
|
||||
|
||||
return entityMetadata;
|
||||
});
|
||||
@ -128,9 +112,9 @@ export class EntityMetadataBuilder {
|
||||
}
|
||||
|
||||
// create and add foreign key
|
||||
const foreignKey = new ForeignKeyMetadata(metadata.table,
|
||||
[relationalColumn],
|
||||
inverseSideMetadata.table,
|
||||
const foreignKey = new ForeignKeyMetadata(metadata.table,
|
||||
[relationalColumn],
|
||||
inverseSideMetadata.table,
|
||||
[inverseSideMetadata.primaryColumn],
|
||||
relation.onDelete
|
||||
);
|
||||
@ -153,6 +137,7 @@ export class EntityMetadataBuilder {
|
||||
const tableName = metadata.table.name + "_" + relation.name + "_" +
|
||||
inverseSideMetadata.table.name + "_" + inverseSideMetadata.primaryColumn.name;
|
||||
|
||||
|
||||
const tableMetadata = new JunctionTableMetadata(tableName);
|
||||
const column1options: ColumnOptions = {
|
||||
length: metadata.primaryColumn.length,
|
||||
@ -193,14 +178,9 @@ export class EntityMetadataBuilder {
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private isTableMetadataExtendsAbstractMetadata(tableMetadata: TableMetadata, abstractMetadata: TableMetadata): boolean {
|
||||
return tableMetadata.target.prototype instanceof abstractMetadata.target;
|
||||
}
|
||||
|
||||
private filterObjectPropertyMetadatasIfNotExist<T extends PropertyMetadata>(newMetadatas: T[], existsMetadatas: T[]): T[] {
|
||||
private filterRepeatedMetadatas<T extends PropertyMetadata>(newMetadatas: T[], existsMetadatas: T[]): T[] {
|
||||
return newMetadatas.filter(fieldFromMapped => {
|
||||
return !!existsMetadatas.find(fieldFromDocument => fieldFromDocument.propertyName === fieldFromMapped.propertyName);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,4 @@
|
||||
import {TableMetadata} from "../metadata/TableMetadata";
|
||||
import {MetadataAlreadyExistsError} from "./error/MetadataAlreadyExistsError";
|
||||
import {MetadataWithSuchNameAlreadyExistsError} from "./error/MetadataWithSuchNameAlreadyExistsError";
|
||||
import {RelationMetadata} from "../metadata/RelationMetadata";
|
||||
import {IndexMetadata} from "../metadata/IndexMetadata";
|
||||
import {CompoundIndexMetadata} from "../metadata/CompoundIndexMetadata";
|
||||
@ -10,6 +8,8 @@ import {EntityListenerMetadata} from "../metadata/EntityListenerMetadata";
|
||||
import {NamingStrategyMetadata} from "../metadata/NamingStrategyMetadata";
|
||||
import {JoinColumnMetadata} from "../metadata/JoinColumnMetadata";
|
||||
import {JoinTableMetadata} from "../metadata/JoinTableMetadata";
|
||||
import {TargetMetadataCollection} from "../metadata/collection/TargetMetadataCollection";
|
||||
import {PropertyMetadataCollection} from "../metadata/collection/PropertyMetadataCollection";
|
||||
|
||||
/**
|
||||
* Storage all metadatas of all available types: tables, fields, subscribers, relations, etc.
|
||||
@ -17,191 +17,103 @@ import {JoinTableMetadata} from "../metadata/JoinTableMetadata";
|
||||
*/
|
||||
export class MetadataStorage {
|
||||
|
||||
// todo: type in function validation, inverse side function validation
|
||||
// todo: check on build for duplicate names, since naming checking was removed from MetadataStorage
|
||||
// todo: duplicate name checking for: table, relation, column, index, naming strategy, join tables/columns?
|
||||
// todo: check for duplicate targets too since this check has been removed too
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private tableMetadatas: TableMetadata[] = [];
|
||||
private eventSubscriberMetadatas: EventSubscriberMetadata[] = [];
|
||||
private columnMetadatas: ColumnMetadata[] = [];
|
||||
private indexMetadatas: IndexMetadata[] = [];
|
||||
private entityListenerMetadatas: EntityListenerMetadata[] = [];
|
||||
private compoundIndexMetadatas: CompoundIndexMetadata[] = [];
|
||||
private namingStrategyMetadatas: NamingStrategyMetadata[] = [];
|
||||
private relationMetadatas: RelationMetadata[] = [];
|
||||
private joinColumnMetadatas: JoinColumnMetadata[] = [];
|
||||
private joinTableMetadatas: JoinTableMetadata[] = [];
|
||||
readonly tableMetadatas = new TargetMetadataCollection<TableMetadata>();
|
||||
readonly namingStrategyMetadatas = new TargetMetadataCollection<NamingStrategyMetadata>();
|
||||
readonly eventSubscriberMetadatas = new TargetMetadataCollection<EventSubscriberMetadata>();
|
||||
readonly compoundIndexMetadatas = new TargetMetadataCollection<CompoundIndexMetadata>();
|
||||
readonly columnMetadatas = new PropertyMetadataCollection<ColumnMetadata>();
|
||||
readonly relationMetadatas = new PropertyMetadataCollection<RelationMetadata>();
|
||||
readonly joinColumnMetadatas = new PropertyMetadataCollection<JoinColumnMetadata>();
|
||||
readonly joinTableMetadatas = new PropertyMetadataCollection<JoinTableMetadata>();
|
||||
readonly indexMetadatas = new PropertyMetadataCollection<IndexMetadata>();
|
||||
readonly entityListenerMetadatas = new PropertyMetadataCollection<EntityListenerMetadata>();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Adder Methods
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
addTableMetadata(metadata: TableMetadata) {
|
||||
if (this.hasTableMetadataWithObjectConstructor(metadata.target))
|
||||
throw new MetadataAlreadyExistsError("Table", metadata.target);
|
||||
|
||||
if (metadata.name && this.hasTableMetadataWithName(metadata.name))
|
||||
throw new MetadataWithSuchNameAlreadyExistsError("Table", metadata.name);
|
||||
|
||||
this.tableMetadatas.push(metadata);
|
||||
constructor(tableMetadatas?: TargetMetadataCollection<TableMetadata>,
|
||||
namingStrategyMetadatas?: TargetMetadataCollection<NamingStrategyMetadata>,
|
||||
eventSubscriberMetadatas?: TargetMetadataCollection<EventSubscriberMetadata>,
|
||||
compoundIndexMetadatas?: TargetMetadataCollection<CompoundIndexMetadata>,
|
||||
columnMetadatas?: PropertyMetadataCollection<ColumnMetadata>,
|
||||
relationMetadatas?: PropertyMetadataCollection<RelationMetadata>,
|
||||
joinColumnMetadatas?: PropertyMetadataCollection<JoinColumnMetadata>,
|
||||
joinTableMetadatas?: PropertyMetadataCollection<JoinTableMetadata>,
|
||||
indexMetadatas?: PropertyMetadataCollection<IndexMetadata>,
|
||||
entityListenerMetadatas?: PropertyMetadataCollection<EntityListenerMetadata>) {
|
||||
if (tableMetadatas)
|
||||
this.tableMetadatas = tableMetadatas;
|
||||
if (namingStrategyMetadatas)
|
||||
this.namingStrategyMetadatas = namingStrategyMetadatas;
|
||||
if (eventSubscriberMetadatas)
|
||||
this.eventSubscriberMetadatas = eventSubscriberMetadatas;
|
||||
if (compoundIndexMetadatas)
|
||||
this.compoundIndexMetadatas = compoundIndexMetadatas;
|
||||
if (columnMetadatas)
|
||||
this.columnMetadatas = columnMetadatas;
|
||||
if (relationMetadatas)
|
||||
this.relationMetadatas = relationMetadatas;
|
||||
if (joinColumnMetadatas)
|
||||
this.joinColumnMetadatas = joinColumnMetadatas;
|
||||
if (joinTableMetadatas)
|
||||
this.joinTableMetadatas = joinTableMetadatas;
|
||||
if (indexMetadatas)
|
||||
this.indexMetadatas = indexMetadatas;
|
||||
if (entityListenerMetadatas)
|
||||
this.entityListenerMetadatas = entityListenerMetadatas;
|
||||
}
|
||||
|
||||
addRelationMetadata(metadata: RelationMetadata) {
|
||||
if (this.hasRelationWithOneMetadataOnProperty(metadata.target, metadata.propertyName))
|
||||
throw new MetadataAlreadyExistsError("RelationMetadata", metadata.target, metadata.propertyName);
|
||||
|
||||
if (metadata.name && this.hasRelationWithOneMetadataWithName(metadata.target, metadata.name))
|
||||
throw new MetadataWithSuchNameAlreadyExistsError("RelationMetadata", metadata.name);
|
||||
|
||||
this.relationMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addColumnMetadata(metadata: ColumnMetadata) {
|
||||
if (this.hasFieldMetadataOnProperty(metadata.target, metadata.propertyName))
|
||||
throw new MetadataAlreadyExistsError("Column", metadata.target);
|
||||
|
||||
if (metadata.name && this.hasFieldMetadataWithName(metadata.target, metadata.name))
|
||||
throw new MetadataWithSuchNameAlreadyExistsError("Column", metadata.name);
|
||||
|
||||
this.columnMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addEventSubscriberMetadata(metadata: EventSubscriberMetadata) {
|
||||
if (this.hasEventSubscriberWithObjectConstructor(metadata.target))
|
||||
throw new MetadataAlreadyExistsError("EventSubscriber", metadata.target);
|
||||
|
||||
this.eventSubscriberMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addIndexMetadata(metadata: IndexMetadata) {
|
||||
if (this.hasFieldMetadataOnProperty(metadata.target, metadata.propertyName))
|
||||
throw new MetadataAlreadyExistsError("Index", metadata.target);
|
||||
|
||||
if (metadata.name && this.hasFieldMetadataWithName(metadata.target, metadata.name))
|
||||
throw new MetadataWithSuchNameAlreadyExistsError("Index", metadata.name);
|
||||
|
||||
this.indexMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addCompoundIndexMetadata(metadata: CompoundIndexMetadata) {
|
||||
if (this.hasCompoundIndexMetadataWithObjectConstructor(metadata.target))
|
||||
throw new MetadataAlreadyExistsError("CompoundIndex", metadata.target);
|
||||
|
||||
this.compoundIndexMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addNamingStrategyMetadata(metadata: NamingStrategyMetadata) {
|
||||
if (this.hasNamingStrategyMetadataWithObjectConstructor(metadata.target))
|
||||
throw new MetadataAlreadyExistsError("NamingStrategy", metadata.target);
|
||||
|
||||
this.namingStrategyMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addEntityListenerMetadata(metadata: EntityListenerMetadata) {
|
||||
if (this.hasFieldMetadataOnProperty(metadata.target, metadata.propertyName))
|
||||
throw new MetadataAlreadyExistsError("EventListener", metadata.target);
|
||||
|
||||
this.entityListenerMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addJoinTableMetadata(metadata: JoinTableMetadata) {
|
||||
// if (this.hasFieldMetadataOnProperty(metadata.target, metadata.propertyName)) // todo later
|
||||
// throw new MetadataAlreadyExistsError("EventListener", metadata.target);
|
||||
this.joinTableMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
addJoinColumnMetadata(metadata: JoinColumnMetadata) {
|
||||
// if (this.hasFieldMetadataOnProperty(metadata.target, metadata.propertyName)) // todo later
|
||||
// throw new MetadataAlreadyExistsError("EventListener", metadata.target);
|
||||
this.joinColumnMetadatas.push(metadata);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
findEventSubscribersForClasses(classes: Function[]): EventSubscriberMetadata[] {
|
||||
return this.eventSubscriberMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
/**
|
||||
* Creates a new copy of the MetadataStorage with same metadatas as in current metadata storage, but filtered
|
||||
* by classes.
|
||||
*/
|
||||
mergeWithAbstract(allTableMetadatas: TargetMetadataCollection<TableMetadata>,
|
||||
tableMetadata: TableMetadata) {
|
||||
|
||||
const compoundIndexMetadatas = this.compoundIndexMetadatas.filterByClass(tableMetadata.target);
|
||||
const columnMetadatas = this.columnMetadatas.filterByClass(tableMetadata.target);
|
||||
const relationMetadatas = this.relationMetadatas.filterByClass(tableMetadata.target);
|
||||
const joinColumnMetadatas = this.joinColumnMetadatas.filterByClass(tableMetadata.target);
|
||||
const joinTableMetadatas = this.joinTableMetadatas.filterByClass(tableMetadata.target);
|
||||
const indexMetadatas = this.indexMetadatas.filterByClass(tableMetadata.target);
|
||||
const entityListenerMetadatas = this.entityListenerMetadatas.filterByClass(tableMetadata.target);
|
||||
|
||||
allTableMetadatas
|
||||
.filter(metadata => tableMetadata.isInherited(metadata))
|
||||
.forEach(parentMetadata => {
|
||||
const metadatasFromAbstract = this.mergeWithAbstract(allTableMetadatas, parentMetadata);
|
||||
|
||||
columnMetadatas.push(...metadatasFromAbstract.columnMetadatas.filterRepeatedMetadatas(columnMetadatas));
|
||||
relationMetadatas.push(...metadatasFromAbstract.relationMetadatas.filterRepeatedMetadatas(relationMetadatas));
|
||||
joinColumnMetadatas.push(...metadatasFromAbstract.joinColumnMetadatas.filterRepeatedMetadatas(joinColumnMetadatas));
|
||||
joinTableMetadatas.push(...metadatasFromAbstract.joinTableMetadatas.filterRepeatedMetadatas(joinTableMetadatas));
|
||||
indexMetadatas.push(...metadatasFromAbstract.indexMetadatas.filterRepeatedMetadatas(indexMetadatas));
|
||||
entityListenerMetadatas.push(...metadatasFromAbstract.entityListenerMetadatas.filterRepeatedMetadatas(entityListenerMetadatas));
|
||||
});
|
||||
|
||||
return {
|
||||
compoundIndexMetadatas: compoundIndexMetadatas,
|
||||
columnMetadatas: columnMetadatas,
|
||||
relationMetadatas: relationMetadatas,
|
||||
joinColumnMetadatas: joinColumnMetadatas,
|
||||
joinTableMetadatas: joinTableMetadatas,
|
||||
indexMetadatas: indexMetadatas,
|
||||
entityListenerMetadatas: entityListenerMetadatas
|
||||
};
|
||||
}
|
||||
|
||||
findEntityListenersForClasses(classes: Function[]): EntityListenerMetadata[] {
|
||||
return this.entityListenerMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findTableMetadatasForClasses(classes: Function[]): TableMetadata[] {
|
||||
return this.tableMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1 && !metadata.isAbstract);
|
||||
}
|
||||
|
||||
findCompoundIndexMetadatasForClasses(classes: Function[]): CompoundIndexMetadata[] {
|
||||
return this.compoundIndexMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findAbstractTableMetadatasForClasses(classes: Function[]): TableMetadata[] {
|
||||
return this.tableMetadatas.filter(metadata => metadata.isAbstract && classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findIndexMetadatasForClasses(classes: Function[]): IndexMetadata[] {
|
||||
return this.indexMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findFieldMetadatasForClasses(classes: Function[]): ColumnMetadata[] {
|
||||
return this.columnMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findRelationMetadatasForClasses(classes: Function[]): RelationMetadata[] {
|
||||
return this.relationMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findJoinTableMetadatasForClasses(classes: Function[]): JoinTableMetadata[] {
|
||||
return this.joinTableMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findJoinColumnMetadatasForClasses(classes: Function[]): JoinColumnMetadata[] {
|
||||
return this.joinColumnMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
findNamingStrategiesForClasses(classes: Function[]): NamingStrategyMetadata[] {
|
||||
return this.namingStrategyMetadatas.filter(metadata => classes.indexOf(metadata.target) !== -1);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private hasTableMetadataWithObjectConstructor(constructor: Function): boolean {
|
||||
return !!this.tableMetadatas.find(metadata => metadata.target === constructor);
|
||||
}
|
||||
|
||||
private hasCompoundIndexMetadataWithObjectConstructor(constructor: Function): boolean {
|
||||
return !!this.compoundIndexMetadatas.find(metadata => metadata.target === constructor);
|
||||
}
|
||||
|
||||
private hasNamingStrategyMetadataWithObjectConstructor(constructor: Function): boolean {
|
||||
return !!this.namingStrategyMetadatas.find(metadata => metadata.target === constructor);
|
||||
}
|
||||
|
||||
private hasEventSubscriberWithObjectConstructor(constructor: Function): boolean {
|
||||
return !!this.eventSubscriberMetadatas.find(metadata => metadata.target === constructor);
|
||||
}
|
||||
|
||||
private hasFieldMetadataOnProperty(constructor: Function, propertyName: string): boolean {
|
||||
return !!this.columnMetadatas.find(metadata => metadata.target === constructor && metadata.propertyName === propertyName);
|
||||
}
|
||||
|
||||
private hasRelationWithOneMetadataOnProperty(constructor: Function, propertyName: string): boolean {
|
||||
return !!this.relationMetadatas.find(metadata => metadata.target === constructor && metadata.propertyName === propertyName);
|
||||
}
|
||||
|
||||
private hasTableMetadataWithName(name: string): boolean {
|
||||
return !!this.tableMetadatas.find(metadata => metadata.name === name);
|
||||
}
|
||||
|
||||
private hasFieldMetadataWithName(constructor: Function, name: string): boolean {
|
||||
return !!this.columnMetadatas.find(metadata => metadata.target === constructor && metadata.name === name);
|
||||
}
|
||||
|
||||
private hasRelationWithOneMetadataWithName(constructor: Function, name: string): boolean {
|
||||
return !!this.relationMetadatas.find(metadata => metadata.target === constructor && metadata.name === name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,53 +1,7 @@
|
||||
import {PropertyMetadata} from "./PropertyMetadata";
|
||||
import {ColumnOptions} from "./options/ColumnOptions";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategy";
|
||||
import {ColumnType} from "./types/ColumnTypes";
|
||||
|
||||
/**
|
||||
* Constructor arguments for ColumnMetadata class.
|
||||
*/
|
||||
export interface ColumnMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
target?: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this column is applied.
|
||||
*/
|
||||
propertyName?: string;
|
||||
|
||||
/**
|
||||
* Class's property type (reflected) to which this column is applied.
|
||||
*/
|
||||
propertyType: string;
|
||||
|
||||
/**
|
||||
* Indicates if this column is primary key or not.
|
||||
*/
|
||||
isPrimaryKey?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is create date column or not.
|
||||
*/
|
||||
isCreateDate?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is update date column or not.
|
||||
*/
|
||||
isUpdateDate?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is virtual or not.
|
||||
*/
|
||||
isVirtual?: boolean;
|
||||
|
||||
/**
|
||||
* Extra column options.
|
||||
*/
|
||||
options: ColumnOptions;
|
||||
}
|
||||
import {ColumnMetadataArgs} from "./args/ColumnMetadataArgs";
|
||||
|
||||
/**
|
||||
* This metadata contains all information about class's column.
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
import {TargetMetadata} from "./TargetMetadata";
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about table's compound index.
|
||||
*/
|
||||
export class CompoundIndexMetadata {
|
||||
export class CompoundIndexMetadata extends TargetMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Readonly Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
readonly target: Function;
|
||||
|
||||
/**
|
||||
* Fields combination to be used as index.
|
||||
*/
|
||||
@ -22,7 +19,7 @@ export class CompoundIndexMetadata {
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function, fields: string[]) {
|
||||
this.target = target;
|
||||
super(target);
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
|
||||
@ -1,23 +1,8 @@
|
||||
import {TargetMetadata} from "./TargetMetadata";
|
||||
|
||||
/**
|
||||
* Contains metadata information about ORM event subscribers.
|
||||
*/
|
||||
export class EventSubscriberMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Readonly Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
readonly target: Function;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function) {
|
||||
this.target = target;
|
||||
}
|
||||
export class EventSubscriberMetadata extends TargetMetadata {
|
||||
|
||||
}
|
||||
@ -12,7 +12,7 @@ export class IndexMetadata extends PropertyMetadata {
|
||||
/**
|
||||
* The name of the index.
|
||||
*/
|
||||
readonly name: string|undefined;
|
||||
readonly name: string;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
@ -20,7 +20,9 @@ export class IndexMetadata extends PropertyMetadata {
|
||||
|
||||
constructor(target: Function, propertyName: string, name?: string) {
|
||||
super(target, propertyName);
|
||||
this.name = name; // todo: if there is no name, then generate it
|
||||
|
||||
if (name)
|
||||
this.name = name; // todo: if there is no name, then generate it (using naming strategy?)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
import {TargetMetadata} from "./TargetMetadata";
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about naming strategy.
|
||||
*/
|
||||
export class NamingStrategyMetadata {
|
||||
export class NamingStrategyMetadata extends TargetMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Readonly Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
readonly target: Function;
|
||||
|
||||
/**
|
||||
* Naming strategy name.
|
||||
*/
|
||||
@ -22,7 +19,7 @@ export class NamingStrategyMetadata {
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function, name: string) {
|
||||
this.target = target;
|
||||
super(target);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
import {TargetMetadata} from "./TargetMetadata";
|
||||
|
||||
/**
|
||||
* This represents metadata of some object's property.
|
||||
*/
|
||||
export abstract class PropertyMetadata {
|
||||
export abstract class PropertyMetadata extends TargetMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Readonly Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
readonly target: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this decorator is applied.
|
||||
*/
|
||||
@ -22,8 +19,7 @@ export abstract class PropertyMetadata {
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target?: Function, propertyName?: string) {
|
||||
if (target)
|
||||
this.target = target;
|
||||
super(target);
|
||||
|
||||
if (propertyName)
|
||||
this.propertyName = propertyName;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import {PropertyMetadata} from "./PropertyMetadata";
|
||||
import {RelationTypes, RelationType} from "./types/RelationTypes";
|
||||
import {RelationOptions} from "./options/RelationOptions";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategy";
|
||||
import {EntityMetadata} from "./EntityMetadata";
|
||||
import {OnDeleteType} from "./ForeignKeyMetadata";
|
||||
import {JoinTableMetadata} from "./JoinTableMetadata";
|
||||
import {JoinColumnMetadata} from "./JoinColumnMetadata";
|
||||
import {RelationMetadataArgs} from "./args/RelationMetadataArgs";
|
||||
|
||||
/**
|
||||
* Function that returns a type of the field. Returned value must be a class used on the relation.
|
||||
@ -17,42 +17,6 @@ export type RelationTypeInFunction = ((type?: any) => Function);
|
||||
*/
|
||||
export type PropertyTypeInFunction<T> = string|((t: T) => string|any);
|
||||
|
||||
/**
|
||||
* Relation metadata constructor arguments.
|
||||
*/
|
||||
export interface RelationMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this relation is applied.
|
||||
*/
|
||||
target: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this relation is applied.
|
||||
*/
|
||||
propertyName: string;
|
||||
|
||||
/**
|
||||
* Type of relation. Can be one of the value of the RelationTypes class.
|
||||
*/
|
||||
relationType: RelationType;
|
||||
|
||||
/**
|
||||
* Type of the relation. This type is in function because of language specifics and problems with recursive
|
||||
* referenced classes.
|
||||
*/
|
||||
type: RelationTypeInFunction;
|
||||
|
||||
/**
|
||||
* Inverse side of the relation.
|
||||
*/
|
||||
inverseSideProperty: PropertyTypeInFunction<any>;
|
||||
|
||||
/**
|
||||
* Additional relation options.
|
||||
*/
|
||||
options: RelationOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about some document's relation.
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategy";
|
||||
import {TargetMetadata} from "./TargetMetadata";
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about specific table.
|
||||
*/
|
||||
export class TableMetadata {
|
||||
export class TableMetadata extends TargetMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Public Properties
|
||||
@ -18,11 +19,6 @@ export class TableMetadata {
|
||||
// Readonly Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
readonly target: Function;
|
||||
|
||||
/**
|
||||
* Indicates if this table is abstract or not. Regular tables can inherit columns from abstract tables.
|
||||
*/
|
||||
@ -44,8 +40,7 @@ export class TableMetadata {
|
||||
constructor(target?: Function, name?: string);
|
||||
constructor(target: Function, isAbstract: boolean);
|
||||
constructor(target: Function, nameOrIsAbstract?: string|boolean, maybeIsAbstract?: boolean) {
|
||||
if (target)
|
||||
this.target = target;
|
||||
super(target);
|
||||
if (typeof nameOrIsAbstract === "string")
|
||||
this._name = nameOrIsAbstract;
|
||||
if (typeof nameOrIsAbstract === "boolean")
|
||||
@ -68,4 +63,14 @@ export class TableMetadata {
|
||||
return this.namingStrategy ? this.namingStrategy.tableName((<any>this.target).name) : (<any>this.target).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this table is inherited from another table.
|
||||
*/
|
||||
isInherited(anotherTable: TableMetadata) {
|
||||
return Object.getPrototypeOf(this.target.prototype).constructor === anotherTable.target;
|
||||
// we cannot use instanceOf in this method, because we need order of inherited tables, to ensure that
|
||||
// properties get inherited in a right order. To achieve it we can only check a first parent of the class
|
||||
// return this.target.prototype instanceof anotherTable.target;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
21
src/metadata/TargetMetadata.ts
Normal file
21
src/metadata/TargetMetadata.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* This represents metadata of some object.
|
||||
*/
|
||||
export abstract class TargetMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Readonly Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
readonly target: Function;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target?: Function) {
|
||||
if (target)
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
}
|
||||
47
src/metadata/args/ColumnMetadataArgs.ts
Normal file
47
src/metadata/args/ColumnMetadataArgs.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {ColumnOptions} from "../options/ColumnOptions";
|
||||
|
||||
/**
|
||||
* Constructor arguments for ColumnMetadata class.
|
||||
*/
|
||||
export interface ColumnMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
target?: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this column is applied.
|
||||
*/
|
||||
propertyName?: string;
|
||||
|
||||
/**
|
||||
* Class's property type (reflected) to which this column is applied.
|
||||
*/
|
||||
propertyType: string;
|
||||
|
||||
/**
|
||||
* Indicates if this column is primary key or not.
|
||||
*/
|
||||
isPrimaryKey?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is create date column or not.
|
||||
*/
|
||||
isCreateDate?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is update date column or not.
|
||||
*/
|
||||
isUpdateDate?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is virtual or not.
|
||||
*/
|
||||
isVirtual?: boolean;
|
||||
|
||||
/**
|
||||
* Extra column options.
|
||||
*/
|
||||
options: ColumnOptions;
|
||||
}
|
||||
41
src/metadata/args/RelationMetadataArgs.ts
Normal file
41
src/metadata/args/RelationMetadataArgs.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import {RelationType} from "../types/RelationTypes";
|
||||
import {RelationOptions} from "../options/RelationOptions";
|
||||
import {PropertyTypeInFunction, RelationTypeInFunction} from "../RelationMetadata";
|
||||
|
||||
/**
|
||||
* Relation metadata constructor arguments.
|
||||
*/
|
||||
export interface RelationMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this relation is applied.
|
||||
*/
|
||||
target: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this relation is applied.
|
||||
*/
|
||||
propertyName: string;
|
||||
|
||||
/**
|
||||
* Type of relation. Can be one of the value of the RelationTypes class.
|
||||
*/
|
||||
relationType: RelationType;
|
||||
|
||||
/**
|
||||
* Type of the relation. This type is in function because of language specifics and problems with recursive
|
||||
* referenced classes.
|
||||
*/
|
||||
type: RelationTypeInFunction;
|
||||
|
||||
/**
|
||||
* Inverse side of the relation.
|
||||
*/
|
||||
inverseSideProperty: PropertyTypeInFunction<any>;
|
||||
|
||||
/**
|
||||
* Additional relation options.
|
||||
*/
|
||||
options: RelationOptions;
|
||||
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
import {EntityMetadata} from "./EntityMetadata";
|
||||
import {EntityMetadataNotFound} from "./error/EntityMetadataNotFound";
|
||||
import {EntityMetadata} from "../EntityMetadata";
|
||||
import {EntityMetadataNotFound} from "../error/EntityMetadataNotFound";
|
||||
|
||||
/**
|
||||
* Array for the entity metadatas.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export class EntityMetadataArray extends Array<EntityMetadata> {
|
||||
export class EntityMetadataCollection extends Array<EntityMetadata> {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
17
src/metadata/collection/PropertyMetadataCollection.ts
Normal file
17
src/metadata/collection/PropertyMetadataCollection.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import {TargetMetadataCollection} from "./TargetMetadataCollection";
|
||||
import {PropertyMetadata} from "../PropertyMetadata";
|
||||
|
||||
export class PropertyMetadataCollection<T extends PropertyMetadata> extends TargetMetadataCollection<T> {
|
||||
|
||||
filterRepeatedMetadatas(existsMetadatas: T[]): this {
|
||||
const collection = new (<any> this.constructor)();
|
||||
this
|
||||
.filter(metadata => {
|
||||
return !existsMetadatas.find(fieldFromDocument => fieldFromDocument.propertyName === metadata.propertyName);
|
||||
})
|
||||
.forEach(metadata => collection.add(metadata));
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
}
|
||||
30
src/metadata/collection/TargetMetadataCollection.ts
Normal file
30
src/metadata/collection/TargetMetadataCollection.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import {TargetMetadata} from "../TargetMetadata";
|
||||
|
||||
export class TargetMetadataCollection<T extends TargetMetadata> extends Array<T> {
|
||||
|
||||
filterByClass(cls: Function): this {
|
||||
return this.filterByClasses([cls]);
|
||||
}
|
||||
|
||||
filterByClasses(classes: Function[]): this {
|
||||
const collection = new (<any> this.constructor)();
|
||||
this.filter(metadata => classes.indexOf(metadata.target) !== -1)
|
||||
.forEach(metadata => collection.add(metadata));
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
add(metadata: T) {
|
||||
// if (this.hasWithClass(metadata.target))
|
||||
// throw new MetadataAlreadyExistsError((<any> metadata.constructor).name, metadata.target);
|
||||
// if (metadata.name && this.hasTableMetadataWithName(metadata.name))
|
||||
// throw new MetadataWithSuchNameAlreadyExistsError("Table", metadata.name);
|
||||
|
||||
this.push(metadata);
|
||||
}
|
||||
|
||||
private hasWithClass(constructor: Function): boolean {
|
||||
return !!this.find(metadata => metadata.target === constructor);
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,7 +3,7 @@ import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {SchemaBuilder} from "../schema-builder/SchemaBuilder";
|
||||
import {EntityMetadataArray} from "../metadata/EntityMetadataArray";
|
||||
import {EntityMetadataCollection} from "../metadata/collection/EntityMetadataCollection";
|
||||
|
||||
/**
|
||||
* Creates indexes based on the given metadata.
|
||||
@ -17,7 +17,7 @@ export class SchemaCreator {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private schemaBuilder: SchemaBuilder,
|
||||
private entityMetadatas: EntityMetadataArray) {
|
||||
private entityMetadatas: EntityMetadataCollection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user