///
declare module '@ioc:Adonis/Lucid/Database' {
import { Knex } from 'knex';
import { DialectContract, QueryClientContract, TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
/**
* Extracted from ts-essentials
*/
type Dictionary = {
[key in K]: T;
};
/**
* Get one or many of a generic
*/
type OneOrMany = T | T[];
/**
* Allowing a generic value along with raw query instance or a subquery
* instance
*/
type ValueWithSubQueries = T | ChainableContract | RawQuery;
/**
* Acceptable raw queries
*/
type RawQuery = RawBuilderContract | RawQueryBuilderContract | Knex.Raw | Knex.RawQueryBuilder;
/**
* A known set of values allowed when defining values for different
* clauses
*/
type StrictValues = string | number | boolean | Date | Array | Array | Array | Array | Buffer | RawQuery | ReferenceBuilderContract;
/**
* Strict set of allowed values except the raw queries
*/
type StrictValuesWithoutRaw = Exclude;
/**
* Shape of raw query bindings
*/
type RawQueryBindings = {
[key: string]: StrictValues;
} | StrictValues[];
/**
* A builder method to allow raw queries. However, the return type is the
* instance of current query builder. This is used for `.{verb}Raw` methods.
*/
interface RawQueryFn {
(sql: string | RawQuery): Builder;
(sql: string, bindings: RawQueryBindings): Builder;
}
/**
* Query callback is used to write wrapped queries. We get rid of `this` from
* knex, since it makes everything confusing.
*/
type QueryCallback = (builder: Builder) => void;
/**
* Shape of the function accepted by the chainable query builder to
* pass lucid query builder to wrapped callbacks like
* `.where(function () {})`.
*
* - This method will accept the wrapped callback
* - Return a new method, that is accepted by Knex.
* - When knex calls that method, this method will invoke the user wrapped
* callback, but instead of passing the knex query builder, it will
* pass the appropriate lucid query builder.
*/
type DBQueryCallback = (userFn: QueryCallback, keysResolver?: (columnName: string) => string) => (builder: Knex.QueryBuilder) => void;
/**
* Possible signatures for a select method on database query builder.
*/
interface DatabaseQueryBuilderSelect {
/**
* Selecting columns as a dictionary with key as the alias and value is
* the original column.
*/
(columns: Dictionary): Builder;
/**
* An array of values with subqueries
*/
(columns: ValueWithSubQueries[]): Builder;
/**
* A spread of array arguments
*/
(...columns: ValueWithSubQueries[]): Builder;
/**
* Wildcard selector.
*/
(column: '*'): Builder;
}
/**
* Possible signatures for adding a where clause
*/
interface Where {
/**
* Callback for wrapped clauses
*/
(callback: QueryCallback): Builder;
/**
* Passing an object of named key-value pair
*/
(clause: Dictionary): Builder;
/**
* Key-value pair. The value can also be a subquery
*/
(key: string | RawQuery, value: StrictValues | ChainableContract): Builder;
(key: string | RawQuery, operator: string, value: StrictValues | ChainableContract): Builder;
}
/**
* Possible signatures for adding a where column clause
*/
interface WhereColumn {
/**
* Key-value pair.
*/
(column: string | RawQuery, comparisonColumn: string): Builder;
(column: string | RawQuery, operator: string, comparisonColumn: string): Builder;
}
/**
* Possible signatures for adding where in clause.
*/
interface WhereIn {
/**
* Column name and array of values
*/
(K: string | RawQuery, value: StrictValues[]): Builder;
/**
* Column names and array of values as an 2d array
*/
(K: string[], value: StrictValues[][]): Builder;
/**
* Column name with a subquery for a callback that yields an array of
* results
*/
(k: string | RawQuery, subquery: ChainableContract | QueryCallback | RawBuilderContract | RawQuery): Builder;
/**
* Column names along with a subquery that yields an array
*/
(k: string[], subquery: ChainableContract | RawBuilderContract | RawQuery): Builder;
}
/**
* Possible signatures for adding whereNull clause.
*/
interface WhereNull {
(key: string | RawQuery): Builder;
}
/**
* Possibles signatures for adding a where exists clause
*/
interface WhereExists {
(callback: QueryCallback | ChainableContract | RawBuilderContract | RawQuery): Builder;
}
/**
* Possibles signatures for adding a where between clause
*/
interface WhereBetween {
/**
* Accept any string as a key for supporting prefix columns
*/
(key: string | RawQuery, value: [StrictValues | ChainableContract, StrictValues | ChainableContract]): Builder;
}
/**
* Possible signatures for join query
*/
interface Join {
/**
* Defining the join table with primary and secondary columns
* to match
*/
(table: string, primaryColumn: string, secondaryColumn: string): Builder;
/**
* Defining the join table with primary and secondary columns
* to match, where secondary column is output of a raw query
*/
(table: string, primaryColumn: string, raw: RawQuery): Builder;
/**
* Defining the join table with primary and secondary columns
* to match with a custom operator
*/
(table: string, primaryColumn: string, operator: string, secondaryColumn: string): Builder;
/**
* Join with a callback. The callback receives an array of join class from
* knex directly.
*/
(table: string, callback: Knex.JoinCallback): Builder;
}
/**
* Possible signatures for a distinct clause
*/
interface Distinct {
(columns: string[]): Builder;
(...columns: string[]): Builder;
(column: '*'): Builder;
}
/**
* The signatures are same as the `distinct` method. For subqueries and
* raw queries, one must use `groupByRaw`.
*/
interface GroupBy extends Distinct {
}
/**
* Possible signatures for aggregate functions. Aggregates will push to the
* result set. Unlike knex, we force defining aliases for each aggregate.
*/
interface Aggregate {
/**
* Accepting column with the alias for the count.
*/
(column: OneOrMany>, alias?: string): Builder;
/**
* Accepting an object for multiple counts in a single query.
*/
(columns: Dictionary>, string>): Builder;
}
/**
* Possible signatures for orderBy method.
*/
interface OrderBy {
/**
* Order by a column and optional direction
*/
(column: string | ChainableContract | RawBuilderContract | RawQuery, direction?: 'asc' | 'desc'): Builder;
/**
* Order by multiple columns in default direction
*/
(columns: string[]): Builder;
/**
* Order by multiple columns and custom direction for each of them
*/
(columns: {
column: string | ChainableContract | RawBuilderContract | RawQuery;
order?: 'asc' | 'desc';
}[]): Builder;
}
/**
* Possible signatures for a union clause
*/
interface Union {
(callback: OneOrMany>, wrap?: boolean): Builder;
(subquery: OneOrMany, wrap?: boolean): Builder;
}
/**
* Same signature as union
*/
interface UnionAll extends Union {
}
/**
* Same signature as union
*/
interface Intersect extends Union {
}
/**
* Possible signatures for having clause
*/
interface Having {
/**
* A subquery callback
*/
(callback: QueryCallback | RawBuilderContract | RawQuery): Builder;
/**
* Key operator and value. Value can be a subquery as well
*/
(key: string | RawQuery, operator: string, value: StrictValues | ChainableContract | RawBuilderContract | RawQuery): Builder;
}
/**
* Possible signatures for `having in` clause.
*/
interface HavingIn {
/**
* Key and an array of literal values, raw queries or
* subqueries.
*/
(key: string | RawQuery, value: (StrictValues | ChainableContract | RawBuilderContract | RawQuery)[]): Builder;
/**
* Key, along with a query callback
*/
(key: string | RawQuery, callback: QueryCallback): Builder;
}
/**
* Possible signatures for `having null` clause
*/
interface HavingNull extends WhereNull {
}
/**
* Possible signatures for `having exists` clause
*/
interface HavingExists {
/**
* A query callback or a sub query
*/
(callback: QueryCallback | ChainableContract): Builder;
}
/**
* Possible signatures for having between
*/
interface HavingBetween extends WhereBetween {
}
/**
* Possible signatures of `with` CTE
*/
interface With {
(alias: string, query: RawQuery | ChainableContract | QueryCallback): Builder;
}
/**
* Possible signatures for defining table for a select query.
*/
interface FromTable {
(table: string | Dictionary | QueryCallback | ChainableContract): Builder;
}
/**
* Possible signatures for the `returning` method.
*/
interface Returning {
(column: OneOrMany): Builder;
}
/**
* Possible signatures for performing an update
*/
interface Update {
/**
* Accepts an array of object of named key/value pair and returns an array
* of Generic return columns.
*/
(values: Dictionary, returning?: OneOrMany): Builder;
/**
* Accepts a key-value pair to update.
*/
(column: string, value: any, returning?: OneOrMany): Builder;
}
/**
* Possible signatures for incrementing/decrementing
* values
*/
interface Counter {
(column: string, counter?: number): Builder;
(values: Dictionary): Builder;
}
/**
* Possible signatures for an insert query
*/
interface Insert {
(values: Dictionary): Builder;
}
/**
* Possible signatures for doing multiple inserts in a single query
*/
interface MultiInsert {
(values: Dictionary[]): Builder;
}
/**
* The chainable contract has all the methods that can be chained
* to build a query. This interface will never have any
* methods to execute a query.
*/
interface ChainableContract {
knexQuery: Knex.QueryBuilder;
columns: (string | Knex.QueryBuilder | Knex.RawQueryBuilder)[];
subQueryAlias?: string;
hasAggregates: boolean;
hasGroupBy: boolean;
hasUnion: boolean;
keysResolver?: (columnName: string) => string;
from: FromTable;
select: DatabaseQueryBuilderSelect;
wrapExisting(): this;
where: Where;
orWhere: Where;
andWhere: Where;
whereNot: Where;
orWhereNot: Where;
andWhereNot: Where;
whereColumn: WhereColumn;
orWhereColumn: WhereColumn;
andWhereColumn: WhereColumn;
whereNotColumn: WhereColumn;
orWhereNotColumn: WhereColumn;
andWhereNotColumn: WhereColumn;
whereIn: WhereIn;
orWhereIn: WhereIn;
andWhereIn: WhereIn;
whereNotIn: WhereIn;
orWhereNotIn: WhereIn;
andWhereNotIn: WhereIn;
whereNull: WhereNull;
orWhereNull: WhereNull;
andWhereNull: WhereNull;
whereNotNull: WhereNull;
orWhereNotNull: WhereNull;
andWhereNotNull: WhereNull;
whereExists: WhereExists;
orWhereExists: WhereExists;
andWhereExists: WhereExists;
whereNotExists: WhereExists;
orWhereNotExists: WhereExists;
andWhereNotExists: WhereExists;
whereBetween: WhereBetween;
orWhereBetween: WhereBetween;
andWhereBetween: WhereBetween;
whereNotBetween: WhereBetween;
orWhereNotBetween: WhereBetween;
andWhereNotBetween: WhereBetween;
whereRaw: RawQueryFn;
orWhereRaw: RawQueryFn;
andWhereRaw: RawQueryFn;
join: Join;
innerJoin: Join;
leftJoin: Join;
leftOuterJoin: Join;
rightJoin: Join;
rightOuterJoin: Join;
fullOuterJoin: Join;
crossJoin: Join;
joinRaw: RawQueryFn;
having: Having;
orHaving: Having;
andHaving: Having;
havingIn: HavingIn;
orHavingIn: HavingIn;
andHavingIn: HavingIn;
havingNotIn: HavingIn;
orHavingNotIn: HavingIn;
andHavingNotIn: HavingIn;
havingNull: HavingNull;
orHavingNull: HavingNull;
andHavingNull: HavingNull;
havingNotNull: HavingNull;
orHavingNotNull: HavingNull;
andHavingNotNull: HavingNull;
havingExists: HavingExists;
orHavingExists: HavingExists;
andHavingExists: HavingExists;
havingNotExists: HavingExists;
orHavingNotExists: HavingExists;
andHavingNotExists: HavingExists;
havingBetween: HavingBetween;
orHavingBetween: HavingBetween;
andHavingBetween: HavingBetween;
havingNotBetween: HavingBetween;
orHavingNotBetween: HavingBetween;
andHavingNotBetween: HavingBetween;
havingRaw: RawQueryFn;
orHavingRaw: RawQueryFn;
andHavingRaw: RawQueryFn;
distinct: Distinct;
distinctOn: Distinct;
groupBy: GroupBy;
groupByRaw: RawQueryFn;
orderBy: OrderBy;
orderByRaw: RawQueryFn;
union: Union;
unionAll: UnionAll;
intersect: Intersect;
with: With;
withRecursive: With;
withSchema(schema: string): this;
as(name: string): this;
offset(offset: number): this;
limit(limit: number): this;
clearSelect(): this;
clearWhere(): this;
clearOrder(): this;
clearHaving(): this;
clearLimit(): this;
clearOffset(): this;
forUpdate(...tableNames: string[]): this;
forShare(...tableNames: string[]): this;
skipLocked(): this;
noWait(): this;
/**
* Executes the callback when condition is truthy
*/
if(condition: any, matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Executes the callback when condition is falsy
*/
unless(condition: any, matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Write blocks to match from
*/
match(...blocks: ([condition: any, callback: (query: this) => any] | ((query: this) => any))[]): this;
}
/**
* Shape of the raw query that can also be passed as a value to
* other queries
*/
interface RawQueryBuilderContract extends ExcutableQueryBuilderContract {
knexQuery: Knex.Raw;
client: QueryClientContract;
wrap(before: string, after: string): this;
}
/**
* Reference builder
*/
interface ReferenceBuilderContract {
withSchema(name: string): this;
as(name: string): this;
toKnex(client: Knex.Client): Knex.Ref;
}
/**
* Static raw builder
*/
interface RawBuilderContract {
wrap(before: string, after: string): this;
toKnex(client: Knex.Client): Knex.Raw;
}
/**
* The keys for the simple paginator meta
* data
*/
type SimplePaginatorMetaKeys = {
total: string;
perPage: string;
currentPage: string;
lastPage: string;
firstPage: string;
firstPageUrl: string;
lastPageUrl: string;
nextPageUrl: string;
previousPageUrl: string;
};
/**
* Shape of the simple paginator that works with offset and limit
*/
interface SimplePaginatorContract extends Array {
all(): Result[];
readonly firstPage: number;
readonly perPage: number;
readonly currentPage: number;
readonly lastPage: number;
readonly hasPages: boolean;
readonly hasMorePages: boolean;
readonly isEmpty: boolean;
readonly total: number;
readonly hasTotal: boolean;
namingStrategy: {
paginationMetaKeys(): SimplePaginatorMetaKeys;
};
baseUrl(url: string): this;
queryString(values: {
[key: string]: any;
}): this;
getUrl(page: number): string;
getMeta(): any;
getNextPageUrl(): string | null;
getPreviousPageUrl(): string | null;
getUrlsForRange(start: number, end: number): {
url: string;
page: number;
isActive: boolean;
}[];
toJSON(): {
meta: any;
data: Result[];
};
}
/**
* Database query builder exposes the API to construct SQL query using fluent
* chainable API
*/
interface DatabaseQueryBuilderContract> extends ChainableContract, ExcutableQueryBuilderContract {
client: QueryClientContract;
returning: Returning;
/**
* Clone current query
*/
clone(): DatabaseQueryBuilderContract;
/**
* Execute and get first result
*/
first(): Promise;
/**
* Execute and get first result or fail
*/
firstOrFail(): Promise;
/**
* Perform delete operation
*/
del(returning?: OneOrMany): this;
delete(returning?: OneOrMany): this;
/**
* A shorthand to define limit and offset based upon the
* current page
*/
forPage(page: number, perPage?: number): this;
/**
* Execute query with pagination
*/
paginate(page: number, perPage?: number): Promise>;
/**
* Mutations (update and increment can be one query aswell)
*/
update: Update;
increment: Counter;
decrement: Counter;
/**
* Aggregates
*/
count: Aggregate;
countDistinct: Aggregate;
min: Aggregate;
max: Aggregate;
sum: Aggregate;
sumDistinct: Aggregate;
avg: Aggregate;
avgDistinct: Aggregate;
/**
* Executes the callback when dialect matches one of the mentioned
* dialects
*/
ifDialect(dialect: DialectContract['name'] | DialectContract['name'][], matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Executes the callback when dialect matches doesn't all the mentioned
* dialects
*/
unlessDialect(dialect: DialectContract['name'] | DialectContract['name'][], matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
}
/**
* Insert query builder to perform database inserts.
*/
interface InsertQueryBuilderContract extends ExcutableQueryBuilderContract {
knexQuery: Knex.QueryBuilder;
client: QueryClientContract;
/**
* Table for the insert query
*/
table(table: string): this;
withSchema(schema: string): this;
/**
* Define returning columns
*/
returning: Returning;
/**
* Inserting a single record.
*/
insert: Insert;
/**
* Inserting multiple columns at once
*/
multiInsert: MultiInsert;
}
/**
* A executable query builder will always have these methods on it.
*/
interface ExcutableQueryBuilderContract extends Promise {
debug(debug: boolean): this;
timeout(time: number, options?: {
cancel: boolean;
}): this;
useTransaction(trx: TransactionClientContract): this;
reporterData(data: any): this;
toQuery(): string;
exec(): Promise;
toSQL(): Knex.Sql;
}
}