mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
metadata refactoring
This commit is contained in:
parent
68f4cc48be
commit
4dfe6f9946
@ -94,9 +94,7 @@ export class EntityMetadataBuilder {
|
||||
// here we create a junction entity metadata for a new junction table of many-to-many relation
|
||||
const junctionEntityMetadata = this.junctionEntityMetadataBuilder.build(relation, joinTable);
|
||||
relation.registerForeignKeys(...junctionEntityMetadata.foreignKeys);
|
||||
relation.junctionEntityMetadata = junctionEntityMetadata;
|
||||
if (relation.inverseRelation)
|
||||
relation.inverseRelation.junctionEntityMetadata = junctionEntityMetadata;
|
||||
relation.registerJunctionEntityMetadata(junctionEntityMetadata);
|
||||
|
||||
// compute new entity metadata properties and push it to entity metadatas pool
|
||||
this.computeEntityMetadata(junctionEntityMetadata);
|
||||
@ -210,10 +208,10 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.embeddeds.forEach(embedded => embedded.build(this.connection.driver.namingStrategy));
|
||||
entityMetadata.embeddeds.forEach(embedded => {
|
||||
embedded.columnsFromTree.forEach(column => column.build(this.connection.driver.namingStrategy));
|
||||
embedded.relationsFromTree.forEach(relation => relation.build(this.connection.driver.namingStrategy));
|
||||
embedded.relationsFromTree.forEach(relation => relation.build());
|
||||
});
|
||||
entityMetadata.ownColumns.forEach(column => column.build(this.connection.driver.namingStrategy));
|
||||
entityMetadata.ownRelations.forEach(relation => relation.build(this.connection.driver.namingStrategy));
|
||||
entityMetadata.ownRelations.forEach(relation => relation.build());
|
||||
entityMetadata.relations = entityMetadata.embeddeds.reduce((relations, embedded) => relations.concat(embedded.relationsFromTree), entityMetadata.ownRelations);
|
||||
entityMetadata.oneToOneRelations = entityMetadata.relations.filter(relation => relation.isOneToOne);
|
||||
entityMetadata.oneToManyRelations = entityMetadata.relations.filter(relation => relation.isOneToMany);
|
||||
@ -236,6 +234,13 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.objectIdColumn = entityMetadata.columns.find(column => column.isObjectId);
|
||||
entityMetadata.foreignKeys.forEach(foreignKey => foreignKey.build(this.connection.driver.namingStrategy));
|
||||
entityMetadata.propertiesMap = entityMetadata.createPropertiesMap();
|
||||
|
||||
entityMetadata.relationIds.forEach(relationId => relationId.build());
|
||||
// entityMetadata.relationCounts.forEach(relationCount => relationCount.build());
|
||||
entityMetadata.embeddeds.forEach(embedded => {
|
||||
embedded.relationIdsFromTree.forEach(relationId => relationId.build());
|
||||
// embedded.relationCountsFromTree.forEach(relationCount => relationCount.build());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,6 +17,8 @@ export class ColumnMetadata {
|
||||
|
||||
/**
|
||||
* Entity metadata where this column metadata is.
|
||||
*
|
||||
* For example for @Column() name: string in Post, entityMetadata will be metadata of Post entity.
|
||||
*/
|
||||
entityMetadata: EntityMetadata;
|
||||
|
||||
|
||||
@ -3,6 +3,8 @@ import {RelationMetadata} from "./RelationMetadata";
|
||||
import {EntityMetadata} from "./EntityMetadata";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
|
||||
import {EmbeddedMetadataArgs} from "../metadata-args/EmbeddedMetadataArgs";
|
||||
import {RelationIdMetadata} from "./RelationIdMetadata";
|
||||
import {RelationCountMetadata} from "./RelationCountMetadata";
|
||||
|
||||
/**
|
||||
* Contains all information about entity's embedded property.
|
||||
@ -87,7 +89,7 @@ export class EmbeddedMetadata {
|
||||
embeddedMetadataTree: EmbeddedMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Returns embed metadatas from all levels of the parent tree.
|
||||
* Embed metadatas from all levels of the parent tree.
|
||||
*
|
||||
* example: post[data][information][counters].id where "data", "information" and "counters" are embeds
|
||||
* this method will return [embed metadata of data, embed metadata of information, embed metadata of counters]
|
||||
@ -95,10 +97,20 @@ export class EmbeddedMetadata {
|
||||
columnsFromTree: ColumnMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Returns all relations of this embed and all relations from its child embeds.
|
||||
* Relations of this embed and all relations from its child embeds.
|
||||
*/
|
||||
relationsFromTree: RelationMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Relation ids of this embed and all relation ids from its child embeds.
|
||||
*/
|
||||
relationIdsFromTree: RelationIdMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Relation counts of this embed and all relation counts from its child embeds.
|
||||
*/
|
||||
relationCountsFromTree: RelationCountMetadata[] = [];
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@ -87,6 +87,10 @@ export class ForeignKeyMetadata {
|
||||
// Public Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Builds some depend foreign key properties.
|
||||
* Must be called after all entity metadatas and their columns are built.
|
||||
*/
|
||||
build(namingStrategy: NamingStrategyInterface) {
|
||||
this.columnNames = this.columns.map(column => column.databaseName);
|
||||
this.referencedColumnNames = this.referencedColumns.map(column => column.databaseName);
|
||||
|
||||
@ -79,6 +79,10 @@ export class IndexMetadata {
|
||||
// Public Build Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Builds some depend index properties.
|
||||
* Must be called after all entity metadata's properties map, columns and relations are built.
|
||||
*/
|
||||
build(namingStrategy: NamingStrategyInterface): this {
|
||||
this.tableName = this.entityMetadata.tableName;
|
||||
|
||||
|
||||
@ -17,6 +17,11 @@ export class RelationCountMetadata {
|
||||
*/
|
||||
entityMetadata: EntityMetadata;
|
||||
|
||||
/**
|
||||
* Relation which needs to be counted.
|
||||
*/
|
||||
relation: RelationMetadata;
|
||||
|
||||
/**
|
||||
* Relation name which need to count.
|
||||
*/
|
||||
@ -51,27 +56,28 @@ export class RelationCountMetadata {
|
||||
args: RelationCountMetadataArgs
|
||||
}) {
|
||||
this.entityMetadata = options.entityMetadata;
|
||||
const args = options.args;
|
||||
this.target = args.target;
|
||||
this.propertyName = args.propertyName;
|
||||
this.relationNameOrFactory = args.relation;
|
||||
this.alias = args.alias;
|
||||
this.queryBuilderFactory = args.queryBuilderFactory;
|
||||
this.target = options.args.target;
|
||||
this.propertyName = options.args.propertyName;
|
||||
this.relationNameOrFactory = options.args.relation;
|
||||
this.alias = options.args.alias;
|
||||
this.queryBuilderFactory = options.args.queryBuilderFactory;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Accessors
|
||||
// Public Builder Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Relation which need to count.
|
||||
* Builds some depend relation count metadata properties.
|
||||
* This builder method should be used only after entity metadata, its properties map and all relations are build.
|
||||
*/
|
||||
get relation(): RelationMetadata {
|
||||
const propertyName = this.relationNameOrFactory instanceof Function ? this.relationNameOrFactory(this.entityMetadata.propertiesMap) : this.relationNameOrFactory;
|
||||
const relation = this.entityMetadata.relations.find(relation => relation.propertyName === propertyName);
|
||||
build() {
|
||||
const propertyPath = this.relationNameOrFactory instanceof Function ? this.relationNameOrFactory(this.entityMetadata.propertiesMap) : this.relationNameOrFactory;
|
||||
const relation = this.entityMetadata.findRelationWithPropertyPath(propertyPath);
|
||||
if (!relation)
|
||||
throw new Error(`Cannot find relation ${propertyName}. Wrong relation specified for @RelationCount decorator.`);
|
||||
throw new Error(`Cannot find relation ${propertyPath}. Wrong relation specified for @RelationCount decorator.`);
|
||||
|
||||
return relation;
|
||||
this.relation = relation;
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,6 +17,11 @@ export class RelationIdMetadata {
|
||||
*/
|
||||
entityMetadata: EntityMetadata;
|
||||
|
||||
/**
|
||||
* Relation from which ids will be extracted.
|
||||
*/
|
||||
relation: RelationMetadata;
|
||||
|
||||
/**
|
||||
* Relation name which need to count.
|
||||
*/
|
||||
@ -51,28 +56,28 @@ export class RelationIdMetadata {
|
||||
args: RelationIdMetadataArgs
|
||||
}) {
|
||||
this.entityMetadata = options.entityMetadata;
|
||||
const args = options.args;
|
||||
this.target = args.target;
|
||||
this.propertyName = args.propertyName;
|
||||
this.relationNameOrFactory = args.relation;
|
||||
this.alias = args.alias;
|
||||
this.queryBuilderFactory = args.queryBuilderFactory;
|
||||
this.target = options.args.target;
|
||||
this.propertyName = options.args.propertyName;
|
||||
this.relationNameOrFactory = options.args.relation;
|
||||
this.alias = options.args.alias;
|
||||
this.queryBuilderFactory = options.args.queryBuilderFactory;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Accessors
|
||||
// Public Builder Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Relation which need to count.
|
||||
* Builds some depend relation id properties.
|
||||
* This builder method should be used only after entity metadata, its properties map and all relations are build.
|
||||
*/
|
||||
get relation(): RelationMetadata {
|
||||
const propertyName = this.relationNameOrFactory instanceof Function ? this.relationNameOrFactory(this.entityMetadata.propertiesMap) : this.relationNameOrFactory;
|
||||
const relation = this.entityMetadata.relations.find(relation => relation.propertyName === propertyName);
|
||||
build() {
|
||||
const propertyPath = this.relationNameOrFactory instanceof Function ? this.relationNameOrFactory(this.entityMetadata.propertiesMap) : this.relationNameOrFactory;
|
||||
const relation = this.entityMetadata.findRelationWithPropertyPath(propertyPath);
|
||||
if (!relation)
|
||||
throw new Error(`Cannot find relation ${propertyName}. Wrong relation specified for @RelationId decorator.`);
|
||||
throw new Error(`Cannot find relation ${propertyPath}. Wrong relation specified for @RelationId decorator.`);
|
||||
|
||||
return relation;
|
||||
this.relation = relation;
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,11 +18,6 @@ export class RelationMetadata {
|
||||
// Public Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Relation type, e.g. is it one-to-one, one-to-many, many-to-one or many-to-many.
|
||||
*/
|
||||
relationType: RelationType;
|
||||
|
||||
/**
|
||||
* Entity metadata of the entity where this relation is placed.
|
||||
*
|
||||
@ -39,6 +34,7 @@ export class RelationMetadata {
|
||||
|
||||
/**
|
||||
* Entity metadata of the junction table.
|
||||
* Junction tables have their own entity metadata objects.
|
||||
* Defined only for many-to-many relations.
|
||||
*/
|
||||
junctionEntityMetadata?: EntityMetadata;
|
||||
@ -50,9 +46,9 @@ export class RelationMetadata {
|
||||
embeddedMetadata?: EmbeddedMetadata;
|
||||
|
||||
/**
|
||||
* Foreign keys created for this relation.
|
||||
* Relation type, e.g. is it one-to-one, one-to-many, many-to-one or many-to-many.
|
||||
*/
|
||||
foreignKeys: ForeignKeyMetadata[] = [];
|
||||
relationType: RelationType;
|
||||
|
||||
/**
|
||||
* Target entity to which this relation is applied.
|
||||
@ -124,28 +120,6 @@ export class RelationMetadata {
|
||||
*/
|
||||
onDelete?: OnDeleteType;
|
||||
|
||||
/**
|
||||
* Join table name.
|
||||
*/
|
||||
joinTableName: string;
|
||||
|
||||
/**
|
||||
* Join table columns.
|
||||
* Join columns can be obtained only from owner side of the relation.
|
||||
* From non-owner side of the relation join columns will be empty.
|
||||
* If this relation is a many-to-one/one-to-one then it takes join columns from the current entity.
|
||||
* If this relation is many-to-many then it takes all owner join columns from the junction entity.
|
||||
*/
|
||||
joinColumns: ColumnMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Inverse join table columns.
|
||||
* Inverse join columns are supported only for many-to-many relations
|
||||
* and can be obtained only from owner side of the relation.
|
||||
* From non-owner side of the relation join columns will be undefined.
|
||||
*/
|
||||
inverseJoinColumns: ColumnMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Gets the property's type to which this relation is applied.
|
||||
*
|
||||
@ -213,7 +187,11 @@ export class RelationMetadata {
|
||||
inverseSidePropertyPath: string;
|
||||
|
||||
/**
|
||||
* Inverse side of the relation.
|
||||
* Inverse side of the relation set by user.
|
||||
*
|
||||
* Inverse side set in the relation can be either string - property name of the column on inverse side,
|
||||
* either can be a function that accepts a map of properties with the object and returns one of them.
|
||||
* Second approach is used to achieve type-safety.
|
||||
*/
|
||||
givenInverseSidePropertyFactory: PropertyTypeFactory<any>;
|
||||
|
||||
@ -222,6 +200,33 @@ export class RelationMetadata {
|
||||
*/
|
||||
inverseRelation?: RelationMetadata;
|
||||
|
||||
/**
|
||||
* Join table name.
|
||||
*/
|
||||
joinTableName: string;
|
||||
|
||||
/**
|
||||
* Foreign keys created for this relation.
|
||||
*/
|
||||
foreignKeys: ForeignKeyMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Join table columns.
|
||||
* Join columns can be obtained only from owner side of the relation.
|
||||
* From non-owner side of the relation join columns will be empty.
|
||||
* If this relation is a many-to-one/one-to-one then it takes join columns from the current entity.
|
||||
* If this relation is many-to-many then it takes all owner join columns from the junction entity.
|
||||
*/
|
||||
joinColumns: ColumnMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Inverse join table columns.
|
||||
* Inverse join columns are supported only for many-to-many relations
|
||||
* and can be obtained only from owner side of the relation.
|
||||
* From non-owner side of the relation join columns will be undefined.
|
||||
*/
|
||||
inverseJoinColumns: ColumnMetadata[] = [];
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
@ -368,10 +373,18 @@ export class RelationMetadata {
|
||||
// Builder Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
build(namingStrategy: NamingStrategyInterface) {
|
||||
/**
|
||||
* Builds some depend relation metadata properties.
|
||||
* This builder method should be used only after embedded metadata tree was build.
|
||||
*/
|
||||
build() {
|
||||
this.propertyPath = this.buildPropertyPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers given foreign keys in the relation.
|
||||
* This builder method should be used to register foreign key in the relation.
|
||||
*/
|
||||
registerForeignKeys(...foreignKeys: ForeignKeyMetadata[]) {
|
||||
this.foreignKeys.push(...foreignKeys);
|
||||
this.joinColumns = this.foreignKeys[0] ? this.foreignKeys[0].columns : [];
|
||||
@ -385,11 +398,21 @@ export class RelationMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse side set in the relation can be either string - property name of the column on inverse side,
|
||||
* either can be a function that accepts a map of properties with the object and returns one of them.
|
||||
* Second approach is used to achieve type-safety.
|
||||
*
|
||||
* todo: revisit comment
|
||||
* Registers a given junction entity metadata.
|
||||
* This builder method can be called after junction entity metadata for the many-to-many relation was created.
|
||||
*/
|
||||
registerJunctionEntityMetadata(junctionEntityMetadata: EntityMetadata) {
|
||||
this.junctionEntityMetadata = junctionEntityMetadata;
|
||||
this.joinTableName = junctionEntityMetadata.tableName;
|
||||
if (this.inverseRelation) {
|
||||
this.inverseRelation.junctionEntityMetadata = junctionEntityMetadata;
|
||||
this.joinTableName = junctionEntityMetadata.tableName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds inverse side property path based on given inverse side property factory.
|
||||
* This builder method should be used only after properties map of the inverse entity metadata was build.
|
||||
*/
|
||||
buildInverseSidePropertyPath(): string {
|
||||
|
||||
@ -408,14 +431,13 @@ export class RelationMetadata {
|
||||
return this.entityMetadata.treeParentRelation.propertyName;
|
||||
}
|
||||
|
||||
return ""; // todo: return undefined instead?
|
||||
return "";
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
protected buildPropertyPath(): string {
|
||||
/**
|
||||
* Builds relation's property path based on its embedded tree.
|
||||
*/
|
||||
buildPropertyPath(): string {
|
||||
if (!this.embeddedMetadata || !this.embeddedMetadata.parentPropertyNames.length)
|
||||
return this.propertyName;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user