@creator.co/wapi 1.2.4 → 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 (49) hide show
  1. package/.github/workflows/npmpublish.yml +1 -1
  2. package/dist/jest.config.js +1 -1
  3. package/dist/jest.config.js.map +1 -1
  4. package/dist/package.json +8 -2
  5. package/dist/src/BaseEvent/Transaction.d.ts +10 -0
  6. package/dist/src/BaseEvent/Transaction.js +147 -37
  7. package/dist/src/BaseEvent/Transaction.js.map +1 -1
  8. package/dist/src/Database/Database.d.ts +18 -0
  9. package/dist/src/Database/Database.js +18 -0
  10. package/dist/src/Database/Database.js.map +1 -0
  11. package/dist/src/Database/DatabaseManager.d.ts +32 -0
  12. package/dist/src/Database/DatabaseManager.js +50 -0
  13. package/dist/src/Database/DatabaseManager.js.map +1 -0
  14. package/dist/src/Database/DatabaseTransaction.d.ts +65 -0
  15. package/dist/src/Database/DatabaseTransaction.js +183 -0
  16. package/dist/src/Database/DatabaseTransaction.js.map +1 -0
  17. package/dist/src/Database/integrations/knex/KnexDatabase.d.ts +22 -0
  18. package/dist/src/Database/integrations/knex/KnexDatabase.js +108 -0
  19. package/dist/src/Database/integrations/knex/KnexDatabase.js.map +1 -0
  20. package/dist/src/Database/integrations/knex/KnexTransaction.d.ts +37 -0
  21. package/dist/src/Database/integrations/knex/KnexTransaction.js +60 -0
  22. package/dist/src/Database/integrations/knex/KnexTransaction.js.map +1 -0
  23. package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +30 -0
  24. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +108 -0
  25. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -0
  26. package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +37 -0
  27. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +60 -0
  28. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -0
  29. package/dist/src/Server/lib/container/Proxy.js +3 -2
  30. package/dist/src/Server/lib/container/Proxy.js.map +1 -1
  31. package/jest.config.ts +1 -1
  32. package/package.json +8 -2
  33. package/src/BaseEvent/Transaction.ts +48 -18
  34. package/src/Database/Database.ts +19 -0
  35. package/src/Database/DatabaseManager.ts +51 -0
  36. package/src/Database/DatabaseTransaction.ts +118 -0
  37. package/src/Database/integrations/knex/KnexDatabase.ts +47 -0
  38. package/src/Database/integrations/knex/KnexTransaction.ts +51 -0
  39. package/src/Database/integrations/pgsql/PostgresDatabase.ts +49 -0
  40. package/src/Database/integrations/pgsql/PostgresTransaction.ts +54 -0
  41. package/src/Database/types.d.ts +49 -0
  42. package/src/Server/lib/container/Proxy.ts +2 -1
  43. package/tests/BaseEvent/Transaction.test.ts +59 -0
  44. package/tests/Database/DatabaseManager.test.ts +55 -0
  45. package/tests/Database/integrations/knex/KnexDatabase.test.ts +53 -0
  46. package/tests/Database/integrations/knex/KnexTransaction.test.ts +133 -0
  47. package/tests/Database/integrations/pg/PostgresDatabase.test.ts +50 -0
  48. package/tests/Database/integrations/pg/PostgresTransaction.test.ts +51 -0
  49. package/tsconfig.json +5 -0
