@creator.co/wapi 1.3.19 → 1.4.0-alpha2
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.
- package/dist/package.json +2 -1
- package/dist/src/BaseEvent/Transaction.d.ts +1 -1
- package/dist/src/Database/Database.d.ts +8 -5
- package/dist/src/Database/Database.js +5 -3
- package/dist/src/Database/Database.js.map +1 -1
- package/dist/src/Database/DatabaseManager.d.ts +30 -9
- package/dist/src/Database/DatabaseManager.js +24 -8
- package/dist/src/Database/DatabaseManager.js.map +1 -1
- package/dist/src/Database/DatabaseTransaction.d.ts +66 -31
- package/dist/src/Database/DatabaseTransaction.js +51 -30
- package/dist/src/Database/DatabaseTransaction.js.map +1 -1
- package/dist/src/Database/index.d.ts +2 -1
- package/dist/src/Database/index.js.map +1 -1
- package/dist/src/Database/integrations/knex/KnexDatabase.d.ts +22 -8
- package/dist/src/Database/integrations/knex/KnexDatabase.js +17 -11
- package/dist/src/Database/integrations/knex/KnexDatabase.js.map +1 -1
- package/dist/src/Database/integrations/knex/KnexTransaction.d.ts +39 -16
- package/dist/src/Database/integrations/knex/KnexTransaction.js +83 -17
- package/dist/src/Database/integrations/knex/KnexTransaction.js.map +1 -1
- package/dist/src/Database/integrations/kysely/KyselyDatabase.d.ts +55 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.js +127 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.js.map +1 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.d.ts +70 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.js +186 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.js.map +1 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +16 -11
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +18 -16
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -1
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +42 -16
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +84 -18
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -1
- package/dist/src/Database/types.d.ts +47 -26
- package/dist/src/Logger/Logger.d.ts +6 -6
- package/dist/src/Logger/Logger.js +12 -15
- package/dist/src/Logger/Logger.js.map +1 -1
- package/package.json +2 -1
- package/src/BaseEvent/Transaction.ts +2 -2
- package/src/Database/Database.ts +8 -5
- package/src/Database/DatabaseManager.ts +34 -17
- package/src/Database/DatabaseTransaction.ts +79 -35
- package/src/Database/index.ts +2 -0
- package/src/Database/integrations/knex/KnexDatabase.ts +22 -11
- package/src/Database/integrations/knex/KnexTransaction.ts +52 -19
- package/src/Database/integrations/kysely/KyselyDatabase.ts +87 -0
- package/src/Database/integrations/kysely/KyselyTransaction.ts +172 -0
- package/src/Database/integrations/pgsql/PostgresDatabase.ts +26 -14
- package/src/Database/integrations/pgsql/PostgresTransaction.ts +55 -22
- package/src/Database/types.ts +53 -31
- package/src/Logger/Logger.ts +12 -15
- package/tests/Database/DatabaseManager.test.ts +16 -1
- package/tests/Database/integrations/knex/KnexDatabase.test.ts +2 -2
- package/tests/Database/integrations/knex/KnexTransaction.test.ts +52 -45
- package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +109 -0
- package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +118 -0
- package/tests/Database/integrations/pg/PostgresDatabase.test.ts +32 -6
- package/tests/Database/integrations/pg/PostgresTransaction.test.ts +75 -9
- package/tsconfig.json +1 -0
|
@@ -4,7 +4,7 @@ import { DbConfig } from '../../../../src/Database'
|
|
|
4
4
|
import { KnexDatabase } from '../../../../src/Database/integrations/knex/KnexDatabase'
|
|
5
5
|
import { KnexTransactionImpl } from '../../../../src/Database/integrations/knex/KnexTransaction'
|
|
6
6
|
|
|
7
|
-
const testResources = (config: Partial<DbConfig<'knex'>>) => {
|
|
7
|
+
const testResources = async (config: Partial<DbConfig<'knex'>>) => {
|
|
8
8
|
const database = {
|
|
9
9
|
config: {
|
|
10
10
|
autoCommit: true,
|
|
@@ -12,25 +12,31 @@ const testResources = (config: Partial<DbConfig<'knex'>>) => {
|
|
|
12
12
|
} as DbConfig<'knex'>,
|
|
13
13
|
} as KnexDatabase
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const txMock = jest.fn() as any
|
|
16
|
+
txMock.commit = jest.fn()
|
|
17
|
+
txMock.rollback = jest.fn()
|
|
18
|
+
txMock.select = jest.fn()
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const wMock = jest.fn() as any
|
|
21
|
+
wMock.transaction = jest.fn(() => txMock)
|
|
22
|
+
|
|
23
|
+
const writer = wMock as Knex
|
|
24
|
+
const transaction = txMock as Knex.Transaction
|
|
21
25
|
|
|
22
26
|
return {
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
transaction,
|
|
28
|
+
writer,
|
|
29
|
+
underTest: await KnexTransactionImpl.newTransaction(writer, database),
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
describe('KnexTransaction', () => {
|
|
29
34
|
test('Can only commit once', async () => {
|
|
30
|
-
const {
|
|
35
|
+
const { writer, transaction, underTest } = await testResources({})
|
|
31
36
|
await underTest.commit()
|
|
32
37
|
expect(underTest.isOpen()).toBe(false)
|
|
33
|
-
expect(
|
|
38
|
+
expect(writer.transaction).toBeCalled()
|
|
39
|
+
expect(transaction.commit).toBeCalled()
|
|
34
40
|
|
|
35
41
|
await expect(underTest.commit).rejects.toThrowError(
|
|
36
42
|
'Cannot commit, transaction is already closed!'
|
|
@@ -38,28 +44,29 @@ describe('KnexTransaction', () => {
|
|
|
38
44
|
})
|
|
39
45
|
|
|
40
46
|
test("Can't commit after rollback", async () => {
|
|
41
|
-
const {
|
|
47
|
+
const { writer, transaction, underTest } = await testResources({})
|
|
42
48
|
await underTest.rollback()
|
|
43
49
|
expect(underTest.isOpen()).toBe(false)
|
|
44
|
-
expect(
|
|
50
|
+
expect(writer.transaction).toBeCalled()
|
|
51
|
+
expect(transaction.rollback).toBeCalled()
|
|
45
52
|
|
|
46
53
|
await expect(underTest.commit).rejects.toThrowError(
|
|
47
54
|
'Cannot commit, transaction is already closed!'
|
|
48
55
|
)
|
|
49
56
|
})
|
|
50
57
|
|
|
51
|
-
test('Forwards calls to
|
|
52
|
-
const {
|
|
58
|
+
test('Forwards calls to transaction', async () => {
|
|
59
|
+
const { transaction, underTest } = await testResources({})
|
|
53
60
|
await underTest.select('name')
|
|
54
|
-
expect(
|
|
61
|
+
expect(transaction.select).toBeCalledWith('name')
|
|
55
62
|
})
|
|
56
63
|
|
|
57
|
-
test('Blocks
|
|
58
|
-
const {
|
|
64
|
+
test('Blocks transaction calls after commit', async () => {
|
|
65
|
+
const { transaction, underTest } = await testResources({})
|
|
59
66
|
expect(underTest.select).toBeDefined()
|
|
60
67
|
|
|
61
68
|
await underTest.commit()
|
|
62
|
-
expect(
|
|
69
|
+
expect(transaction.commit).toBeCalled()
|
|
63
70
|
expect(underTest.isOpen()).toBe(false)
|
|
64
71
|
|
|
65
72
|
expect(underTest.select).toBeUndefined()
|
|
@@ -68,74 +75,74 @@ describe('KnexTransaction', () => {
|
|
|
68
75
|
|
|
69
76
|
describe('KnexTransaction - closeSuccess', () => {
|
|
70
77
|
test('Close success commits', async () => {
|
|
71
|
-
const {
|
|
78
|
+
const { transaction, underTest } = await testResources({})
|
|
72
79
|
await underTest.closeSuccess()
|
|
73
|
-
expect(
|
|
80
|
+
expect(transaction.commit).toBeCalled()
|
|
74
81
|
})
|
|
75
82
|
|
|
76
83
|
test("Close success, doesn't commit again if already committed", async () => {
|
|
77
|
-
const {
|
|
84
|
+
const { transaction, underTest } = await testResources({})
|
|
78
85
|
await underTest.commit()
|
|
79
|
-
expect(
|
|
86
|
+
expect(transaction.commit).toBeCalledTimes(1)
|
|
80
87
|
await underTest.closeSuccess()
|
|
81
|
-
expect(
|
|
88
|
+
expect(transaction.commit).toBeCalledTimes(1)
|
|
82
89
|
})
|
|
83
90
|
|
|
84
91
|
test('Close success, rolls back if not autocommit', async () => {
|
|
85
|
-
const {
|
|
92
|
+
const { transaction, underTest } = await testResources({ autoCommit: false })
|
|
86
93
|
await underTest.closeSuccess()
|
|
87
|
-
expect(
|
|
94
|
+
expect(transaction.rollback).toBeCalled()
|
|
88
95
|
})
|
|
89
96
|
|
|
90
97
|
test("Close success, doesn't rollback if already committed", async () => {
|
|
91
|
-
const {
|
|
98
|
+
const { transaction, underTest } = await testResources({ autoCommit: false })
|
|
92
99
|
await underTest.commit()
|
|
93
|
-
expect(
|
|
100
|
+
expect(transaction.commit).toBeCalledTimes(1)
|
|
94
101
|
await underTest.closeSuccess()
|
|
95
|
-
expect(
|
|
96
|
-
expect(
|
|
102
|
+
expect(transaction.rollback).not.toBeCalled()
|
|
103
|
+
expect(transaction.commit).toBeCalledTimes(1)
|
|
97
104
|
})
|
|
98
105
|
|
|
99
106
|
test("Close success, doesn't rollback if already rolled back", async () => {
|
|
100
|
-
const {
|
|
107
|
+
const { transaction, underTest } = await testResources({ autoCommit: false })
|
|
101
108
|
await underTest.rollback()
|
|
102
|
-
expect(
|
|
109
|
+
expect(transaction.rollback).toBeCalledTimes(1)
|
|
103
110
|
await underTest.closeSuccess()
|
|
104
|
-
expect(
|
|
105
|
-
expect(
|
|
111
|
+
expect(transaction.rollback).toBeCalledTimes(1)
|
|
112
|
+
expect(transaction.commit).not.toBeCalled()
|
|
106
113
|
})
|
|
107
114
|
})
|
|
108
115
|
|
|
109
116
|
describe('KnexTransaction - closeFailure', () => {
|
|
110
117
|
test('Close failure rolls back', async () => {
|
|
111
|
-
const {
|
|
118
|
+
const { transaction, underTest } = await testResources({})
|
|
112
119
|
await underTest.closeFailure()
|
|
113
|
-
expect(
|
|
120
|
+
expect(transaction.rollback).toBeCalled()
|
|
114
121
|
})
|
|
115
122
|
|
|
116
123
|
test("Close failure, doesn't rollback again if already rolled back", async () => {
|
|
117
|
-
const {
|
|
124
|
+
const { transaction, underTest } = await testResources({})
|
|
118
125
|
await underTest.rollback()
|
|
119
|
-
expect(
|
|
126
|
+
expect(transaction.rollback).toBeCalledTimes(1)
|
|
120
127
|
await underTest.closeFailure()
|
|
121
|
-
expect(
|
|
128
|
+
expect(transaction.rollback).toBeCalledTimes(1)
|
|
122
129
|
})
|
|
123
130
|
|
|
124
131
|
test("Close failure, doesn't rollback if already committed", async () => {
|
|
125
|
-
const {
|
|
132
|
+
const { transaction, underTest } = await testResources({ autoCommit: false })
|
|
126
133
|
await underTest.commit()
|
|
127
|
-
expect(
|
|
134
|
+
expect(transaction.commit).toBeCalledTimes(1)
|
|
128
135
|
await underTest.closeFailure()
|
|
129
|
-
expect(
|
|
130
|
-
expect(
|
|
136
|
+
expect(transaction.rollback).not.toBeCalled()
|
|
137
|
+
expect(transaction.commit).toBeCalledTimes(1)
|
|
131
138
|
})
|
|
132
139
|
})
|
|
133
140
|
|
|
134
141
|
describe('KnexTransaction - call direct', () => {
|
|
135
|
-
test('Calls
|
|
136
|
-
const {
|
|
142
|
+
test('Calls transaction', async () => {
|
|
143
|
+
const { transaction, underTest } = await testResources({ autoCommit: false })
|
|
137
144
|
|
|
138
145
|
underTest('test')
|
|
139
|
-
expect(
|
|
146
|
+
expect(transaction).toBeCalledWith('test')
|
|
140
147
|
})
|
|
141
148
|
})
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { expect as c_expect } from 'chai'
|
|
2
|
+
import { PostgresDialect } from 'kysely'
|
|
3
|
+
import { PoolClient } from 'pg'
|
|
4
|
+
|
|
5
|
+
import type { DbConfig } from '../../../../src/Database'
|
|
6
|
+
import { KyselyDatabase } from '../../../../src/Database/integrations/kysely/KyselyDatabase'
|
|
7
|
+
|
|
8
|
+
const config: DbConfig<'kysely'> = {
|
|
9
|
+
type: 'kysely',
|
|
10
|
+
username: 'username',
|
|
11
|
+
password: 'password',
|
|
12
|
+
host: 'host',
|
|
13
|
+
port: 1234,
|
|
14
|
+
database: 'database',
|
|
15
|
+
maxConnections: 1,
|
|
16
|
+
autoCommit: true,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const config2: DbConfig<'kysely'> = {
|
|
20
|
+
...config,
|
|
21
|
+
readReplica: config,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const expectedImplConfig = {
|
|
25
|
+
host: config.host,
|
|
26
|
+
port: config.port,
|
|
27
|
+
user: config.username,
|
|
28
|
+
password: config.password,
|
|
29
|
+
database: config.database,
|
|
30
|
+
max: config.maxConnections,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('KyselyDatabase', () => {
|
|
34
|
+
let mockTrans
|
|
35
|
+
let mockClient
|
|
36
|
+
let mockDriver
|
|
37
|
+
let mockDialect
|
|
38
|
+
let mockPgTrans
|
|
39
|
+
let mockPgClient
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
mockTrans = {
|
|
42
|
+
execute: jest.fn(async cb => {
|
|
43
|
+
cb(mockTrans)
|
|
44
|
+
}),
|
|
45
|
+
} as any
|
|
46
|
+
mockClient = jest.fn(
|
|
47
|
+
() =>
|
|
48
|
+
({
|
|
49
|
+
transaction: () => mockTrans,
|
|
50
|
+
}) as any as PostgresDialect
|
|
51
|
+
)
|
|
52
|
+
KyselyDatabase['kyselyProvider'] = mockClient as any
|
|
53
|
+
|
|
54
|
+
mockDriver = {
|
|
55
|
+
execute: jest.fn(async () => {}),
|
|
56
|
+
} as any
|
|
57
|
+
mockDialect = jest.fn(
|
|
58
|
+
() =>
|
|
59
|
+
({
|
|
60
|
+
createDriver: () => mockDriver,
|
|
61
|
+
}) as any as PostgresDialect
|
|
62
|
+
)
|
|
63
|
+
KyselyDatabase['kyselyPgProvider'] = mockDialect as any
|
|
64
|
+
|
|
65
|
+
mockPgTrans = {
|
|
66
|
+
query: jest.fn(() => {}),
|
|
67
|
+
} as any
|
|
68
|
+
mockPgClient = jest.fn(
|
|
69
|
+
() =>
|
|
70
|
+
({
|
|
71
|
+
connect: async () => mockPgTrans,
|
|
72
|
+
}) as PoolClient
|
|
73
|
+
)
|
|
74
|
+
KyselyDatabase['pgProvider'] = mockPgClient as any
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('KyselyDatabase', async () => {
|
|
78
|
+
const underTest = new KyselyDatabase(config)
|
|
79
|
+
expect(mockPgClient).toHaveBeenNthCalledWith(1, expectedImplConfig)
|
|
80
|
+
expect(mockDialect).toHaveBeenCalledTimes(1)
|
|
81
|
+
expect(mockClient).toHaveBeenNthCalledWith(1, { dialect: underTest.pgClient })
|
|
82
|
+
|
|
83
|
+
const trans = await underTest.transaction()
|
|
84
|
+
|
|
85
|
+
expect(mockTrans.execute).toHaveBeenCalledTimes(1)
|
|
86
|
+
expect(trans.reader).toBeUndefined()
|
|
87
|
+
expect(trans.writer).toBeInstanceOf(Object)
|
|
88
|
+
expect(trans.writer.transaction).toBeInstanceOf(Function)
|
|
89
|
+
expect(trans).toBeInstanceOf(Function)
|
|
90
|
+
expect(trans['transaction']).toBe(mockTrans)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('KyselyDatabase - read replica', async () => {
|
|
94
|
+
const underTest = new KyselyDatabase(config2)
|
|
95
|
+
expect(mockPgClient).toHaveBeenNthCalledWith(2, expectedImplConfig)
|
|
96
|
+
expect(mockDialect).toHaveBeenCalledTimes(2)
|
|
97
|
+
expect(mockClient).toHaveBeenNthCalledWith(1, { dialect: underTest.pgClient })
|
|
98
|
+
expect(mockClient).toHaveBeenNthCalledWith(2, { dialect: underTest.pgReadClient })
|
|
99
|
+
|
|
100
|
+
const trans = await underTest.transaction()
|
|
101
|
+
|
|
102
|
+
expect(mockTrans.execute).toHaveBeenCalledTimes(1)
|
|
103
|
+
expect(trans.writer).toBeInstanceOf(Object)
|
|
104
|
+
expect(trans.writer.transaction).toBeInstanceOf(Function)
|
|
105
|
+
expect(trans.reader).toBeInstanceOf(Object)
|
|
106
|
+
expect(trans).toBeInstanceOf(Function)
|
|
107
|
+
expect(trans['transaction']).toBe(mockTrans)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Kysely, PostgresDialect, Transaction } from 'kysely'
|
|
2
|
+
|
|
3
|
+
import type { DbConfig } from '../../../../src/Database'
|
|
4
|
+
import { KyselyDatabase } from '../../../../src/Database/integrations/kysely/KyselyDatabase'
|
|
5
|
+
import { KyselyTransactionImpl } from '../../../../src/Database/integrations/kysely/KyselyTransaction'
|
|
6
|
+
|
|
7
|
+
const testResources = async (config: Partial<DbConfig<'kysely'>>) => {
|
|
8
|
+
type DB = {
|
|
9
|
+
view: {
|
|
10
|
+
id: number
|
|
11
|
+
}
|
|
12
|
+
secondView: {
|
|
13
|
+
title: string
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const database = {
|
|
18
|
+
config: {
|
|
19
|
+
autoCommit: true,
|
|
20
|
+
...config,
|
|
21
|
+
} as DbConfig<'kysely'>,
|
|
22
|
+
} as KyselyDatabase<DB>
|
|
23
|
+
|
|
24
|
+
const transaction = jest.fn().mockImplementation(() => {
|
|
25
|
+
return {
|
|
26
|
+
execute: jest.fn(async cb => {
|
|
27
|
+
try {
|
|
28
|
+
await cb(transaction)
|
|
29
|
+
} catch (e) {
|
|
30
|
+
/* empty */
|
|
31
|
+
}
|
|
32
|
+
}),
|
|
33
|
+
executeQuery: jest.fn(),
|
|
34
|
+
}
|
|
35
|
+
})() as any as Transaction<DB>
|
|
36
|
+
|
|
37
|
+
const writer = jest.fn().mockImplementation(() => {
|
|
38
|
+
return {
|
|
39
|
+
transaction: jest.fn(() => transaction),
|
|
40
|
+
}
|
|
41
|
+
})() as any as Kysely<DB>
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
transaction,
|
|
45
|
+
writer,
|
|
46
|
+
underTest: await KyselyTransactionImpl.newTransaction(writer, database),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe('KyselyTransaction', () => {
|
|
51
|
+
test('Transaction starts opened', async () => {
|
|
52
|
+
const { transaction, underTest } = await testResources({})
|
|
53
|
+
expect(underTest.isOpen()).toBe(true)
|
|
54
|
+
expect(transaction['execute']).toHaveBeenCalledTimes(1)
|
|
55
|
+
|
|
56
|
+
await expect(underTest.begin).rejects.toThrowError(
|
|
57
|
+
'Cannot begin, transaction is already opened!'
|
|
58
|
+
)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('Can only commit once', async () => {
|
|
62
|
+
const { underTest } = await testResources({})
|
|
63
|
+
await underTest.commit()
|
|
64
|
+
expect(underTest.isOpen()).toBe(false)
|
|
65
|
+
|
|
66
|
+
await expect(underTest.commit).rejects.toThrowError(
|
|
67
|
+
'Cannot commit, transaction is already closed!'
|
|
68
|
+
)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('Can only rollback once', async () => {
|
|
72
|
+
const { underTest } = await testResources({})
|
|
73
|
+
await underTest.rollback()
|
|
74
|
+
expect(underTest.isOpen()).toBe(false)
|
|
75
|
+
await expect(underTest.rollback).rejects.toThrowError(
|
|
76
|
+
'Cannot rollback, transaction is already closed!'
|
|
77
|
+
)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test("Can't open transaction twice", async () => {
|
|
81
|
+
const { underTest } = await testResources({})
|
|
82
|
+
expect(underTest.isOpen()).toBe(true)
|
|
83
|
+
|
|
84
|
+
await expect(underTest.begin).rejects.toThrowError(
|
|
85
|
+
'Cannot begin, transaction is already opened!'
|
|
86
|
+
)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('Can commit, begin and commit again ', async () => {
|
|
90
|
+
const { underTest } = await testResources({})
|
|
91
|
+
await underTest.commit()
|
|
92
|
+
expect(underTest.isOpen()).toBe(false)
|
|
93
|
+
await underTest.begin()
|
|
94
|
+
expect(underTest.isOpen()).toBe(true)
|
|
95
|
+
await underTest.commit()
|
|
96
|
+
expect(underTest.isOpen()).toBe(false)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('Can commit, begin and rollback ', async () => {
|
|
100
|
+
const { underTest } = await testResources({})
|
|
101
|
+
await underTest.commit()
|
|
102
|
+
expect(underTest.isOpen()).toBe(false)
|
|
103
|
+
await underTest.begin()
|
|
104
|
+
expect(underTest.isOpen()).toBe(true)
|
|
105
|
+
await underTest.rollback()
|
|
106
|
+
expect(underTest.isOpen()).toBe(false)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('Can rollback, begin and commit ', async () => {
|
|
110
|
+
const { underTest } = await testResources({})
|
|
111
|
+
await underTest.rollback()
|
|
112
|
+
expect(underTest.isOpen()).toBe(false)
|
|
113
|
+
await underTest.begin()
|
|
114
|
+
expect(underTest.isOpen()).toBe(true)
|
|
115
|
+
await underTest.commit()
|
|
116
|
+
expect(underTest.isOpen()).toBe(false)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
@@ -10,11 +10,15 @@ const config: DbConfig<'pg'> = {
|
|
|
10
10
|
host: 'host',
|
|
11
11
|
port: 1234,
|
|
12
12
|
database: 'database',
|
|
13
|
-
driver: 'driver',
|
|
14
13
|
maxConnections: 1,
|
|
15
14
|
autoCommit: true,
|
|
16
15
|
}
|
|
17
16
|
|
|
17
|
+
const config2: DbConfig<'pg'> = {
|
|
18
|
+
...config,
|
|
19
|
+
readReplica: config,
|
|
20
|
+
}
|
|
21
|
+
|
|
18
22
|
const expectedImplConfig = {
|
|
19
23
|
host: config.host,
|
|
20
24
|
port: config.port,
|
|
@@ -25,25 +29,47 @@ const expectedImplConfig = {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
describe('PostgresDatabase', () => {
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
let mockTrans
|
|
33
|
+
let mockClient
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
mockTrans = {
|
|
30
36
|
query: jest.fn(() => {}),
|
|
31
37
|
} as any
|
|
32
|
-
|
|
38
|
+
mockClient = jest.fn(
|
|
33
39
|
() =>
|
|
34
40
|
({
|
|
35
41
|
connect: async () => mockTrans,
|
|
36
42
|
}) as PoolClient
|
|
37
43
|
)
|
|
38
44
|
PostgresDatabase['pgProvider'] = mockClient as any
|
|
45
|
+
})
|
|
39
46
|
|
|
47
|
+
test('PostgresDatabase', async () => {
|
|
40
48
|
const underTest = new PostgresDatabase(config)
|
|
41
|
-
expect(mockClient).
|
|
49
|
+
expect(mockClient).toHaveBeenNthCalledWith(1, expectedImplConfig)
|
|
50
|
+
|
|
51
|
+
const trans = await underTest.transaction()
|
|
52
|
+
|
|
53
|
+
expect(mockTrans.query).toBeCalledWith('BEGIN')
|
|
54
|
+
expect(trans.reader).toBeUndefined()
|
|
55
|
+
expect(trans.writer).toBeInstanceOf(Object)
|
|
56
|
+
expect(trans.writer.connect).toBeInstanceOf(Function)
|
|
57
|
+
expect(trans).toBeInstanceOf(Function)
|
|
58
|
+
expect(trans['transaction']).toBe(mockTrans)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('PostgresDatabase - read replica', async () => {
|
|
62
|
+
const underTest = new PostgresDatabase(config2)
|
|
63
|
+
expect(mockClient).toHaveBeenNthCalledWith(2, expectedImplConfig)
|
|
42
64
|
|
|
43
65
|
const trans = await underTest.transaction()
|
|
44
66
|
|
|
45
67
|
expect(mockTrans.query).toBeCalledWith('BEGIN')
|
|
68
|
+
expect(trans.reader).toBeInstanceOf(Object)
|
|
69
|
+
expect(trans.reader.connect).toBeInstanceOf(Function)
|
|
70
|
+
expect(trans.writer).toBeInstanceOf(Object)
|
|
71
|
+
expect(trans.writer.connect).toBeInstanceOf(Function)
|
|
46
72
|
expect(trans).toBeInstanceOf(Function)
|
|
47
|
-
expect(trans['
|
|
73
|
+
expect(trans['transaction']).toBe(mockTrans)
|
|
48
74
|
})
|
|
49
75
|
})
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { PoolClient } from 'pg'
|
|
1
|
+
import { Pool, PoolClient } from 'pg'
|
|
2
2
|
|
|
3
3
|
import type { DbConfig } from '../../../../src/Database'
|
|
4
4
|
import { PostgresDatabase } from '../../../../src/Database/integrations/pgsql/PostgresDatabase'
|
|
5
5
|
import { PostgresTransactionImpl } from '../../../../src/Database/integrations/pgsql/PostgresTransaction'
|
|
6
6
|
|
|
7
|
-
const testResources = (config: Partial<DbConfig<'pg'>>) => {
|
|
7
|
+
const testResources = async (config: Partial<DbConfig<'pg'>>) => {
|
|
8
8
|
const database = {
|
|
9
9
|
config: {
|
|
10
10
|
autoCommit: true,
|
|
@@ -12,7 +12,7 @@ const testResources = (config: Partial<DbConfig<'pg'>>) => {
|
|
|
12
12
|
} as DbConfig<'pg'>,
|
|
13
13
|
} as PostgresDatabase
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const transaction = jest.fn().mockImplementation(() => {
|
|
16
16
|
return {
|
|
17
17
|
commit: jest.fn(),
|
|
18
18
|
rollback: jest.fn(),
|
|
@@ -20,18 +20,35 @@ const testResources = (config: Partial<DbConfig<'pg'>>) => {
|
|
|
20
20
|
}
|
|
21
21
|
})() as any as PoolClient
|
|
22
22
|
|
|
23
|
+
const writer = jest.fn().mockImplementation(() => {
|
|
24
|
+
return {
|
|
25
|
+
connect: jest.fn(() => transaction),
|
|
26
|
+
}
|
|
27
|
+
})() as any as Pool
|
|
28
|
+
|
|
23
29
|
return {
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
transaction,
|
|
31
|
+
writer,
|
|
32
|
+
underTest: await PostgresTransactionImpl.newTransaction(writer, database),
|
|
26
33
|
}
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
describe('PostgresTransaction', () => {
|
|
37
|
+
test('Transaction starts opened', async () => {
|
|
38
|
+
const { transaction, underTest } = await testResources({})
|
|
39
|
+
expect(underTest.isOpen()).toBe(true)
|
|
40
|
+
expect(transaction.query).toHaveBeenNthCalledWith(1, 'BEGIN')
|
|
41
|
+
|
|
42
|
+
await expect(underTest.begin).rejects.toThrowError(
|
|
43
|
+
'Cannot begin, transaction is already opened!'
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
|
|
30
47
|
test('Can only commit once', async () => {
|
|
31
|
-
const {
|
|
48
|
+
const { transaction, underTest } = await testResources({})
|
|
32
49
|
await underTest.commit()
|
|
33
50
|
expect(underTest.isOpen()).toBe(false)
|
|
34
|
-
expect(
|
|
51
|
+
expect(transaction.query).toBeCalledWith('COMMIT')
|
|
35
52
|
|
|
36
53
|
await expect(underTest.commit).rejects.toThrowError(
|
|
37
54
|
'Cannot commit, transaction is already closed!'
|
|
@@ -39,13 +56,62 @@ describe('PostgresTransaction', () => {
|
|
|
39
56
|
})
|
|
40
57
|
|
|
41
58
|
test('Can only rollback once', async () => {
|
|
42
|
-
const {
|
|
59
|
+
const { transaction, underTest } = await testResources({})
|
|
43
60
|
await underTest.rollback()
|
|
44
61
|
expect(underTest.isOpen()).toBe(false)
|
|
45
|
-
expect(
|
|
62
|
+
expect(transaction.query).toBeCalledWith('ROLLBACK')
|
|
46
63
|
|
|
47
64
|
await expect(underTest.rollback).rejects.toThrowError(
|
|
48
65
|
'Cannot rollback, transaction is already closed!'
|
|
49
66
|
)
|
|
50
67
|
})
|
|
68
|
+
|
|
69
|
+
test("Can't open transaction twice", async () => {
|
|
70
|
+
const { transaction, underTest } = await testResources({})
|
|
71
|
+
expect(underTest.isOpen()).toBe(true)
|
|
72
|
+
expect(transaction.query).toHaveBeenNthCalledWith(1, 'BEGIN')
|
|
73
|
+
|
|
74
|
+
await expect(underTest.begin).rejects.toThrowError(
|
|
75
|
+
'Cannot begin, transaction is already opened!'
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('Can commit, begin and commit again ', async () => {
|
|
80
|
+
const { transaction, underTest } = await testResources({})
|
|
81
|
+
await underTest.commit()
|
|
82
|
+
expect(underTest.isOpen()).toBe(false)
|
|
83
|
+
expect(transaction.query).toBeCalledWith('COMMIT')
|
|
84
|
+
await underTest.begin()
|
|
85
|
+
expect(underTest.isOpen()).toBe(true)
|
|
86
|
+
expect(transaction.query).toHaveBeenNthCalledWith(3, 'BEGIN')
|
|
87
|
+
await underTest.commit()
|
|
88
|
+
expect(underTest.isOpen()).toBe(false)
|
|
89
|
+
expect(transaction.query).toHaveBeenNthCalledWith(4, 'COMMIT')
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('Can commit, begin and rollback ', async () => {
|
|
93
|
+
const { transaction, underTest } = await testResources({})
|
|
94
|
+
await underTest.commit()
|
|
95
|
+
expect(underTest.isOpen()).toBe(false)
|
|
96
|
+
expect(transaction.query).toBeCalledWith('COMMIT')
|
|
97
|
+
await underTest.begin()
|
|
98
|
+
expect(underTest.isOpen()).toBe(true)
|
|
99
|
+
expect(transaction.query).toHaveBeenNthCalledWith(3, 'BEGIN')
|
|
100
|
+
await underTest.rollback()
|
|
101
|
+
expect(underTest.isOpen()).toBe(false)
|
|
102
|
+
expect(transaction.query).toHaveBeenNthCalledWith(4, 'ROLLBACK')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('Can rollback, begin and commit ', async () => {
|
|
106
|
+
const { transaction, underTest } = await testResources({})
|
|
107
|
+
await underTest.rollback()
|
|
108
|
+
expect(underTest.isOpen()).toBe(false)
|
|
109
|
+
expect(transaction.query).toBeCalledWith('ROLLBACK')
|
|
110
|
+
await underTest.begin()
|
|
111
|
+
expect(underTest.isOpen()).toBe(true)
|
|
112
|
+
expect(transaction.query).toHaveBeenNthCalledWith(3, 'BEGIN')
|
|
113
|
+
await underTest.commit()
|
|
114
|
+
expect(underTest.isOpen()).toBe(false)
|
|
115
|
+
expect(transaction.query).toHaveBeenNthCalledWith(4, 'COMMIT')
|
|
116
|
+
})
|
|
51
117
|
})
|