@creator.co/wapi 1.2.3 → 1.2.5

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 (121) hide show
  1. package/.github/workflows/npmpublish.yml +2 -5
  2. package/README.md +1 -3
  3. package/dist/index.d.ts +11 -0
  4. package/dist/index.js +24 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/jest.config.d.ts +3 -0
  7. package/dist/jest.config.js +34 -0
  8. package/dist/jest.config.js.map +1 -0
  9. package/dist/package.json +70 -0
  10. package/dist/src/API/Request.d.ts +140 -0
  11. package/dist/src/API/Request.js +182 -0
  12. package/dist/src/API/Request.js.map +1 -0
  13. package/dist/src/API/Response.d.ts +256 -0
  14. package/dist/src/API/Response.js +398 -0
  15. package/dist/src/API/Response.js.map +1 -0
  16. package/dist/src/API/Utils.d.ts +63 -0
  17. package/dist/src/API/Utils.js +104 -0
  18. package/dist/src/API/Utils.js.map +1 -0
  19. package/dist/src/BaseEvent/EventProcessor.d.ts +81 -0
  20. package/dist/src/BaseEvent/EventProcessor.js +182 -0
  21. package/dist/src/BaseEvent/EventProcessor.js.map +1 -0
  22. package/dist/src/BaseEvent/Process.d.ts +74 -0
  23. package/dist/src/BaseEvent/Process.js +142 -0
  24. package/dist/src/BaseEvent/Process.js.map +1 -0
  25. package/dist/src/BaseEvent/Transaction.d.ts +39 -0
  26. package/dist/src/BaseEvent/Transaction.js +354 -0
  27. package/dist/src/BaseEvent/Transaction.js.map +1 -0
  28. package/dist/src/Config/Configuration.d.ts +131 -0
  29. package/dist/src/Config/Configuration.js +153 -0
  30. package/dist/src/Config/Configuration.js.map +1 -0
  31. package/dist/src/Config/EnvironmentVar.d.ts +101 -0
  32. package/dist/src/Config/EnvironmentVar.js +213 -0
  33. package/dist/src/Config/EnvironmentVar.js.map +1 -0
  34. package/dist/src/Crypto/Crypto.d.ts +57 -0
  35. package/dist/src/Crypto/Crypto.js +126 -0
  36. package/dist/src/Crypto/Crypto.js.map +1 -0
  37. package/dist/src/Crypto/JWT.d.ts +64 -0
  38. package/dist/src/Crypto/JWT.js +74 -0
  39. package/dist/src/Crypto/JWT.js.map +1 -0
  40. package/dist/src/Database/Database.d.ts +18 -0
  41. package/dist/src/Database/Database.js +18 -0
  42. package/dist/src/Database/Database.js.map +1 -0
  43. package/dist/src/Database/DatabaseManager.d.ts +32 -0
  44. package/dist/src/Database/DatabaseManager.js +50 -0
  45. package/dist/src/Database/DatabaseManager.js.map +1 -0
  46. package/dist/src/Database/DatabaseTransaction.d.ts +65 -0
  47. package/dist/src/Database/DatabaseTransaction.js +183 -0
  48. package/dist/src/Database/DatabaseTransaction.js.map +1 -0
  49. package/dist/src/Database/integrations/knex/KnexDatabase.d.ts +22 -0
  50. package/dist/src/Database/integrations/knex/KnexDatabase.js +108 -0
  51. package/dist/src/Database/integrations/knex/KnexDatabase.js.map +1 -0
  52. package/dist/src/Database/integrations/knex/KnexTransaction.d.ts +37 -0
  53. package/dist/src/Database/integrations/knex/KnexTransaction.js +60 -0
  54. package/dist/src/Database/integrations/knex/KnexTransaction.js.map +1 -0
  55. package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +30 -0
  56. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +108 -0
  57. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -0
  58. package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +37 -0
  59. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +60 -0
  60. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -0
  61. package/dist/src/Globals.d.ts +161 -0
  62. package/dist/src/Globals.js +173 -0
  63. package/dist/src/Globals.js.map +1 -0
  64. package/dist/src/Logger/Logger.d.ts +180 -0
  65. package/dist/src/Logger/Logger.js +412 -0
  66. package/dist/src/Logger/Logger.js.map +1 -0
  67. package/dist/src/Mailer/Mailer.d.ts +107 -0
  68. package/dist/src/Mailer/Mailer.js +313 -0
  69. package/dist/src/Mailer/Mailer.js.map +1 -0
  70. package/dist/src/Publisher/Publisher.d.ts +47 -0
  71. package/dist/src/Publisher/Publisher.js +141 -0
  72. package/dist/src/Publisher/Publisher.js.map +1 -0
  73. package/dist/src/Server/RouteResolver.d.ts +41 -0
  74. package/dist/src/Server/RouteResolver.js +135 -0
  75. package/dist/src/Server/RouteResolver.js.map +1 -0
  76. package/dist/src/Server/Router.d.ts +104 -0
  77. package/dist/src/Server/Router.js +45 -0
  78. package/dist/src/Server/Router.js.map +1 -0
  79. package/dist/src/Server/lib/ContainerServer.d.ts +58 -0
  80. package/dist/src/Server/lib/ContainerServer.js +143 -0
  81. package/dist/src/Server/lib/ContainerServer.js.map +1 -0
  82. package/dist/src/Server/lib/Server.d.ts +60 -0
  83. package/dist/src/Server/lib/Server.js +137 -0
  84. package/dist/src/Server/lib/Server.js.map +1 -0
  85. package/dist/src/Server/lib/container/GenericHandler.d.ts +4 -0
  86. package/dist/src/Server/lib/container/GenericHandler.js +138 -0
  87. package/dist/src/Server/lib/container/GenericHandler.js.map +1 -0
  88. package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +67 -0
  89. package/dist/src/Server/lib/container/GenericHandlerEvent.js +189 -0
  90. package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +1 -0
  91. package/dist/src/Server/lib/container/HealthHandler.d.ts +3 -0
  92. package/dist/src/Server/lib/container/HealthHandler.js +45 -0
  93. package/dist/src/Server/lib/container/HealthHandler.js.map +1 -0
  94. package/dist/src/Server/lib/container/Proxy.d.ts +95 -0
  95. package/dist/src/Server/lib/container/Proxy.js +202 -0
  96. package/dist/src/Server/lib/container/Proxy.js.map +1 -0
  97. package/dist/src/Server/lib/container/Utils.d.ts +18 -0
  98. package/dist/src/Server/lib/container/Utils.js +84 -0
  99. package/dist/src/Server/lib/container/Utils.js.map +1 -0
  100. package/dist/src/Validation/Validator.d.ts +21 -0
  101. package/dist/src/Validation/Validator.js +48 -0
  102. package/dist/src/Validation/Validator.js.map +1 -0
  103. package/jest.config.ts +2 -9
  104. package/package.json +10 -4
  105. package/src/BaseEvent/Transaction.ts +48 -18
  106. package/src/Database/Database.ts +19 -0
  107. package/src/Database/DatabaseManager.ts +51 -0
  108. package/src/Database/DatabaseTransaction.ts +118 -0
  109. package/src/Database/integrations/knex/KnexDatabase.ts +47 -0
  110. package/src/Database/integrations/knex/KnexTransaction.ts +51 -0
  111. package/src/Database/integrations/pgsql/PostgresDatabase.ts +49 -0
  112. package/src/Database/integrations/pgsql/PostgresTransaction.ts +54 -0
  113. package/src/Database/types.d.ts +49 -0
  114. package/src/Server/lib/container/Proxy.ts +2 -1
  115. package/tests/BaseEvent/Transaction.test.ts +59 -0
  116. package/tests/Database/DatabaseManager.test.ts +55 -0
  117. package/tests/Database/integrations/knex/KnexDatabase.test.ts +53 -0
  118. package/tests/Database/integrations/knex/KnexTransaction.test.ts +133 -0
  119. package/tests/Database/integrations/pg/PostgresDatabase.test.ts +50 -0
  120. package/tests/Database/integrations/pg/PostgresTransaction.test.ts +51 -0
  121. package/tsconfig.json +5 -0
