metadata build refactoring

This commit is contained in:
Umed Khudoiberdiev 2016-05-25 19:40:56 +05:00
parent 697178f3b7
commit 9465e2f1fe
20 changed files with 196 additions and 192 deletions

View File

@ -10,7 +10,8 @@ export function JoinColumn(options?: JoinColumnOptions): Function {
const args: JoinColumnMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
options: options
name: options.name,
referencedColumnName: options.referencedColumnName
};
getMetadataArgsStorage().joinColumns.add(args);
};

View File

@ -10,7 +10,9 @@ export function JoinTable(options?: JoinTableOptions): Function {
const args: JoinTableMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
options: options
name: options.name,
joinColumn: options.joinColumn,
inverseJoinColumn: options.inverseJoinColumn
};
getMetadataArgsStorage().joinTables.add(args);
};

View File

@ -12,6 +12,9 @@ import {ColumnTypes} from "../metadata/types/ColumnTypes";
import {getMetadataArgsStorage} from "../index";
import {RelationMetadata} from "../metadata/RelationMetadata";
import {JoinTableMetadata} from "../metadata/JoinTableMetadata";
import {JoinTableMetadataArgs} from "../metadata/args/JoinTableMetadataArgs";
import {PropertyMetadataArgsCollection} from "../metadata/collection/PropertyMetadataArgsCollection";
import {ColumnMetadataArgs} from "../metadata/args/ColumnMetadataArgs";
/**
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
@ -22,8 +25,10 @@ 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?
// todo: check if multiple tree parent metadatas in validator
// todo: tree decorators can be used only on closure table (validation)
// todo: throw error if parent tree metadata was not specified in a closure table
private entityValidator = new EntityMetadataValidator();
@ -34,49 +39,25 @@ export class EntityMetadataBuilder {
/**
* Builds a complete metadata aggregations for the given entity classes.
*/
build(namingStrategy: NamingStrategyInterface,
entityClasses: Function[]): EntityMetadata[] {
build(namingStrategy: NamingStrategyInterface, entityClasses: Function[]): EntityMetadata[] {
const allMetadataArgsStorage = getMetadataArgsStorage();
const entityMetadatas = getMetadataArgsStorage().getMergedTableMetadatas(entityClasses).map(mergedArgs => {
// filter the only metadata we need - those which are bind to the given table classes
const allTableMetadataArgs = allMetadataArgsStorage.tables.filterByClasses(entityClasses);
const tableMetadatas = allTableMetadataArgs
.filterByClasses(entityClasses)
.filter(metadata => metadata.type !== "abstract");
// set naming strategy
// allMetadataStorage.tableMetadatas.forEach(tableMetadata => tableMetadata.namingStrategy = namingStrategy);
// allTableMetadatas.forEach(column => column.namingStrategy = namingStrategy);
// entityMetadata.relations.forEach(relation => relation.namingStrategy = namingStrategy);
const entityMetadatas = tableMetadatas.map(tableMetadata => {
const mergedArgs = allMetadataArgsStorage.mergeWithAbstract(allTableMetadataArgs, tableMetadata);
// create layouts from metadatas
const table = new TableMetadata(tableMetadata);
// create metadatas from args
const table = new TableMetadata(mergedArgs.table);
const columns = mergedArgs.columns.map(args => new ColumnMetadata(args));
const relations = mergedArgs.relations.map(args => new RelationMetadata(args));
const indices = mergedArgs.indices.map(args => new IndexMetadata(args));
// todo no need to set naming strategy everywhere - childs can obtain it from their parents
// tableMetadata.namingStrategy = namingStrategy;
// todo: check if multiple tree parent metadatas in validator
// todo: tree decorators can be used only on closure table (validation)
// todo: throw error if parent tree metadata was not specified in a closure table
// create a new entity metadata
const entityMetadata = new EntityMetadata(
namingStrategy,
table,
columns,
relations,
indices
);
const entityMetadata = new EntityMetadata(namingStrategy, table, columns, relations, indices);
// set entity metadata everywhere its used
table.entityMetadata = entityMetadata;
columns.forEach(column => column.entityMetadata = entityMetadata);
relations.forEach(relation => relation.entityMetadata = entityMetadata);
indices.forEach(index => index.entityMetadata = entityMetadata);
// create entity's relations join tables
entityMetadata.manyToManyRelations.forEach(relation => {
const joinTableMetadata = mergedArgs.joinTables.findByProperty(relation.propertyName);
@ -88,27 +69,27 @@ export class EntityMetadataBuilder {
});
// create entity's relations join columns
entityMetadata.relations.forEach(relation => {
const joinColumnMetadata = mergedArgs.joinColumns.findByProperty(relation.propertyName);
if (joinColumnMetadata) {
const joinColumn = new JoinColumnMetadata(joinColumnMetadata);
relation.joinColumn = joinColumn;
joinColumn.relation = relation;
}
});
entityMetadata.oneToOneRelations
.concat(entityMetadata.manyToOneRelations)
.forEach(relation => {
// since for many-to-one relations having JoinColumn is not required on decorators level, we need to go
// throw all of them which don't have JoinColumn decorators and create it for them
let joinColumnMetadata = mergedArgs.joinColumns.findByProperty(relation.propertyName);
if (!joinColumnMetadata && relation.isManyToOne) {
joinColumnMetadata = {
target: relation.target,
propertyName: relation.propertyName
};
}
if (joinColumnMetadata) {
const joinColumn = new JoinColumnMetadata(joinColumnMetadata);
relation.joinColumn = joinColumn;
joinColumn.relation = relation;
}
});
// since for many-to-one relations having JoinColumn is not required on decorators level, we need to go
// throw all of them which don't have JoinColumn decorators and create it for them
entityMetadata.manyToOneRelations.forEach(relation => {
let joinColumnMetadata = mergedArgs.joinColumns.findByProperty(relation.propertyName);
if (!joinColumnMetadata) {
joinColumnMetadata = { target: relation.target, propertyName: relation.propertyName, options: <JoinColumnOptions> {} };
const joinColumn = new JoinColumnMetadata(joinColumnMetadata);
relation.joinColumn = joinColumn;
joinColumn.relation = relation;
}
});
return entityMetadata;
});
@ -171,45 +152,44 @@ export class EntityMetadataBuilder {
const closureTableName = namingStrategy.closureJunctionTableName(metadata.table.name);
const closureJunctionTableMetadata = new TableMetadata(undefined, closureTableName, "closureJunction");
const column1Args: ColumnMetadataArgs = {
propertyType: metadata.primaryColumn.type,
mode: "virtual",
options: <ColumnOptions> {
length: metadata.primaryColumn.length,
type: metadata.primaryColumn.type,
name: "ancestor"
}
};
const column2Args: ColumnMetadataArgs = {
propertyType: metadata.primaryColumn.type,
mode: "virtual",
options: <ColumnOptions> {
length: metadata.primaryColumn.length,
type: metadata.primaryColumn.type,
name: "descendant"
}
};
const column3Args: ColumnMetadataArgs = {
propertyType: ColumnTypes.INTEGER,
mode: "virtual",
options: {
type: ColumnTypes.INTEGER,
name: "level"
}
};
const columns = [
new ColumnMetadata(metadata, {
target: Function, // todo: temp, fix it later
propertyName: "", // todo: temp, fix it later
propertyType: metadata.primaryColumn.type,
mode: "regular", // or virtual?
options: <ColumnOptions> {
length: metadata.primaryColumn.length,
type: metadata.primaryColumn.type,
name: "ancestor"
}
}),
new ColumnMetadata(metadata, {
target: Function, // todo: temp, fix it later
propertyName: "", // todo: temp, fix it later
propertyType: metadata.primaryColumn.type,
mode: "regular", // or virtual?
options: <ColumnOptions> {
length: metadata.primaryColumn.length,
type: metadata.primaryColumn.type,
name: "descendant"
}
})
new ColumnMetadata(metadata, column1Args),
new ColumnMetadata(metadata, column2Args)
];
if (metadata.hasTreeLevelColumn) {
columns.push(new ColumnMetadata(metadata, {
target: Function, // todo: temp, fix it later
propertyName: "", // todo: temp, fix it later
propertyType: ColumnTypes.INTEGER,
mode: "regular", // or virtual?
options: {
type: ColumnTypes.INTEGER,
name: "level"
}
}));
}
if (metadata.hasTreeLevelColumn)
columns.push(new ColumnMetadata(metadata, column3Args));
const closureJunctionEntityMetadata = new EntityMetadata(namingStrategy, closureJunctionTableMetadata, columns, [], []);
closureJunctionTableMetadata.entityMetadata = closureJunctionEntityMetadata;
closureJunctionEntityMetadata.foreignKeys.push(
new ForeignKeyMetadata(closureJunctionEntityMetadata, closureJunctionTableMetadata, [columns[0]], metadata.table, [metadata.primaryColumn]),
new ForeignKeyMetadata(closureJunctionEntityMetadata, closureJunctionTableMetadata, [columns[1]], metadata.table, [metadata.primaryColumn])
@ -258,6 +238,7 @@ export class EntityMetadataBuilder {
})
];
const junctionEntityMetadata = new EntityMetadata(namingStrategy, tableMetadata, columns, [], []);
tableMetadata.entityMetadata = junctionEntityMetadata;
junctionEntityMetadata.foreignKeys.push(
new ForeignKeyMetadata(junctionEntityMetadata, tableMetadata, [columns[0]], metadata.table, [column1]),
new ForeignKeyMetadata(junctionEntityMetadata, tableMetadata, [columns[1]], relation.inverseEntityMetadata.table, [column2])

View File

@ -1,15 +1,5 @@
import {TableMetadata} from "../metadata/TableMetadata";
import {RelationMetadata} from "../metadata/RelationMetadata";
import {IndexMetadata} from "../metadata/IndexMetadata";
import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {EventSubscriberMetadata} from "../metadata/EventSubscriberMetadata";
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";
import {RelationsCountMetadata} from "../metadata/RelationsCountMetadata";
import {TargetMetadataArgsCollection} from "../metadata/collection/TargetMetadataArgsCollection";
import {PropertyMetadataArgsCollection} from "../metadata/collection/PropertyMetadataArgsCollection";
import {RelationMetadataArgs} from "../metadata/args/RelationMetadataArgs";
import {ColumnMetadataArgs} from "../metadata/args/ColumnMetadataArgs";
import {RelationsCountMetadataArgs} from "../metadata/args/RelationsCountMetadataArgs";
@ -37,27 +27,43 @@ export class MetadataArgsStorage {
// Properties
// -------------------------------------------------------------------------
readonly tables = new TargetMetadataCollection<TableMetadataArgs>();
readonly namingStrategies = new TargetMetadataCollection<NamingStrategyMetadataArgs>();
readonly eventSubscribers = new TargetMetadataCollection<EventSubscriberMetadataArgs>();
readonly indices = new TargetMetadataCollection<IndexMetadataArgs>();
readonly columns = new PropertyMetadataCollection<ColumnMetadataArgs>();
readonly relations = new PropertyMetadataCollection<RelationMetadataArgs>();
readonly joinColumns = new PropertyMetadataCollection<JoinColumnMetadataArgs>();
readonly joinTables = new PropertyMetadataCollection<JoinTableMetadataArgs>();
readonly entityListeners = new PropertyMetadataCollection<EntityListenerMetadataArgs>();
readonly relationCounts = new PropertyMetadataCollection<RelationsCountMetadataArgs>();
readonly tables = new TargetMetadataArgsCollection<TableMetadataArgs>();
readonly namingStrategies = new TargetMetadataArgsCollection<NamingStrategyMetadataArgs>();
readonly eventSubscribers = new TargetMetadataArgsCollection<EventSubscriberMetadataArgs>();
readonly indices = new TargetMetadataArgsCollection<IndexMetadataArgs>();
readonly columns = new PropertyMetadataArgsCollection<ColumnMetadataArgs>();
readonly relations = new PropertyMetadataArgsCollection<RelationMetadataArgs>();
readonly joinColumns = new PropertyMetadataArgsCollection<JoinColumnMetadataArgs>();
readonly joinTables = new PropertyMetadataArgsCollection<JoinTableMetadataArgs>();
readonly entityListeners = new PropertyMetadataArgsCollection<EntityListenerMetadataArgs>();
readonly relationCounts = new PropertyMetadataArgsCollection<RelationsCountMetadataArgs>();
// -------------------------------------------------------------------------
// Public Methods
// -------------------------------------------------------------------------
/**
* Gets merged (with all abstract classes) table metadatas for the given classes.
*/
getMergedTableMetadatas(classes: Function[]) {
const allTableMetadataArgs = this.tables.filterByClasses(classes);
const tableMetadatas = this.tables.filterByClasses(classes).filter(table => table.type !== "abstract");
return tableMetadatas.map(tableMetadata => {
return this.mergeWithAbstract(allTableMetadataArgs, tableMetadata);
});
}
// -------------------------------------------------------------------------
// Private Methods
// -------------------------------------------------------------------------
/**
* Creates a new copy of the MetadataStorage with same metadatas as in current metadata storage, but filtered
* by classes.
*/
mergeWithAbstract(allTableMetadatas: TargetMetadataCollection<TableMetadataArgs>,
tableMetadata: TableMetadataArgs) {
private mergeWithAbstract(allTableMetadatas: TargetMetadataArgsCollection<TableMetadataArgs>,
tableMetadata: TableMetadataArgs) {
const indices = this.indices.filterByClass(tableMetadata.target);
const columns = this.columns.filterByClass(tableMetadata.target);
@ -75,29 +81,30 @@ export class MetadataArgsStorage {
metadatasFromAbstract.columns
.filterRepeatedMetadatas(columns)
.forEach(metadata => columns.push(metadata));
metadatasFromAbstract.relations
.filterRepeatedMetadatas(relations)
.forEach(metadata => relations.push(metadata));
metadatasFromAbstract.joinColumns
.filterRepeatedMetadatas(joinColumns)
.forEach(metadata => joinColumns.push(metadata));
metadatasFromAbstract.joinTables
.filterRepeatedMetadatas(joinTables)
.forEach(metadata => joinTables.push(metadata));
metadatasFromAbstract.entityListeners
.filterRepeatedMetadatas(entityListeners)
.forEach(metadata => entityListeners.push(metadata));
metadatasFromAbstract.relationCounts
.filterRepeatedMetadatas(relationCounts)
.forEach(metadata => relationCounts.push(metadata));
});
return {
table: tableMetadata,
indices: indices,
columns: columns,
relations: relations,
@ -108,10 +115,6 @@ export class MetadataArgsStorage {
};
}
// -------------------------------------------------------------------------
// Private Methods
// -------------------------------------------------------------------------
/**
* Checks if this table is inherited from another table.
*/
@ -119,6 +122,8 @@ export class MetadataArgsStorage {
// 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;
if (!firstTargetMetadata.target)
return false;
return Object.getPrototypeOf(firstTargetMetadata.target.prototype).constructor === secondTargetMetadata.target;
}

View File

@ -11,7 +11,7 @@ export class MissingJoinColumnError extends Error {
super();
if (relation.hasInverseSide) {
this.message = `JoinColumn is missing on both sides of ${entityMetadata.name}#${relation.propertyName} and ` +
`${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} one-to-one relationship. ` +
`${relation.inverseEntityMetadata.name}#${relation.inverseRelation.propertyName} one-to-one relationship. ` +
`You need to put JoinColumn decorator on one of the sides.`;
} else {
this.message = `JoinColumn is missing on ${entityMetadata.name}#${relation.propertyName} one-to-one relationship. ` +

View File

@ -11,11 +11,11 @@ export class MissingJoinTableError extends Error {
super();
if (relation.hasInverseSide) {
this.message = `JoinTable is missing on both sides of ${entityMetadata.name}#${relation.name} and ` +
`${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} many-to-many relationship. ` +
this.message = `JoinTable is missing on both sides of ${entityMetadata.name}#${relation.propertyName} and ` +
`${relation.inverseEntityMetadata.name}#${relation.inverseRelation.propertyName} many-to-many relationship. ` +
`You need to put decorator decorator on one of the sides.`;
} else {
this.message = `JoinTable is missing on ${entityMetadata.name}#${relation.name} many-to-many relationship. ` +
this.message = `JoinTable is missing on ${entityMetadata.name}#${relation.propertyName} many-to-many relationship. ` +
`You need to put JoinTable decorator on it.`;
}
}

View File

@ -9,7 +9,7 @@ export class UsingJoinColumnIsNotAllowedError extends Error {
constructor(entityMetadata: EntityMetadata, relation: RelationMetadata) {
super();
this.message = `Using JoinColumn on ${entityMetadata.name}#${relation.name} is wrong. ` +
this.message = `Using JoinColumn on ${entityMetadata.name}#${relation.propertyName} is wrong. ` +
`You can use JoinColumn only on one-to-one and many-to-one relations.`;
}

View File

@ -10,7 +10,7 @@ export class UsingJoinColumnOnlyOnOneSideAllowedError extends Error {
constructor(entityMetadata: EntityMetadata, relation: RelationMetadata) {
super();
this.message = `Using JoinColumn is allowed only on one side of the one-to-one relationship. ` +
`Both ${entityMetadata.name}#${relation.name} and ${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} ` +
`Both ${entityMetadata.name}#${relation.propertyName} and ${relation.inverseEntityMetadata.name}#${relation.inverseRelation.propertyName} ` +
`has JoinTable decorators. Choose one of them and left JoinTable decorator only on it.`;
}

View File

@ -9,8 +9,8 @@ export class UsingJoinTableIsNotAllowedError extends Error {
constructor(entityMetadata: EntityMetadata, relation: RelationMetadata) {
super();
this.message = `Using JoinTable on ${entityMetadata.name}#${relation.name} is wrong. ` +
`${entityMetadata.name}#${relation.name} has ${relation.relationType} relation, ` +
this.message = `Using JoinTable on ${entityMetadata.name}#${relation.propertyName} is wrong. ` +
`${entityMetadata.name}#${relation.propertyName} has ${relation.relationType} relation, ` +
`however you can use JoinTable only on many-to-many relations.`;
}

View File

@ -10,7 +10,7 @@ export class UsingJoinTableOnlyOnOneSideAllowedError extends Error {
constructor(entityMetadata: EntityMetadata, relation: RelationMetadata) {
super();
this.message = `Using JoinTable is allowed only on one side of the many-to-many relationship. ` +
`Both ${entityMetadata.name}#${relation.name} and ${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} ` +
`Both ${entityMetadata.name}#${relation.propertyName} and ${relation.inverseEntityMetadata.name}#${relation.inverseRelation.propertyName} ` +
`has JoinTable decorators. Choose one of them and left JoinColumn decorator only on it.`;
}

View File

@ -68,11 +68,6 @@ export class EntityMetadata {
this.columns = columns;
this.relations = relations;
this.indices = indices;
table.entityMetadata = this;
columns.forEach(column => column.entityMetadata = this);
relations.forEach(relation => relation.entityMetadata = this);
indices.forEach(index => index.entityMetadata = this);
}
// -------------------------------------------------------------------------

View File

@ -24,12 +24,12 @@ export class JoinColumnMetadata extends PropertyMetadata {
/**
* Join column name.
*/
private readonly _name: string;
private readonly _name: string|undefined;
/**
* Join column referenced column name.
*/
private readonly _referencedColumnName: string;
private readonly referencedColumnName: string|undefined;
// ---------------------------------------------------------------------
// Constructor
@ -37,11 +37,8 @@ export class JoinColumnMetadata extends PropertyMetadata {
constructor(args: JoinColumnMetadataArgs) {
super(args.target, args.propertyName);
if (args.options.name)
this._name = args.options.name;
if (args.options.referencedColumnName)
this._referencedColumnName = args.options.referencedColumnName;
this._name = args.name;
this.referencedColumnName = args.referencedColumnName;
}
// ---------------------------------------------------------------------
@ -59,10 +56,10 @@ export class JoinColumnMetadata extends PropertyMetadata {
* Referenced join column.
*/
get referencedColumn(): ColumnMetadata {
if (this._referencedColumnName) {
const referencedColumn = this.relation.inverseEntityMetadata.columns.find(column => column.name === this._referencedColumnName);
if (this.referencedColumnName) {
const referencedColumn = this.relation.inverseEntityMetadata.columns.find(column => column.name === this.referencedColumnName);
if (!referencedColumn)
throw new Error(`Referenced column ${this._referencedColumnName} was not found in entity ${this.name}`);
throw new Error(`Referenced column ${this.referencedColumnName} was not found in entity ${this.name}`);
}
return this.relation.inverseEntityMetadata.primaryColumn;

View File

@ -53,21 +53,21 @@ export class JoinTableMetadata extends PropertyMetadata {
constructor(args: JoinTableMetadataArgs) {
super(args.target, args.propertyName);
if (args.options.name)
this._name = args.options.name;
if (args.name)
this._name = args.name;
if (args.options.joinColumn) {
if (args.options.joinColumn.name)
this._joinColumnName = args.options.joinColumn.name;
if (args.options.joinColumn.referencedColumnName)
this._joinColumnReferencedColumnName = args.options.joinColumn.referencedColumnName;
if (args.joinColumn) {
if (args.joinColumn.name)
this._joinColumnName = args.joinColumn.name;
if (args.joinColumn.referencedColumnName)
this._joinColumnReferencedColumnName = args.joinColumn.referencedColumnName;
}
if (args.options.inverseJoinColumn) {
if (args.options.inverseJoinColumn.name)
this._inverseJoinColumnName = args.options.inverseJoinColumn.name;
if (args.options.inverseJoinColumn.referencedColumnName)
this._inverseJoinColumnReferencedColumnName = args.options.inverseJoinColumn.referencedColumnName;
if (args.inverseJoinColumn) {
if (args.inverseJoinColumn.name)
this._inverseJoinColumnName = args.inverseJoinColumn.name;
if (args.inverseJoinColumn.referencedColumnName)
this._inverseJoinColumnReferencedColumnName = args.inverseJoinColumn.referencedColumnName;
}
}

View File

@ -166,12 +166,7 @@ export class RelationMetadata extends PropertyMetadata {
if (!this.isOwning || this.isManyToMany)
throw new Error(`Relation name cannot be retrieved for many-to-many relations or not owning relations.`);
// todo: maybe need to throw exception if its a many-to-many relation?
if (this.joinColumn && this.joinColumn.name)
return this.entityMetadata.namingStrategy.relationNameCustomized(this.joinColumn.name);
return this.entityMetadata.namingStrategy.relationName(this.propertyName);
return this.joinColumn.name;
}
/**
@ -180,11 +175,24 @@ export class RelationMetadata extends PropertyMetadata {
* Also only owning sides of the relations have this property.
*/
get referencedColumnName(): string {
if (!this.isOwning)
throw new Error(`Only owning side of the relations can have information about referenced column names.`);
// for many-to-one and owner one-to-one relations we get referenced column from join column
if (this.joinColumn && this.joinColumn.referencedColumn && this.joinColumn.referencedColumn.name)
return this.joinColumn.referencedColumn.name;
// todo: maybe join column should never be null, and this data should come from join column?
return this.inverseEntityMetadata.primaryColumn.propertyName;
// for many-to-many relation we give referenced column depend of owner side
if (this.joinTable) { // need to check if this algorithm works correctly
if (this.isOwning) {
return this.joinTable.referencedColumn.name;
} else {
return this.joinTable.inverseReferencedColumn.name;
}
}
// this should not be possible, but anyway throw error
throw new Error(`Cannot get referenced column name of the relation ${this.entityMetadata.name}#${this.name}`);
}
/**

View File

@ -9,12 +9,12 @@ export interface ColumnMetadataArgs {
/**
* Class to which column is applied.
*/
readonly target: Function;
readonly target?: Function;
/**
* Class's property name to which column is applied.
*/
readonly propertyName: string;
readonly propertyName?: string;
/**
* Class's property type (reflected) to which column is applied.

View File

@ -1,5 +1,3 @@
import {JoinColumnOptions} from "../options/JoinColumnOptions";
/**
* Arguments for JoinColumnMetadata class.
*/
@ -16,8 +14,13 @@ export interface JoinColumnMetadataArgs {
readonly propertyName: string;
/**
* Class's property type (reflected) to which join column is applied.
* Name of the column.
*/
readonly options: JoinColumnOptions;
readonly name?: string;
/**
* Name of the column in the entity to which this column is referenced.
*/
readonly referencedColumnName?: string;
}

View File

@ -1,4 +1,4 @@
import {JoinTableOptions} from "../options/JoinTableOptions";
import {JoinColumnOptions} from "../options/JoinColumnOptions";
/**
* Arguments for JoinTableMetadata class.
@ -16,8 +16,19 @@ export interface JoinTableMetadataArgs {
readonly propertyName: string;
/**
* Class's property type (reflected) to which this column is applied.
* Name of the table that will be created to store values of the both tables (join table).
* By default is auto generated.
*/
readonly options: JoinTableOptions;
readonly name?: string;
/**
* First column of the join table.
*/
readonly joinColumn?: JoinColumnOptions;
/**
* Second (inverse) column of the join table.
*/
readonly inverseJoinColumn?: JoinColumnOptions;
}

View File

@ -6,6 +6,6 @@ export interface TargetMetadataArgs {
/**
* Class to which this arguments is applied.
*/
readonly target: Function;
readonly target?: Function;
}

View File

@ -1,7 +1,6 @@
import {TargetMetadataCollection} from "./TargetMetadataCollection";
import {PropertyMetadata} from "../PropertyMetadata";
import {TargetMetadataArgsCollection} from "./TargetMetadataArgsCollection";
export class PropertyMetadataCollection<T extends PropertyMetadata> extends TargetMetadataCollection<T> {
export class PropertyMetadataArgsCollection<T extends { target?: Function, propertyName?: string }> extends TargetMetadataArgsCollection<T> {
// -------------------------------------------------------------------------
// Public Methods

View File

@ -1,7 +1,7 @@
import {MetadataAlreadyExistsError} from "../../metadata-storage/error/MetadataAlreadyExistsError";
import {TargetMetadataArgs} from "../args/TargetMetadataArgs";
export class TargetMetadataCollection<T extends TargetMetadataArgs> extends Array<T> {
export class TargetMetadataArgsCollection<T extends { target?: Function }> extends Array<T> {
// -------------------------------------------------------------------------
// Public Methods
@ -13,21 +13,23 @@ export class TargetMetadataCollection<T extends TargetMetadataArgs> extends Arra
filterByClasses(classes: Function[]): this {
const collection = new (<any> this.constructor)();
this.filter(metadata => classes.indexOf(metadata.target) !== -1)
this
.filter(metadata => {
if (!metadata.target) return false;
return classes.indexOf(metadata.target) !== -1;
})
.forEach(metadata => collection.add(metadata));
return collection;
}
add(metadata: T, checkForDuplicateTargets = false) {
if (checkForDuplicateTargets && this.hasWithTarget(metadata.target))
throw new MetadataAlreadyExistsError((<any> metadata.constructor).name, metadata.target);
if (checkForDuplicateTargets) {
if (!metadata.target)
throw new Error(`Target is not set in the given metadata.`);
this.push(metadata);
}
addUniq(metadata: T) {
if (this.hasWithTarget(metadata.target))
throw new MetadataAlreadyExistsError((<any> metadata.constructor).name, metadata.target);
if (this.hasWithTarget(metadata.target))
throw new MetadataAlreadyExistsError((<any> metadata.constructor).name, metadata.target);
}
this.push(metadata);
}