This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
@@ -0,0 +1,106 @@
import { SimplePaginatorContract, SimplePaginatorMetaKeys } from '@ioc:Adonis/Lucid/Database';
/**
* Simple paginator works with the data set provided by the standard
* `offset` and `limit` based pagination.
*/
export declare class SimplePaginator extends Array implements SimplePaginatorContract<any> {
private totalNumber;
readonly perPage: number;
readonly currentPage: number;
private qs;
private url;
private rows;
/**
* Naming strategy for the pagination meta keys
*/
static namingStrategy: {
paginationMetaKeys(): SimplePaginatorMetaKeys;
};
/**
* Can be defined at per instance level as well
*/
namingStrategy: {
paginationMetaKeys(): SimplePaginatorMetaKeys;
};
/**
* The first page is always 1
*/
readonly firstPage: number;
/**
* Find if results set is empty or not
*/
readonly isEmpty: boolean;
/**
* Casting `total` to a number. Later, we can think of situations
* to cast it to a bigint
*/
readonly total: number;
/**
* Find if there are total records or not. This is not same as
* `isEmpty`.
*
* The `isEmpty` reports about the current set of results. However `hasTotal`
* reports about the total number of records, regardless of the current.
*/
readonly hasTotal: boolean;
/**
* The Last page number
*/
readonly lastPage: number;
/**
* Find if there are more pages to come
*/
readonly hasMorePages: boolean;
/**
* Find if there are enough results to be paginated or not
*/
readonly hasPages: boolean;
constructor(totalNumber: number, perPage: number, currentPage: number, ...rows: any[]);
/**
* A reference to the result rows
*/
all(): any[];
/**
* Returns JSON meta data
*/
getMeta(): any;
/**
* Returns JSON representation of the paginated
* data
*/
toJSON(): {
meta: any;
data: any[];
};
/**
* Define query string to be appended to the pagination links
*/
queryString(values: {
[key: string]: any;
}): this;
/**
* Define base url for making the pagination links
*/
baseUrl(url: string): this;
/**
* Returns url for a given page. Doesn't validates the integrity of the
* page
*/
getUrl(page: number): string;
/**
* Returns url for the next page
*/
getNextPageUrl(): string | null;
/**
* Returns URL for the previous page
*/
getPreviousPageUrl(): string | null;
/**
* Returns an array of urls under a given range
*/
getUrlsForRange(start: number, end: number): {
url: string;
page: number;
isActive: boolean;
}[];
}
@@ -0,0 +1,230 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SimplePaginator = void 0;
const qs_1 = require("qs");
const SnakeCase_1 = require("../../Orm/NamingStrategies/SnakeCase");
/**
* Simple paginator works with the data set provided by the standard
* `offset` and `limit` based pagination.
*/
class SimplePaginator extends Array {
constructor(totalNumber, perPage, currentPage, ...rows) {
super(...rows);
Object.defineProperty(this, "totalNumber", {
enumerable: true,
configurable: true,
writable: true,
value: totalNumber
});
Object.defineProperty(this, "perPage", {
enumerable: true,
configurable: true,
writable: true,
value: perPage
});
Object.defineProperty(this, "currentPage", {
enumerable: true,
configurable: true,
writable: true,
value: currentPage
});
Object.defineProperty(this, "qs", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(this, "url", {
enumerable: true,
configurable: true,
writable: true,
value: '/'
});
Object.defineProperty(this, "rows", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* Can be defined at per instance level as well
*/
Object.defineProperty(this, "namingStrategy", {
enumerable: true,
configurable: true,
writable: true,
value: SimplePaginator.namingStrategy
});
/**
* The first page is always 1
*/
Object.defineProperty(this, "firstPage", {
enumerable: true,
configurable: true,
writable: true,
value: 1
});
/**
* Find if results set is empty or not
*/
Object.defineProperty(this, "isEmpty", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* Casting `total` to a number. Later, we can think of situations
* to cast it to a bigint
*/
Object.defineProperty(this, "total", {
enumerable: true,
configurable: true,
writable: true,
value: Number(this.totalNumber)
});
/**
* Find if there are total records or not. This is not same as
* `isEmpty`.
*
* The `isEmpty` reports about the current set of results. However `hasTotal`
* reports about the total number of records, regardless of the current.
*/
Object.defineProperty(this, "hasTotal", {
enumerable: true,
configurable: true,
writable: true,
value: this.total > 0
});
/**
* The Last page number
*/
Object.defineProperty(this, "lastPage", {
enumerable: true,
configurable: true,
writable: true,
value: Math.max(Math.ceil(this.total / this.perPage), 1)
});
/**
* Find if there are more pages to come
*/
Object.defineProperty(this, "hasMorePages", {
enumerable: true,
configurable: true,
writable: true,
value: this.lastPage > this.currentPage
});
/**
* Find if there are enough results to be paginated or not
*/
Object.defineProperty(this, "hasPages", {
enumerable: true,
configurable: true,
writable: true,
value: this.lastPage !== 1
});
this.rows = rows;
this.isEmpty = this.rows.length === 0;
}
/**
* A reference to the result rows
*/
all() {
return this.rows;
}
/**
* Returns JSON meta data
*/
getMeta() {
const metaKeys = this.namingStrategy.paginationMetaKeys();
return {
[metaKeys.total]: this.total,
[metaKeys.perPage]: this.perPage,
[metaKeys.currentPage]: this.currentPage,
[metaKeys.lastPage]: this.lastPage,
[metaKeys.firstPage]: this.firstPage,
[metaKeys.firstPageUrl]: this.getUrl(1),
[metaKeys.lastPageUrl]: this.getUrl(this.lastPage),
[metaKeys.nextPageUrl]: this.getNextPageUrl(),
[metaKeys.previousPageUrl]: this.getPreviousPageUrl(),
};
}
/**
* Returns JSON representation of the paginated
* data
*/
toJSON() {
return {
meta: this.getMeta(),
data: this.all(),
};
}
/**
* Define query string to be appended to the pagination links
*/
queryString(values) {
this.qs = values;
return this;
}
/**
* Define base url for making the pagination links
*/
baseUrl(url) {
this.url = url;
return this;
}
/**
* Returns url for a given page. Doesn't validates the integrity of the
* page
*/
getUrl(page) {
const qs = (0, qs_1.stringify)(Object.assign({}, this.qs, { page: page < 1 ? 1 : page }));
return `${this.url}?${qs}`;
}
/**
* Returns url for the next page
*/
getNextPageUrl() {
if (this.hasMorePages) {
return this.getUrl(this.currentPage + 1);
}
return null;
}
/**
* Returns URL for the previous page
*/
getPreviousPageUrl() {
if (this.currentPage > 1) {
return this.getUrl(this.currentPage - 1);
}
return null;
}
/**
* Returns an array of urls under a given range
*/
getUrlsForRange(start, end) {
let urls = [];
for (let i = start; i <= end; i++) {
urls.push({ url: this.getUrl(i), page: i, isActive: i === this.currentPage });
}
return urls;
}
}
exports.SimplePaginator = SimplePaginator;
/**
* Naming strategy for the pagination meta keys
*/
Object.defineProperty(SimplePaginator, "namingStrategy", {
enumerable: true,
configurable: true,
writable: true,
value: new SnakeCase_1.SnakeCaseNamingStrategy()
});
@@ -0,0 +1,721 @@
/// <reference path="../../../adonis-typings/index.d.ts" />
import { Knex } from 'knex';
import { Macroable } from 'macroable';
import { ChainableContract, DBQueryCallback } from '@ioc:Adonis/Lucid/Database';
/**
* The chainable query builder to consturct SQL queries for selecting, updating and
* deleting records.
*
* The API internally uses the knex query builder. However, many of methods may have
* different API.
*/
export declare abstract class Chainable extends Macroable implements ChainableContract {
knexQuery: Knex.QueryBuilder;
private queryCallback;
keysResolver?: ((columnName: string) => string) | undefined;
hasAggregates: boolean;
hasGroupBy: boolean;
hasUnion: boolean;
/**
* Collection where clauses in a 2nd array. Calling `wrapExisting`
* adds a new stack item
*/
private whereStack;
/**
* Returns the recent most array from the where stack
*/
private getRecentStackItem;
/**
* Returns the wrapping method for a given where method
*/
private getWrappingMethod;
/**
* Applies the where clauses
*/
protected applyWhere(): void;
/**
* An array of selected columns
*/
get columns(): ChainableContract['columns'];
/**
* Custom alias for the query results. Ignored if it not a
* subquery
*/
subQueryAlias?: string;
constructor(knexQuery: Knex.QueryBuilder, queryCallback: DBQueryCallback, keysResolver?: ((columnName: string) => string) | undefined);
/**
* Raises exception when only one argument is passed to a where
* clause and it is a string. It means the value is undefined
*/
private validateWhereSingleArgument;
/**
* Returns the value pair for the `whereBetween` clause
*/
private getBetweenPair;
/**
* Normalizes the columns aggregates functions to something
* knex can process.
*/
private normalizeAggregateColumns;
/**
* Resolves the column name considering raw queries as well.
*/
private resolveColumn;
/**
* Resolves column names
*/
protected resolveKey(columns: any, checkForObject?: boolean, returnValue?: any): any;
/**
* Apply existing query flags to a new query builder. This is
* done during clone operation
*/
protected applyQueryFlags(query: Chainable): void;
/**
* Transforms the value to something that knex can internally understand and
* handle. It includes.
*
* 1. Returning the `knexBuilder` for sub queries.
* 2. Returning the `knex.refBuilder` for reference builder.
* 2. Returning the `knexBuilder` for raw queries.
* 3. Wrapping callbacks, so that the end user receives an instance Lucid query
* builder and not knex query builder.
*/
protected transformValue(value: any): any;
/**
* Transforms the user callback to something that knex
* can internally process
*/
protected transformCallback(value: any): any;
/**
* Returns the underlying knex raw query builder for Lucid raw
* query builder
*/
protected transformRaw(value: any): any;
/**
* Define columns for selection
*/
select(...args: any[]): this;
/**
* Select table for the query. Re-calling this method multiple times will
* use the last selected table
*/
from(table: any): this;
/**
* Wrap existing where clauses to its own group
*/
wrapExisting(): this;
/**
* Add a `where` clause
*/
where(key: any, operator?: any, value?: any): this;
/**
* Add a `or where` clause
*/
orWhere(key: any, operator?: any, value?: any): this;
/**
* Alias for `where`
*/
andWhere(key: any, operator?: any, value?: any): this;
/**
* Adding `where not` clause
*/
whereNot(key: any, operator?: any, value?: any): this;
/**
* Adding `or where not` clause
*/
orWhereNot(key: any, operator?: any, value?: any): this;
/**
* Alias for [[whereNot]]
*/
andWhereNot(key: any, operator?: any, value?: any): this;
/**
* Add a where clause on a given column
*/
whereColumn(column: any, operator: any, comparisonColumn?: any): this;
/**
* Add a orWhere clause on a given column
*/
orWhereColumn(column: any, operator: any, comparisonColumn?: any): this;
/**
* Alias for whereColumn
*/
andWhereColumn(column: any, operator: any, comparisonColumn?: any): this;
/**
* Add a whereNot clause on a given column
*/
whereNotColumn(column: any, operator: any, comparisonColumn?: any): this;
/**
* Add a orWhereNotColumn clause on a given column
*/
orWhereNotColumn(column: any, operator: any, comparisonColumn?: any): this;
/**
* Alias for whereNotColumn
*/
andWhereNotColumn(column: any, operator: any, comparisonColumn?: any): this;
/**
* Adding a `where in` clause
*/
whereIn(columns: any, value: any): this;
/**
* Adding a `or where in` clause
*/
orWhereIn(columns: any, value: any): this;
/**
* Alias for [[whereIn]]
*/
andWhereIn(key: any, value: any): this;
/**
* Adding a `where not in` clause
*/
whereNotIn(columns: any, value: any): this;
/**
* Adding a `or where not in` clause
*/
orWhereNotIn(columns: any, value: any): this;
/**
* Alias for [[whereNotIn]]
*/
andWhereNotIn(key: any, value: any): this;
/**
* Adding `where not null` clause
*/
whereNull(key: any): this;
/**
* Adding `or where not null` clause
*/
orWhereNull(key: any): this;
/**
* Alias for [[whereNull]]
*/
andWhereNull(key: any): this;
/**
* Adding `where not null` clause
*/
whereNotNull(key: any): this;
/**
* Adding `or where not null` clause
*/
orWhereNotNull(key: any): this;
/**
* Alias for [[whereNotNull]]
*/
andWhereNotNull(key: any): this;
/**
* Add a `where exists` clause
*/
whereExists(value: any): this;
/**
* Add a `or where exists` clause
*/
orWhereExists(value: any): this;
/**
* Alias for [[whereExists]]
*/
andWhereExists(value: any): this;
/**
* Add a `where not exists` clause
*/
whereNotExists(value: any): this;
/**
* Add a `or where not exists` clause
*/
orWhereNotExists(value: any): this;
/**
* Alias for [[whereNotExists]]
*/
andWhereNotExists(value: any): this;
/**
* Add where between clause
*/
whereBetween(key: any, value: [any, any]): this;
/**
* Add where between clause
*/
orWhereBetween(key: any, value: any): this;
/**
* Alias for [[whereBetween]]
*/
andWhereBetween(key: any, value: any): this;
/**
* Add where between clause
*/
whereNotBetween(key: any, value: any): this;
/**
* Add where between clause
*/
orWhereNotBetween(key: any, value: any): this;
/**
* Alias for [[whereNotBetween]]
*/
andWhereNotBetween(key: any, value: any): this;
/**
* Adding a where clause using raw sql
*/
whereRaw(sql: any, bindings?: any): this;
/**
* Adding a or where clause using raw sql
*/
orWhereRaw(sql: any, bindings?: any): this;
/**
* Alias for [[whereRaw]]
*/
andWhereRaw(sql: any, bindings?: any): this;
/**
* Add a `where like` clause
*/
whereLike(key: any, value: any): this;
/**
* Add a `where like` clause
*/
orWhereLike(key: any, value?: any): this;
/**
* Add a `where like` clause
*/
andWhereLike(key: any, value?: any): this;
/**
* Add a `where like` clause
*/
whereILike(key: any, value?: any): this;
/**
* Add a `where like` clause
*/
orWhereILike(key: any, value?: any): this;
/**
* Add a `where like` clause
*/
andWhereILike(key: any, value?: any): this;
/**
* Define a where clause with value that matches for JSON
*/
whereJson(column: string, value: any): this;
/**
* Define a or where clause with value that matches for JSON
*/
orWhereJson(column: string, value: any): this;
/**
* Define a where clause with value that matches for JSON
*
* @alias whereJson
*/
andWhereJson(column: string, value: any): this;
/**
* Define a where clause with value that matches for JSON
*/
whereNotJson(column: string, value: any): this;
/**
* Define a or where clause with value that matches for JSON
*/
orWhereNotJson(column: string, value: any): this;
/**
* Define a where clause with value that matches for JSON
*
* @alias whereNotJson
*/
andWhereNotJson(column: string, value: any): this;
/**
* Define a where clause with value that matches for a superset of
* JSON
*/
whereJsonSuperset(column: string, value: any): this;
/**
* Define a or where clause with value that matches for a superset of
* JSON
*/
orWhereJsonSuperset(column: string, value: any): this;
/**
* Define or where clause with value that matches for a superset of
* JSON
*
* @alias whereJsonSuperset
*/
andWhereJsonSuperset(column: string, value: any): this;
/**
* Define a where clause with value that matches for a superset of
* JSON
*/
whereNotJsonSuperset(column: string, value: any): this;
/**
* Define a or where clause with value that matches for a superset of
* JSON
*/
orWhereNotJsonSuperset(column: string, value: any): this;
/**
* Define or where clause with value that matches for a superset of
* JSON
*
* @alias whereNotJsonSuperset
*/
andWhereNotJsonSuperset(column: string, value: any): this;
/**
* Define a where clause with value that matches for a subset of
* JSON
*/
whereJsonSubset(column: string, value: any): this;
/**
* Define a or where clause with value that matches for a subset of
* JSON
*/
orWhereJsonSubset(column: string, value: any): this;
/**
* Define or where clause with value that matches for a subset of
* JSON
*
* @alias whereJsonSubset
*/
andWhereJsonSubset(column: string, value: any): this;
/**
* Define a where clause with value that matches for a subset of
* JSON
*/
whereNotJsonSubset(column: string, value: any): this;
/**
* Define a or where clause with value that matches for a subset of
* JSON
*/
orWhereNotJsonSubset(column: string, value: any): this;
/**
* Define or where clause with value that matches for a subset of
* JSON
*
* @alias whereNotJsonSubset
*/
andWhereNotJsonSubset(column: string, value: any): this;
/**
* Adds a where clause with comparison of a value returned
* by a JsonPath given an operator and a value.
*/
whereJsonPath(column: string, jsonPath: string, operator: any, value?: any): this;
/**
* Adds a or where clause with comparison of a value returned
* by a JsonPath given an operator and a value.
*/
orWhereJsonPath(column: string, jsonPath: string, operator: any, value?: any): this;
/**
* Adds a where clause with comparison of a value returned
* by a JsonPath given an operator and a value.
*
* @alias whereJsonPath
*/
andWhereJsonPath(column: string, jsonPath: string, operator: any, value?: any): this;
/**
* Add a join clause
*/
join(table: any, first: any, operator?: any, second?: any): this;
/**
* Add an inner join clause
*/
innerJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add a left join clause
*/
leftJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add a left outer join clause
*/
leftOuterJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add a right join clause
*/
rightJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add a right outer join clause
*/
rightOuterJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add a full outer join clause
*/
fullOuterJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add a cross join clause
*/
crossJoin(table: any, first: any, operator?: any, second?: any): this;
/**
* Add join clause as a raw query
*/
joinRaw(sql: any, bindings?: any): this;
/**
* Adds a having clause. The having clause breaks for `postgreSQL` when
* referencing alias columns, since PG doesn't support alias columns
* being referred within `having` clause. The end user has to
* use raw queries in this case.
*/
having(key: any, operator?: any, value?: any): this;
/**
* Adds or having clause. The having clause breaks for `postgreSQL` when
* referencing alias columns, since PG doesn't support alias columns
* being referred within `having` clause. The end user has to
* use raw queries in this case.
*/
orHaving(key: any, operator?: any, value?: any): this;
/**
* Alias for [[having]]
*/
andHaving(key: any, operator?: any, value?: any): this;
/**
* Adding having in clause to the query
*/
havingIn(key: any, value: any): this;
/**
* Adding or having in clause to the query
*/
orHavingIn(key: any, value: any): this;
/**
* Alias for [[havingIn]]
*/
andHavingIn(key: any, value: any): this;
/**
* Adding having not in clause to the query
*/
havingNotIn(key: any, value: any): this;
/**
* Adding or having not in clause to the query
*/
orHavingNotIn(key: any, value: any): this;
/**
* Alias for [[havingNotIn]]
*/
andHavingNotIn(key: any, value: any): this;
/**
* Adding having null clause
*/
havingNull(key: any): this;
/**
* Adding or having null clause
*/
orHavingNull(key: any): this;
/**
* Alias for [[havingNull]] clause
*/
andHavingNull(key: any): this;
/**
* Adding having not null clause
*/
havingNotNull(key: any): this;
/**
* Adding or having not null clause
*/
orHavingNotNull(key: any): this;
/**
* Alias for [[havingNotNull]] clause
*/
andHavingNotNull(key: any): this;
/**
* Adding `having exists` clause
*/
havingExists(value: any): this;
/**
* Adding `or having exists` clause
*/
orHavingExists(value: any): this;
/**
* Alias for [[havingExists]]
*/
andHavingExists(value: any): this;
/**
* Adding `having not exists` clause
*/
havingNotExists(value: any): this;
/**
* Adding `or having not exists` clause
*/
orHavingNotExists(value: any): this;
/**
* Alias for [[havingNotExists]]
*/
andHavingNotExists(value: any): this;
/**
* Adding `having between` clause
*/
havingBetween(key: any, value: any): this;
/**
* Adding `or having between` clause
*/
orHavingBetween(key: any, value: any): this;
/**
* Alias for [[havingBetween]]
*/
andHavingBetween(key: any, value: any): this;
/**
* Adding `having not between` clause
*/
havingNotBetween(key: any, value: any): this;
/**
* Adding `or having not between` clause
*/
orHavingNotBetween(key: any, value: any): this;
/**
* Alias for [[havingNotBetween]]
*/
andHavingNotBetween(key: any, value: any): this;
/**
* Adding a where clause using raw sql
*/
havingRaw(sql: any, bindings?: any): this;
/**
* Adding a where clause using raw sql
*/
orHavingRaw(sql: any, bindings?: any): this;
/**
* Alias for [[havingRaw]]
*/
andHavingRaw(sql: any, bindings?: any): this;
/**
* Add distinct clause
*/
distinct(...columns: any[]): this;
/**
* Add distinctOn clause
*/
distinctOn(...columns: any[]): this;
/**
* Add group by clause
*/
groupBy(...columns: any[]): this;
/**
* Add group by clause as a raw query
*/
groupByRaw(sql: any, bindings?: any): this;
/**
* Add order by clause
*/
orderBy(column: any, direction?: any): this;
/**
* Add order by clause as a raw query
*/
orderByRaw(sql: any, bindings?: any): this;
/**
* Define select offset
*/
offset(value: number): this;
/**
* Define results limit
*/
limit(value: number): this;
/**
* Define union queries
*/
union(queries: any, wrap?: boolean): this;
/**
* Define union all queries
*/
unionAll(queries: any, wrap?: boolean): this;
/**
* Define intersect queries
*/
intersect(queries: any, wrap?: boolean): this;
/**
* Clear select columns
*/
clearSelect(): this;
/**
* Clear where clauses
*/
clearWhere(): this;
/**
* Clear order by
*/
clearOrder(): this;
/**
* Clear having
*/
clearHaving(): this;
/**
* Clear limit
*/
clearLimit(): this;
/**
* Clear offset
*/
clearOffset(): this;
/**
* Specify `FOR UPDATE` lock mode for a given
* query
*/
forUpdate(...tableNames: string[]): this;
/**
* Specify `FOR SHARE` lock mode for a given
* query
*/
forShare(...tableNames: string[]): this;
/**
* Skip locked rows
*/
skipLocked(): this;
/**
* Fail when query wants a locked row
*/
noWait(): this;
/**
* Define `with` CTE
*/
with(alias: any, query: any, columns?: string[]): this;
/**
* Define `with` CTE with recursive keyword
*/
withRecursive(alias: any, query: any, columns?: string[]): this;
/**
* Define `with materialized` CTE
*/
withMaterialized(alias: any, query: any, columns?: string[]): this;
/**
* Define not `with materialized` CTE
*/
withNotMaterialized(alias: any, query: any, columns?: string[]): this;
/**
* Define schema for the table
*/
withSchema(schema: any): this;
/**
* Define table alias
*/
as(alias: any): this;
/**
* Count rows for the current query
*/
count(columns: any, alias?: any): this;
/**
* Count distinct rows for the current query
*/
countDistinct(columns: any, alias?: any): this;
/**
* Make use of `min` aggregate function
*/
min(columns: any, alias?: any): this;
/**
* Make use of `max` aggregate function
*/
max(columns: any, alias?: any): this;
/**
* Make use of `avg` aggregate function
*/
avg(columns: any, alias?: any): this;
/**
* Make use of distinct `avg` aggregate function
*/
avgDistinct(columns: any, alias?: any): this;
/**
* Make use of `sum` aggregate function
*/
sum(columns: any, alias?: any): this;
/**
* Make use of distinct `sum` aggregate function
*/
sumDistinct(columns: any, alias?: any): this;
/**
* A shorthand for applying offset and limit based upon
* the current page
*/
forPage(page: number, perPage: number): this;
/**
* Define a query to constraint to be defined when condition is truthy
*/
if(condition: any, matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Define a query to constraint to be defined when condition is falsy
*/
unless(condition: any, matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Define matching blocks just like `if/else if and else`.
*/
match(...blocks: ([condition: any, callback: (query: this) => any] | ((query: this) => any))[]): this;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,137 @@
/// <reference path="../../../adonis-typings/index.d.ts" />
import { Knex } from 'knex';
import { DialectContract, QueryClientContract, TransactionClientContract, DatabaseQueryBuilderContract } from '@ioc:Adonis/Lucid/Database';
import { Chainable } from './Chainable';
import { SimplePaginator } from '../Paginator/SimplePaginator';
/**
* Database query builder exposes the API to construct and run queries for selecting,
* updating and deleting records.
*/
export declare class DatabaseQueryBuilder extends Chainable implements DatabaseQueryBuilderContract {
client: QueryClientContract;
keysResolver?: ((columnName: string) => string) | undefined;
/**
* Custom data someone want to send to the profiler and the
* query event
*/
private customReporterData;
/**
* Control whether to debug the query or not. The initial
* value is inherited from the query client
*/
private debugQueries;
/**
* Required by macroable
*/
protected static macros: {};
protected static getters: {};
constructor(builder: Knex.QueryBuilder, client: QueryClientContract, keysResolver?: ((columnName: string) => string) | undefined);
/**
* Ensures that we are not executing `update` or `del` when using read only
* client
*/
private ensureCanPerformWrites;
/**
* Returns the log data
*/
private getQueryData;
/**
* Define custom reporter data. It will be merged with
* the existing data
*/
reporterData(data: any): this;
/**
* Delete rows under the current query
*/
del(returning?: string | string[]): this;
/**
* Alias for [[del]]
*/
delete(returning?: string | string[]): this;
/**
* Clone the current query builder
*/
clone(): DatabaseQueryBuilder;
/**
* Define returning columns
*/
returning(columns: any): this;
/**
* Perform update by incrementing value for a given column. Increments
* can be clubbed with `update` as well
*/
increment(column: any, counter?: any): this;
/**
* Perform update by decrementing value for a given column. Decrements
* can be clubbed with `update` as well
*/
decrement(column: any, counter?: any): this;
/**
* Perform update
*/
update(column: any, value?: any, returning?: string | string[]): this;
/**
* Fetch and return first results from the results set. This method
* will implicitly set a `limit` on the query
*/
first(): Promise<any>;
/**
* Fetch and return first results from the results set. This method
* will implicitly set a `limit` on the query
*/
firstOrFail(): Promise<any>;
/**
* Define a query to constraint to be defined when condition is truthy
*/
ifDialect(dialects: DialectContract['name'] | DialectContract['name'][], matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Define a query to constraint to be defined when condition is falsy
*/
unlessDialect(dialects: DialectContract['name'] | DialectContract['name'][], matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this;
/**
* Turn on/off debugging for this query
*/
debug(debug: boolean): this;
/**
* Define query timeout
*/
timeout(time: number, options?: {
cancel: boolean;
}): this;
/**
* Returns SQL query as a string
*/
toQuery(): string;
/**
* Run query inside the given transaction
*/
useTransaction(transaction: TransactionClientContract): this;
/**
* Executes the query
*/
exec(): Promise<any>;
/**
* Paginate through rows inside a given table
*/
paginate(page: number, perPage?: number): Promise<SimplePaginator>;
/**
* Get sql representation of the query
*/
toSQL(): Knex.Sql;
/**
* Implementation of `then` for the promise API
*/
then(resolve: any, reject?: any): any;
/**
* Implementation of `catch` for the promise API
*/
catch(reject: any): any;
/**
* Implementation of `finally` for the promise API
*/
finally(fullfilled: any): Promise<any>;
/**
* Required when Promises are extended
*/
get [Symbol.toStringTag](): string;
}
@@ -0,0 +1,318 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DatabaseQueryBuilder = void 0;
const utils_1 = require("@poppinss/utils");
const Chainable_1 = require("./Chainable");
const QueryRunner_1 = require("../../QueryRunner");
const SimplePaginator_1 = require("../Paginator/SimplePaginator");
/**
* Wrapping the user function for a query callback and give them
* a new instance of the `DatabaseQueryBuilder` and not
* knex.QueryBuilder
*/
const queryCallback = (userFn, keysResolver) => {
return (builder) => {
/**
* Sub queries don't need the client, since client is used to execute the query
* and subqueries are not executed seperately. That's why we just pass
* an empty object.
*
* Other option is to have this method for each instance of the class, but this
* is waste of resources.
*/
const query = new DatabaseQueryBuilder(builder, {}, keysResolver);
userFn(query);
query['applyWhere']();
};
};
/**
* Database query builder exposes the API to construct and run queries for selecting,
* updating and deleting records.
*/
class DatabaseQueryBuilder extends Chainable_1.Chainable {
constructor(builder, client, keysResolver) {
super(builder, queryCallback, keysResolver);
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: client
});
Object.defineProperty(this, "keysResolver", {
enumerable: true,
configurable: true,
writable: true,
value: keysResolver
});
/**
* Custom data someone want to send to the profiler and the
* query event
*/
Object.defineProperty(this, "customReporterData", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* Control whether to debug the query or not. The initial
* value is inherited from the query client
*/
Object.defineProperty(this, "debugQueries", {
enumerable: true,
configurable: true,
writable: true,
value: this.client.debug
});
}
/**
* Ensures that we are not executing `update` or `del` when using read only
* client
*/
ensureCanPerformWrites() {
if (this.client && this.client.mode === 'read') {
throw new utils_1.Exception('Updates and deletes cannot be performed in read mode');
}
}
/**
* Returns the log data
*/
getQueryData() {
return {
connection: this.client.connectionName,
inTransaction: this.client.isTransaction,
...this.customReporterData,
};
}
/**
* Define custom reporter data. It will be merged with
* the existing data
*/
reporterData(data) {
this.customReporterData = data;
return this;
}
/**
* Delete rows under the current query
*/
del(returning) {
this.ensureCanPerformWrites();
returning ? this.knexQuery.del(returning) : this.knexQuery.del();
return this;
}
/**
* Alias for [[del]]
*/
delete(returning) {
return this.del(returning);
}
/**
* Clone the current query builder
*/
clone() {
const clonedQuery = new DatabaseQueryBuilder(this.knexQuery.clone(), this.client);
this.applyQueryFlags(clonedQuery);
clonedQuery.debug(this.debugQueries);
this.customReporterData && clonedQuery.reporterData(this.customReporterData);
return clonedQuery;
}
/**
* Define returning columns
*/
returning(columns) {
if (this.client.dialect.supportsReturningStatement) {
columns = Array.isArray(columns)
? columns.map((column) => this.resolveKey(column))
: this.resolveKey(columns);
this.knexQuery.returning(columns);
}
return this;
}
/**
* Perform update by incrementing value for a given column. Increments
* can be clubbed with `update` as well
*/
increment(column, counter) {
this.ensureCanPerformWrites();
this.knexQuery.increment(this.resolveKey(column, true), counter);
return this;
}
/**
* Perform update by decrementing value for a given column. Decrements
* can be clubbed with `update` as well
*/
decrement(column, counter) {
this.ensureCanPerformWrites();
this.knexQuery.decrement(this.resolveKey(column, true), counter);
return this;
}
/**
* Perform update
*/
update(column, value, returning) {
this.ensureCanPerformWrites();
if (value === undefined && returning === undefined) {
this.knexQuery.update(this.resolveKey(column, true));
}
else if (returning === undefined) {
this.knexQuery.update(this.resolveKey(column), value);
}
else {
this.knexQuery.update(this.resolveKey(column), value, returning);
}
return this;
}
/**
* Fetch and return first results from the results set. This method
* will implicitly set a `limit` on the query
*/
async first() {
const result = await this.limit(1)['exec']();
return result[0] || null;
}
/**
* Fetch and return first results from the results set. This method
* will implicitly set a `limit` on the query
*/
async firstOrFail() {
const row = await this.first();
if (!row) {
throw new utils_1.Exception('Row not found', 404, 'E_ROW_NOT_FOUND');
}
return row;
}
/**
* Define a query to constraint to be defined when condition is truthy
*/
ifDialect(dialects, matchCallback, noMatchCallback) {
dialects = Array.isArray(dialects) ? dialects : [dialects];
if (dialects.includes(this.client.dialect.name)) {
matchCallback(this);
}
else if (noMatchCallback) {
noMatchCallback(this);
}
return this;
}
/**
* Define a query to constraint to be defined when condition is falsy
*/
unlessDialect(dialects, matchCallback, noMatchCallback) {
dialects = Array.isArray(dialects) ? dialects : [dialects];
if (!dialects.includes(this.client.dialect.name)) {
matchCallback(this);
}
else if (noMatchCallback) {
noMatchCallback(this);
}
return this;
}
/**
* Turn on/off debugging for this query
*/
debug(debug) {
this.debugQueries = debug;
return this;
}
/**
* Define query timeout
*/
timeout(time, options) {
this.knexQuery['timeout'](time, options);
return this;
}
/**
* Returns SQL query as a string
*/
toQuery() {
this.applyWhere();
return this.knexQuery.toQuery();
}
/**
* Run query inside the given transaction
*/
useTransaction(transaction) {
this.knexQuery.transacting(transaction.knexClient);
return this;
}
/**
* Executes the query
*/
async exec() {
this.applyWhere();
return new QueryRunner_1.QueryRunner(this.client, this.debugQueries, this.getQueryData()).run(this.knexQuery);
}
/**
* Paginate through rows inside a given table
*/
async paginate(page, perPage = 20) {
/**
* Cast to number
*/
page = Number(page);
perPage = Number(perPage);
const countQuery = this.client
.query()
.from(this.clone().clearOrder().clearLimit().clearOffset().as('subQuery'))
.count('* as total');
const aggregates = await countQuery.exec();
const total = aggregates[0].total;
const results = total > 0 ? await this.forPage(page, perPage).exec() : [];
return new SimplePaginator_1.SimplePaginator(total, perPage, page, ...results);
}
/**
* Get sql representation of the query
*/
toSQL() {
this.applyWhere();
return this.knexQuery.toSQL();
}
/**
* Implementation of `then` for the promise API
*/
then(resolve, reject) {
return this.exec().then(resolve, reject);
}
/**
* Implementation of `catch` for the promise API
*/
catch(reject) {
return this.exec().catch(reject);
}
/**
* Implementation of `finally` for the promise API
*/
finally(fullfilled) {
return this.exec().finally(fullfilled);
}
/**
* Required when Promises are extended
*/
get [Symbol.toStringTag]() {
return this.constructor.name;
}
}
exports.DatabaseQueryBuilder = DatabaseQueryBuilder;
/**
* Required by macroable
*/
Object.defineProperty(DatabaseQueryBuilder, "macros", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(DatabaseQueryBuilder, "getters", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
@@ -0,0 +1,111 @@
/// <reference path="../../../adonis-typings/index.d.ts" />
import { Knex } from 'knex';
import { Macroable } from 'macroable';
import { QueryClientContract, TransactionClientContract, InsertQueryBuilderContract } from '@ioc:Adonis/Lucid/Database';
/**
* Exposes the API for performing SQL inserts
*/
export declare class InsertQueryBuilder extends Macroable implements InsertQueryBuilderContract {
knexQuery: Knex.QueryBuilder;
client: QueryClientContract;
/**
* Custom data someone want to send to the profiler and the
* query event
*/
private customReporterData;
/**
* Control whether to debug the query or not. The initial
* value is inherited from the query client
*/
private debugQueries;
/**
* Required by macroable
*/
protected static macros: {};
protected static getters: {};
constructor(knexQuery: Knex.QueryBuilder, client: QueryClientContract);
/**
* Returns the log data
*/
private getQueryData;
/**
* Transforms the value to something that knex can internally understand and
* handle. It includes.
*
* 1. Returning the `knexBuilder` for sub queries.
* 2. Returning the `knexBuilder` for raw queries.
*/
protected transformValue(value: any): any;
/**
* Returns the underlying knex raw query builder for Lucid raw
* query builder
*/
protected transformRaw(value: any): any;
/**
* Define custom reporter data. It will be merged with
* the existing data
*/
reporterData(data: any): this;
/**
* Define table for performing the insert query
*/
table(table: any): this;
/**
* Define schema for the table
*/
withSchema(schema: any): this;
/**
* Define returning columns for the insert query
*/
returning(column: any): any;
/**
* Perform insert query
*/
insert(columns: any): this;
/**
* Insert multiple rows in a single query
*/
multiInsert(columns: any): this;
/**
* Turn on/off debugging for this query
*/
debug(debug: boolean): this;
/**
* Define query timeout
*/
timeout(time: number, options?: {
cancel: boolean;
}): this;
/**
* Returns SQL query as a string
*/
toQuery(): string;
/**
* Run query inside the given transaction
*/
useTransaction(transaction: TransactionClientContract): this;
/**
* Executes the query
*/
exec(): Promise<any>;
/**
* Get sql representation of the query
*/
toSQL(): Knex.Sql;
/**
* Implementation of `then` for the promise API
*/
then(resolve: any, reject?: any): any;
/**
* Implementation of `catch` for the promise API
*/
catch(reject: any): any;
/**
* Implementation of `finally` for the promise API
*/
finally(fullfilled: any): Promise<any>;
/**
* Required when Promises are extended
*/
get [Symbol.toStringTag](): string;
}
+231
View File
@@ -0,0 +1,231 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.InsertQueryBuilder = void 0;
const macroable_1 = require("macroable");
const Raw_1 = require("./Raw");
const QueryRunner_1 = require("../../QueryRunner");
const Raw_2 = require("../StaticBuilder/Raw");
const Reference_1 = require("../StaticBuilder/Reference");
/**
* Exposes the API for performing SQL inserts
*/
class InsertQueryBuilder extends macroable_1.Macroable {
constructor(knexQuery, client) {
super();
Object.defineProperty(this, "knexQuery", {
enumerable: true,
configurable: true,
writable: true,
value: knexQuery
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: client
});
/**
* Custom data someone want to send to the profiler and the
* query event
*/
Object.defineProperty(this, "customReporterData", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* Control whether to debug the query or not. The initial
* value is inherited from the query client
*/
Object.defineProperty(this, "debugQueries", {
enumerable: true,
configurable: true,
writable: true,
value: this.client.debug
});
}
/**
* Returns the log data
*/
getQueryData() {
return {
connection: this.client.connectionName,
inTransaction: this.client.isTransaction,
...this.customReporterData,
};
}
/**
* Transforms the value to something that knex can internally understand and
* handle. It includes.
*
* 1. Returning the `knexBuilder` for sub queries.
* 2. Returning the `knexBuilder` for raw queries.
*/
transformValue(value) {
if (value instanceof Reference_1.ReferenceBuilder) {
return value.toKnex(this.knexQuery.client);
}
return this.transformRaw(value);
}
/**
* Returns the underlying knex raw query builder for Lucid raw
* query builder
*/
transformRaw(value) {
if (value instanceof Raw_1.RawQueryBuilder) {
return value['knexQuery'];
}
if (value instanceof Raw_2.RawBuilder) {
return value.toKnex(this.knexQuery.client);
}
return value;
}
/**
* Define custom reporter data. It will be merged with
* the existing data
*/
reporterData(data) {
this.customReporterData = data;
return this;
}
/**
* Define table for performing the insert query
*/
table(table) {
this.knexQuery.table(table);
return this;
}
/**
* Define schema for the table
*/
withSchema(schema) {
this.knexQuery.withSchema(schema);
return this;
}
/**
* Define returning columns for the insert query
*/
returning(column) {
if (this.client.dialect.supportsReturningStatement) {
this.knexQuery.returning(column);
}
return this;
}
/**
* Perform insert query
*/
insert(columns) {
if (columns && Array.isArray(columns)) {
columns = columns.map((column) => {
return column && typeof column === 'object'
? Object.keys(column).reduce((result, key) => {
result[key] = this.transformValue(column[key]);
return result;
}, {})
: column;
});
}
else if (columns && typeof columns === 'object') {
columns = Object.keys(columns).reduce((result, key) => {
result[key] = this.transformValue(columns[key]);
return result;
}, {});
}
this.knexQuery.insert(columns);
return this;
}
/**
* Insert multiple rows in a single query
*/
multiInsert(columns) {
return this.insert(columns);
}
/**
* Turn on/off debugging for this query
*/
debug(debug) {
this.debugQueries = debug;
return this;
}
/**
* Define query timeout
*/
timeout(time, options) {
this.knexQuery['timeout'](time, options);
return this;
}
/**
* Returns SQL query as a string
*/
toQuery() {
return this.knexQuery.toQuery();
}
/**
* Run query inside the given transaction
*/
useTransaction(transaction) {
this.knexQuery.transacting(transaction.knexClient);
return this;
}
/**
* Executes the query
*/
async exec() {
return new QueryRunner_1.QueryRunner(this.client, this.debugQueries, this.getQueryData()).run(this.knexQuery);
}
/**
* Get sql representation of the query
*/
toSQL() {
return this.knexQuery.toSQL();
}
/**
* Implementation of `then` for the promise API
*/
then(resolve, reject) {
return this.exec().then(resolve, reject);
}
/**
* Implementation of `catch` for the promise API
*/
catch(reject) {
return this.exec().catch(reject);
}
/**
* Implementation of `finally` for the promise API
*/
finally(fullfilled) {
return this.exec().finally(fullfilled);
}
/**
* Required when Promises are extended
*/
get [Symbol.toStringTag]() {
return this.constructor.name;
}
}
exports.InsertQueryBuilder = InsertQueryBuilder;
/**
* Required by macroable
*/
Object.defineProperty(InsertQueryBuilder, "macros", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(InsertQueryBuilder, "getters", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
+76
View File
@@ -0,0 +1,76 @@
/// <reference path="../../../adonis-typings/index.d.ts" />
import { Knex } from 'knex';
import { QueryClientContract, RawQueryBuilderContract, TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
/**
* Exposes the API to execute raw queries
*/
export declare class RawQueryBuilder implements RawQueryBuilderContract {
knexQuery: Knex.Raw;
client: QueryClientContract;
/**
* Custom data someone want to send to the profiler and the
* query event
*/
private customReporterData;
/**
* Control whether to debug the query or not. The initial
* value is inherited from the query client
*/
private debugQueries;
constructor(knexQuery: Knex.Raw, client: QueryClientContract);
/**
* Returns the log data
*/
private getQueryData;
/**
* Define custom reporter data. It will be merged with
* the existing data
*/
reporterData(data: any): this;
/**
* Wrap the query with before/after strings.
*/
wrap(before: string, after: string): this;
/**
* Turn on/off debugging for this query
*/
debug(debug: boolean): this;
/**
* Define query timeout
*/
timeout(time: number, options?: {
cancel: boolean;
}): this;
/**
* Returns SQL query as a string
*/
toQuery(): string;
/**
* Run query inside the given transaction
*/
useTransaction(transaction: TransactionClientContract): this;
/**
* Executes the query
*/
exec(): Promise<any>;
/**
* Get sql representation of the query
*/
toSQL(): Knex.Sql;
/**
* Implementation of `then` for the promise API
*/
then(resolve: any, reject?: any): any;
/**
* Implementation of `catch` for the promise API
*/
catch(reject: any): any;
/**
* Implementation of `finally` for the promise API
*/
finally(fullfilled: any): Promise<any>;
/**
* Required when Promises are extended
*/
get [Symbol.toStringTag](): string;
}
+140
View File
@@ -0,0 +1,140 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RawQueryBuilder = void 0;
const QueryRunner_1 = require("../../QueryRunner");
/**
* Exposes the API to execute raw queries
*/
class RawQueryBuilder {
constructor(knexQuery, client) {
Object.defineProperty(this, "knexQuery", {
enumerable: true,
configurable: true,
writable: true,
value: knexQuery
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: client
});
/**
* Custom data someone want to send to the profiler and the
* query event
*/
Object.defineProperty(this, "customReporterData", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* Control whether to debug the query or not. The initial
* value is inherited from the query client
*/
Object.defineProperty(this, "debugQueries", {
enumerable: true,
configurable: true,
writable: true,
value: this.client.debug
});
}
/**
* Returns the log data
*/
getQueryData() {
return {
connection: this.client.connectionName,
inTransaction: this.client.isTransaction,
...this.customReporterData,
};
}
/**
* Define custom reporter data. It will be merged with
* the existing data
*/
reporterData(data) {
this.customReporterData = data;
return this;
}
/**
* Wrap the query with before/after strings.
*/
wrap(before, after) {
this.knexQuery.wrap(before, after);
return this;
}
/**
* Turn on/off debugging for this query
*/
debug(debug) {
this.debugQueries = debug;
return this;
}
/**
* Define query timeout
*/
timeout(time, options) {
this.knexQuery['timeout'](time, options);
return this;
}
/**
* Returns SQL query as a string
*/
toQuery() {
return this.knexQuery.toQuery();
}
/**
* Run query inside the given transaction
*/
useTransaction(transaction) {
this.knexQuery.transacting(transaction.knexClient);
return this;
}
/**
* Executes the query
*/
async exec() {
return new QueryRunner_1.QueryRunner(this.client, this.debugQueries, this.getQueryData()).run(this.knexQuery);
}
/**
* Get sql representation of the query
*/
toSQL() {
return this.knexQuery.toSQL();
}
/**
* Implementation of `then` for the promise API
*/
then(resolve, reject) {
return this.exec().then(resolve, reject);
}
/**
* Implementation of `catch` for the promise API
*/
catch(reject) {
return this.exec().catch(reject);
}
/**
* Implementation of `finally` for the promise API
*/
finally(fullfilled) {
return this.exec().finally(fullfilled);
}
/**
* Required when Promises are extended
*/
get [Symbol.toStringTag]() {
return this.constructor.name;
}
}
exports.RawQueryBuilder = RawQueryBuilder;
+22
View File
@@ -0,0 +1,22 @@
/// <reference path="../../../adonis-typings/index.d.ts" />
import { Knex } from 'knex';
import { RawBuilderContract } from '@ioc:Adonis/Lucid/Database';
/**
* Exposes the API to construct raw queries. If you want to execute
* raw queries, you can use the RawQueryBuilder
*/
export declare class RawBuilder implements RawBuilderContract {
private sql;
private bindings?;
private wrapBefore;
private wrapAfter;
constructor(sql: string, bindings?: any);
/**
* Wrap the query with before/after strings.
*/
wrap(before: string, after: string): this;
/**
* Converts the raw query to knex raw query instance
*/
toKnex(client: Knex.Client): Knex.Raw;
}
+62
View File
@@ -0,0 +1,62 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RawBuilder = void 0;
/**
* Exposes the API to construct raw queries. If you want to execute
* raw queries, you can use the RawQueryBuilder
*/
class RawBuilder {
constructor(sql, bindings) {
Object.defineProperty(this, "sql", {
enumerable: true,
configurable: true,
writable: true,
value: sql
});
Object.defineProperty(this, "bindings", {
enumerable: true,
configurable: true,
writable: true,
value: bindings
});
Object.defineProperty(this, "wrapBefore", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "wrapAfter", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
}
/**
* Wrap the query with before/after strings.
*/
wrap(before, after) {
this.wrapAfter = after;
this.wrapBefore = before;
return this;
}
/**
* Converts the raw query to knex raw query instance
*/
toKnex(client) {
const rawQuery = client.raw(this.sql, this.bindings);
if (this.wrapBefore && this.wrapAfter) {
rawQuery.wrap(this.wrapBefore, this.wrapAfter);
}
return rawQuery;
}
}
exports.RawBuilder = RawBuilder;
@@ -0,0 +1,25 @@
/// <reference path="../../../adonis-typings/index.d.ts" />
import { Knex } from 'knex';
import { ReferenceBuilderContract } from '@ioc:Adonis/Lucid/Database';
/**
* Reference builder to create SQL reference values
*/
export declare class ReferenceBuilder implements ReferenceBuilderContract {
private ref;
private client;
private schema;
private alias;
constructor(ref: string, client: Knex.Client);
/**
* Define schema
*/
withSchema(schema: string): this;
/**
* Define alias
*/
as(alias: string): this;
/**
* Converts reference to knex
*/
toKnex(client?: Knex.Client): Knex.Ref<any, any>;
}
@@ -0,0 +1,66 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReferenceBuilder = void 0;
/**
* Reference builder to create SQL reference values
*/
class ReferenceBuilder {
constructor(ref, client) {
Object.defineProperty(this, "ref", {
enumerable: true,
configurable: true,
writable: true,
value: ref
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: client
});
Object.defineProperty(this, "schema", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "alias", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
}
/**
* Define schema
*/
withSchema(schema) {
this.schema = schema;
return this;
}
/**
* Define alias
*/
as(alias) {
this.alias = alias;
return this;
}
/**
* Converts reference to knex
*/
toKnex(client) {
const ref = (client || this.client).ref(this.ref);
this.schema && ref.withSchema(this.schema);
this.alias && ref.as(this.alias);
return ref;
}
}
exports.ReferenceBuilder = ReferenceBuilder;
+163
View File
@@ -0,0 +1,163 @@
/// <reference path="../../adonis-typings/index.d.ts" />
/// <reference path="../../adonis-typings/querybuilder.d.ts" />
/// <reference path="../../adonis-typings/database.d.ts" />
/// <reference path="../../adonis-typings/model.d.ts" />
/// <reference path="../../adonis-typings/orm.d.ts" />
/// <reference path="../../adonis-typings/relations.d.ts" />
/// <reference types="@adonisjs/logger/build/adonis-typings/logger" />
/// <reference types="@adonisjs/profiler/build/adonis-typings/profiler" />
/// <reference types="@adonisjs/events/build/adonis-typings" />
/// <reference types="@adonisjs/core/build/adonis-typings/health-check" />
import { Macroable } from 'macroable';
import { EmitterContract } from '@ioc:Adonis/Core/Event';
import { LoggerContract } from '@ioc:Adonis/Core/Logger';
import { ProfilerContract } from '@ioc:Adonis/Core/Profiler';
import { DatabaseConfig, IsolationLevels, DatabaseContract, QueryClientContract, DatabaseClientOptions, TransactionClientContract, ConnectionManagerContract } from '@ioc:Adonis/Lucid/Database';
import { RawBuilder } from './StaticBuilder/Raw';
import { prettyPrint } from '../Helpers/prettyPrint';
import { ModelQueryBuilder } from '../Orm/QueryBuilder';
import { InsertQueryBuilder } from './QueryBuilder/Insert';
import { ReferenceBuilder } from './StaticBuilder/Reference';
import { SimplePaginator } from './Paginator/SimplePaginator';
import { DatabaseQueryBuilder } from './QueryBuilder/Database';
/**
* Database class exposes the API to manage multiple connections and obtain an instance
* of query/transaction clients.
*/
export declare class Database extends Macroable implements DatabaseContract {
private config;
private logger;
private profiler;
private emitter;
/**
* Required by macroable
*/
protected static macros: {};
protected static getters: {};
/**
* Reference to self constructor. TypeScript sucks with "this.constructor"
* https://github.com/microsoft/TypeScript/issues/4586
*/
Database: typeof Database;
/**
* Reference to connections manager
*/
manager: ConnectionManagerContract;
/**
* Primary connection name
*/
primaryConnectionName: string;
/**
* Reference to query builders. We expose them, so that they can be
* extended from outside using macros.
*/
DatabaseQueryBuilder: typeof DatabaseQueryBuilder;
InsertQueryBuilder: typeof InsertQueryBuilder;
ModelQueryBuilder: typeof ModelQueryBuilder;
SimplePaginator: typeof SimplePaginator;
/**
* A store of global transactions
*/
connectionGlobalTransactions: Map<string, TransactionClientContract>;
hasHealthChecksEnabled: boolean;
prettyPrint: typeof prettyPrint;
constructor(config: DatabaseConfig, logger: LoggerContract, profiler: ProfilerContract, emitter: EmitterContract);
/**
* Validate config at runtime
*/
private validateConfig;
/**
* Compute whether health check is enabled or not after registering the connections.
* There are chances that all pre-registered connections are not using health
* checks but a dynamic connection is using it. We don't support that use case
* for now, since it complicates things a lot and forces us to register the
* health checker on demand.
*/
private findIfHealthChecksAreEnabled;
/**
* Registering all connections with the manager, so that we can fetch
* and connect with them whenver required.
*/
private registerConnections;
/**
* Returns the connection node from the connection manager
*/
getRawConnection(name: string): import("@ioc:Adonis/Lucid/Database").ConnectionNode | undefined;
/**
* Returns the query client for a given connection
*/
connection(connection?: string, options?: DatabaseClientOptions): QueryClientContract | TransactionClientContract;
/**
* Returns the knex query builder
*/
knexQuery(): import("knex").Knex.QueryBuilder<any, any>;
/**
* Returns the knex raw query builder
*/
knexRawQuery(sql: string, bindings?: any[]): import("knex").Knex.Raw<any>;
/**
* Returns query builder. Optionally one can define the mode as well
*/
query(options?: DatabaseClientOptions): import("@ioc:Adonis/Lucid/Database").DatabaseQueryBuilderContract<any>;
/**
* Returns insert query builder. Always has to be dual or write mode and
* hence it doesn't matter, since in both `dual` and `write` mode,
* the `write` connection is always used.
*/
insertQuery(options?: DatabaseClientOptions): import("@ioc:Adonis/Lucid/Database").InsertQueryBuilderContract<any[]>;
/**
* Returns a query builder instance for a given model.
*/
modelQuery(model: any, options?: DatabaseClientOptions): import("@ioc:Adonis/Lucid/Orm").ModelQueryBuilderContract<any, any>;
/**
* Returns an instance of raw query builder. Optionally one can
* defined the `read/write` mode in which to execute the
* query
*/
rawQuery(sql: string, bindings?: any, options?: DatabaseClientOptions): import("@ioc:Adonis/Lucid/Database").RawQueryBuilderContract<any>;
/**
* Returns an instance of raw builder. This raw builder queries
* cannot be executed. Use `rawQuery`, if you want to execute
* queries raw queries.
*/
raw(sql: string, bindings?: any): RawBuilder;
/**
* Returns reference builder.
*/
ref(reference: string): ReferenceBuilder;
/**
* Returns instance of a query builder and selects the table
*/
from(table: any): import("@ioc:Adonis/Lucid/Database").DatabaseQueryBuilderContract<any>;
/**
* Returns insert query builder and selects the table
*/
table(table: any): import("@ioc:Adonis/Lucid/Database").InsertQueryBuilderContract<any[]>;
/**
* Returns a transaction instance on the default
* connection
*/
transaction(callback?: {
isolationLevel?: IsolationLevels;
} | ((trx: TransactionClientContract) => Promise<any>), options?: {
isolationLevel?: IsolationLevels;
}): Promise<any>;
/**
* Invokes `manager.report`
*/
report(): Promise<import("@ioc:Adonis/Core/HealthCheck").HealthReportEntry & {
meta: import("@ioc:Adonis/Lucid/Database").ReportNode[];
}>;
/**
* Begin a new global transaction
*/
beginGlobalTransaction(connectionName?: string, options?: Omit<DatabaseClientOptions, 'mode'>): Promise<TransactionClientContract>;
/**
* Commit an existing global transaction
*/
commitGlobalTransaction(connectionName?: string): Promise<void>;
/**
* Rollback an existing global transaction
*/
rollbackGlobalTransaction(connectionName?: string): Promise<void>;
}
+378
View File
@@ -0,0 +1,378 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Database = void 0;
/// <reference path="../../adonis-typings/index.ts" />
const macroable_1 = require("macroable");
const utils_1 = require("@poppinss/utils");
const QueryClient_1 = require("../QueryClient");
const Raw_1 = require("./StaticBuilder/Raw");
const prettyPrint_1 = require("../Helpers/prettyPrint");
const QueryBuilder_1 = require("../Orm/QueryBuilder");
const Manager_1 = require("../Connection/Manager");
const Insert_1 = require("./QueryBuilder/Insert");
const Reference_1 = require("./StaticBuilder/Reference");
const SimplePaginator_1 = require("./Paginator/SimplePaginator");
const Database_1 = require("./QueryBuilder/Database");
/**
* Database class exposes the API to manage multiple connections and obtain an instance
* of query/transaction clients.
*/
class Database extends macroable_1.Macroable {
constructor(config, logger, profiler, emitter) {
super();
Object.defineProperty(this, "config", {
enumerable: true,
configurable: true,
writable: true,
value: config
});
Object.defineProperty(this, "logger", {
enumerable: true,
configurable: true,
writable: true,
value: logger
});
Object.defineProperty(this, "profiler", {
enumerable: true,
configurable: true,
writable: true,
value: profiler
});
Object.defineProperty(this, "emitter", {
enumerable: true,
configurable: true,
writable: true,
value: emitter
});
/**
* Reference to self constructor. TypeScript sucks with "this.constructor"
* https://github.com/microsoft/TypeScript/issues/4586
*/
Object.defineProperty(this, "Database", {
enumerable: true,
configurable: true,
writable: true,
value: Database
});
/**
* Reference to connections manager
*/
Object.defineProperty(this, "manager", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* Primary connection name
*/
Object.defineProperty(this, "primaryConnectionName", {
enumerable: true,
configurable: true,
writable: true,
value: this.config.connection
});
/**
* Reference to query builders. We expose them, so that they can be
* extended from outside using macros.
*/
Object.defineProperty(this, "DatabaseQueryBuilder", {
enumerable: true,
configurable: true,
writable: true,
value: Database_1.DatabaseQueryBuilder
});
Object.defineProperty(this, "InsertQueryBuilder", {
enumerable: true,
configurable: true,
writable: true,
value: Insert_1.InsertQueryBuilder
});
Object.defineProperty(this, "ModelQueryBuilder", {
enumerable: true,
configurable: true,
writable: true,
value: QueryBuilder_1.ModelQueryBuilder
});
Object.defineProperty(this, "SimplePaginator", {
enumerable: true,
configurable: true,
writable: true,
value: SimplePaginator_1.SimplePaginator
});
/**
* A store of global transactions
*/
Object.defineProperty(this, "connectionGlobalTransactions", {
enumerable: true,
configurable: true,
writable: true,
value: new Map()
});
Object.defineProperty(this, "hasHealthChecksEnabled", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "prettyPrint", {
enumerable: true,
configurable: true,
writable: true,
value: prettyPrint_1.prettyPrint
});
this.validateConfig();
this.manager = new Manager_1.ConnectionManager(this.logger, this.emitter);
this.registerConnections();
this.findIfHealthChecksAreEnabled();
}
/**
* Validate config at runtime
*/
validateConfig() {
const validator = new utils_1.ManagerConfigValidator(this.config, 'database', 'config/database');
validator.validateDefault('connection');
validator.validateList('connections', 'connection');
}
/**
* Compute whether health check is enabled or not after registering the connections.
* There are chances that all pre-registered connections are not using health
* checks but a dynamic connection is using it. We don't support that use case
* for now, since it complicates things a lot and forces us to register the
* health checker on demand.
*/
findIfHealthChecksAreEnabled() {
for (let [, conn] of this.manager.connections) {
if (conn.config.healthCheck) {
this.hasHealthChecksEnabled = true;
break;
}
}
}
/**
* Registering all connections with the manager, so that we can fetch
* and connect with them whenver required.
*/
registerConnections() {
Object.keys(this.config.connections).forEach((name) => {
this.manager.add(name, this.config.connections[name]);
});
}
/**
* Returns the connection node from the connection manager
*/
getRawConnection(name) {
return this.manager.get(name);
}
/**
* Returns the query client for a given connection
*/
connection(connection = this.primaryConnectionName, options) {
options = options || {};
/**
* Use default profiler, when no profiler is defined when obtaining
* the query client for a given connection.
*/
if (!options.profiler) {
options.profiler = this.profiler;
}
/**
* Connect is noop when already connected
*/
this.manager.connect(connection);
/**
* Disallow modes other than `read` or `write`
*/
if (options.mode && !['read', 'write'].includes(options.mode)) {
throw new utils_1.Exception(`Invalid mode ${options.mode}. Must be read or write`);
}
/**
* Return the global transaction when it already exists.
*/
if (this.connectionGlobalTransactions.has(connection)) {
this.logger.trace({ connection }, 'using pre-existing global transaction connection');
const globalTransactionClient = this.connectionGlobalTransactions.get(connection);
return globalTransactionClient;
}
/**
* Fetching connection for the given name
*/
const rawConnection = this.getRawConnection(connection).connection;
/**
* Generating query client for a given connection and setting appropriate
* mode on it
*/
this.logger.trace({ connection }, 'creating query client in %s mode', [options.mode || 'dual']);
const queryClient = options.mode
? new QueryClient_1.QueryClient(options.mode, rawConnection, this.emitter)
: new QueryClient_1.QueryClient('dual', rawConnection, this.emitter);
/**
* Passing profiler to the query client for profiling queries
*/
queryClient.profiler = options.profiler;
return queryClient;
}
/**
* Returns the knex query builder
*/
knexQuery() {
return this.connection(this.primaryConnectionName).knexQuery();
}
/**
* Returns the knex raw query builder
*/
knexRawQuery(sql, bindings) {
return this.connection(this.primaryConnectionName).knexRawQuery(sql, bindings);
}
/**
* Returns query builder. Optionally one can define the mode as well
*/
query(options) {
return this.connection(this.primaryConnectionName, options).query();
}
/**
* Returns insert query builder. Always has to be dual or write mode and
* hence it doesn't matter, since in both `dual` and `write` mode,
* the `write` connection is always used.
*/
insertQuery(options) {
return this.connection(this.primaryConnectionName, options).insertQuery();
}
/**
* Returns a query builder instance for a given model.
*/
modelQuery(model, options) {
return this.connection(this.primaryConnectionName, options).modelQuery(model);
}
/**
* Returns an instance of raw query builder. Optionally one can
* defined the `read/write` mode in which to execute the
* query
*/
rawQuery(sql, bindings, options) {
return this.connection(this.primaryConnectionName, options).rawQuery(sql, bindings);
}
/**
* Returns an instance of raw builder. This raw builder queries
* cannot be executed. Use `rawQuery`, if you want to execute
* queries raw queries.
*/
raw(sql, bindings) {
return new Raw_1.RawBuilder(sql, bindings);
}
/**
* Returns reference builder.
*/
ref(reference) {
return new Reference_1.ReferenceBuilder(reference, this.connection().getReadClient().client);
}
/**
* Returns instance of a query builder and selects the table
*/
from(table) {
return this.connection().from(table);
}
/**
* Returns insert query builder and selects the table
*/
table(table) {
return this.connection().table(table);
}
/**
* Returns a transaction instance on the default
* connection
*/
transaction(callback, options) {
const client = this.connection();
return typeof callback === 'function'
? client.transaction(callback, options)
: client.transaction(callback);
}
/**
* Invokes `manager.report`
*/
report() {
return this.manager.report();
}
/**
* Begin a new global transaction
*/
async beginGlobalTransaction(connectionName, options) {
connectionName = connectionName || this.primaryConnectionName;
/**
* Return global transaction as it is
*/
const globalTrx = this.connectionGlobalTransactions.get(connectionName);
if (globalTrx) {
return globalTrx;
}
/**
* Create a new transaction and store a reference to it
*/
const trx = await this.connection(connectionName, options).transaction();
this.connectionGlobalTransactions.set(trx.connectionName, trx);
/**
* Listen for events to drop the reference when transaction
* is over
*/
trx.on('commit', ($trx) => {
this.connectionGlobalTransactions.delete($trx.connectionName);
});
trx.on('rollback', ($trx) => {
this.connectionGlobalTransactions.delete($trx.connectionName);
});
return trx;
}
/**
* Commit an existing global transaction
*/
async commitGlobalTransaction(connectionName) {
connectionName = connectionName || this.primaryConnectionName;
const trx = this.connectionGlobalTransactions.get(connectionName);
if (!trx) {
throw new utils_1.Exception([
'Cannot commit a non-existing global transaction.',
' Make sure you are not calling "commitGlobalTransaction" twice',
].join(''));
}
await trx.commit();
}
/**
* Rollback an existing global transaction
*/
async rollbackGlobalTransaction(connectionName) {
connectionName = connectionName || this.primaryConnectionName;
const trx = this.connectionGlobalTransactions.get(connectionName);
if (!trx) {
throw new utils_1.Exception([
'Cannot rollback a non-existing global transaction.',
' Make sure you are not calling "commitGlobalTransaction" twice',
].join(''));
}
await trx.rollback();
}
}
exports.Database = Database;
/**
* Required by macroable
*/
Object.defineProperty(Database, "macros", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(Database, "getters", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});