@@ -0,0 +1,19 @@
1
+ import { DatabaseTransaction } from './DatabaseTransaction'
2
+ import type { DbConfig } from './types'
3
+
4
+ /**
5
+ * Abstract class representing a database.
6
+ * @template T - The type of database transaction.
7
+ */
8
+ export abstract class Database<T extends DatabaseTransaction> {
9
+ /**
10
+ * Creates a database instance, maintaining a reference to the database configuration.
11
+ */
12
+ protected constructor(public readonly config: DbConfig<any>) {}
13
+
14
+ /**
15
+ * Returns a promise resolving to a new instance of the transaction impl.
16
+ * @returns A promise that resolves to a transaction instance.
17
+ */
18
+ public abstract transaction(): Promise<T>
19
+ }
@@ -0,0 +1,51 @@
1
+ import * as hash from 'object-hash'
2
+
3
+ import { KnexDatabase } from './integrations/knex/KnexDatabase'
4
+ import { PostgresDatabase } from './integrations/pgsql/PostgresDatabase'
5
+ import type { DatabaseImplType, DatabaseType, DbConfig } from './types'
6
+
7
+ /**
8
+ * An object that maps database names to their corresponding database classes.
9
+ * @type {Object}
10
+ * @property {KnexDatabase} knex - The Knex database class.
11
+ * @property {PostgresDatabase} pg - The Postgres database class.
12
+ */
13
+ export const DATABASES = {
14
+ knex: KnexDatabase,
15
+ pg: PostgresDatabase,
16
+ }
17
+
18
+ /**
19
+ * A class that manages databases and provides methods for creating and accessing database instances.
20
+ */
21
+ export class DatabaseManager {
22
+ /**
23
+ * The singleton instance of the DatabaseManager class.
24
+ */
25
+ public static readonly INSTANCE = new DatabaseManager()
26
+ private databases: typeof DATABASES = DATABASES
27
+
28
+ private instances: { [k: string]: DatabaseImplType<any> } = {}
29
+
30
+ /**
31
+ * Creates a new instance of a database based on the provided configuration.
32
+ * @param {DbConfig<S>} config - The configuration object for the database.
33
+ * @returns {DatabaseImplType<S>} - The created database instance.
34
+ * @template S - The type of the database.
35
+ */
36
+ public create<S extends DatabaseType>(config: DbConfig<S>): DatabaseImplType<S> {
37
+ const configHash = hash(config)
38
+ if (this.instances[configHash]) {
39
+ return this.instances[configHash] as any
40
+ }
41
+ const instance = this.instantiateDb(config as any)
42
+ this.instances[configHash] = instance
43
+ return instance as any
44
+ }
45
+
46
+ private instantiateDb(
47
+ config: DbConfig<'knex'> | DbConfig<'pg'>
48
+ ): KnexDatabase | PostgresDatabase {
49
+ return new this.databases[config.type](config as any)
50
+ }
51
+ }
@@ -0,0 +1,118 @@
1
+ import { Database } from './Database'
2
+
3
+ /**
4
+ * Abstract class representing a database transaction.
5
+ * @class DatabaseTransaction
6
+ */
7
+ export abstract class DatabaseTransaction {
8
+ private _isOpen: boolean = true
9
+ protected delegate: any
10
+ protected database: Database<any>
11
+
12
+ /**
13
+ * Returns a boolean value indicating whether the transaction is open or not.
14
+ * @returns {boolean} - true if the object is open, false otherwise.
15
+ */
16
+ public get isOpen(): boolean {
17
+ return this._isOpen
18
+ }
19
+
20
+ /**
21
+ * Constructs a new instance of the class.
22
+ * @param {any} delegate - The delegate object.
23
+ * @param {Database<any>} database - The database object.
24
+ * @protected
25
+ */
26
+ protected constructor(delegate: any, database: Database<any>) {
27
+ this.delegate = delegate
28
+ this.database = database
29
+ }
30
+
31
+ /**
32
+ * Wraps an instance of a subclass of DatabaseTransaction with a Proxy object.
33
+ * The Proxy object intercepts method calls and delegates to the target instance.
34
+ * If the method is on the target instance, it is called directly.
35
+ * If the method is not on the target instance and the transaction is open, it is called on the target's delegate implementation.
36
+ * If the method is not on the target instance and the transaction is closed, an error is thrown.
37
+ * @param {T} subclass - The subclass instance to wrap with a Proxy.
38
+ * @returns {T} - The wrapped subclass instance.
39
+ * @throws {Error} - If the target instance is closed.
40
+ */
41
+ protected static wrapInstance<T extends DatabaseTransaction>(subclass: T): T {
42
+ const bind = (target: any, key: string | symbol) =>
43
+ typeof target[key] === 'function' ? target[key].bind(target) : target[key]
44
+
45
+ return new Proxy<T>(subclass, {
46
+ get(target: T, p: string | symbol): any {
47
+ if (target[p] !== undefined) {
48
+ return bind(target, p)
49
+ } else if (target._isOpen) {
50
+ return bind(target.delegate, p)
51
+ }
52
+ return undefined
53
+ },
54
+ })
55
+ }
56
+
57
+ /**
58
+ * Commits the transaction.
59
+ * @throws {Error} - If the transaction is already closed.
60
+ * @returns None
61
+ */
62
+ public async commit(): Promise<void> {
63
+ if (!this._isOpen) {
64
+ throw new Error('Cannot commit, transaction is already closed!')
65
+ }
66
+ await this.doCommit()
67
+ this._isOpen = false
68
+ }
69
+
70
+ /**
71
+ * Rollbacks the current transaction.
72
+ * @throws {Error} - If the transaction is already closed.
73
+ * @returns {Promise<void>} - A promise that resolves once the rollback is complete.
74
+ */
75
+ public async rollback(): Promise<void> {
76
+ if (!this._isOpen) {
77
+ throw new Error('Cannot rollback, transaction is already closed!')
78
+ }
79
+ await this.doRollback()
80
+ this._isOpen = false
81
+ }
82
+
83
+ /**
84
+ * Closes the transaction after a successful execution.
85
+ * @returns {Promise<void>} - A promise that resolves once the necessary actions are completed.
86
+ */
87
+ public async closeSuccess() {
88
+ if (this._isOpen) {
89
+ if (this.database.config.autoCommit) {
90
+ await this.doCommit()
91
+ } else {
92
+ await this.doRollback()
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Closes the transaction after a failed execution.
99
+ * @returns {Promise<void>} - A promise that resolves once the necessary actions are completed.
100
+ */
101
+ public async closeFailure() {
102
+ if (this._isOpen) {
103
+ await this.doRollback()
104
+ }
105
+ }
106
+
107
+ /**
108
+ * An abstract method that performs the commit operation.
109
+ * @returns {Promise<any>} A promise that resolves when the commit operation is completed.
110
+ */
111
+ protected abstract doCommit(): Promise<any>
112
+
113
+ /**
114
+ * An abstract method that performs a rollback operation.
115
+ * @returns A Promise that resolves when the rollback operation is complete.
116
+ */
117
+ protected abstract doRollback(): Promise<any>
118
+ }
@@ -0,0 +1,47 @@
1
+ import knex, { Knex } from 'knex'
2
+
3
+ import { KnexTransaction, KnexTransactionImpl } from './KnexTransaction'
4
+ import { Database } from '../../Database'
5
+ import type { DbConfig } from '../../types'
6
+
7
+ /**
8
+ * Represents a Knex database connection.
9
+ * @extends Database<KnexTransaction>
10
+ */
11
+ export class KnexDatabase extends Database<KnexTransaction> {
12
+ private static knexProvider: (config: knex.Knex.Config<any>) => knex.Knex<any, unknown[]> = knex
13
+
14
+ private client: Knex
15
+
16
+ /**
17
+ * Constructs a new instance of the database class using the provided configuration.
18
+ * @param {DbConfig<'knex'>} config - The configuration object for the database.
19
+ * @returns None
20
+ */
21
+ public constructor(config: DbConfig<'knex'>) {
22
+ super(config)
23
+ this.client = KnexDatabase.knexProvider({
24
+ client: config.driver,
25
+ connection: {
26
+ host: config.host,
27
+ port: config.port,
28
+ user: config.username,
29
+ password: config.password,
30
+ database: config.database,
31
+ },
32
+ pool: {
33
+ min: 1,
34
+ max: config.maxConnections,
35
+ },
36
+ })
37
+ }
38
+
39
+ /**
40
+ * Initiates a transaction using the underlying database client.
41
+ * @returns {Promise<KnexTransaction>} A promise that resolves to a KnexTransaction object representing the transaction.
42
+ */
43
+ public override async transaction(): Promise<KnexTransaction> {
44
+ const delegate = await this.client.transaction()
45
+ return KnexTransactionImpl.wrapDelegate(delegate, this)
46
+ }
47
+ }
@@ -0,0 +1,51 @@
1
+ import { Knex } from 'knex'
2
+
3
+ import { KnexDatabase } from './KnexDatabase'
4
+ import { DatabaseTransaction } from '../../DatabaseTransaction'
5
+
6
+ /**
7
+ * A type alias for a Knex transaction object.
8
+ * @typedef {KnexTransactionImpl & Knex.Transaction} KnexTransaction
9
+ */
10
+ export type KnexTransaction = KnexTransactionImpl & Knex.Transaction
11
+
12
+ /**
13
+ * Implementation of a Knex transaction that extends the DatabaseTransaction class.
14
+ */
15
+ export class KnexTransactionImpl extends DatabaseTransaction {
16
+ /**
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.
20
+ * @returns None
21
+ */
22
+ private constructor(delegate: Knex.Transaction, database: KnexDatabase) {
23
+ super(delegate, database)
24
+ }
25
+
26
+ /**
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.
31
+ */
32
+ public static wrapDelegate(delegate: Knex.Transaction, database: KnexDatabase): KnexTransaction {
33
+ return DatabaseTransaction.wrapInstance(new KnexTransactionImpl(delegate, database)) as any
34
+ }
35
+
36
+ /**
37
+ * Commits the changes made by the delegate object.
38
+ * @returns None
39
+ */
40
+ protected doCommit() {
41
+ return this.delegate.commit()
42
+ }
43
+
44
+ /**
45
+ * Performs a rollback operation by calling the rollback method of the delegate object.
46
+ * @returns None
47
+ */
48
+ protected doRollback() {
49
+ return this.delegate.rollback()
50
+ }
51
+ }
@@ -0,0 +1,49 @@
1
+ import { Pool } from 'pg'
2
+
3
+ import { PostgresTransaction, PostgresTransactionImpl } from './PostgresTransaction'
4
+ import { Database } from '../../Database'
5
+ import type { DbConfig } from '../../types'
6
+
7
+ /**
8
+ * Represents a Postgres database connection.
9
+ * @extends Database<PostgresTransaction>
10
+ */
11
+ export class PostgresDatabase extends Database<PostgresTransaction> {
12
+ /**
13
+ * A private static property that represents a connection pool for a PostgreSQL database.
14
+ */
15
+ private static pgProvider = Pool
16
+ /**
17
+ * The client property represents a connection pool to a database.
18
+ * @private
19
+ * @type {Pool}
20
+ */
21
+ private client: Pool
22
+
23
+ /**
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.
26
+ * @returns None
27
+ */
28
+ public constructor(config: DbConfig<'pg'>) {
29
+ super(config)
30
+ this.client = new PostgresDatabase.pgProvider({
31
+ host: config.host,
32
+ port: config.port,
33
+ user: config.username,
34
+ password: config.password,
35
+ database: config.database,
36
+ max: config.maxConnections,
37
+ })
38
+ }
39
+
40
+ /**
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.
43
+ */
44
+ public override async transaction(): Promise<PostgresTransaction> {
45
+ const delegate = await this.client.connect()
46
+ await delegate.query('BEGIN')
47
+ return PostgresTransactionImpl.wrapDelegate(delegate, this)
48
+ }
49
+ }
@@ -0,0 +1,54 @@
1
+ import { PoolClient } from 'pg'
2
+
3
+ import { PostgresDatabase } from './PostgresDatabase'
4
+ import { DatabaseTransaction } from '../../DatabaseTransaction'
5
+
6
+ /**
7
+ * A type alias representing a Postgres transaction. It extends the `PostgresTransactionImpl`
8
+ * interface and includes the `PoolClient` interface.
9
+ */
10
+ export type PostgresTransaction = PostgresTransactionImpl & PoolClient
11
+
12
+ /**
13
+ * Represents a transaction in a Postgres database.
14
+ */
15
+ export class PostgresTransactionImpl extends DatabaseTransaction {
16
+ /**
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
21
+ */
22
+ private constructor(delegate: PoolClient, database: PostgresDatabase) {
23
+ super(delegate, database)
24
+ }
25
+
26
+ /**
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.
31
+ */
32
+ public static wrapDelegate(
33
+ delegate: PoolClient,
34
+ database: PostgresDatabase
35
+ ): PostgresTransaction {
36
+ return DatabaseTransaction.wrapInstance(new PostgresTransactionImpl(delegate, database)) as any
37
+ }
38
+
39
+ /**
40
+ * Commits the current transaction.
41
+ * @returns A promise that resolves when the commit is successful.
42
+ */
43
+ protected doCommit() {
44
+ return this.delegate.query('COMMIT')
45
+ }
46
+
47
+ /**
48
+ * Performs a rollback operation in the database.
49
+ * @returns A promise that resolves when the rollback operation is completed.
50
+ */
51
+ protected doRollback() {
52
+ return this.delegate.query('ROLLBACK')
53
+ }
54
+ }
@@ -0,0 +1,49 @@
1
+ import { Database } from './Database'
2
+ import { DATABASES } from './DatabaseManager'
3
+
4
+ /**
5
+ * Represents the available types of databases.
6
+ * @typedef {keyof typeof DATABASES} DatabaseType
7
+ */
8
+ export type DatabaseType = keyof typeof DATABASES
9
+
10
+ /**
11
+ * Represents the instance type of the specified database implementation.
12
+ * @param {Type} Type - The type of the database implementation.
13
+ */
14
+ export type DatabaseImplType<Type extends DatabaseType> = InstanceType<(typeof DATABASES)[Type]>
15
+
16
+ /**
17
+ * Defines a type for a database transaction based on the specified database type.
18
+ * @param {Type} - The database type.
19
+ * @returns The transaction type associated with the specified database type.
20
+ */
21
+ export type DatabaseTransactionType<Type extends DatabaseType> =
22
+ DatabaseImplType<Type> extends Database<infer TransactionType> ? TransactionType : never
23
+
24
+ /**
25
+ * Represents the configuration for a database connection.
26
+ * @template S - The type of the database (e.g. "mysql", "postgres", etc.)
27
+ * @interface DbConfig
28
+ * @property {S} type - The type of the database.
29
+ * @property {string} driver - The driver to use for the database connection.
30
+ * @property {string} host - The host of the database server.
31
+ * @property {number} port - The port number of the database server.
32
+ * @property {string} username - The username for the database connection.
33
+ * @property {string} password - The password for the database connection.
34
+ * @property {string} database - The name of the database to connect to.
35
+ * @property {boolean} autoCommit - Whether or not to automatically commit transactions.
36
+ * @property {number} maxConnections - The maximum number of connections to the database.
37
+ * @returns The transaction type associated with the specified database type.
38
+ */
39
+ export interface DbConfig<S extends DatabaseType> {
40
+ type: S
41
+ driver: string
42
+ host: string
43
+ port: number
44
+ username: string
45
+ password: string
46
+ database: string
47
+ autoCommit: boolean
48
+ maxConnections: number
49
+ }
@@ -150,7 +150,8 @@ export default class Proxy {
150
150
  console.debug('[Proxy] - [STOPPING]')
151
151
  return new Promise(resolve => {
152
152
  this.listener.close(_err => {
153
- if (err || _err) console.log('[Proxy] - exit output:', err || _err)
153
+ const err2 = err || _err
154
+ if (err2) console.log('[Proxy] - exit output:', err2)
154
155
  console.log('[Proxy] - [STOPPED]')
155
156
  process.exit(err || _err ? 1 : 0)
156
157
  resolve(null)
@@ -3,6 +3,7 @@ import { expect } from 'chai'
3
3
 
4
4
  import Response from '../../src/API/Response'
5
5
  import Transaction from '../../src/BaseEvent/Transaction'
6
+ import type { DbConfig } from '../../src/Database/types'
6
7
  import Globals from '../../src/Globals'
7
8
  import { defaultHeaders, emptyEvent, observableContext } from '../Test.utils'
8
9
 
@@ -219,4 +220,62 @@ describe('Transaction error invocation path with exception', () => {
219
220
  })
220
221
  })
221
222
 
223
+ describe('Transaction - db integration', () => {
224
+ const testResources = () => {
225
+ const mockTrans = {
226
+ select: jest.fn(),
227
+ closeSuccess: jest.fn(),
228
+ closeFailure: jest.fn(),
229
+ }
230
+ const mockCreate = jest.fn(
231
+ () => ({ transaction: () => new Promise(resolve => resolve(mockTrans)) }) as any
232
+ )
233
+
234
+ const transaction = new Transaction(emptyEvent(), observableContext())
235
+ transaction['databaseManager'] = {
236
+ create: mockCreate,
237
+ } as any
238
+
239
+ return {
240
+ transaction,
241
+ mockCreate,
242
+ mockTrans,
243
+ }
244
+ }
245
+
246
+ const config = { username: 'test' } as DbConfig<'knex'>
247
+
248
+ test('Transaction provides dbTransaction and calls closeSuccess', async () => {
249
+ const { mockCreate, mockTrans, transaction } = testResources()
250
+
251
+ await transaction.execute(async () => {
252
+ const knexTransaction = await transaction.getDbTransaction(config)
253
+
254
+ knexTransaction.select('name')
255
+
256
+ return Response.SuccessResponse(null)
257
+ })
258
+ j_expect(mockCreate).toBeCalledWith(config)
259
+ j_expect(mockTrans.select).toBeCalledWith('name')
260
+ j_expect(mockTrans.closeSuccess).toBeCalled()
261
+ })
262
+
263
+ test('Errored transaction calls closeFailure', async () => {
264
+ const { mockCreate, transaction, mockTrans } = testResources()
265
+
266
+ const ss = await transaction.execute(async () => {
267
+ const _ii = await transaction.getDbTransaction(config)
268
+ console.log('ii', _ii)
269
+ throw new Error('Something went wrong!')
270
+
271
+ return Response.SuccessResponse(null)
272
+ })
273
+
274
+ console.log(ss)
275
+
276
+ j_expect(mockCreate).toBeCalledWith(config)
277
+ j_expect(mockTrans.closeFailure).toBeCalled()
278
+ })
279
+ })
280
+
222
281
  export {}
@@ -0,0 +1,55 @@
1
+ import { expect } from 'chai'
2
+
3
+ import { DatabaseManager } from '../../src/Database/DatabaseManager'
4
+ import type { DatabaseType, DbConfig } from '../../src/Database/types'
5
+
6
+ type FakeDatabase = { host: string; type: 'knex' | 'pg' }
7
+
8
+ const fakeConfig = (host: string, type: DatabaseType) => {
9
+ return {
10
+ type,
11
+ host,
12
+ } as DbConfig<typeof type>
13
+ }
14
+
15
+ describe('Database Manager', () => {
16
+ test('should correctly create and cache database instances', () => {
17
+ const underTest = new DatabaseManager()
18
+
19
+ underTest['databases'] = {
20
+ knex: jest.fn(config => {
21
+ return { host: config.host, type: 'knex' } as any
22
+ }) as any,
23
+ pg: jest.fn(config => {
24
+ return { host: config.host, type: 'pg' } as any
25
+ }) as any,
26
+ }
27
+
28
+ const create = config => underTest.create({ ...config }) as unknown as FakeDatabase
29
+
30
+ const knexConfig1 = fakeConfig('localhost', 'knex')
31
+ const knexConfig2 = fakeConfig('other', 'knex')
32
+ const pgConfig1 = fakeConfig('localhost', 'pg')
33
+ const pgConfig2 = fakeConfig('other', 'pg')
34
+
35
+ const knex1 = create(knexConfig1)
36
+ const knex2 = create(knexConfig1)
37
+ const knex3 = create(knexConfig2)
38
+
39
+ const pg1 = create(pgConfig1)
40
+ const pg2 = create(pgConfig1)
41
+ const pg3 = create(pgConfig2)
42
+
43
+ expect(knex1).to.equal(knex2).to.not.equal(knex3).to.not.equal(pg1)
44
+
45
+ expect(knexConfig1).to.be.deep.equal(knex1).to.be.deep.equal(knex2)
46
+
47
+ expect(knex3).to.be.deep.equal(knexConfig2)
48
+
49
+ expect(pg1).to.equal(pg2).to.not.equal(pg3)
50
+
51
+ expect(pgConfig1).to.be.deep.equal(pg1).to.be.deep.equal(pg2)
52
+
53
+ expect(pg3).to.be.deep.equal(pgConfig2)
54
+ })
55
+ })
@@ -0,0 +1,53 @@
1
+ import { Knex } from 'knex'
2
+
3
+ import { KnexDatabase } from '../../../../src/Database/integrations/knex/KnexDatabase'
4
+ import { KnexTransactionImpl } from '../../../../src/Database/integrations/knex/KnexTransaction'
5
+ import type { DbConfig } from '../../../../src/Database/types'
6
+
7
+ const config: DbConfig<'knex'> = {
8
+ type: 'knex',
9
+ username: 'username',
10
+ password: 'password',
11
+ host: 'host',
12
+ port: 1234,
13
+ database: 'database',
14
+ driver: 'driver',
15
+ maxConnections: 1,
16
+ autoCommit: true,
17
+ }
18
+
19
+ const expectedImplConfig = {
20
+ client: config.driver,
21
+ connection: {
22
+ host: config.host,
23
+ port: config.port,
24
+ user: config.username,
25
+ password: config.password,
26
+ database: config.database,
27
+ },
28
+ pool: {
29
+ min: 1,
30
+ max: config.maxConnections,
31
+ },
32
+ }
33
+
34
+ describe('KnexDatabase', () => {
35
+ test('KnexDatabase', async () => {
36
+ const mockTrans = { a: 'b' } as any
37
+ const mockClient = jest.fn(
38
+ () =>
39
+ ({
40
+ transaction: async () => mockTrans,
41
+ }) as Knex
42
+ )
43
+ KnexDatabase['knexProvider'] = mockClient
44
+
45
+ const underTest = new KnexDatabase(config)
46
+ expect(mockClient).toBeCalledWith(expectedImplConfig)
47
+
48
+ const trans = await underTest.transaction()
49
+
50
+ expect(trans).toBeInstanceOf(KnexTransactionImpl)
51
+ expect(trans['delegate']).toBe(mockTrans)
52
+ })
53
+ })