UNPKG

ionic-orm-2

Version:

Data-mapper ORM for Ionic WebSQL and SQLite

257 lines (256 loc) 10.4 kB
import { RelationTypes } from "./types/RelationTypes"; /** * Contains all information about some entity's relation. */ export class RelationMetadata { // --------------------------------------------------------------------- // Constructor // --------------------------------------------------------------------- constructor(args) { /** * Indicates if this is a parent (can be only many-to-one relation) relation in the tree tables. */ this.isTreeParent = false; /** * Indicates if this is a children (can be only one-to-many relation) relation in the tree tables. */ this.isTreeChildren = false; /** * Indicates if relation column value can be nullable or not. */ this.isNullable = true; this.target = args.target; this.propertyName = args.propertyName; this.relationType = args.relationType; if (args.inverseSideProperty) this._inverseSideProperty = args.inverseSideProperty; if (args.propertyType) this.propertyType = args.propertyType; if (args.isLazy) this.isLazy = args.isLazy; if (args.options.cascadeInsert || args.options.cascadeAll) this.isCascadeInsert = true; if (args.options.cascadeUpdate || args.options.cascadeAll) this.isCascadeUpdate = true; if (args.options.cascadeRemove || args.options.cascadeAll) this.isCascadeRemove = true; if (args.options.nullable) this.isNullable = args.options.nullable; if (args.options.onDelete) this.onDelete = args.options.onDelete; if (args.options.primary) this.isPrimary = args.options.primary; if (args.isTreeParent) this.isTreeParent = true; if (args.isTreeChildren) this.isTreeChildren = true; if (!this._type) this._type = args.type; } // --------------------------------------------------------------------- // Accessors // --------------------------------------------------------------------- /** * Gets relation's entity target. * Original target returns target of the class where relation is. * This class can be an abstract class, but relation even is from that class, * but its more related to a specific entity. That's why we need this field. */ get entityTarget() { return this.entityMetadata.target; } /** * Gets the name of column in the database. * //Cannot be used with many-to-many relations since they don't have a column in the database. * //Also only owning sides of the relations have this property. */ get name() { // if (!this.isOwning || this.isManyToMany) if (this.isOwning) { if (this.joinTable) { return this.joinTable.joinColumnName; } else if (this.joinColumn) { return this.joinColumn.name; } } else if (this.hasInverseSide) { if (this.inverseRelation.joinTable) { return this.inverseRelation.joinTable.inverseJoinColumnName; } else if (this.inverseRelation.joinColumn && this.inverseRelation.joinColumn.referencedColumn) { return this.inverseRelation.joinColumn.referencedColumn.name; } } throw new Error(`Relation name cannot be retrieved.`); } /** * Gets the name of column to which this relation is referenced. * //Cannot be used with many-to-many relations since all referenced are in the junction table. * //Also only owning sides of the relations have this property. */ get referencedColumnName() { // 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; // 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; } }*/ if (this.isOwning) { if (this.joinTable) { return this.joinTable.referencedColumn.name; } else if (this.joinColumn) { return this.joinColumn.referencedColumn.name; } } else if (this.hasInverseSide) { if (this.inverseRelation.joinTable) { return this.inverseRelation.joinTable.inverseReferencedColumn.name; } else if (this.inverseRelation.joinColumn) { return this.inverseRelation.joinColumn.name; // todo: didn't get this logic here } } // 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}`); } /** * Gets the column to which this relation is referenced. */ get referencedColumn() { if (this.isOwning) { if (this.joinTable) { return this.joinTable.referencedColumn; } else if (this.joinColumn) { return this.joinColumn.referencedColumn; } } else if (this.hasInverseSide) { if (this.inverseRelation.joinTable) { return this.inverseRelation.joinTable.inverseReferencedColumn; } else if (this.inverseRelation.joinColumn) { return this.inverseRelation.joinColumn.referencedColumn; } } // this should not be possible, but anyway throw error throw new Error(`Cannot get referenced column of the relation ${this.entityMetadata.name}#${this.name}`); } /** * Gets the property's type to which this relation is applied. */ get type() { return this._type instanceof Function ? this._type() : this._type; } /** * Indicates if this side is an owner of this relation. */ get isOwning() { return !!(this.isManyToOne || (this.isManyToMany && this.joinTable) || (this.isOneToOne && this.joinColumn)); } /** * Checks if this relation's type is "one-to-one". */ get isOneToOne() { return this.relationType === RelationTypes.ONE_TO_ONE; } /** * Checks if this relation is owner side of the "one-to-one" relation. */ get isOneToOneOwner() { return this.isOneToOne && this.isOwning; } /** * Checks if this relation is NOT owner side of the "one-to-one" relation. */ get isOneToOneNotOwner() { return this.isOneToOne && !this.isOwning; } /** * Checks if this relation's type is "one-to-many". */ get isOneToMany() { return this.relationType === RelationTypes.ONE_TO_MANY; } /** * Checks if this relation's type is "many-to-one". */ get isManyToOne() { return this.relationType === RelationTypes.MANY_TO_ONE; } /** * Checks if this relation's type is "many-to-many". */ get isManyToMany() { return this.relationType === RelationTypes.MANY_TO_MANY; } /** * Checks if inverse side is specified by a relation. */ get hasInverseSide() { return this.inverseEntityMetadata && this.inverseEntityMetadata.hasRelationWithPropertyName(this.inverseSideProperty); } /** * Gets the property name of the inverse side of the relation. */ get inverseSideProperty() { if (this._inverseSideProperty) { return this.computeInverseSide(this._inverseSideProperty); } else if (this.isTreeParent && this.entityMetadata.hasTreeChildrenRelation) { return this.entityMetadata.treeChildrenRelation.propertyName; } else if (this.isTreeChildren && this.entityMetadata.hasTreeParentRelation) { return this.entityMetadata.treeParentRelation.propertyName; } return ""; } /** * Gets the relation metadata of the inverse side of this relation. */ get inverseRelation() { const relation = this.inverseEntityMetadata.findRelationWithPropertyName(this.inverseSideProperty); if (!relation) throw new Error(`Inverse side was not found in the relation ${this.entityMetadata.name}#${this.inverseSideProperty}`); return relation; } // --------------------------------------------------------------------- // Public Methods // --------------------------------------------------------------------- /** * Gets given entity's relation's value. * Using of this method helps to access value of the lazy loaded relation. */ getEntityValue(entity) { return this.isLazy ? entity["__" + this.propertyName + "__"] : entity[this.propertyName]; } // --------------------------------------------------------------------- // Private Methods // --------------------------------------------------------------------- /** * 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. */ computeInverseSide(inverseSide) { const ownerEntityPropertiesMap = this.inverseEntityMetadata.createPropertiesMap(); if (typeof inverseSide === "function") return inverseSide(ownerEntityPropertiesMap); if (typeof inverseSide === "string") return inverseSide; // throw new Error("Cannot compute inverse side of the relation"); return ""; } } //# sourceMappingURL=RelationMetadata.js.map