UNPKG

25.9 kBTypeScriptView Raw
1/// <reference path="querybuilder.d.ts" />
2/// <reference types="@adonisjs/events/build/adonis-typings" />
3/// <reference types="@adonisjs/profiler/build/adonis-typings/profiler" />
4/// <reference types="node" />
5/// <reference types="@adonisjs/logger/build/adonis-typings/logger" />
6declare module '@ioc:Adonis/Lucid/Database' {
7 import { Knex } from 'knex';
8 import { Pool } from 'tarn';
9 import { EventEmitter } from 'events';
10 import { ConnectionOptions } from 'tls';
11 import { EmitterContract } from '@ioc:Adonis/Core/Event';
12 import { MacroableConstructorContract } from 'macroable';
13 import { LoggerContract } from '@ioc:Adonis/Core/Logger';
14 import { HealthReportEntry } from '@ioc:Adonis/Core/HealthCheck';
15 import { LucidModel, ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
16 import { ProfilerRowContract, ProfilerContract } from '@ioc:Adonis/Core/Profiler';
17 /**
18 * Same as knex. Need to redefine, as knex doesn't export this
19 * type
20 */
21 export type IsolationLevels = 'read uncommitted' | 'read committed' | 'snapshot' | 'repeatable read' | 'serializable';
22 /**
23 * Migration node returned by the migration source
24 * implementation
25 */
26 export type FileNode<T> = {
27 absPath: string;
28 name: string;
29 getSource: () => T | Promise<T>;
30 };
31 /**
32 * Dialect specific methods
33 */
34 export interface DialectContract {
35 readonly name: 'mssql' | 'mysql' | 'oracledb' | 'postgres' | 'redshift' | 'sqlite3' | 'better-sqlite3';
36 readonly dateTimeFormat: string;
37 readonly version?: string;
38 readonly supportsAdvisoryLocks: boolean;
39 readonly supportsViews: boolean;
40 readonly supportsTypes: boolean;
41 readonly supportsReturningStatement: boolean;
42 getAllTables(schemas?: string[]): Promise<string[]>;
43 dropAllTables(schemas?: string[]): Promise<void>;
44 getAllViews(schemas?: string[]): Promise<string[]>;
45 dropAllViews(schemas?: string[]): Promise<void>;
46 getAllTypes(schemas?: string[]): Promise<string[]>;
47 dropAllTypes(schemas?: string[]): Promise<void>;
48 truncate(table: string, cascade?: boolean): Promise<void>;
49 getAdvisoryLock(key: string | number, timeout?: number): Promise<boolean>;
50 releaseAdvisoryLock(key: string | number): Promise<boolean>;
51 }
52 /**
53 * Shape of the transaction function to create a new transaction
54 */
55 export interface TransactionFn {
56 <T>(callback: (trx: TransactionClientContract) => Promise<T>, options?: {
57 isolationLevel?: IsolationLevels;
58 }): Promise<T>;
59 (options?: {
60 isolationLevel?: IsolationLevels;
61 }): Promise<TransactionClientContract>;
62 }
63 /**
64 * Shape of the query client, that is used to retrive instances
65 * of query builder
66 */
67 export interface QueryClientContract {
68 emitter: EmitterContract;
69 /**
70 * Custom profiler to time queries
71 */
72 profiler?: ProfilerRowContract | ProfilerContract;
73 /**
74 * Tells if client is a transaction client or not
75 */
76 readonly isTransaction: boolean;
77 /**
78 * The database dialect in use
79 */
80 readonly dialect: DialectContract;
81 /**
82 * The client mode in which it is execute queries
83 */
84 readonly mode: 'dual' | 'write' | 'read';
85 /**
86 * The name of the connnection from which the client
87 * was originated
88 */
89 readonly connectionName: string;
90 /**
91 * Is debug enabled on the connnection or not. Also opens up the API to
92 * disable debug for a given client
93 */
94 debug: boolean;
95 /**
96 * Returns schema instance for the write client
97 */
98 schema: Knex.SchemaBuilder;
99 /**
100 * Returns the read and write clients
101 */
102 getReadClient(): Knex<any, any>;
103 getWriteClient(): Knex<any, any>;
104 /**
105 * Returns the query builder for a given model
106 */
107 modelQuery<T extends LucidModel, Result = T>(model: T): ModelQueryBuilderContract<T, Result>;
108 /**
109 * Returns the knex query builder instance
110 */
111 knexQuery(): Knex.QueryBuilder;
112 /**
113 * Returns the knex raw query builder instance
114 */
115 knexRawQuery(sql: string, bindings?: RawQueryBindings): Knex.Raw;
116 /**
117 * Get new query builder instance for select, update and
118 * delete calls
119 */
120 query<Result = any>(): DatabaseQueryBuilderContract<Result>;
121 /**
122 * Get new query builder instance inserts
123 */
124 insertQuery<ReturnColumns = any>(): InsertQueryBuilderContract<ReturnColumns[]>;
125 /**
126 * Get raw query builder instance
127 */
128 rawQuery<Result = any>(sql: string, bindings?: RawQueryBindings): RawQueryBuilderContract<Result>;
129 /**
130 * Returns instance of reference builder
131 */
132 ref(reference: string): ReferenceBuilderContract;
133 /**
134 * Returns instance of raw builder
135 */
136 raw(sql: string, bindings?: RawQueryBindings): RawBuilderContract;
137 /**
138 * Truncate a given table
139 */
140 truncate(table: string, cascade?: boolean): Promise<void>;
141 /**
142 * Returns columns info for a given table
143 */
144 columnsInfo(table: string): Promise<{
145 [column: string]: Knex.ColumnInfo;
146 }>;
147 columnsInfo(table: string, column: string): Promise<Knex.ColumnInfo>;
148 /**
149 * Get all tables of the database
150 */
151 getAllTables(schemas?: string[]): Promise<string[]>;
152 /**
153 * Returns an array of all views names for one or many schemas
154 */
155 getAllViews(schemas?: string[]): Promise<string[]>;
156 /**
157 * Returns an array of all types names
158 */
159 getAllTypes(schemas?: string[]): Promise<string[]>;
160 /**
161 * Drop all tables inside database
162 */
163 dropAllTables(schemas?: string[]): Promise<void>;
164 /**
165 * Drop all views inside the database
166 */
167 dropAllViews(schemas?: string[]): Promise<void>;
168 /**
169 * Drop all types inside the database
170 */
171 dropAllTypes(schemas?: string[]): Promise<void>;
172 /**
173 * Same as `query()`, but also selects the table for the query. The `from` method
174 * doesn't allow defining the return type and one must use `query` to define
175 * that.
176 */
177 from: FromTable<DatabaseQueryBuilderContract<any>>;
178 /**
179 * Same as `insertQuery()`, but also selects the table for the query.
180 * The `table` method doesn't allow defining the return type and
181 * one must use `insertQuery` to define that.
182 */
183 table: <ReturnColumns = any>(table: string) => InsertQueryBuilderContract<ReturnColumns[]>;
184 /**
185 * Get instance of transaction client
186 */
187 transaction: TransactionFn;
188 /**
189 * Work with advisory locks
190 */
191 getAdvisoryLock(key: string | number, timeout?: number): Promise<boolean>;
192 releaseAdvisoryLock(key: string | number): Promise<boolean>;
193 }
194 /**
195 * The shape of transaction client to run queries under a given
196 * transaction on a single connection
197 */
198 export interface TransactionClientContract extends QueryClientContract, EventEmitter {
199 knexClient: Knex.Transaction;
200 /**
201 * Custom profiler to time queries
202 */
203 profiler?: ProfilerRowContract;
204 /**
205 * Is transaction completed or not
206 */
207 isCompleted: boolean;
208 /**
209 * Commit transaction
210 */
211 commit(): Promise<void>;
212 /**
213 * Rollback transaction
214 */
215 rollback(): Promise<void>;
216 /**
217 * Returns the read and write transaction clients
218 */
219 getReadClient(): Knex.Transaction<any, any>;
220 getWriteClient(): Knex.Transaction<any, any>;
221 /**
222 * Transaction named events
223 */
224 on(event: 'commit', handler: (client: this) => void): this;
225 on(event: 'rollback', handler: (client: this) => void): this;
226 once(event: 'commit', handler: (client: this) => void): this;
227 once(event: 'rollback', handler: (client: this) => void): this;
228 after(event: 'rollback' | 'commit', handler: () => void | Promise<void>): this;
229 }
230 /**
231 * Connection node used by majority of database
232 * clients
233 */
234 type SharedConnectionNode = {
235 host?: string;
236 user?: string;
237 password?: string;
238 database?: string;
239 port?: number;
240 };
241 /**
242 * Shape of the report node for the database connection report
243 */
244 export type ReportNode = {
245 connection: string;
246 message: string;
247 error: any;
248 };
249 /**
250 * Migrations config
251 */
252 export type MigratorConfig = {
253 disableTransactions?: boolean;
254 paths?: string[];
255 tableName?: string;
256 disableRollbacksInProduction?: boolean;
257 naturalSort?: boolean;
258 };
259 /**
260 * Seeders config
261 */
262 export type SeedersConfig = {
263 paths: string[];
264 };
265 /**
266 * Shared config options for all clients
267 */
268 type SharedConfigNode = {
269 useNullAsDefault?: boolean;
270 debug?: boolean;
271 asyncStackTraces?: boolean;
272 revision?: number;
273 healthCheck?: boolean;
274 migrations?: MigratorConfig;
275 seeders?: SeedersConfig;
276 pool?: {
277 afterCreate?: (conn: any, done: any) => void;
278 min?: number;
279 max?: number;
280 acquireTimeoutMillis?: number;
281 createTimeoutMillis?: number;
282 idleTimeoutMillis?: number;
283 createRetryIntervalMillis?: number;
284 reapIntervalMillis?: number;
285 log?: (msg: string) => any;
286 validate?: (resource: any) => boolean;
287 propagateCreateError?: boolean;
288 };
289 };
290 /**
291 * The Sqlite specific config options are taken directly from the
292 * driver. https://github.com/mapbox/node-sqlite3/wiki/API#new-sqlite3databasefilename-mode-callback
293 *
294 * Knex forwards all config options to the driver directly. So feel
295 * free to define them (let us know, in case any options are missing)
296 */
297 export type SqliteConfig = SharedConfigNode & {
298 client: 'sqlite' | 'sqlite3' | 'better-sqlite3';
299 connection: {
300 filename: string;
301 flags?: string[];
302 debug?: boolean;
303 mode?: any;
304 };
305 replicas?: never;
306 };
307 /**
308 * The MYSQL specific config options are taken directly from the
309 * driver. https://www.npmjs.com/package/mysql#connection-options
310 *
311 * Knex forwards all config options to the driver directly. So feel
312 * free to define them (let us know, in case any options are missing)
313 */
314 type MysqlConnectionNode = {
315 socketPath?: string;
316 localAddress?: string;
317 charset?: string;
318 timezone?: string;
319 stringifyObjects?: boolean;
320 insecureAuth?: boolean;
321 typeCast?: boolean;
322 supportBigNumbers?: boolean;
323 bigNumberStrings?: boolean;
324 dateStrings?: boolean | string[];
325 flags?: string;
326 ssl?: any;
327 };
328 export type MysqlConfig = SharedConfigNode & {
329 client: 'mysql' | 'mysql2';
330 version?: string;
331 connection?: SharedConnectionNode & MysqlConnectionNode;
332 replicas?: {
333 write: {
334 connection: MysqlConfig['connection'];
335 pool?: MysqlConfig['pool'];
336 };
337 read: {
338 connection: MysqlConfig['connection'][];
339 pool?: MysqlConfig['pool'];
340 };
341 };
342 };
343 /**
344 * Config is picked from PostgreSQL driver, just refer their docs
345 * https://node-postgres.com/features/connecting#programmatic.
346 *
347 * - `returning` is added by knex and not driver.
348 * - `searchPath` is also added by Knex.
349 *
350 * Knex forwards all config options to the driver directly. So feel
351 * free to define them (let us know, in case any options are missing)
352 */
353 type PostgresConnectionNode = {
354 ssl?: boolean | ConnectionOptions;
355 };
356 export type PostgreConfig = SharedConfigNode & {
357 client: 'pg' | 'postgres' | 'postgresql';
358 version?: string;
359 returning?: string;
360 connection?: string | (SharedConnectionNode & PostgresConnectionNode);
361 replicas?: {
362 write: {
363 connection: PostgreConfig['connection'];
364 pool?: PostgreConfig['pool'];
365 };
366 read: {
367 connection: PostgreConfig['connection'][];
368 pool?: PostgreConfig['pool'];
369 };
370 };
371 searchPath?: string[];
372 wrapIdentifier?: (value: string) => string;
373 };
374 /**
375 * Redshift uses `pg` driver. So config options are same as Postgres.
376 * https://node-postgres.com/features/connecting#programmatic.
377 *
378 * Knex forwards all config options to the driver directly. So feel
379 * free to define them (let us know, in case any options are missing)
380 */
381 export type RedshiftConfig = PostgreConfig & {
382 client: 'redshift';
383 };
384 /**
385 * Please install `oracledb` driver and not the `oracle`. The later is
386 * deprecated. Config is only allowed for `oracledb`.
387 *
388 * Please refer to the driver configuration docs to learn more about the
389 * config values.
390 * https://oracle.github.io/node-oracledb/doc/api.html#oracledbproperties
391 */
392 type OracleConnectionNode = {
393 autoCommit?: boolean;
394 connectionClass?: string;
395 edition?: string;
396 externalAuth?: boolean;
397 fetchArraySize?: number;
398 fetchAsBuffer?: any[];
399 lobPrefetchSize?: number;
400 maxRows?: number;
401 oracleClientVersion?: number;
402 };
403 export type OracleConfig = SharedConfigNode & {
404 client: 'oracledb';
405 connection?: SharedConnectionNode & OracleConnectionNode;
406 replicas?: {
407 write: {
408 connection: OracleConfig['connection'];
409 pool?: OracleConfig['pool'];
410 };
411 read: {
412 connection: OracleConfig['connection'][];
413 pool?: OracleConfig['pool'];
414 };
415 };
416 fetchAsString?: any[];
417 };
418 /**
419 * Config values are taken directly from the driver config.
420 * https://www.npmjs.com/package/mssql#config.
421 *
422 * Knex forwards all config options to the driver directly. So feel
423 * free to define them (let us know, in case any options are missing)
424 */
425 type MssqlConnectionNode = {
426 server: string;
427 domain?: string;
428 connectionTimeout?: number;
429 requestTimeout?: number;
430 parseJSON?: boolean;
431 options?: {
432 encrypt?: boolean;
433 useUTC?: boolean;
434 tdsVersion?: string;
435 appName?: string;
436 abortTransactionOnError?: boolean;
437 trustedConnection?: boolean;
438 enableArithAbort?: boolean;
439 isolationLevel?: 'READ_UNCOMMITTED' | 'READ_COMMITTED' | 'REPEATABLE_READ' | 'SERIALIZABLE' | 'SNAPSHOT';
440 maxRetriesOnTransientErrors?: number;
441 multiSubnetFailover?: boolean;
442 packetSize?: number;
443 trustServerCertificate?: boolean;
444 };
445 };
446 export type MssqlConfig = SharedConfigNode & {
447 client: 'mssql';
448 version?: string;
449 connection?: SharedConnectionNode & MssqlConnectionNode;
450 replicas?: {
451 write: {
452 connection: MssqlConfig['connection'];
453 pool?: MssqlConfig['pool'];
454 };
455 read: {
456 connection: MssqlConfig['connection'][];
457 pool?: MssqlConfig['pool'];
458 };
459 };
460 };
461 /**
462 * Connection config must be the config from one of the
463 * available dialects
464 */
465 export type ConnectionConfig = SqliteConfig | MysqlConfig | PostgreConfig | OracleConfig | RedshiftConfig | MssqlConfig;
466 /**
467 * Shape of config inside the database config file
468 */
469 export type DatabaseConfig = {
470 connection: string;
471 connections: {
472 [key: string]: ConnectionConfig;
473 };
474 };
475 /**
476 * The shape of a connection within the connection manager
477 */
478 export type ConnectionNode = {
479 name: string;
480 config: ConnectionConfig;
481 connection?: ConnectionContract;
482 state: 'registered' | 'migrating' | 'open' | 'closing' | 'closed';
483 };
484 /**
485 * Connection manager to manage one or more database
486 * connections.
487 */
488 export interface ConnectionManagerContract {
489 /**
490 * List of registered connection. You must check the connection state
491 * to understand, if it is connected or not
492 */
493 connections: Map<string, ConnectionNode>;
494 /**
495 * Add a new connection to the list of managed connection. You must call
496 * connect separately to instantiate a connection instance
497 */
498 add(connectionName: string, config: ConnectionConfig): void;
499 /**
500 * Instantiate a connection. It is a noop, when connection for the given
501 * name is already instantiated
502 */
503 connect(connectionName: string): void;
504 /**
505 * Get connection node
506 */
507 get(connectionName: string): ConnectionNode | undefined;
508 /**
509 * Find if a connection name is managed by the manager or not
510 */
511 has(connectionName: string): boolean;
512 /**
513 * Patch the existing connection config. This triggers the disconnect on the
514 * old connection
515 */
516 patch(connectionName: string, config: ConnectionConfig): void;
517 /**
518 * Find if a managed connection is instantiated or not
519 */
520 isConnected(connectionName: string): boolean;
521 /**
522 * Close a given connection. This is also kill the underlying knex connection
523 * pool
524 */
525 close(connectionName: string, release?: boolean): Promise<void>;
526 /**
527 * Close all managed connections
528 */
529 closeAll(release?: boolean): Promise<void>;
530 /**
531 * Release a given connection. Releasing a connection means, you will have to
532 * re-add it using the `add` method
533 */
534 release(connectionName: string): Promise<void>;
535 /**
536 * Returns the health check report for registered connections
537 */
538 report(): Promise<HealthReportEntry & {
539 meta: ReportNode[];
540 }>;
541 }
542 /**
543 * Connection represents a single knex instance with inbuilt
544 * pooling capabilities.
545 */
546 export interface ConnectionContract extends EventEmitter {
547 client?: Knex;
548 readClient?: Knex;
549 readonly dialectName: 'mssql' | 'mysql' | 'mysql2' | 'oracledb' | 'postgres' | 'redshift' | 'sqlite3';
550 /**
551 * Property to find if explicit read/write is enabled
552 */
553 readonly hasReadWriteReplicas: boolean;
554 /**
555 * Read/write connection pools
556 */
557 pool: null | Pool<any>;
558 readPool: null | Pool<any>;
559 /**
560 * Name of the connection
561 */
562 readonly name: string;
563 /**
564 * Find if connection is ready or not
565 */
566 readonly ready: boolean;
567 /**
568 * Untouched config
569 */
570 config: ConnectionConfig;
571 /**
572 * List of emitted events
573 */
574 on(event: 'connect', callback: (connection: ConnectionContract) => void): this;
575 on(event: 'error', callback: (error: Error, connection: ConnectionContract) => void): this;
576 on(event: 'disconnect', callback: (connection: ConnectionContract) => void): this;
577 on(event: 'disconnect:error', callback: (error: Error, connection: ConnectionContract) => void): this;
578 /**
579 * Make knex connection
580 */
581 connect(): void;
582 /**
583 * Disconnect knex
584 */
585 disconnect(): Promise<void>;
586 /**
587 * Returns the connection report
588 */
589 getReport(): Promise<ReportNode>;
590 }
591 /**
592 * Options when retrieving new query client from the database
593 * query builder
594 */
595 export type DatabaseClientOptions = Partial<{
596 mode: 'read' | 'write';
597 profiler: ProfilerRowContract | ProfilerContract;
598 }>;
599 /**
600 * Shape of the data emitted by the `db:query event`
601 */
602 export type DbQueryEventNode = {
603 connection: string;
604 model?: string;
605 ddl?: boolean;
606 duration?: [number, number];
607 method: string;
608 sql: string;
609 bindings?: any[];
610 inTransaction?: boolean;
611 };
612 /**
613 * Database contract serves as the main API to interact with multiple
614 * database connections
615 */
616 export interface DatabaseContract {
617 Database: MacroableConstructorContract<DatabaseContract> & {
618 new (config: DatabaseConfig, logger: LoggerContract, profiler: ProfilerContract, emitter: EmitterContract): DatabaseContract;
619 };
620 DatabaseQueryBuilder: MacroableConstructorContract<DatabaseQueryBuilderContract>;
621 InsertQueryBuilder: MacroableConstructorContract<InsertQueryBuilderContract>;
622 ModelQueryBuilder: MacroableConstructorContract<ModelQueryBuilderContract<any, any>>;
623 SimplePaginator: {
624 namingStrategy: {
625 paginationMetaKeys(): SimplePaginatorMetaKeys;
626 };
627 new <Row>(total: number, perPage: number, currentPage: number, ...rows: Row[]): SimplePaginatorContract<Row>;
628 };
629 hasHealthChecksEnabled: boolean;
630 /**
631 * Pretty print query logs
632 */
633 prettyPrint: (queryLog: DbQueryEventNode) => void;
634 /**
635 * Name of the primary connection defined inside `config/database.ts`
636 * file
637 */
638 primaryConnectionName: string;
639 /**
640 * Reference to the connection manager
641 */
642 manager: ConnectionManagerContract;
643 /**
644 * Returns the raw connection instance
645 */
646 getRawConnection: ConnectionManagerContract['get'];
647 /**
648 * Get query client for a given connection. Optionally one can also define
649 * the mode of the connection and profiler row
650 */
651 connection(connectionName?: string, options?: DatabaseClientOptions): QueryClientContract;
652 /**
653 * Returns the knex query builder instance
654 */
655 knexQuery(): Knex.QueryBuilder;
656 /**
657 * Returns the knex raw query builder instance
658 */
659 knexRawQuery(sql: string, bindings?: RawQueryBindings): Knex.Raw;
660 /**
661 * Returns the query builder for a given model
662 */
663 modelQuery<T extends LucidModel, Result = T>(model: T, options?: DatabaseClientOptions): ModelQueryBuilderContract<T, Result>;
664 /**
665 * Get query builder instance for a given connection.
666 */
667 query<Result = any>(options?: DatabaseClientOptions): DatabaseQueryBuilderContract<Result>;
668 /**
669 * Get insert query builder instance for a given connection.
670 */
671 insertQuery<ReturnColumns = any>(options?: DatabaseClientOptions): InsertQueryBuilderContract<ReturnColumns[]>;
672 /**
673 * Get raw query builder instance
674 */
675 rawQuery<Result = any>(sql: string, bindings?: RawQueryBindings, options?: DatabaseClientOptions): RawQueryBuilderContract<Result>;
676 /**
677 * Returns instance of reference builder
678 */
679 ref(reference: string): ReferenceBuilderContract;
680 /**
681 * Returns instance of raw builder
682 */
683 raw(sql: string, bindings?: RawQueryBindings): RawBuilderContract;
684 /**
685 * Selects a table on the default connection by instantiating a new query
686 * builder instance. This method provides no control over the client
687 * mode and one must use `query` for that
688 */
689 from: QueryClientContract['from'];
690 /**
691 * Selects a table on the default connection by instantiating a new query
692 * builder instance. This method provides no control over the client
693 * mode and one must use `insertQuery` for that
694 */
695 table: QueryClientContract['table'];
696 /**
697 * Start a new transaction
698 */
699 transaction: TransactionFn;
700 /**
701 * Returns the health check report for registered connections
702 */
703 report(): Promise<HealthReportEntry & {
704 meta: ReportNode[];
705 }>;
706 /**
707 * Begin a new global transaction. Multiple calls to this
708 * method is a noop
709 */
710 beginGlobalTransaction(connectionName?: string, options?: Exclude<DatabaseClientOptions, 'mode'>): Promise<TransactionClientContract>;
711 /**
712 * Commit an existing global transaction
713 */
714 commitGlobalTransaction(connectionName?: string): Promise<void>;
715 /**
716 * Rollback an existing global transaction
717 */
718 rollbackGlobalTransaction(connectionName?: string): Promise<void>;
719 }
720 const Database: DatabaseContract;
721 export default Database;
722}