import { Filter } from './Filter'; import { Condition } from './Condition'; import { Operator } from './Operator'; import { FailCallback, Query, ResultOptions, ResultListCallback, SingleResultCallback, CountCallback, flatArgs, } from './Query'; import type { Entity } from '../binding'; import { Node } from './Node'; /** * The Query Builder allows creating filtered and combined queries */ export interface Builder extends Query, Condition {} // mixin the condition implementation export class Builder extends Query { /** * Joins the conditions by an logical AND * @param args The query nodes to join * @return Returns a new query which joins the given queries by a logical AND */ and(...args: Array | Query[]>): Operator { return this.addOperator('$and', flatArgs(args)); } /** * Joins the conditions by an logical OR * @param args The query nodes to join * @return Returns a new query which joins the given queries by a logical OR */ or(...args: Array | Query[]>): Operator { return this.addOperator('$or', flatArgs(args)); } /** * Joins the conditions by an logical NOR * @param args The query nodes to join * @return Returns a new query which joins the given queries by a logical NOR */ nor(...args: Array | Query[]>): Operator { return this.addOperator('$nor', flatArgs(args)); } /** * @inheritDoc */ resultList(options?: ResultOptions | ResultListCallback, doneCallback?: ResultListCallback | FailCallback, failCallback?: FailCallback) { return this.where({}).resultList(options, doneCallback, failCallback); } /** * @inheritDoc */ singleResult(options?: ResultOptions | SingleResultCallback, doneCallback?: SingleResultCallback | FailCallback, failCallback?: FailCallback) { return this.where({}).singleResult(options, doneCallback, failCallback); } /** * @inheritDoc */ count(doneCallback?: CountCallback, failCallback?: FailCallback) { return this.where({}).count(doneCallback, failCallback); } addOperator(operator: string, args: Node[]) { if (args.length < 2) { throw new Error(`Only two or more queries can be joined with an ${operator} operator.`); } args.forEach((arg, index) => { if (!(arg instanceof Node)) { throw new Error(`Argument at index ${index} is not a query.`); } }); return new Operator(this.entityManager, this.resultClass, operator, args); } addOrder(fieldOrSort: string | { [field: string]: 1 | -1 }, order?: 1 | -1) { return new Filter(this.entityManager, this.resultClass).addOrder(fieldOrSort, order); } addFilter(field: string | null, filter: string | null, value: any): Filter { return new Filter(this.entityManager, this.resultClass).addFilter(field, filter, value); } addOffset(offset: number) { return new Filter(this.entityManager, this.resultClass).addOffset(offset); } addLimit(limit: number) { return new Filter(this.entityManager, this.resultClass).addLimit(limit); } } Object.assign(Builder.prototype, Condition);