@creator.co/wapi 1.3.19-alpha1 → 1.4.0-alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/package.json +2 -1
  2. package/dist/src/API/Request.js.map +1 -1
  3. package/dist/src/API/Response.js.map +1 -1
  4. package/dist/src/API/Utils.js.map +1 -1
  5. package/dist/src/BaseEvent/EventProcessor.js.map +1 -1
  6. package/dist/src/BaseEvent/Transaction.d.ts +1 -1
  7. package/dist/src/Config/Configuration.js.map +1 -1
  8. package/dist/src/Config/EnvironmentVar.js.map +1 -1
  9. package/dist/src/Crypto/JWT.js.map +1 -1
  10. package/dist/src/Database/Database.d.ts +8 -5
  11. package/dist/src/Database/Database.js +5 -3
  12. package/dist/src/Database/Database.js.map +1 -1
  13. package/dist/src/Database/DatabaseManager.d.ts +30 -9
  14. package/dist/src/Database/DatabaseManager.js +25 -10
  15. package/dist/src/Database/DatabaseManager.js.map +1 -1
  16. package/dist/src/Database/DatabaseTransaction.d.ts +66 -31
  17. package/dist/src/Database/DatabaseTransaction.js +51 -30
  18. package/dist/src/Database/DatabaseTransaction.js.map +1 -1
  19. package/dist/src/Database/integrations/knex/KnexDatabase.d.ts +22 -8
  20. package/dist/src/Database/integrations/knex/KnexDatabase.js +18 -13
  21. package/dist/src/Database/integrations/knex/KnexDatabase.js.map +1 -1
  22. package/dist/src/Database/integrations/knex/KnexTransaction.d.ts +39 -16
  23. package/dist/src/Database/integrations/knex/KnexTransaction.js +83 -17
  24. package/dist/src/Database/integrations/knex/KnexTransaction.js.map +1 -1
  25. package/dist/src/Database/integrations/kysely/KyselyDatabase.d.ts +55 -0
  26. package/dist/src/Database/integrations/kysely/KyselyDatabase.js +126 -0
  27. package/dist/src/Database/integrations/kysely/KyselyDatabase.js.map +1 -0
  28. package/dist/src/Database/integrations/kysely/KyselyTransaction.d.ts +70 -0
  29. package/dist/src/Database/integrations/kysely/KyselyTransaction.js +186 -0
  30. package/dist/src/Database/integrations/kysely/KyselyTransaction.js.map +1 -0
  31. package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +16 -11
  32. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +19 -18
  33. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -1
  34. package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +42 -16
  35. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +84 -18
  36. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -1
  37. package/dist/src/Database/types.d.ts +47 -26
  38. package/dist/src/Logger/Logger.d.ts +6 -6
  39. package/dist/src/Logger/Logger.js +12 -15
  40. package/dist/src/Logger/Logger.js.map +1 -1
  41. package/dist/src/Publisher/Publisher.js.map +1 -1
  42. package/dist/src/Server/RouteResolver.js.map +1 -1
  43. package/dist/src/Server/lib/ContainerServer.js.map +1 -1
  44. package/dist/src/Server/lib/Server.js.map +1 -1
  45. package/dist/src/Server/lib/container/GenericHandler.js +2 -2
  46. package/dist/src/Server/lib/container/GenericHandler.js.map +1 -1
  47. package/dist/src/Server/lib/container/GenericHandlerEvent.js +1 -1
  48. package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +1 -1
  49. package/dist/src/Server/lib/container/Utils.js.map +1 -1
  50. package/dist/src/Validation/Validator.js.map +1 -1
  51. package/package.json +2 -1
  52. package/src/BaseEvent/Transaction.ts +2 -2
  53. package/src/Database/Database.ts +8 -5
  54. package/src/Database/DatabaseManager.ts +34 -17
  55. package/src/Database/DatabaseTransaction.ts +79 -35
  56. package/src/Database/integrations/knex/KnexDatabase.ts +22 -11
  57. package/src/Database/integrations/knex/KnexTransaction.ts +52 -19
  58. package/src/Database/integrations/kysely/KyselyDatabase.ts +87 -0
  59. package/src/Database/integrations/kysely/KyselyTransaction.ts +172 -0
  60. package/src/Database/integrations/pgsql/PostgresDatabase.ts +26 -14
  61. package/src/Database/integrations/pgsql/PostgresTransaction.ts +55 -22
  62. package/src/Database/types.ts +53 -31
  63. package/src/Logger/Logger.ts +12 -15
  64. package/src/Server/lib/container/GenericHandler.ts +2 -2
  65. package/tests/Database/DatabaseManager.test.ts +16 -1
  66. package/tests/Database/integrations/knex/KnexDatabase.test.ts +2 -2
  67. package/tests/Database/integrations/knex/KnexTransaction.test.ts +52 -45
  68. package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +109 -0
  69. package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +118 -0
  70. package/tests/Database/integrations/pg/PostgresDatabase.test.ts +32 -6
  71. package/tests/Database/integrations/pg/PostgresTransaction.test.ts +75 -9
  72. package/tsconfig.json +1 -0