@@ -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
+ })
@@ -0,0 +1,133 @@
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 testResources = (config: Partial<DbConfig<'knex'>>) => {
8
+ const database = {
9
+ config: {
10
+ autoCommit: true,
11
+ ...config,
12
+ } as DbConfig<'knex'>,
13
+ } as KnexDatabase
14
+
15
+ const delegate = jest.fn().mockImplementation(() => {
16
+ return {
17
+ commit: jest.fn(),
18
+ rollback: jest.fn(),
19
+ select: jest.fn(),
20
+ }
21
+ })() as any as Knex.Transaction
22
+
23
+ return {
24
+ delegate,
25
+ underTest: KnexTransactionImpl.wrapDelegate(delegate, database),
26
+ }
27
+ }
28
+
29
+ describe('KnexTransaction', () => {
30
+ test('Can only commit once', async () => {
31
+ const { delegate, underTest } = testResources({})
32
+ await underTest.commit()
33
+ expect(underTest.isOpen).toBe(false)
34
+ expect(delegate.commit).toBeCalled()
35
+
36
+ await expect(underTest.commit).rejects.toThrowError(
37
+ 'Cannot commit, transaction is already closed!'
38
+ )
39
+ })
40
+
41
+ test("Can't commit after rollback", async () => {
42
+ const { delegate, underTest } = testResources({})
43
+ await underTest.rollback()
44
+ expect(underTest.isOpen).toBe(false)
45
+ expect(delegate.rollback).toBeCalled()
46
+
47
+ await expect(underTest.commit).rejects.toThrowError(
48
+ 'Cannot commit, transaction is already closed!'
49
+ )
50
+ })
51
+
52
+ test('Forwards calls to delegate', async () => {
53
+ const { delegate, underTest } = testResources({})
54
+ await underTest.select('name')
55
+ expect(delegate.select).toBeCalledWith('name')
56
+ })
57
+
58
+ test('Blocks delegate calls after commit', async () => {
59
+ const { delegate, underTest } = testResources({})
60
+ expect(underTest.select).toBeDefined()
61
+
62
+ await underTest.commit()
63
+ expect(delegate.commit).toBeCalled()
64
+ expect(underTest.isOpen).toBe(false)
65
+
66
+ expect(underTest.select).toBeUndefined()
67
+ })
68
+ })
69
+
70
+ describe('KnexTransaction - closeSuccess', () => {
71
+ test('Close success commits', async () => {
72
+ const { delegate, underTest } = testResources({})
73
+ await underTest.closeSuccess()
74
+ expect(delegate.commit).toBeCalled()
75
+ })
76
+
77
+ test("Close success, doesn't commit again if already committed", async () => {
78
+ const { delegate, underTest } = testResources({})
79
+ await underTest.commit()
80
+ expect(delegate.commit).toBeCalledTimes(1)
81
+ await underTest.closeSuccess()
82
+ expect(delegate.commit).toBeCalledTimes(1)
83
+ })
84
+
85
+ test('Close success, rolls back if not autocommit', async () => {
86
+ const { delegate, underTest } = testResources({ autoCommit: false })
87
+ await underTest.closeSuccess()
88
+ expect(delegate.rollback).toBeCalled()
89
+ })
90
+
91
+ test("Close success, doesn't rollback if already committed", async () => {
92
+ const { delegate, underTest } = testResources({ autoCommit: false })
93
+ await underTest.commit()
94
+ expect(delegate.commit).toBeCalledTimes(1)
95
+ await underTest.closeSuccess()
96
+ expect(delegate.rollback).not.toBeCalled()
97
+ expect(delegate.commit).toBeCalledTimes(1)
98
+ })
99
+
100
+ test("Close success, doesn't rollback if already rolled back", async () => {
101
+ const { delegate, underTest } = testResources({ autoCommit: false })
102
+ await underTest.rollback()
103
+ expect(delegate.rollback).toBeCalledTimes(1)
104
+ await underTest.closeSuccess()
105
+ expect(delegate.rollback).toBeCalledTimes(1)
106
+ expect(delegate.commit).not.toBeCalled()
107
+ })
108
+ })
109
+
110
+ describe('KnexTransaction - closeFailure', () => {
111
+ test('Close failure rolls back', async () => {
112
+ const { delegate, underTest } = testResources({})
113
+ await underTest.closeFailure()
114
+ expect(delegate.rollback).toBeCalled()
115
+ })
116
+
117
+ test("Close failure, doesn't rollback again if already rolled back", async () => {
118
+ const { delegate, underTest } = testResources({})
119
+ await underTest.rollback()
120
+ expect(delegate.rollback).toBeCalledTimes(1)
121
+ await underTest.closeFailure()
122
+ expect(delegate.rollback).toBeCalledTimes(1)
123
+ })
124
+
125
+ test("Close failure, doesn't rollback if already committed", async () => {
126
+ const { delegate, underTest } = testResources({ autoCommit: false })
127
+ await underTest.commit()
128
+ expect(delegate.commit).toBeCalledTimes(1)
129
+ await underTest.closeFailure()
130
+ expect(delegate.rollback).not.toBeCalled()
131
+ expect(delegate.commit).toBeCalledTimes(1)
132
+ })
133
+ })
@@ -0,0 +1,50 @@
1
+ import { PoolClient } from 'pg'
2
+
3
+ import { PostgresDatabase } from '../../../../src/Database/integrations/pgsql/PostgresDatabase'
4
+ import { PostgresTransactionImpl } from '../../../../src/Database/integrations/pgsql/PostgresTransaction'
5
+ import type { DbConfig } from '../../../../src/Database/types'
6
+
7
+ const config: DbConfig<'pg'> = {
8
+ type: 'pg',
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
+ host: config.host,
21
+ port: config.port,
22
+ user: config.username,
23
+ password: config.password,
24
+ database: config.database,
25
+ max: config.maxConnections,
26
+ }
27
+
28
+ describe('PostgresDatabase', () => {
29
+ test('PostgresDatabase', async () => {
30
+ const mockTrans = {
31
+ query: jest.fn(() => {}),
32
+ } as any
33
+ const mockClient = jest.fn(
34
+ () =>
35
+ ({
36
+ connect: async () => mockTrans,
37
+ }) as PoolClient
38
+ )
39
+ PostgresDatabase['pgProvider'] = mockClient as any
40
+
41
+ const underTest = new PostgresDatabase(config)
42
+ expect(mockClient).toBeCalledWith(expectedImplConfig)
43
+
44
+ const trans = await underTest.transaction()
45
+
46
+ expect(mockTrans.query).toBeCalledWith('BEGIN')
47
+ expect(trans).toBeInstanceOf(PostgresTransactionImpl)
48
+ expect(trans['delegate']).toBe(mockTrans)
49
+ })
50
+ })
@@ -0,0 +1,51 @@
1
+ import { PoolClient } from 'pg'
2
+
3
+ import { PostgresDatabase } from '../../../../src/Database/integrations/pgsql/PostgresDatabase'
4
+ import { PostgresTransactionImpl } from '../../../../src/Database/integrations/pgsql/PostgresTransaction'
5
+ import type { DbConfig } from '../../../../src/Database/types'
6
+
7
+ const testResources = (config: Partial<DbConfig<'pg'>>) => {
8
+ const database = {
9
+ config: {
10
+ autoCommit: true,
11
+ ...config,
12
+ } as DbConfig<'pg'>,
13
+ } as PostgresDatabase
14
+
15
+ const delegate = jest.fn().mockImplementation(() => {
16
+ return {
17
+ commit: jest.fn(),
18
+ rollback: jest.fn(),
19
+ query: jest.fn(),
20
+ }
21
+ })() as any as PoolClient
22
+
23
+ return {
24
+ delegate,
25
+ underTest: PostgresTransactionImpl.wrapDelegate(delegate, database),
26
+ }
27
+ }
28
+
29
+ describe('PostgresTransaction', () => {
30
+ test('Can only commit once', async () => {
31
+ const { delegate, underTest } = testResources({})
32
+ await underTest.commit()
33
+ expect(underTest.isOpen).toBe(false)
34
+ expect(delegate.query).toBeCalledWith('COMMIT')
35
+
36
+ await expect(underTest.commit).rejects.toThrowError(
37
+ 'Cannot commit, transaction is already closed!'
38
+ )
39
+ })
40
+
41
+ test('Can only rollback once', async () => {
42
+ const { delegate, underTest } = testResources({})
43
+ await underTest.rollback()
44
+ expect(underTest.isOpen).toBe(false)
45
+ expect(delegate.query).toBeCalledWith('ROLLBACK')
46
+
47
+ await expect(underTest.rollback).rejects.toThrowError(
48
+ 'Cannot rollback, transaction is already closed!'
49
+ )
50
+ })
51
+ })
package/tsconfig.json CHANGED
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "exclude": ["**/*.test.*", "**/__mocks__/*", "**/__tests__/*", "**/tests/*"],
3
3
  "compilerOptions": {
4
+ "lib": [
5
+ "es5",
6
+ "es6",
7
+ "dom"
8
+ ],
4
9
  "noImplicitAny": false,
5
10
  "noEmitOnError": true,
6
11
  "removeComments": false,