/// 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; } }