UNPKG

blow-data

Version:
147 lines (124 loc) 4.54 kB
'use strict'; import {isUndefined, isFunction, isNull} from 'util'; import {Observable} from 'rxjs'; import {IQueryWhere, IQuery, Query, IQueryObject} from 'blow-query'; import * as _ from './helpers'; import {manager} from './manager'; import { IModelRelationMetadataOptions, IModelRelationMetadata, IPersistedModelConstructor } from './interfaces'; export class ModelRelationMetadata implements IModelRelationMetadata { protected _name: string; protected _type: string; protected _model: IPersistedModelConstructor | string; protected _foreignKey: string; protected _hidden: boolean; constructor(options: IModelRelationMetadataOptions) { this._name = options.name; this._type = options.type; this._model = options.model; this._foreignKey = options.foreignKey; this._hidden = isUndefined(options.hidden) ? false : options.hidden; } get name(): string { return this._name; } get type(): string { return this._type; } get model(): IPersistedModelConstructor | string { return this._model; } get foreignKey(): string { return this._foreignKey; } get hidden(): boolean { return this._hidden; } apply(model: IPersistedModelConstructor): void { switch(this.type) { case 'belongsTo': { const relationName = this.name; const targetModel = <IPersistedModelConstructor>(_.getModel(this.model)); const targetKey = _.getModel(this.model).metadata.idProperty; if(!model.metadata.hasProperty(this.foreignKey)) { model.metadata.defineProperty({ name: this.foreignKey, type: targetKey.type }); } const rootModel = model; const rootKey = model.metadata.getProperty(this.foreignKey); Object.defineProperty(model.prototype, relationName, { enumerable: false, configurable: false, get: function() { const inst = this; return function(data) { if(arguments.length > 0) { inst[rootKey.name] = data[targetKey.name]; } else { if(inst[rootKey.name]) { return targetModel.findById(inst[rootKey.name]); } else { return Observable.of(undefined); } } } } }); } break; case 'hasMany': { const relationName = this.name; const rootModel = model; const rootKey = model.metadata.idProperty; const targetMetadata = _.getModel(this.model).metadata; if(!targetMetadata.hasProperty(this.foreignKey)) { targetMetadata.defineProperty({ name: this.foreignKey, type: rootKey.type }); } const targetModel = <IPersistedModelConstructor>(_.getModel(this.model)); const targetKey = targetMetadata.getProperty(this.foreignKey); Object.defineProperty(model.prototype, relationName, { enumerable: false, configurable: false, get: function() { const inst = this; return { create(data: {[key: string]: any}) { data[targetKey.name] = inst[rootKey.name]; return targetModel.create(data); }, find(query?: IQuery | IQueryObject) { const q: IQuery = new Query(query); q.equal(targetKey.name, inst[rootKey.name]); return targetModel.find(q); }, findById(id: any) { const q: IQuery = new Query(); q.equal(targetKey.name, inst[rootKey.name]); q.equal(targetModel.metadata.idProperty.name, id); return targetModel.findOne(q); }, destroy(query?: IQueryWhere) { const q: IQuery = new Query({where: query}); q.equal(targetKey.name, inst[rootKey.name]); return targetModel.destroy(q.toJSON().where); }, destroyById(id: any) { const q: IQuery = new Query(); q.equal(targetModel.metadata.idProperty.name, id); return this.destroy(q.toJSON().where); } } } }); } break; } } }