import { Id } from '../types'; import { BaseModel } from './base'; import { Keys } from './entities'; /** * @param {BaseModel} parent The parent BaseModel * @param {string} relationKey The name of the property on the parent to refer the relation to (e.g. users.forms where forms is the relationKey) * @param {string} foreignKey The foreignKey on the relation refering to the parent. (e.g userId on a form) * @param {Keys} storeKey The store key of the relation items. */ export class HasOne { protected _parent: BaseModel; public _foreignKey: string; public _relationKey: string; public _storeKey: Keys; constructor( parent: BaseModel, relationKey: string, foreignKey: string, storeKey: Keys, ) { this._parent = parent; this._foreignKey = foreignKey; this._relationKey = relationKey; this._storeKey = storeKey; } async getLocal(parentId: Id) { const actualId = await this._parent.getId(parentId); return ( this._parent._store.find( this._storeKey, (item) => item[this._foreignKey] === actualId, ) ); } async get(parentId: Id) { const actualId = await this._parent.getId(parentId); const cached = await this.getLocal(actualId); if (cached) { return cached; } const data = await this._parent._requestModel[this._relationKey].get( actualId, ); this._parent._store.set(this._storeKey, data, { deep: false }); return data; } async create(parentId: Id, item: DataType) { const actualId = await this._parent.getId(parentId); const data = await this._parent._requestModel[this._relationKey].post( actualId, item, ); this._parent._store.set(this._storeKey, data, { deep: false }); return data; } } export function hasOne({ relationKey, foreignKey, storeKey, }: { relationKey: string; foreignKey: string; storeKey: Keys; }) { return function _DecoratorName( ctor: C, ) { return class extends ctor { constructor(...args: any[]) { super(...args); this[relationKey] = new HasOne( >(this), relationKey, foreignKey, storeKey, ); } }; }; }