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.
lib/src/orm/model/relation/HasTreeParent.ts

76 lines
2.2 KiB

import {Relation, RelationNotLoadedError} from './Relation'
import {TreeModel} from '../TreeModel'
import {RelationBuilder} from './RelationBuilder'
import {raw} from '../../dialect/SQLDialect'
import {AbstractBuilder} from '../../builder/AbstractBuilder'
import {ModelBuilder} from '../ModelBuilder'
import {Collection, Maybe} from '../../../util'
export class HasTreeParent<T extends TreeModel<T>> extends Relation<T, T, Maybe<T>> {
protected parentInstance?: T
protected loaded = false
protected constructor(
protected model: T,
protected readonly leftTreeField: string,
protected readonly parentIdField: string,
) {
super(model, model)
}
protected get parentValue(): any {
return this.model.key()
}
public query(): RelationBuilder<T> {
return this.builder()
.tap(b => this.model.applyScopes(b))
.select(raw('*'))
.orderByAscending(this.leftTreeField)
}
public applyScope(where: AbstractBuilder<T>): void {
const parentId = this.model.parentId()
if ( !parentId ) {
where.whereMatchNone()
return
}
where.where(this.parentIdField, '=', parentId)
}
public buildEagerQuery(parentQuery: ModelBuilder<T>, result: Collection<T>): ModelBuilder<T> {
const parentIds = result.map(model => model.parentId()).whereDefined()
return this.model.query()
.without('subtree')
.whereIn(this.parentIdField, parentIds)
}
public matchResults(possiblyRelated: Collection<T>): Collection<T> {
return possiblyRelated.filter(related => related.key() === this.model.parentId())
}
public setValue(related: Maybe<T>): void {
this.loaded = true
this.parentInstance = related
}
public getValue(): Maybe<T> {
if ( !this.loaded && this.model.parentId() ) {
throw new RelationNotLoadedError()
}
return this.parentInstance
}
public isLoaded(): boolean {
return this.loaded || !this.model.parentId()
}
public async get(): Promise<Maybe<T>> {
return this.fetch().first()
}
}