@@ -6,17 +6,24 @@ import { Database } from '../../Database'
6
6
  import type { DbConfig } from '../../types'
7
7
 
8
8
  /**
9
- * Represents a Knex database connection.
10
- * @extends Database<KnexTransaction>
9
+ * Represents a KnexDatabase class that extends Database and provides methods for interacting with a Knex database.
11
10
  */
12
11
  export class KnexDatabase extends Database<KnexTransaction> {
13
- private static knexProvider: (config: knex.Knex.Config<any>) => knex.Knex<any, unknown[]> = knex
14
-
15
- private client: Knex
12
+ /**
13
+ * A static property that provides a Knex instance based on the given configuration.
14
+ * @param {knex.Knex.Config<any>} config - The configuration object for Knex.
15
+ * @returns {knex.Knex<any, unknown[]>} A Knex instance based on the provided configuration.
16
+ */
17
+ public static knexProvider: (config: knex.Knex.Config<any>) => knex.Knex<any, unknown[]> = knex
18
+ /**
19
+ * Represents a Knex client for interacting with a database.
20
+ * @type {Knex}
21
+ */
22
+ public readonly client: Knex
16
23
 
17
24
  /**
18
- * Constructs a new instance of the database class using the provided configuration.
19
- * @param {DbConfig<'knex'>} config - The configuration object for the database.
25
+ * Constructor for creating a new instance of a database connection using Knex.
26
+ * @param {DbConfig<'knex'>} config - The configuration object for the Knex database.
20
27
  * @returns None
21
28
  */
22
29
  public constructor(config: DbConfig<'knex'>) {
@@ -25,6 +32,11 @@ export class KnexDatabase extends Database<KnexTransaction> {
25
32
  this.client = KnexDatabase.knexProvider(this.constructConfig(config))
26
33
  }
27
34
 
35
+ /**
36
+ * Constructs a Knex configuration object based on the provided DbConfig.
37
+ * @param {DbConfig<'knex'>} config - The database configuration object.
38
+ * @returns The Knex configuration object with appropriate settings based on the input config.
39
+ */
28
40
  private constructConfig(config: DbConfig<'knex'>) {
29
41
  const knexConfig = {
30
42
  client: config.driver,
@@ -45,11 +57,10 @@ export class KnexDatabase extends Database<KnexTransaction> {
45
57
  }
46
58
 
47
59
  /**
48
- * Initiates a transaction using the underlying database client.
49
- * @returns {Promise<KnexTransaction>} A promise that resolves to a KnexTransaction object representing the transaction.
60
+ * Override method to start a new transaction using KnexTransactionImpl.
61
+ * @returns {Promise<KnexTransaction>} A promise that resolves to a KnexTransaction object.
50
62
  */
51
63
  public override async transaction(): Promise<KnexTransaction> {
52
- const delegate = await this.client.transaction()
53
- return KnexTransactionImpl.wrapDelegate(delegate, this)
64
+ return await KnexTransactionImpl.newTransaction(this.client, this)
54
65
  }
55
66
  }
@@ -1,51 +1,84 @@
1
1
  import { Knex } from 'knex'
2
2
 
3
3
  import { KnexDatabase } from './KnexDatabase'
4
+ import { Database } from '../../Database'
4
5
  import { DatabaseTransaction } from '../../DatabaseTransaction'
5
6
 
6
7
  /**
7
- * A type alias for a Knex transaction object.
8
- * @typedef {KnexTransactionImpl & Knex.Transaction} KnexTransaction
8
+ * Represents a Knex transaction, combining the functionality of KnexTransactionImpl
9
+ * and Knex.Transaction types.
9
10
  */
10
11
  export type KnexTransaction = KnexTransactionImpl & Knex.Transaction
11
12
 
12
13
  /**
13
- * Implementation of a Knex transaction that extends the DatabaseTransaction class.
14
+ * Represents a Knex database transaction implementation that extends DatabaseTransaction.
15
+ * @class
14
16
  */
15
17
  export class KnexTransactionImpl extends DatabaseTransaction {
16
18
  /**
17
- * Constructs a new instance of the private class.
18
- * @param {Knex.Transaction} delegate - The delegate transaction object.
19
- * @param {KnexDatabase} database - The database object.
19
+ * The Knex instance used for writing operations.
20
+ * @type {Knex}
21
+ */
22
+ public readonly writer: Knex
23
+ /**
24
+ * Represents a transaction in Knex, a SQL query builder for Node.js.
25
+ * This property is used to perform a series of database operations as a single unit of work.
26
+ * @type {Knex.Transaction} - The transaction object provided by Knex.
27
+ */
28
+ protected transaction: Knex.Transaction
29
+ /**
30
+ * A protected property representing the database connection using KnexTransaction.
31
+ * @type {Database<KnexTransaction>}
32
+ */
33
+ protected database: Database<KnexTransaction>
34
+
35
+ /**
36
+ * Constructs a new instance of the class with the provided Knex writer and database.
37
+ * @param {Knex} writer - The Knex instance used for writing to the database.
38
+ * @param {KnexDatabase} database - The KnexDatabase instance used for database operations.
20
39
  * @returns None
21
40
  */
22
- private constructor(delegate: Knex.Transaction, database: KnexDatabase) {
23
- super(delegate, database)
41
+ private constructor(writer: Knex, database: KnexDatabase) {
42
+ super(writer, database)
43
+ }
44
+
45
+ /**
46
+ * Creates a new database transaction using the provided Knex instance and database configuration.
47
+ * @param {Knex} write - The Knex instance used for read and write operations.
48
+ * @param {KnexDatabase} database - The database configuration for the transaction.
49
+ * @returns {Promise<KnexTransaction>} A promise that resolves to a new database transaction.
50
+ */
51
+ public static async newTransaction(
52
+ write: Knex,
53
+ database: KnexDatabase
54
+ ): Promise<KnexTransaction> {
55
+ const tx = new KnexTransactionImpl(write, database)
56
+ await tx.begin()
57
+ return DatabaseTransaction.proxyInstance(tx) as any
24
58
  }
25
59
 
26
60
  /**
27
- * Wraps a delegate transaction object with a custom implementation of the KnexTransaction interface.
28
- * @param {Knex.Transaction} delegate - The delegate transaction object to wrap.
29
- * @param {KnexDatabase} database - The KnexDatabase instance associated with the transaction.
30
- * @returns {KnexTransaction} - The wrapped transaction object.
61
+ * Initiates a transaction using the writer and assigns it to the 'transaction' property.
62
+ * @returns {Promise<Transaction>} A promise that resolves to the transaction object.
31
63
  */
32
- public static wrapDelegate(delegate: Knex.Transaction, database: KnexDatabase): KnexTransaction {
33
- return DatabaseTransaction.wrapInstance(new KnexTransactionImpl(delegate, database)) as any
64
+ protected doBegin = async () => {
65
+ this.transaction = await this.writer.transaction()
66
+ return this.transaction
34
67
  }
35
68
 
36
69
  /**
37
- * Commits the changes made by the delegate object.
70
+ * Commits the current transaction.
38
71
  * @returns None
39
72
  */
40
73
  protected doCommit = () => {
41
- return this.delegate.commit()
74
+ return this.transaction.commit()
42
75
  }
43
76
 
44
77
  /**
45
- * Performs a rollback operation by calling the rollback method of the delegate object.
46
- * @returns None
78
+ * Rollback the current transaction.
79
+ * @returns The result of the rollback operation.
47
80
  */
48
81
  protected doRollback = () => {
49
- return this.delegate.rollback()
82
+ return this.transaction.rollback()
50
83
  }
51
84
  }
@@ -0,0 +1,87 @@
1
+ import { Kysely, PostgresDialect } from 'kysely'
2
+ import { Pool } from 'pg'
3
+
4
+ import { KyselyTransaction, KyselyTransactionImpl } from './KyselyTransaction'
5
+ import { Database } from '../../Database'
6
+ import type { DbConfig } from '../../types'
7
+
8
+ /**
9
+ * Represents a database connection using the Kysely library with support for transactions.
10
+ * @template DBSchema - The schema type for the database.
11
+ */
12
+ export class KyselyDatabase<DBSchema> extends Database<KyselyTransaction<DBSchema>> {
13
+ /**
14
+ * Represents a PostgreSQL provider for querying data using the PostgresDialect.
15
+ * @type {PostgresDialect}
16
+ */
17
+ public static kyselyPgProvider = PostgresDialect
18
+ /**
19
+ * A public static property that provides access to the Kysely class.
20
+ * This property can be accessed without creating an instance of the class.
21
+ */
22
+ public static kyselyProvider = Kysely
23
+ /**
24
+ * A static property that represents a connection pool for PostgreSQL database connections.
25
+ * @type {Pool}
26
+ */
27
+ public static pgProvider = Pool
28
+ /**
29
+ * Represents a PostgreSQL client using the PostgresDialect.
30
+ */
31
+ public readonly pgClient: PostgresDialect
32
+ /**
33
+ * Represents a client for querying the database with the specified schema.
34
+ * @type {Kysely<DBSchema>} client - The client for querying the database.
35
+ */
36
+ public readonly client: Kysely<DBSchema>
37
+ /**
38
+ * Optional property representing the Postgres dialect for reading in a database client.
39
+ */
40
+ public readonly pgReadClient?: PostgresDialect
41
+ /**
42
+ * Represents a client for reading from the database.
43
+ * @type {Kysely<DBSchema> | undefined} - The client for reading from the database.
44
+ */
45
+ public readonly readClient?: Kysely<DBSchema>
46
+
47
+ /**
48
+ * Constructor for creating a database connection using the provided configuration.
49
+ * @param {DbConfig<'kysely'>} config - The configuration object for the database connection.
50
+ * @returns None
51
+ */
52
+ public constructor(config: DbConfig<'kysely'>) {
53
+ super(config)
54
+ this.pgClient = new KyselyDatabase.kyselyPgProvider({
55
+ pool: new KyselyDatabase.pgProvider({
56
+ host: config.host,
57
+ port: config.port,
58
+ user: config.username,
59
+ password: config.password,
60
+ database: config.database,
61
+ max: config.maxConnections,
62
+ }),
63
+ })
64
+ this.client = new KyselyDatabase.kyselyProvider<DBSchema>({ dialect: this.pgClient })
65
+ if (config.readReplica) {
66
+ this.pgReadClient = new KyselyDatabase.kyselyPgProvider({
67
+ pool: new KyselyDatabase.pgProvider({
68
+ host: config.readReplica.host,
69
+ port: config.readReplica.port,
70
+ user: config.readReplica.username,
71
+ password: config.readReplica.password,
72
+ database: config.readReplica.database,
73
+ max: config.readReplica.maxConnections,
74
+ }),
75
+ })
76
+ this.readClient = new KyselyDatabase.kyselyProvider<DBSchema>({ dialect: this.pgReadClient })
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Override method that starts a new transaction using the provided client and read client.
82
+ * @returns A Promise that resolves to a KyselyTransaction object for the specified database schema.
83
+ */
84
+ public override async transaction(): Promise<KyselyTransaction<DBSchema>> {
85
+ return KyselyTransactionImpl.newTransaction<DBSchema>(this.client, this, this.readClient)
86
+ }
87
+ }
@@ -0,0 +1,172 @@
1
+ import { Kysely, Transaction } from 'kysely'
2
+
3
+ import { KyselyDatabase } from './KyselyDatabase'
4
+ import { Database } from '../../Database'
5
+ import { DatabaseTransaction } from '../../DatabaseTransaction'
6
+
7
+ /**
8
+ * Represents a transaction for querying a database with a specific schema.
9
+ * @typeparam DBSchema - The schema of the database.
10
+ * @type {KyselyTransactionImpl<DBSchema> & Transaction<DBSchema>}
11
+ */
12
+ export type KyselyTransaction<DBSchema> = KyselyTransactionImpl<DBSchema> & Transaction<DBSchema>
13
+ /**
14
+ * Represents a transaction in a Postgres database.
15
+ */
16
+ export class KyselyTransactionImpl<DBSchema> extends DatabaseTransaction {
17
+ /**
18
+ * A readonly property representing a writer for a Kysely object.
19
+ * @type {Kysely<any>}
20
+ */
21
+ public readonly writer: Kysely<any>
22
+ /**
23
+ * A readonly property representing a reader of type Kysely<any>.
24
+ * This property allows reading data of any type using the Kysely interface.
25
+ */
26
+ public readonly reader: Kysely<any>
27
+ /**
28
+ * A protected property representing a transaction of type any.
29
+ */
30
+ protected transaction: Transaction<any>
31
+ /**
32
+ * A protected property representing a database instance.
33
+ * @type {Database<KyselyTransaction<DBSchema>>}
34
+ */
35
+ protected database: Database<KyselyTransaction<DBSchema>>
36
+ /**
37
+ * A private property that represents a deferred object.
38
+ * @type {Deferred<any>}
39
+ */
40
+ private txWrapper: Deferred<any>
41
+ /**
42
+ * Constructs a new instance of the class.
43
+ * @param {Kysely<DBSchema>} delegate - The delegate object for the database query.
44
+ * @param {KyselyDatabase<DBSchema>} database - The database object for the query.
45
+ * @param {Kysely<DBSchema>} [reader] - An optional reader object for the query.
46
+ * @returns None
47
+ */
48
+ private constructor(
49
+ delegate: Kysely<DBSchema>,
50
+ database: KyselyDatabase<DBSchema>,
51
+ reader?: Kysely<DBSchema>
52
+ ) {
53
+ super(delegate, database, reader)
54
+ }
55
+
56
+ /**
57
+ * Creates a new database transaction for the given database schema.
58
+ * @param {Kysely<DBSchema>} connection - The connection object for the transaction.
59
+ * @param {KyselyDatabase<DBSchema>} database - The database object for the transaction.
60
+ * @param {Kysely<DBSchema>} [reader] - An optional reader object for the transaction.
61
+ * @returns {Promise<KyselyTransaction<DBSchema>>} A promise that resolves to the created transaction.
62
+ */
63
+ public static async newTransaction<DBSchema>(
64
+ connection: Kysely<DBSchema>,
65
+ database: KyselyDatabase<DBSchema>,
66
+ reader?: Kysely<DBSchema>
67
+ ): Promise<KyselyTransaction<DBSchema>> {
68
+ const tx = new KyselyTransactionImpl<DBSchema>(connection, database, reader)
69
+ await tx.begin()
70
+ return DatabaseTransaction.proxyInstance(tx) as any
71
+ }
72
+
73
+ /**
74
+ * Asynchronously begins a transaction using a writer and resolves the transaction once it is executed.
75
+ * @returns A Promise that resolves with the transaction object once the transaction is executed.
76
+ */
77
+ protected doBegin = async () => {
78
+ this.txWrapper = new Deferred<any>()
79
+ return new Promise(resolve => {
80
+ this.writer
81
+ .transaction()
82
+ .execute(async trx => {
83
+ this.transaction = trx
84
+ resolve(trx) // resolve with tx
85
+ return this.txWrapper.promise // wait for wrapper to be solved
86
+ })
87
+ .catch(() => {
88
+ // Don't do anything here. Just swallow the exception.
89
+ })
90
+ })
91
+ }
92
+
93
+ /**
94
+ * Executes the commit operation by resolving the transaction wrapper and returning a resolved Promise.
95
+ * @returns A Promise that resolves to null.
96
+ */
97
+ protected doCommit = () => {
98
+ this.txWrapper.resolve(null)
99
+ return Promise.resolve()
100
+ }
101
+
102
+ /**
103
+ * Performs a rollback operation by rejecting the transaction wrapper with an error.
104
+ * @returns A resolved Promise after the rollback operation is completed.
105
+ */
106
+ protected doRollback = () => {
107
+ this.txWrapper.reject(new Error('Rollback'))
108
+ return Promise.resolve()
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Represents a deferred promise that can be resolved or rejected at a later time.
114
+ * @template T - The type of the value that the promise will resolve to.
115
+ */
116
+ class Deferred<T> {
117
+ /**
118
+ * A private readonly Promise object that resolves to type T.
119
+ */
120
+ private readonly _promise: Promise<T>
121
+ /**
122
+ * A private property that holds a function to resolve a Promise with a value of type T.
123
+ * @param {T | PromiseLike<T>} value - The value or promise to be resolved.
124
+ */
125
+ private _resolve?: (value: T | PromiseLike<T>) => void
126
+ /**
127
+ * A function that can be called to reject a promise with an optional reason.
128
+ * @param {any} [reason] - An optional reason for rejecting the promise.
129
+ */
130
+ private _reject?: (reason?: any) => void
131
+
132
+ /**
133
+ * Constructor for creating a new Promise instance with resolve and reject functions.
134
+ * @constructor
135
+ */
136
+ constructor() {
137
+ this._promise = new Promise<T>((resolve, reject) => {
138
+ this._reject = reject
139
+ this._resolve = resolve
140
+ })
141
+ }
142
+
143
+ /**
144
+ * Getter method to retrieve the Promise object.
145
+ * @returns {Promise<T>} A Promise object of type T.
146
+ */
147
+ public get promise(): Promise<T> {
148
+ return this._promise
149
+ }
150
+
151
+ /**
152
+ * Resolves the Promise with the given value.
153
+ * @param {T | PromiseLike<T>} value - The value to resolve the Promise with.
154
+ * @returns void
155
+ */
156
+ public resolve(value: T | PromiseLike<T>): void {
157
+ if (this._resolve) {
158
+ this._resolve(value)
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Rejects the Promise with the given reason, if the reject function is available.
164
+ * @param {any} reason - The reason for rejecting the Promise.
165
+ * @returns void
166
+ */
167
+ public reject(reason?: any): void {
168
+ if (this._reject) {
169
+ this._reject(reason)
170
+ }
171
+ }
172
+ }
@@ -5,24 +5,28 @@ import { Database } from '../../Database'
5
5
  import type { DbConfig } from '../../types'
6
6
 
7
7
  /**
8
- * Represents a Postgres database connection.
8
+ * Represents a Postgres database connection that extends the Database class.
9
9
  * @extends Database<PostgresTransaction>
10
10
  */
11
11
  export class PostgresDatabase extends Database<PostgresTransaction> {
12
12
  /**
13
- * A private static property that represents a connection pool for a PostgreSQL database.
13
+ * A public static property that represents a connection pool for a PostgreSQL database.
14
+ * This property is used to manage and provide connections to the PostgreSQL database.
14
15
  */
15
- private static pgProvider = Pool
16
+ public static pgProvider = Pool
16
17
  /**
17
- * The client property represents a connection pool to a database.
18
- * @private
19
- * @type {Pool}
18
+ * Represents a connection pool to manage multiple client connections to the database.
20
19
  */
21
- private client: Pool
20
+ public readonly client: Pool
21
+ /**
22
+ * A private property that represents a connection pool for clients.
23
+ * @type {Pool | undefined}
24
+ */
25
+ public readonly readClient?: Pool
22
26
 
23
27
  /**
24
- * Constructs a new instance of the class with the given database configuration.
25
- * @param {DbConfig<'pg'>} config - The configuration object for the PostgreSQL database.
28
+ * Constructor for creating a new instance of a database connection using Postgres.
29
+ * @param {DbConfig<'pg'>} config - The configuration object for the Postgres database.
26
30
  * @returns None
27
31
  */
28
32
  public constructor(config: DbConfig<'pg'>) {
@@ -35,15 +39,23 @@ export class PostgresDatabase extends Database<PostgresTransaction> {
35
39
  database: config.database,
36
40
  max: config.maxConnections,
37
41
  })
42
+ if (config.readReplica) {
43
+ this.readClient = new PostgresDatabase.pgProvider({
44
+ host: config.readReplica.host,
45
+ port: config.readReplica.port,
46
+ user: config.readReplica.username,
47
+ password: config.readReplica.password,
48
+ database: config.readReplica.database,
49
+ max: config.readReplica.maxConnections,
50
+ })
51
+ }
38
52
  }
39
53
 
40
54
  /**
41
- * Initiates a new transaction in the PostgreSQL database.
42
- * @returns {Promise<PostgresTransaction>} A promise that resolves to a PostgresTransaction object representing the new transaction.
55
+ * Creates a new Postgres transaction using the provided client and read client.
56
+ * @returns {Promise<PostgresTransaction>} A promise that resolves to a new PostgresTransaction object.
43
57
  */
44
58
  public override async transaction(): Promise<PostgresTransaction> {
45
- const delegate = await this.client.connect()
46
- await delegate.query('BEGIN')
47
- return PostgresTransactionImpl.wrapDelegate(delegate, this)
59
+ return PostgresTransactionImpl.newTransaction(this.client, this, this.readClient)
48
60
  }
49
61
  }
@@ -1,6 +1,7 @@
1
- import { PoolClient } from 'pg'
1
+ import { Pool, PoolClient } from 'pg'
2
2
 
3
3
  import { PostgresDatabase } from './PostgresDatabase'
4
+ import { Database } from '../../Database'
4
5
  import { DatabaseTransaction } from '../../DatabaseTransaction'
5
6
 
6
7
  /**
@@ -14,41 +15,73 @@ export type PostgresTransaction = PostgresTransactionImpl & PoolClient
14
15
  */
15
16
  export class PostgresTransactionImpl extends DatabaseTransaction {
16
17
  /**
17
- * Constructs a new instance of the private class.
18
- * @param {PoolClient} delegate - The delegate object.
19
- * @param {PostgresDatabase} database - The database object.
20
- * @returns None
18
+ * A Pool object used for writing operations.
19
+ * @readonly
21
20
  */
22
- private constructor(delegate: PoolClient, database: PostgresDatabase) {
23
- super(delegate, database)
21
+ public readonly writer: Pool
22
+ /**
23
+ * A readonly property representing a pool reader.
24
+ */
25
+ public readonly reader: Pool
26
+ /**
27
+ * Represents a database transaction using a PoolClient.
28
+ * @type {PoolClient}
29
+ */
30
+ protected transaction: PoolClient
31
+ /**
32
+ * A protected property representing a database of type Database<PostgresTransaction>.
33
+ * This property is used to interact with a Postgres database using transactions.
34
+ */
35
+ protected database: Database<PostgresTransaction>
36
+ /**
37
+ * Constructs a new instance of the class with the provided writer, database, and optional reader.
38
+ * @param {Pool} writer - The writer pool for database operations.
39
+ * @param {PostgresDatabase} database - The Postgres database instance.
40
+ * @param {Pool} [reader] - The reader pool for database operations (optional).
41
+ */
42
+ private constructor(writer: Pool, database: PostgresDatabase, reader?: Pool) {
43
+ super(writer, database, reader)
44
+ }
45
+
46
+ /**
47
+ * Creates a new database transaction using the provided writer and database instances.
48
+ * @param {Pool} writer - The writer instance for the transaction.
49
+ * @param {PostgresDatabase} database - The database instance for the transaction.
50
+ * @param {Pool} [reader] - Optional reader instance for the transaction.
51
+ * @returns {Promise<PostgresTransaction>} A promise that resolves to a new PostgresTransaction instance.
52
+ */
53
+ public static async newTransaction(
54
+ writer: Pool,
55
+ database: PostgresDatabase,
56
+ reader?: Pool
57
+ ): Promise<PostgresTransaction> {
58
+ const tx = new PostgresTransactionImpl(writer, database, reader)
59
+ await tx.begin() // defaults to opened
60
+ return DatabaseTransaction.proxyInstance(tx) as any
24
61
  }
25
62
 
26
63
  /**
27
- * Static factory method for creating a new instance, wrapping a delegate PoolClient.
28
- * @param {PoolClient} delegate - The delegate client to wrap.
29
- * @param {PostgresDatabase} database - The PostgresDatabase instance associated with the transaction.
30
- * @returns {PostgresTransaction} - A wrapped PostgresTransaction instance.
64
+ * Initiates a transaction by connecting to the writer and executing a 'BEGIN' query.
65
+ * @returns {Promise<void>} A promise that resolves when the transaction is successfully initiated.
31
66
  */
32
- public static wrapDelegate(
33
- delegate: PoolClient,
34
- database: PostgresDatabase
35
- ): PostgresTransaction {
36
- return DatabaseTransaction.wrapInstance(new PostgresTransactionImpl(delegate, database)) as any
67
+ protected doBegin = async () => {
68
+ this.transaction = await this.writer.connect()
69
+ return this.transaction.query('BEGIN')
37
70
  }
38
71
 
39
72
  /**
40
- * Commits the current transaction.
41
- * @returns A promise that resolves when the commit is successful.
73
+ * Executes a COMMIT query to commit the current transaction.
74
+ * @returns A Promise that resolves when the COMMIT query is successfully executed.
42
75
  */
43
76
  protected doCommit = () => {
44
- return this.delegate.query('COMMIT')
77
+ return this.transaction.query('COMMIT')
45
78
  }
46
79
 
47
80
  /**
48
- * Performs a rollback operation in the database.
49
- * @returns A promise that resolves when the rollback operation is completed.
81
+ * Rolls back the current transaction by executing a 'ROLLBACK' query.
82
+ * @returns A Promise that resolves when the rollback is successful.
50
83
  */
51
84
  protected doRollback = () => {
52
- return this.delegate.query('ROLLBACK')
85
+ return this.transaction.query('ROLLBACK')
53
86
  }
54
87
  }