import {Model} from '../Model.ts' import AppClass from '../../../../lib/src/lifecycle/AppClass.ts' import RelationResultOperator from '../RelationResultOperator.ts' import ConnectionExecutable from '../../builder/type/ConnectionExecutable.ts' import {AsyncCollection} from '../../../../lib/src/collection/AsyncCollection.ts' import {Collection} from '../../../../lib/src/collection/Collection.ts' import {WhereBuilder} from '../../builder/type/WhereBuilder.ts' import {RelationBuilder} from './RelationBuilder.ts' import {Select} from '../../builder/type/Select.ts' import {FieldSet} from '../../builder/types.ts' import {Update} from '../../builder/type/Update.ts' import {Delete} from '../../builder/type/Delete.ts' import ModelResultOperator from '../ModelResultOperator.ts' import {ModelSelect} from '../query/ModelSelect.ts' export type RelationResult = T | Collection | undefined export abstract class Relation, T2 extends Model> extends AppClass { constructor( protected parent: T, public readonly related: T2, ) { super() } protected abstract get parent_value(): any public get_operator() { const related_class = this.related.constructor as typeof Model return this.make(ModelResultOperator, related_class) } public abstract query(): ConnectionExecutable public abstract scope_query(where: WhereBuilder): void public abstract build_eager_query(parent_query: ModelSelect, result: Collection): ModelSelect public abstract match_results(possibly_related: Collection): Collection public abstract set_value(related: Collection): void public abstract get_value(): Collection | T2 | undefined public abstract is_loaded(): boolean public fetch(): AsyncCollection { return this.query().results() } public abstract get(): Promise> public then(callback: (result: RelationResult) => any) { if ( this.is_loaded() ) { callback(this.get_value() as RelationResult) } else { this.get().then(result => { if ( result instanceof Collection ) { this.set_value(result as any) } callback(result) }) } } public get value(): RelationResult { return this.get_value() } public get related_query_source() { const related_class = this.related.constructor as typeof Model return related_class.query_source() } public builder(): RelationBuilder { return new RelationBuilder(this) } public select(...fields: FieldSet[]): Select { if ( fields.length < 1 ) fields.push(this.related.qualify_column('*')) return this.builder().select(...fields) } public update(): Update { return this.builder().update() } public delete(): Delete { return this.builder().delete() } }