diff --git a/.env b/.env
index 31ad2276..c2504c93 100644
--- a/.env
+++ b/.env
@@ -1,12 +1,12 @@
DB=pg
DB_NAME=lucid
-MYSQL_HOST=0.0.0.0
+MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_USER=virk
MYSQL_PASSWORD=password
-PG_HOST=0.0.0.0
+PG_HOST=pg
PG_PORT=5432
PG_USER=virk
PG_PASSWORD=password
diff --git a/Dockerfile b/Dockerfile
index 2b02858f..71a4f541 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -11,8 +11,5 @@ WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
-RUN wget https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -O /wait-for-it.sh
-RUN chmod +x /wait-for-it.sh
-
COPY . .
RUN npm run build
diff --git a/adonis-typings/database.ts b/adonis-typings/database.ts
index b9e4e819..23ae8da6 100644
--- a/adonis-typings/database.ts
+++ b/adonis-typings/database.ts
@@ -10,22 +10,27 @@
///
declare module '@ioc:Adonis/Addons/Database' {
- import * as knex from 'knex'
import { Pool } from 'tarn'
+ import * as knex from 'knex'
import { EventEmitter } from 'events'
- import { DatabaseQueryBuilderContract } from '@ioc:Adonis/Addons/DatabaseQueryBuilder'
+ import {
+ DatabaseQueryBuilderContract,
+ InsertQueryBuilderContract,
+ RawBuilderContract,
+ QueryClientContract,
+ } from '@ioc:Adonis/Addons/DatabaseQueryBuilder'
/**
* Connection node used by majority of database
* clients
*/
type SharedConnectionNode = {
- host: string,
- user: string,
- password: string,
- database: string,
- port: number,
+ host?: string,
+ user?: string,
+ password?: string,
+ database?: string,
+ port?: number,
}
/**
@@ -63,6 +68,7 @@ declare module '@ioc:Adonis/Addons/Database' {
filename: string,
mode?: any,
},
+ replicas?: never,
}
/**
@@ -72,22 +78,34 @@ declare module '@ioc:Adonis/Addons/Database' {
* Knex forwards all config options to the driver directly. So feel
* free to define them (let us know, in case any options are missing)
*/
+ type MysqlConnectionNode = {
+ socketPath?: string,
+ localAddress?: string,
+ charset?: string,
+ timezone?: string,
+ stringifyObjects?: boolean,
+ insecureAuth?: boolean,
+ typeCast?: boolean,
+ supportBigNumbers?: boolean,
+ bigNumberStrings?: boolean,
+ dateStrings?: boolean | string[],
+ flags?: string,
+ ssl?: any,
+ }
+
export type MysqlConfigContract = SharedConfigNode & {
client: 'mysql',
version?: string,
- connection: SharedConnectionNode & {
- socketPath?: string,
- localAddress?: string,
- charset?: string,
- timezone?: string,
- stringifyObjects?: boolean,
- insecureAuth?: boolean,
- typeCast?: boolean,
- supportBigNumbers?: boolean,
- bigNumberStrings?: boolean,
- dateStrings?: boolean | string[],
- flags?: string,
- ssl?: any,
+ connection?: SharedConnectionNode & MysqlConnectionNode,
+ replicas?: {
+ write: {
+ connection: MysqlConfigContract['connection'],
+ pool?: MysqlConfigContract['pool'],
+ }
+ read: {
+ connection: MysqlConfigContract['connection'][],
+ pool?: MysqlConfigContract['pool'],
+ },
},
}
@@ -116,7 +134,17 @@ declare module '@ioc:Adonis/Addons/Database' {
client: 'pg' | 'postgres' | 'postgresql',
version?: string,
returning?: string,
- connection: string | SharedConnectionNode,
+ connection?: string | SharedConnectionNode,
+ replicas?: {
+ write: {
+ connection: PostgreConfigContract['connection'],
+ pool?: PostgreConfigContract['pool'],
+ }
+ read: {
+ connection: PostgreConfigContract['connection'][],
+ pool?: PostgreConfigContract['pool'],
+ },
+ },
searchPath?: string[],
}
@@ -139,18 +167,30 @@ declare module '@ioc:Adonis/Addons/Database' {
* config values.
* https://oracle.github.io/node-oracledb/doc/api.html#oracledbproperties
*/
+ type OracleConnectionNode = {
+ autoCommit?: boolean,
+ connectionClass?: string,
+ edition?: string,
+ externalAuth?: boolean,
+ fetchArraySize?: number,
+ fetchAsBuffer?: any[],
+ lobPrefetchSize?: number,
+ maxRows?: number,
+ oracleClientVersion?: number,
+ }
+
export type OracleConfigContract = SharedConfigNode & {
client: 'oracledb',
- connection: SharedConnectionNode & {
- autoCommit?: boolean,
- connectionClass?: string,
- edition?: string,
- externalAuth?: boolean,
- fetchArraySize?: number,
- fetchAsBuffer?: any[],
- lobPrefetchSize?: number,
- maxRows?: number,
- oracleClientVersion?: number,
+ connection?: SharedConnectionNode & OracleConnectionNode,
+ replicas?: {
+ write: {
+ connection: OracleConfigContract['connection'],
+ pool?: OracleConfigContract['pool'],
+ }
+ read: {
+ connection: OracleConfigContract['connection'][],
+ pool?: OracleConfigContract['pool'],
+ },
},
fetchAsString?: any[],
}
@@ -162,14 +202,26 @@ declare module '@ioc:Adonis/Addons/Database' {
* Knex forwards all config options to the driver directly. So feel
* free to define them (let us know, in case any options are missing)
*/
+ type MssqlConnectionNode = {
+ domain?: string,
+ connectionTimeout?: number,
+ requestTimeout?: number,
+ parseJSON?: boolean,
+ }
+
export type MssqlConfigContract = SharedConfigNode & {
client: 'mssql',
version?: string,
- connection: SharedConnectionNode & {
- domain?: string,
- connectionTimeout?: number,
- requestTimeout?: number,
- parseJSON?: boolean,
+ connection?: SharedConnectionNode & MssqlConnectionNode,
+ replicas?: {
+ write: {
+ connection: MssqlConfigContract['connection'],
+ pool?: MssqlConfigContract['pool'],
+ }
+ read: {
+ connection: MssqlConfigContract['connection'][],
+ pool?: MssqlConfigContract['pool'],
+ },
},
}
@@ -206,19 +258,64 @@ declare module '@ioc:Adonis/Addons/Database' {
* connections.
*/
export interface ConnectionManagerContract extends EventEmitter {
+ /**
+ * List of registered connection. You must check the connection state
+ * to understand, if it is connected or not
+ */
connections: Map
- on (event: 'connect', callback: (connection: ConnectionContract) => void)
- on (event: 'disconnect', callback: (connection: ConnectionContract) => void)
+ /**
+ * Everytime a connection is created
+ */
+ on (event: 'connect', callback: (connection: ConnectionContract) => void): this
+ /**
+ * Everytime a connection leaves
+ */
+ on (event: 'disconnect', callback: (connection: ConnectionContract) => void): this
+
+ /**
+ * Add a new connection to the list of managed connection. You must call
+ * connect seperately to instantiate a connection instance
+ */
add (connectionName: string, config: ConnectionConfigContract): void
+
+ /**
+ * Instantiate a connection. It is a noop, when connection for the given
+ * name is already instantiated
+ */
connect (connectionName: string): void
+
+ /**
+ * Get connection node
+ */
get (connectionName: string): ConnectionManagerConnectionNode | undefined
+
+ /**
+ * Find if a connection name is managed by the manager or not
+ */
has (connectionName: string): boolean
+
+ /**
+ * Find if a managed connection is instantiated or not
+ */
isConnected (connectionName: string): boolean
+ /**
+ * Close a given connection. This is also kill the underlying knex connection
+ * pool
+ */
close (connectionName: string, release?: boolean): Promise
+
+ /**
+ * Close all managed connections
+ */
closeAll (release?: boolean): Promise
+
+ /**
+ * Release a given connection. Releasing a connection means, you will have to
+ * re-add it using the `add` method
+ */
release (connectionName: string): Promise
}
@@ -226,26 +323,39 @@ declare module '@ioc:Adonis/Addons/Database' {
* Connection represents a single knex instance with inbuilt
* pooling capabilities.
*/
- export interface ConnectionContract extends EventEmitter {
- client?: knex,
+ export interface ConnectionContract extends EventEmitter, QueryClientContract {
+ /**
+ * Read/write connection pools
+ */
pool: null | Pool,
+ readPool: null | Pool,
+
+ /**
+ * Name of the connection
+ */
name: string,
+
+ /**
+ * Untouched config
+ */
config: ConnectionConfigContract,
/**
* List of emitted events
*/
- on (event: 'connect', callback: (connection: ConnectionContract) => void)
- on (event: 'error', callback: (connection: ConnectionContract, error: Error) => void)
- on (event: 'disconnect', callback: (connection: ConnectionContract) => void)
- on (event: 'disconnect:error', callback: (connection: ConnectionContract, error: Error) => void)
+ on (event: 'connect', callback: (connection: ConnectionContract) => void): this
+ on (event: 'error', callback: (connection: ConnectionContract, error: Error) => void): this
+ on (event: 'disconnect', callback: (connection: ConnectionContract) => void): this
+ on (event: 'disconnect:error', callback: (connection: ConnectionContract, error: Error) => void): this
+ /**
+ * Make knex connection
+ */
connect (): void,
- disconnect (): Promise,
- }
- export interface DatabaseContract {
- query (): DatabaseQueryBuilderContract,
- from: DatabaseQueryBuilderContract['from'],
+ /**
+ * Disconnect knex
+ */
+ disconnect (): Promise,
}
}
diff --git a/adonis-typings/querybuilder.ts b/adonis-typings/querybuilder.ts
index a506b887..cd71848e 100644
--- a/adonis-typings/querybuilder.ts
+++ b/adonis-typings/querybuilder.ts
@@ -8,14 +8,27 @@
*/
declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
+ import * as knex from 'knex'
import { Dictionary } from 'ts-essentials'
- import { JoinCallback, Sql, Raw } from 'knex'
- export interface Registery {
+ /**
+ * The types for values for the aggregates. We need this coz of
+ * the history with bigints in Javascript
+ */
+ export interface AggregatesRegistry {
Count: number,
}
- type OneOrMany = T | 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 | RawContract
/**
* A known set of values allowed when defining values for different
@@ -34,22 +47,8 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
| RawContract
/**
- * Allowing a generic value along with raw query instance or a subquery
- * instance
- */
- type ValueWithSubQueries = T | ChainableContract | RawContract
-
- /**
- * Shape of raw query instance
- */
- interface RawContract {
- wrap (before: string, after: string): this
- toQuery (): string
- toSQL (): Sql
- }
-
- /**
- * Shape of raw query builder
+ * Shape of raw query builder. The builder is a method used to build
+ * raw queries.
*/
interface RawBuilderContract {
(sql: string): RawContract
@@ -58,8 +57,8 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
}
/**
- * Shape of raw query builder. The different is, it will return
- * the existing query builder chain instead of `RawContract`
+ * 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 RawQueryBuilderContract {
(sql: string): Builder
@@ -69,56 +68,61 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
}
/**
- * Query callback is used to write wrapped queries.
+ * 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
)
/**
- * Possible signatures for a select method on database query builder.
- * The models query builder may have a different signature all
- * together.
+ * Possible signatures for a select method on database query builder. The select narrows the result
+ * based upon many factors.
+ *
+ * 1. select(*) uses the main result generic. Which means everything is returned.
+ * 2. select(columns) narrows the result set to explicitly defined keys.
+ * 3. Calling `select(columns)` for multiple times appends to the explicit result set.
+ * 4. Calling `select(*)` after named selects will append all columns to the named columns.
+ * 5. Aliases defined as object will return typed output.
*/
interface DatabaseQueryBuilderSelect<
- Record extends Dictionary,
- Result extends any = Record
+ Builder extends ChainableContract,
+ Record extends Dictionary,
> {
/**
* Selecting named columns as array
*/
- (columns: K[]): DatabaseQueryBuilderContract
+ (columns: K[]): Builder
/**
* Selecting named columns as spread
*/
- (...columns: K[]): DatabaseQueryBuilderContract
+ (...columns: K[]): Builder
/**
* Selecting columns as a dictionary with key as the alias and value is
* the original column. When aliases are defined, the return output
* will have the alias columns and not the original one's
*/
- > (
- columns: Columns,
- ): DatabaseQueryBuilderContract
+ (columns: Dictionary): Builder
/**
* String fallback when columns to be selected aren't derived from
* record. Here we allow subqueries, raw queries or an array
* of strings.
*/
- (columns: (string | ChainableContract | RawContract)[]): DatabaseQueryBuilderContract
+ (columns: ValueWithSubQueries[]): Builder
/**
* Selecting columns as spread
*/
- (...columns: (string | ChainableContract | RawContract)[]): DatabaseQueryBuilderContract
+ (...columns: ValueWithSubQueries[]): Builder
/**
- * Wildcard selector
+ * Wildcard selector. Fallback to original `Result` type, since we are
+ * selecting everything.
*/
- (column: '*'): DatabaseQueryBuilderContract
+ (column: '*'): Builder
}
/**
@@ -126,7 +130,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface Where<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* Callback for wrapped clauses
@@ -155,6 +159,12 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
operator: string,
value: ValueWithSubQueries,
): Builder
+
+ /**
+ * Accepting any string as a key for supporting `dot` aliases
+ */
+ (key: string, value: StrictValues | ChainableContract): Builder
+ (key: string, operator: string, value: StrictValues | ChainableContract): Builder
}
/**
@@ -162,7 +172,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface WhereIn<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* A named column as the key and an array of values including a literal
@@ -177,13 +187,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
* A named column as the key along with a sub query. The subquery must yield
* an array of values to be valid at runtime
*/
- (key: K, subquery: ChainableContract): Builder
-
- /**
- * A named column as the key along with a query callback. The query callback
- * must yield an array of values to be valid at runtime.
- */
- (key: K, callback: QueryCallback): Builder
+ (key: K, value: ChainableContract | QueryCallback): Builder
/**
* Accepting multiple columns and 2d array of values. The values must be
@@ -239,6 +243,15 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
* Typed array of columns, with untyped values
*/
(key: K[], value: (StrictValues | ChainableContract)[][]): Builder
+
+ /**
+ * Allowing any string key (mainly for prefixed columns) with all
+ * possible values
+ */
+ (K: string, value: (StrictValues | ChainableContract)[]): Builder
+ (K: string[], value: (StrictValues | ChainableContract)[][]): Builder
+ (k: string, subquery: ChainableContract | QueryCallback): Builder
+ (k: string[], subquery: ChainableContract): Builder
}
/**
@@ -246,9 +259,10 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface WhereNull<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
(key: K): Builder
+ (key: string): Builder
}
/**
@@ -263,7 +277,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface WhereBetween<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* Typed column with an tuple of a literal value, a raw query or
@@ -273,12 +287,14 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
ValueWithSubQueries,
ValueWithSubQueries,
]): Builder
- }
- /**
- * Possibles signatures for a raw where clause.
- */
- interface WhereRaw extends RawQueryBuilderContract {
+ /**
+ * Accept any string as a key for supporting prefix columns
+ */
+ (key: string, value: [
+ StrictValues | ChainableContract,
+ StrictValues | ChainableContract,
+ ]): Builder
}
/**
@@ -307,13 +323,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
* Join with a callback. The callback receives an array of join class from
* knex directly.
*/
- (table: string, callback: JoinCallback): Builder
- }
-
- /**
- * Possible signatures for a raw join
- */
- interface JoinRaw extends RawQueryBuilderContract {
+ (table: string, callback: knex.JoinCallback): Builder
}
/**
@@ -321,7 +331,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface Distinct<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* Named keys
@@ -355,23 +365,17 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface GroupBy<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> extends Distinct {
}
/**
- * GroupByRaw is same as `RawQueryBuilderContract`
- */
- interface GroupByRaw extends RawQueryBuilderContract {
- }
-
- /**
- * Possible signatures for aggregate functions. It will append
- * to the pre existing result
+ * Possible signatures for aggregate functions. Aggregates will push to the
+ * result set. Unlike knex, we force defining aliases for each aggregate.
*/
interface Aggregate <
- Record extends Dictionary,
- Result extends any = Record,
+ Record extends Dictionary,
+ Result extends any,
> {
/**
* Accepting a typed column with the alias for the count. Unlike knex
@@ -381,7 +385,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
(
column: OneOrMany,
alias: Alias,
- ): DatabaseQueryBuilderContract)>
+ ): DatabaseQueryBuilderContract>
/**
* Accepting an object for multiple counts in a single query. Again
@@ -393,7 +397,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
Columns extends Dictionary, Alias>,
>(
columns: Columns,
- ): DatabaseQueryBuilderContract
+ ): DatabaseQueryBuilderContract
/**
* Accepting an un typed column with the alias for the count.
@@ -401,7 +405,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
(
column: OneOrMany>,
alias: Alias,
- ): DatabaseQueryBuilderContract)>
+ ): DatabaseQueryBuilderContract>
/**
* Accepting an object for multiple counts in a single query. Again
@@ -412,7 +416,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
Columns extends Dictionary>, Alias>,
>(
columns: Columns,
- ): DatabaseQueryBuilderContract
+ ): DatabaseQueryBuilderContract
}
/**
@@ -420,7 +424,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface OrderBy<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* Order by a named column and optional direction
@@ -453,12 +457,6 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
(columns: { column: string, order?: 'asc' | 'desc' }[]): Builder
}
- /**
- * OrderByRaw is same as RawQueryBuilderContract
- */
- interface OrderByRaw extends RawQueryBuilderContract {
- }
-
/**
* Possible signatures for a union clause
*/
@@ -499,8 +497,8 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface Having<
Builder extends ChainableContract,
- Record extends Dictionary,
- > extends RawQueryBuilderContract {
+ Record extends Dictionary,
+ > {
/**
* A subquery callback
*/
@@ -535,7 +533,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface HavingIn<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* A typed key, along with an array of literal values, a raw queries or
@@ -560,12 +558,8 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface HavingNull<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> extends WhereNull {
- /**
- * Supporting untyped keys, since having clause can refer alias columns as well.
- */
- (key: string): Builder
}
/**
@@ -583,7 +577,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
*/
interface HavingBetween<
Builder extends ChainableContract,
- Record extends Dictionary,
+ Record extends Dictionary,
> {
/**
* A typed key, along with a tuple of literal values, raw queries or
@@ -605,9 +599,10 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
}
/**
- * Possibles signatures for a raw where clause.
+ * Possible signatures of `with` CTE
*/
- interface HavingRaw extends RawQueryBuilderContract {
+ interface With {
+ (alias: string, query: RawContract | ChainableContract): Builder
}
/**
@@ -618,20 +613,95 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
(table: Dictionary): Builder
}
+ /**
+ * Possible signatures for defining table for a select query. A query
+ * callback is allowed for select queries for computing a value
+ * from a subquery
+ */
+ interface SelectTable extends Table {
+ (callback: QueryCallback): Builder
+ }
+
+ /**
+ * Possible signatures for the `returning` method.
+ */
+ interface Returning<
+ Builder,
+ Record extends Dictionary
+ > {
+ /**
+ * Mark return columns as a single array of value type for the given
+ * key
+ */
+ (column: K): Builder
+
+ /**
+ * Mark return columns as an array of key/value pair with correct types.
+ */
+ (columns: K[]): Builder
+ }
+
/**
* Possible signatures for performing an update
*/
- interface Update {
+ interface Update<
+ Builder extends ChainableContract,
+ Record extends Dictionary
+ > {
/**
* Accepts an array of object of named key/value pair and returns an array
* of Generic return columns.
*/
- (values: { [P in K]: Record[P] }): Promise
+ (values: { [P in K]: Record[P] }): Builder
/**
* Accepts a key/value pair to update.
*/
- (column: K, value: Record[K]): Promise
+ (column: K, value: Record[K]): Builder
+ }
+
+ /**
+ * Possible signatures for incrementing/decrementing
+ * values
+ */
+ interface Counter<
+ Builder extends ChainableContract,
+ Record extends Dictionary
+ > {
+ (column: K, counter?: number): Builder
+ (values: { [P in K]: number }): Builder
+ }
+
+ /**
+ * 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
+ toQuery (): string
+ exec (): Promise
+ toSQL (): knex.Sql
+ }
+
+ /**
+ * Possible signatures for an insert query
+ */
+ interface Insert<
+ Builder extends InsertQueryBuilderContract,
+ Record extends Dictionary
+ > {
+ (values: { [P in K]: Record[P] }): Builder
+ }
+
+ /**
+ * Possible signatures for doing multiple inserts in a single query
+ */
+ interface MultiInsert<
+ Builder extends InsertQueryBuilderContract,
+ Record extends Dictionary
+ > {
+ (values: { [P in K]: Record[P] }[]): Builder
}
/**
@@ -640,9 +710,9 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
* methods to execute a query.
*/
export interface ChainableContract <
- Record extends Dictionary = Dictionary,
+ Record extends Dictionary = Dictionary,
> {
- from: Table
+ from: SelectTable
where: Where
orWhere: Where
@@ -684,9 +754,9 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
orWhereNotBetween: WhereBetween
andWhereNotBetween: WhereBetween
- whereRaw: WhereRaw
- orWhereRaw: WhereRaw
- andWhereRaw: WhereRaw
+ whereRaw: RawQueryBuilderContract
+ orWhereRaw: RawQueryBuilderContract
+ andWhereRaw: RawQueryBuilderContract
join: Join
innerJoin: Join
@@ -696,7 +766,7 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
rightOuterJoin: Join
fullOuterJoin: Join
crossJoin: Join
- joinRaw: JoinRaw
+ joinRaw: RawQueryBuilderContract
having: Having
orHaving: Having
@@ -734,23 +804,29 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
orHavingNotBetween: HavingBetween
andHavingNotBetween: HavingBetween
- havingRaw: HavingRaw
- orHavingRaw: HavingRaw
- andHavingRaw: HavingRaw
+ havingRaw: RawQueryBuilderContract
+ orHavingRaw: RawQueryBuilderContract
+ andHavingRaw: RawQueryBuilderContract
distinct: Distinct
groupBy: GroupBy
- groupByRaw: GroupByRaw
+ groupByRaw: RawQueryBuilderContract
orderBy: OrderBy
- orderByRaw: OrderByRaw
+ orderByRaw: RawQueryBuilderContract
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
@@ -764,9 +840,6 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
skipLocked (): this
noWait (): this
-
- toSQL (): Sql
- toString (): string
}
/**
@@ -774,123 +847,161 @@ declare module '@ioc:Adonis/Addons/DatabaseQueryBuilder' {
* query builder and Model query builder will behave differently.
*/
export interface DatabaseQueryBuilderContract <
- Record extends Dictionary = Dictionary,
+ Record extends Dictionary = Dictionary,
Result extends any = Record,
- > extends ChainableContract, Promise {
- select: DatabaseQueryBuilderSelect,
+ > extends ChainableContract, ExcutableQueryBuilderContract {
+ select: DatabaseQueryBuilderSelect
+
+ /**
+ * Aggregates
+ */
+ count: Aggregate
+ countDistinct: Aggregate
+ min: Aggregate
+ max: Aggregate
+ sum: Aggregate
+ avg: Aggregate
+ avgDistinct: Aggregate
- count: Aggregate,
- countDistinct: Aggregate,
- min: Aggregate,
- max: Aggregate,
- sum: Aggregate,
- avg: Aggregate,
- avgDistinct: Aggregate,
+ returning: Returning
+ update: Update
+ increment: Counter
+ decrement: Counter
+ del (): this
/**
- * Returns the first row
+ * Clone current query
*/
- first (): Result
+ clone<
+ ClonedRecord extends Dictionary = Record,
+ ClonedResult = Result,
+ > (): DatabaseQueryBuilderContract
+
+ /**
+ * Execute and get first result
+ */
+ first (): Promise
}
/**
- * Possible signatures for the `returning` method when called on
- * the insert query builder.
+ * Insert query builder to perform database inserts
*/
- interface InsertReturning> {
+ export interface InsertQueryBuilderContract<
+ Record extends Dictionary = Dictionary,
+ ReturnColumns extends any[] = any[]
+ > extends ExcutableQueryBuilderContract {
/**
- * Mark return columns as a single array of value type for the given
- * key
+ * Table for the insert query
*/
- (
- column: K,
- ): InsertQueryBuilderContract
+ table: Table
/**
- * Mark return columns as an array of key/value pair with correct types.
+ * Define returning columns
*/
- (
- columns: K[],
- ): InsertQueryBuilderContract
- }
+ returning: Returning
- /**
- * Possible signatures for an insert query
- */
- interface Insert<
- Record extends Dictionary,
- ReturnColumns extends any[]
- > {
/**
- * Defers the `insert` to `exec` method
+ * Inserting a single record.
*/
- (
- columns: { [P in K]: Record[P] },
- defer: true,
- ): InsertQueryBuilderContract
+ insert: Insert
/**
- * Performs the insert right away when defer is not defined or is set to false
+ * Inserting multiple columns at once
*/
- (columns: { [P in K]: Record[P] }, defer?: boolean): Promise
+ multiInsert: MultiInsert
}
/**
- * Possible signatures for doing multiple inserts in a single query
+ * Shape of raw query instance
*/
- interface MultiInsert<
- Record extends Dictionary,
- ReturnColumns extends any[]
- > {
+ interface RawContract extends ExcutableQueryBuilderContract {
+ wrap (before: string, after: string): this
+ }
+
+ /**
+ * Shape of the query client, that is used to retrive instances
+ * of query builder
+ */
+ interface QueryClientContract {
/**
- * Defers the `insert` to `exec` method
+ * Tells if client is a transaction client or not
*/
- (
- values: { [P in K]: Record[P] }[],
- defer: true,
- ): InsertQueryBuilderContract
+ isTransaction: boolean
/**
- * Accepts an array of object of named key/value pair and returns an array
- * of Generic return columns.
+ * The database dialect in use
*/
- (values: { [P in K]: Record[P] }[], defer?: boolean): Promise
- }
+ dialect: string
- /**
- * Insert query builder can be obtained by specifying return columns
- * using `returning` method
- */
- export interface InsertQueryBuilderContract <
- Record extends Dictionary = Dictionary,
- ReturnColumns extends any[] = number[]
- > {
- table: Table
+ /**
+ * Returns the read and write clients
+ */
+ getReadClient (): knex | knex.Transaction
+ getWriteClient (): knex | knex.Transaction
/**
- * Define returning columns
+ * Get new query builder instance for select, update and
+ * delete calls
*/
- returning: InsertReturning
+ query (): DatabaseQueryBuilderContract,
/**
- * Inserting a single record.
+ * Get new query builder instance inserts
*/
- insert: Insert
+ insertQuery (): InsertQueryBuilderContract,
/**
- * In single insert, we always know that one item inside an array is returned, so
- * instead of using `val[]`, we make use of `[val]`. However, in `multiInsert`,
- * we need the `val[]`. So that's why, we pick the insert item of the
- * `ReturnColumns` and return an array of it. COMPLEX 🤷
+ * Get raw query builder instance
*/
- multiInsert: MultiInsert
+ raw: RawBuilderContract,
/**
- * Execute the insert
+ * Truncate a given table
*/
- exec (): Promise
+ truncate (table: string): Promise,
- toSQL (): Sql
- toString (): string
+ /**
+ * Returns columns info for a given table
+ */
+ columnsInfo (table: string): Promise<{ [column: string]: knex.ColumnInfo }>,
+ columnsInfo (table: string, column: string): Promise,
+
+ /**
+ * Same as `query()`, but also selects the table for the query
+ */
+ from: DatabaseQueryBuilderContract['from'],
+
+ /**
+ * Same as `insertQuery()`, but also selects the table for the query
+ */
+ table: InsertQueryBuilderContract['table'],
+
+ /**
+ * Get instance of transaction client
+ */
+ transaction (): Promise,
+ }
+
+ /**
+ * The shape of transaction client to run queries under a given
+ * transaction on a single connection
+ */
+ interface TransactionClientContract extends QueryClientContract {
+ knexClient: knex.Transaction,
+
+ /**
+ * Is transaction completed or not
+ */
+ isCompleted: boolean,
+
+ /**
+ * Commit transaction
+ */
+ commit (): Promise,
+
+ /**
+ * Rollback transaction
+ */
+ rollback (): Promise
}
}
diff --git a/index.ts b/index.ts
index 28f22d70..e69de29b 100644
--- a/index.ts
+++ b/index.ts
@@ -1,141 +0,0 @@
-// import * as Knex from 'knex'
-// // // import { join } from 'path'
-// import { DatabaseQueryBuilderContract } from '@ioc:Adonis/Addons/DatabaseQueryBuilder'
-
-// const knex = Knex({
-// client: 'pg',
-// connection: {
-// host: '0.0.0.0',
-// user: 'virk',
-// password: '',
-// database: 'directory-service',
-// },
-// pool: {
-// min: 0,
-// max: 5,
-// idleTimeoutMillis: 30000,
-// },
-// useNullAsDefault: true,
-// })
-
-// knex()
-// .from('foo')
-// .havingIn('f', ['a'])
-
-// // // let i = 0;
-// // knex['_context'].client.pool.on('destroySuccess', _eventId => {
-// // // i++
-// // console.log(
-// // knex['_context'].client.pool.numUsed(),
-// // knex['_context'].client.pool.numFree(),
-// // knex['_context'].client.pool.numPendingAcquires(),
-// // )
-
-// // // if (i === 3) {
-// // // knex['_context'].client.pool.destroy()
-// // // }
-// // });
-
-// // knex['_context'].client.pool.on('poolDestroySuccess', _resource => {
-// // console.log('poolDestroySuccess>>>')
-// // });
-
-// // // setInterval(() => {
-// // // console.log('ping')
-// // // }, 1000)
-
-// // // type User = {
-// // // id: number,
-// // // }
-
-// // // console.log(knex.raw(['10']).toQuery())
-
-// // // knex.schema.createTable('users', (table) => {
-// // // table.increments('id')
-// // // table.string('username')
-// // // table.integer('age')
-// // // table.timestamps()
-// // // }).then(() => console.log('created'))
-
-// // // knex.table('users').insert([
-// // // { username: 'virk', age: 29 }, { username: 'nikk', age: 28 }, { username: 'prasan', age: 29 },
-// // // ]).then(console.log)
-
-// // Promise.all([
-// // knex
-// // .select('*')
-// // .from('users')
-// // .debug(true)
-// // .then((result) => {
-// // console.log(result)
-// // }),
-// // knex
-// // .select('*')
-// // .from('users')
-// // .debug(true)
-// // .then((result) => {
-// // console.log(result)
-// // }),
-// // knex
-// // .select('*')
-// // .from('users')
-// // .debug(true)
-// // .then((result) => {
-// // console.log(result)
-// // }),
-// // knex
-// // .select('*')
-// // .from('users')
-// // .debug(true)
-// // .then((result) => {
-// // console.log(result)
-// // }),
-// // knex
-// // .select('*')
-// // .from('users')
-// // .debug(true)
-// // .then((result) => {
-// // console.log(result)
-// // }),
-// // ]).then(() => {
-// // })
-
-// // // knex.transaction().then((trx) => {
-// // // })
-
-// // // console.log(query.toSQL())
-
-// // // type FilteredKeys = { [P in keyof T]: T[P] extends Function ? never : P }[keyof T]
-
-// // // type GetRefs = T['refs'] extends object ? {
-// // // [P in keyof T['refs']]: InstanceType[P]
-// // // } : {
-// // // [P in FilteredKeys>]: InstanceType[P]
-// // // }
-
-// // // class BaseModel {
-// // // public static refs: unknown
-
-// // // public static query (
-// // // this: T,
-// // // ): DatabaseQueryBuilderContract, InstanceType