You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
3.0 KiB

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> = T | Collection<T> | undefined
export abstract class Relation<T extends Model<T>, T2 extends Model<T2>> 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<T2>
public abstract scope_query(where: WhereBuilder): void
public abstract build_eager_query(parent_query: ModelSelect<T>, result: Collection<T>): ModelSelect<T2>
public abstract match_results(possibly_related: Collection<T>): Collection<T>
public abstract set_value(related: Collection<T2>): void
public abstract get_value(): Collection<T2> | T2 | undefined
public abstract is_loaded(): boolean
public fetch(): AsyncCollection<T2> {
return this.query().results()
}
public abstract get(): Promise<RelationResult<T2>>
public then(callback: (result: RelationResult<T2>) => any) {
if ( this.is_loaded() ) {
callback(this.get_value() as RelationResult<T2>)
} else {
this.get().then(result => {
if ( result instanceof Collection ) {
this.set_value(result as any)
}
callback(result)
})
}
}
public get value(): RelationResult<T2> {
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<T2> {
return new RelationBuilder(this)
}
public select(...fields: FieldSet[]): Select<T2> {
if ( fields.length < 1 ) fields.push(this.related.qualify_column('*'))
return this.builder().select(...fields)
}
public update(): Update<T2> {
return this.builder().update()
}
public delete(): Delete<T2> {
return this.builder().delete()
}
}