@starbemtech/star-db-query-builder 1.3.1 → 1.4.0

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 (75) hide show
  1. package/.claude/skills/star-db-query-builder/SKILL.md +104 -0
  2. package/CHANGELOG.md +82 -45
  3. package/LICENSE +21 -0
  4. package/README.md +194 -94
  5. package/bin/install-skill.js +53 -0
  6. package/dist/src/core/repository.d.ts +92 -9
  7. package/dist/src/core/repository.js +275 -27
  8. package/dist/src/core/repository.js.map +1 -1
  9. package/dist/src/core/types.d.ts +16 -1
  10. package/dist/src/core/utils.d.ts +102 -0
  11. package/dist/src/core/utils.js +287 -70
  12. package/dist/src/core/utils.js.map +1 -1
  13. package/dist/src/db/initDb.d.ts +60 -50
  14. package/dist/src/db/initDb.js +96 -64
  15. package/dist/src/db/initDb.js.map +1 -1
  16. package/dist/src/db/mysqlClient.d.ts +3 -8
  17. package/dist/src/db/mysqlClient.js +9 -11
  18. package/dist/src/db/mysqlClient.js.map +1 -1
  19. package/dist/src/db/pgClient.js +0 -2
  20. package/dist/src/db/pgClient.js.map +1 -1
  21. package/dist/src/monitor/monitor.js +7 -0
  22. package/dist/src/monitor/monitor.js.map +1 -1
  23. package/package.json +27 -19
  24. package/.github/workflows/publish.yml +0 -118
  25. package/.prettierignore +0 -3
  26. package/.prettierrc +0 -5
  27. package/ARCHITECTURE.md +0 -313
  28. package/coverage/base.css +0 -224
  29. package/coverage/block-navigation.js +0 -87
  30. package/coverage/favicon.png +0 -0
  31. package/coverage/index.html +0 -131
  32. package/coverage/lcov-report/base.css +0 -224
  33. package/coverage/lcov-report/block-navigation.js +0 -87
  34. package/coverage/lcov-report/favicon.png +0 -0
  35. package/coverage/lcov-report/index.html +0 -131
  36. package/coverage/lcov-report/mysqlClient.ts.html +0 -685
  37. package/coverage/lcov-report/pgClient.ts.html +0 -823
  38. package/coverage/lcov-report/prettify.css +0 -1
  39. package/coverage/lcov-report/prettify.js +0 -2
  40. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  41. package/coverage/lcov-report/sorter.js +0 -210
  42. package/coverage/lcov.info +0 -533
  43. package/coverage/mysqlClient.ts.html +0 -685
  44. package/coverage/pgClient.ts.html +0 -823
  45. package/coverage/prettify.css +0 -1
  46. package/coverage/prettify.js +0 -2
  47. package/coverage/sort-arrow-sprite.png +0 -0
  48. package/coverage/sorter.js +0 -210
  49. package/dist/src/setupTests.d.ts +0 -26
  50. package/dist/src/setupTests.js +0 -43
  51. package/dist/src/setupTests.js.map +0 -1
  52. package/docs/INDEX.md +0 -145
  53. package/docs/methods/findFirst.md +0 -394
  54. package/docs/methods/findMany.md +0 -587
  55. package/docs/methods/insert.md +0 -536
  56. package/docs/methods/insertMany.md +0 -627
  57. package/docs/methods/joins.md +0 -781
  58. package/docs/methods/rawQuery.md +0 -284
  59. package/docs/methods/transactions.md +0 -737
  60. package/eslint.config.mjs +0 -77
  61. package/index.ts +0 -16
  62. package/jest.config.ts +0 -194
  63. package/scripts/release.sh +0 -123
  64. package/src/core/repository.ts +0 -865
  65. package/src/core/types.ts +0 -97
  66. package/src/core/utils.ts +0 -357
  67. package/src/db/IDatabaseClient.ts +0 -16
  68. package/src/db/__tests__/mysqlClient.test.ts +0 -262
  69. package/src/db/__tests__/pgClient.test.ts +0 -260
  70. package/src/db/initDb.ts +0 -181
  71. package/src/db/mysqlClient.ts +0 -200
  72. package/src/db/pgClient.ts +0 -246
  73. package/src/monitor/monitor.ts +0 -16
  74. package/src/setupTests.ts +0 -45
  75. package/tsconfig.test.json +0 -21
@@ -1,262 +0,0 @@
1
- import { createMysqlClient } from '../mysqlClient'
2
- import { createPool, Pool } from 'mysql2/promise'
3
-
4
- // Mock mysql2 module
5
- jest.mock('mysql2/promise', () => ({
6
- createPool: jest.fn(),
7
- }))
8
-
9
- // Mock monitor
10
- jest.mock('../../monitor/monitor', () => ({
11
- monitor: {
12
- emit: jest.fn(),
13
- },
14
- MonitorEvents: {
15
- CONNECTION_CREATED: 'CONNECTION_CREATED',
16
- QUERY_START: 'QUERY_START',
17
- QUERY_END: 'QUERY_END',
18
- QUERY_ERROR: 'QUERY_ERROR',
19
- RETRY_ATTEMPT: 'RETRY_ATTEMPT',
20
- TRANSACTION_COMMIT: 'TRANSACTION_COMMIT',
21
- TRANSACTION_ROLLBACK: 'TRANSACTION_ROLLBACK',
22
- },
23
- }))
24
-
25
- describe('MySqlClient', () => {
26
- let mockPool: jest.Mocked<Pool>
27
-
28
- beforeEach(() => {
29
- mockPool = {
30
- query: jest.fn(),
31
- connect: jest.fn(),
32
- end: jest.fn(),
33
- execute: jest.fn(),
34
- getConnection: jest.fn(),
35
- config: {},
36
- } as any
37
- ;(createPool as jest.MockedFunction<typeof createPool>).mockReturnValue(
38
- mockPool
39
- )
40
- })
41
-
42
- afterEach(() => {
43
- jest.clearAllMocks()
44
- })
45
-
46
- describe('createMysqlClient', () => {
47
- it('should return client with correct clientType', () => {
48
- const client = createMysqlClient(mockPool)
49
-
50
- expect(client.clientType).toBe('mysql')
51
- })
52
-
53
- it('should execute query and return rows', async () => {
54
- const mockRows = [{ id: 1, name: 'John Doe' }]
55
- mockPool.execute.mockResolvedValue([mockRows, []] as any)
56
-
57
- const client = createMysqlClient(mockPool)
58
- const result = await client.query('SELECT * FROM users WHERE id = ?', [1])
59
-
60
- expect(mockPool.execute).toHaveBeenCalledWith(
61
- 'SELECT * FROM users WHERE id = ?',
62
- [1]
63
- )
64
- expect(result).toEqual(mockRows)
65
- })
66
-
67
- it('should handle query without parameters', async () => {
68
- const mockRows = [{ id: 1, name: 'John Doe' }]
69
- mockPool.execute.mockResolvedValue([mockRows, []] as any)
70
-
71
- const client = createMysqlClient(mockPool)
72
- const result = await client.query('SELECT * FROM users')
73
-
74
- expect(mockPool.execute).toHaveBeenCalledWith(
75
- 'SELECT * FROM users',
76
- undefined
77
- )
78
- expect(result).toEqual(mockRows)
79
- })
80
-
81
- it('should handle empty result set', async () => {
82
- mockPool.execute.mockResolvedValue([[], []] as any)
83
-
84
- const client = createMysqlClient(mockPool)
85
- const result = await client.query('SELECT * FROM users WHERE id = ?', [
86
- 999,
87
- ])
88
-
89
- expect(result).toEqual([])
90
- })
91
-
92
- it('should handle query errors', async () => {
93
- const error = new Error('Database connection failed')
94
- mockPool.execute.mockRejectedValue(error)
95
-
96
- const client = createMysqlClient(mockPool)
97
-
98
- await expect(client.query('SELECT * FROM users')).rejects.toThrow(
99
- 'Database connection failed'
100
- )
101
- })
102
-
103
- it('should handle retry options', async () => {
104
- const mockRows = [{ id: 1, name: 'John Doe' }]
105
- mockPool.execute.mockResolvedValue([mockRows, []] as any)
106
-
107
- const retryOptions = {
108
- retries: 3,
109
- factor: 2,
110
- minTimeout: 1000,
111
- maxTimeout: 5000,
112
- }
113
-
114
- const client = createMysqlClient(mockPool, retryOptions)
115
- const result = await client.query('SELECT * FROM users')
116
-
117
- expect(result).toEqual(mockRows)
118
- })
119
-
120
- it('should handle transient errors with retry', async () => {
121
- const transientError = new Error('Connection lost')
122
- ;(transientError as any).code = 'ECONNRESET'
123
-
124
- const mockRows = [{ id: 1, name: 'John Doe' }]
125
-
126
- // First call fails with transient error, second succeeds
127
- mockPool.execute
128
- .mockRejectedValueOnce(transientError)
129
- .mockResolvedValueOnce([mockRows, []] as any)
130
-
131
- const retryOptions = {
132
- retries: 3,
133
- factor: 2,
134
- minTimeout: 100,
135
- maxTimeout: 500,
136
- }
137
-
138
- const client = createMysqlClient(mockPool, retryOptions)
139
- const result = await client.query('SELECT * FROM users')
140
-
141
- expect(mockPool.execute).toHaveBeenCalledTimes(2)
142
- expect(result).toEqual(mockRows)
143
- })
144
-
145
- it('should throw non-transient errors immediately', async () => {
146
- const permanentError = new Error('Table does not exist')
147
- ;(permanentError as any).code = 'ER_NO_SUCH_TABLE'
148
-
149
- mockPool.execute.mockRejectedValue(permanentError)
150
-
151
- const retryOptions = {
152
- retries: 3,
153
- factor: 2,
154
- minTimeout: 100,
155
- maxTimeout: 500,
156
- }
157
-
158
- const client = createMysqlClient(mockPool, retryOptions)
159
-
160
- await expect(
161
- client.query('SELECT * FROM nonexistent_table')
162
- ).rejects.toThrow('Table does not exist')
163
- expect(mockPool.execute).toHaveBeenCalledTimes(1)
164
- })
165
-
166
- describe('beginTransaction', () => {
167
- let mockConnection: any
168
-
169
- beforeEach(() => {
170
- mockConnection = {
171
- execute: jest.fn(),
172
- beginTransaction: jest.fn(),
173
- commit: jest.fn(),
174
- rollback: jest.fn(),
175
- release: jest.fn(),
176
- }
177
- mockPool.getConnection.mockResolvedValue(mockConnection)
178
- })
179
-
180
- it('should create a transaction client', async () => {
181
- const client = createMysqlClient(mockPool)
182
- const transaction = await client.beginTransaction()
183
-
184
- expect(mockPool.getConnection).toHaveBeenCalled()
185
- expect(mockConnection.beginTransaction).toHaveBeenCalled()
186
- expect(transaction).toHaveProperty('query')
187
- expect(transaction).toHaveProperty('commit')
188
- expect(transaction).toHaveProperty('rollback')
189
- })
190
-
191
- it('should execute queries within transaction', async () => {
192
- const mockRows = [{ id: 1, name: 'John Doe' }]
193
- mockConnection.execute.mockResolvedValue([mockRows, []])
194
-
195
- const client = createMysqlClient(mockPool)
196
- const transaction = await client.beginTransaction()
197
- const result = await transaction.query(
198
- 'SELECT * FROM users WHERE id = ?',
199
- [1]
200
- )
201
-
202
- expect(mockConnection.execute).toHaveBeenCalledWith(
203
- 'SELECT * FROM users WHERE id = ?',
204
- [1]
205
- )
206
- expect(result).toEqual(mockRows)
207
- })
208
-
209
- it('should commit transaction successfully', async () => {
210
- const client = createMysqlClient(mockPool)
211
- const transaction = await client.beginTransaction()
212
- await transaction.commit()
213
-
214
- expect(mockConnection.commit).toHaveBeenCalled()
215
- expect(mockConnection.release).toHaveBeenCalled()
216
- })
217
-
218
- it('should rollback transaction on error', async () => {
219
- const client = createMysqlClient(mockPool)
220
- const transaction = await client.beginTransaction()
221
- await transaction.rollback()
222
-
223
- expect(mockConnection.rollback).toHaveBeenCalled()
224
- expect(mockConnection.release).toHaveBeenCalled()
225
- })
226
-
227
- it('should release connection even if commit fails', async () => {
228
- const commitError = new Error('Commit failed')
229
- mockConnection.commit.mockRejectedValue(commitError)
230
-
231
- const client = createMysqlClient(mockPool)
232
- const transaction = await client.beginTransaction()
233
-
234
- await expect(transaction.commit()).rejects.toThrow('Commit failed')
235
- expect(mockConnection.release).toHaveBeenCalled()
236
- })
237
-
238
- it('should release connection even if rollback fails', async () => {
239
- const rollbackError = new Error('Rollback failed')
240
- mockConnection.rollback.mockRejectedValue(rollbackError)
241
-
242
- const client = createMysqlClient(mockPool)
243
- const transaction = await client.beginTransaction()
244
-
245
- await expect(transaction.rollback()).rejects.toThrow('Rollback failed')
246
- expect(mockConnection.release).toHaveBeenCalled()
247
- })
248
-
249
- it('should release connection if beginTransaction fails', async () => {
250
- const beginError = new Error('Begin transaction failed')
251
- mockConnection.beginTransaction.mockRejectedValue(beginError)
252
-
253
- const client = createMysqlClient(mockPool)
254
-
255
- await expect(client.beginTransaction()).rejects.toThrow(
256
- 'Begin transaction failed'
257
- )
258
- expect(mockConnection.release).toHaveBeenCalled()
259
- })
260
- })
261
- })
262
- })
@@ -1,260 +0,0 @@
1
- import { createPgClient } from '../pgClient'
2
- import { Pool } from 'pg'
3
-
4
- // Mock pg module
5
- jest.mock('pg', () => ({
6
- Pool: jest.fn(),
7
- }))
8
-
9
- // Mock monitor
10
- jest.mock('../../monitor/monitor', () => ({
11
- monitor: {
12
- emit: jest.fn(),
13
- },
14
- MonitorEvents: {
15
- CONNECTION_CREATED: 'CONNECTION_CREATED',
16
- QUERY_START: 'QUERY_START',
17
- QUERY_END: 'QUERY_END',
18
- QUERY_ERROR: 'QUERY_ERROR',
19
- RETRY_ATTEMPT: 'RETRY_ATTEMPT',
20
- TRANSACTION_COMMIT: 'TRANSACTION_COMMIT',
21
- TRANSACTION_ROLLBACK: 'TRANSACTION_ROLLBACK',
22
- },
23
- }))
24
-
25
- describe('PgClient', () => {
26
- let mockPool: jest.Mocked<Pool>
27
-
28
- beforeEach(() => {
29
- mockPool = {
30
- query: jest.fn(),
31
- connect: jest.fn(),
32
- end: jest.fn(),
33
- } as any
34
- ;(Pool as jest.MockedClass<typeof Pool>).mockImplementation(() => mockPool)
35
- })
36
-
37
- afterEach(() => {
38
- jest.clearAllMocks()
39
- })
40
-
41
- describe('createPgClient', () => {
42
- it('should return client with correct clientType', async () => {
43
- const client = await createPgClient(mockPool)
44
- expect(client.clientType).toBe('pg')
45
- })
46
-
47
- it('should execute query and return rows', async () => {
48
- const mockRows = [{ id: 1, name: 'John Doe' }]
49
- mockPool.query.mockResolvedValue({ rows: mockRows, rowCount: 1 } as any)
50
- const client = await createPgClient(mockPool)
51
- const result = await client.query('SELECT * FROM users WHERE id = $1', [
52
- 1,
53
- ])
54
- expect(mockPool.query).toHaveBeenCalledWith(
55
- 'SELECT * FROM users WHERE id = $1',
56
- [1]
57
- )
58
- expect(result).toEqual(mockRows)
59
- })
60
-
61
- it('should handle query without parameters', async () => {
62
- const mockRows = [{ id: 1, name: 'John Doe' }]
63
- mockPool.query.mockResolvedValue({ rows: mockRows, rowCount: 1 } as any)
64
- const client = await createPgClient(mockPool)
65
- const result = await client.query('SELECT * FROM users')
66
- expect(mockPool.query).toHaveBeenCalledWith(
67
- 'SELECT * FROM users',
68
- undefined
69
- )
70
- expect(result).toEqual(mockRows)
71
- })
72
-
73
- it('should handle empty result set', async () => {
74
- mockPool.query.mockResolvedValue({ rows: [], rowCount: 0 } as any)
75
- const client = await createPgClient(mockPool)
76
- const result = await client.query('SELECT * FROM users WHERE id = $1', [
77
- 999,
78
- ])
79
- expect(result).toEqual([])
80
- })
81
-
82
- it('should handle query errors', async () => {
83
- const error = new Error('Database connection failed')
84
- mockPool.query.mockRejectedValue(error)
85
- const client = await createPgClient(mockPool)
86
- await expect(client.query('SELECT * FROM users')).rejects.toThrow(
87
- 'Database connection failed'
88
- )
89
- })
90
-
91
- it('should handle retry options', async () => {
92
- const mockRows = [{ id: 1, name: 'John Doe' }]
93
- mockPool.query.mockResolvedValue({ rows: mockRows, rowCount: 1 } as any)
94
- const retryOptions = {
95
- retries: 3,
96
- factor: 2,
97
- minTimeout: 1000,
98
- maxTimeout: 5000,
99
- }
100
- const client = await createPgClient(mockPool, retryOptions)
101
- const result = await client.query('SELECT * FROM users')
102
- expect(result).toEqual(mockRows)
103
- })
104
-
105
- it('should handle transient errors with retry', async () => {
106
- const transientError = new Error('Connection lost')
107
- ;(transientError as any).code = 'ECONNRESET'
108
- const mockRows = [{ id: 1, name: 'John Doe' }]
109
- // First call fails with transient error, second succeeds
110
- mockPool.query
111
- .mockRejectedValueOnce(transientError)
112
- .mockResolvedValueOnce({ rows: mockRows, rowCount: 1 } as any)
113
- const retryOptions = {
114
- retries: 3,
115
- factor: 2,
116
- minTimeout: 100,
117
- maxTimeout: 500,
118
- }
119
- const client = await createPgClient(mockPool, retryOptions)
120
- const result = await client.query('SELECT * FROM users')
121
- expect(mockPool.query).toHaveBeenCalledTimes(2)
122
- expect(result).toEqual(mockRows)
123
- })
124
-
125
- it('should throw non-transient errors immediately', async () => {
126
- const permanentError = new Error('Table does not exist')
127
- ;(permanentError as any).code = 'ER_NO_SUCH_TABLE'
128
- mockPool.query.mockRejectedValue(permanentError)
129
- const retryOptions = {
130
- retries: 3,
131
- factor: 2,
132
- minTimeout: 100,
133
- maxTimeout: 500,
134
- }
135
- const client = await createPgClient(mockPool, retryOptions)
136
- await expect(
137
- client.query('SELECT * FROM nonexistent_table')
138
- ).rejects.toThrow('Table does not exist')
139
- expect(mockPool.query).toHaveBeenCalledTimes(1)
140
- })
141
-
142
- it('should install unaccent extension when requested', async () => {
143
- mockPool.query
144
- .mockResolvedValueOnce({ rows: [], rowCount: 0 } as any) // Extension not found
145
- .mockResolvedValueOnce({ rows: [], rowCount: 0 } as any) // Extension created
146
- .mockResolvedValueOnce({ rows: [{ id: 1 }], rowCount: 1 } as any) // Query result
147
- const client = await createPgClient(mockPool, undefined, undefined, true)
148
- await client.query('SELECT * FROM users')
149
- expect(mockPool.query).toHaveBeenCalledWith(
150
- expect.stringContaining(
151
- "SELECT 1 FROM pg_extension WHERE extname = 'unaccent'"
152
- )
153
- )
154
- expect(mockPool.query).toHaveBeenCalledWith(
155
- expect.stringContaining('CREATE EXTENSION IF NOT EXISTS unaccent')
156
- )
157
- })
158
-
159
- describe('beginTransaction', () => {
160
- let mockClient: any
161
-
162
- beforeEach(() => {
163
- mockClient = {
164
- query: jest.fn(),
165
- release: jest.fn(),
166
- }
167
- mockPool.connect.mockResolvedValue(mockClient)
168
- })
169
-
170
- it('should create a transaction client', async () => {
171
- const client = await createPgClient(mockPool)
172
- const transaction = await client.beginTransaction()
173
-
174
- expect(mockPool.connect).toHaveBeenCalled()
175
- expect(mockClient.query).toHaveBeenCalledWith('BEGIN')
176
- expect(transaction).toHaveProperty('query')
177
- expect(transaction).toHaveProperty('commit')
178
- expect(transaction).toHaveProperty('rollback')
179
- })
180
-
181
- it('should execute queries within transaction', async () => {
182
- const mockRows = [{ id: 1, name: 'John Doe' }]
183
- mockClient.query.mockResolvedValue({ rows: mockRows, rowCount: 1 })
184
-
185
- const client = await createPgClient(mockPool)
186
- const transaction = await client.beginTransaction()
187
- const result = await transaction.query(
188
- 'SELECT * FROM users WHERE id = $1',
189
- [1]
190
- )
191
-
192
- expect(mockClient.query).toHaveBeenCalledWith(
193
- 'SELECT * FROM users WHERE id = $1',
194
- [1]
195
- )
196
- expect(result).toEqual(mockRows)
197
- })
198
-
199
- it('should commit transaction successfully', async () => {
200
- const client = await createPgClient(mockPool)
201
- const transaction = await client.beginTransaction()
202
- await transaction.commit()
203
-
204
- expect(mockClient.query).toHaveBeenCalledWith('COMMIT')
205
- expect(mockClient.release).toHaveBeenCalled()
206
- })
207
-
208
- it('should rollback transaction on error', async () => {
209
- const client = await createPgClient(mockPool)
210
- const transaction = await client.beginTransaction()
211
- await transaction.rollback()
212
-
213
- expect(mockClient.query).toHaveBeenCalledWith('ROLLBACK')
214
- expect(mockClient.release).toHaveBeenCalled()
215
- })
216
-
217
- it('should release connection even if commit fails', async () => {
218
- const commitError = new Error('Commit failed')
219
-
220
- // Mock the sequence: BEGIN succeeds, COMMIT fails
221
- mockClient.query
222
- .mockResolvedValueOnce({ rows: [], rowCount: 0 }) // BEGIN
223
- .mockRejectedValueOnce(commitError) // COMMIT
224
-
225
- const client = await createPgClient(mockPool)
226
- const transaction = await client.beginTransaction()
227
-
228
- await expect(transaction.commit()).rejects.toThrow('Commit failed')
229
- expect(mockClient.release).toHaveBeenCalled()
230
- })
231
-
232
- it('should release connection even if rollback fails', async () => {
233
- const rollbackError = new Error('Rollback failed')
234
-
235
- // Mock the sequence: BEGIN succeeds, ROLLBACK fails
236
- mockClient.query
237
- .mockResolvedValueOnce({ rows: [], rowCount: 0 }) // BEGIN
238
- .mockRejectedValueOnce(rollbackError) // ROLLBACK
239
-
240
- const client = await createPgClient(mockPool)
241
- const transaction = await client.beginTransaction()
242
-
243
- await expect(transaction.rollback()).rejects.toThrow('Rollback failed')
244
- expect(mockClient.release).toHaveBeenCalled()
245
- })
246
-
247
- it('should release connection if BEGIN fails', async () => {
248
- const beginError = new Error('Begin transaction failed')
249
- mockClient.query.mockRejectedValue(beginError)
250
-
251
- const client = await createPgClient(mockPool)
252
-
253
- await expect(client.beginTransaction()).rejects.toThrow(
254
- 'Begin transaction failed'
255
- )
256
- expect(mockClient.release).toHaveBeenCalled()
257
- })
258
- })
259
- })
260
- })
package/src/db/initDb.ts DELETED
@@ -1,181 +0,0 @@
1
- import { Pool, PoolConfig } from 'pg'
2
- import { createPool as createMySqlPool } from 'mysql2/promise'
3
- import { createPgClient } from './pgClient'
4
- import { createMysqlClient } from './mysqlClient'
5
- import { IDatabaseClient } from './IDatabaseClient'
6
- import { DBClients, RetryOptions } from '../core/types'
7
-
8
- const dbClients: Record<string, IDatabaseClient> = {}
9
- const defaultName = 'default'
10
-
11
- /**
12
- * Initialize a database client with the specified configuration
13
- *
14
- * @template T - The type of connection options (PoolConfig for PostgreSQL or PoolOptions for MySQL)
15
- * @param config - Configuration object for database initialization
16
- * @param config.name - Optional name for the database client (defaults to 'default')
17
- * @param config.type - Database type ('pg' for PostgreSQL or 'mysql' for MySQL)
18
- * @param config.options - Connection options specific to the database type
19
- * @param config.retryOptions - Optional retry configuration for failed queries
20
- * @param config.installUnaccentExtension - Optional flag to install unaccent extension (PostgreSQL only)
21
- * @returns Promise<void> - Resolves when the database client is successfully initialized
22
- *
23
- * @throws {Error} When type is not provided or is invalid
24
- * @throws {Error} When connection options are not provided
25
- * @throws {Error} When an unsupported database type is specified
26
- *
27
- * @example
28
- * // Initialize PostgreSQL client
29
- * await initDb({
30
- * name: 'myPostgresDb',
31
- * type: 'pg',
32
- * options: {
33
- * host: 'localhost',
34
- * port: 5432,
35
- * database: 'mydb',
36
- * user: 'user',
37
- * password: 'password'
38
- * },
39
- * retryOptions: { maxRetries: 3, delay: 1000 },
40
- * installUnaccentExtension: true
41
- * });
42
- *
43
- * @example
44
- * // Initialize MySQL client
45
- * await initDb({
46
- * name: 'myMysqlDb',
47
- * type: 'mysql',
48
- * options: {
49
- * host: 'localhost',
50
- * port: 3306,
51
- * database: 'mydb',
52
- * user: 'user',
53
- * password: 'password'
54
- * },
55
- * retryOptions: { maxRetries: 3, delay: 1000 }
56
- * });
57
- */
58
- export const initDb = async <T>(config: {
59
- name?: string
60
- type: DBClients
61
- options: T
62
- retryOptions?: RetryOptions
63
- installUnaccentExtension?: boolean
64
- }): Promise<void> => {
65
- if (!config.type)
66
- throw new Error('Type is required. Accept values: pg | mysql')
67
-
68
- if (!config.options) throw new Error('Connection options is required')
69
-
70
- if (config.type === 'pg') {
71
- const poolConfig = config.options as unknown as PoolConfig
72
- const pool = new Pool(config.options)
73
- dbClients[config.name || defaultName] = await createPgClient(
74
- pool,
75
- config.retryOptions,
76
- poolConfig,
77
- config.installUnaccentExtension
78
- )
79
-
80
- console.log(
81
- `@starbemtech/star-db-query-builder: Postgres db client "${config.name}" created successfully`
82
- )
83
- } else if (config.type === 'mysql') {
84
- const pool = createMySqlPool(config.options)
85
- dbClients[config.name || defaultName] = createMysqlClient(
86
- pool,
87
- config.retryOptions
88
- )
89
-
90
- console.info(
91
- `@starbemtech/star-db-query-builder: Postgres db client "${config.name}" created successfully`
92
- )
93
- } else {
94
- throw new Error('Unsupported database type')
95
- }
96
- }
97
-
98
- /**
99
- * Initialize a database client with the specified configuration
100
- *
101
- * @template T - The type of connection options (PoolConfig for PostgreSQL or PoolOptions for MySQL)
102
- * @param config - Configuration object for database initialization
103
- * @param config.name - Optional name for the database client (defaults to 'default')
104
- * @param config.type - Database type ('pg' for PostgreSQL or 'mysql' for MySQL)
105
- * @param config.options - Connection options specific to the database type
106
- * @param config.retryOptions - Optional retry configuration for failed queries
107
- * @param config.installUnaccentExtension - Optional flag to install unaccent extension (PostgreSQL only)
108
- * @returns Promise<void> - Resolves when the database client is successfully initialized
109
- *
110
- * @throws {Error} When database type is not provided or is invalid
111
- * @throws {Error} When connection options are not provided
112
- * @throws {Error} When an unsupported database type is specified
113
- *
114
- * @example
115
- * // Initialize PostgreSQL client
116
- * await initDb({
117
- * name: 'myPostgresDb',
118
- * type: 'pg',
119
- * options: {
120
- * host: 'localhost',
121
- * port: 5432,
122
- * database: 'mydb',
123
- * user: 'user',
124
- * password: 'password'
125
- * },
126
- * retryOptions: { maxRetries: 3, delay: 1000 },
127
- * installUnaccentExtension: true
128
- * });
129
- *
130
- * @example
131
- * // Initialize MySQL client
132
- * await initDb({
133
- * name: 'myMysqlDb',
134
- * type: 'mysql',
135
- * options: {
136
- * host: 'localhost',
137
- * port: 3306,
138
- * database: 'mydb',
139
- * user: 'user',
140
- * password: 'password'
141
- * },
142
- * retryOptions: { maxRetries: 3, delay: 1000 }
143
- * });
144
- */
145
- export const getDbClient = (name?: string): IDatabaseClient => {
146
- const client = dbClients[name || defaultName]
147
- if (!client) {
148
- throw new Error(`Database client "${name}" is not initialized`)
149
- }
150
-
151
- return client
152
- }
153
-
154
- /**
155
- * Retrieves a specific database client by name
156
- *
157
- * @param name - Optional name of the database client to retrieve. If not provided, returns the default client
158
- * @returns IDatabaseClient - The requested database client instance
159
- *
160
- * @throws {Error} When the specified database client name is not found or not initialized
161
- *
162
- * @example
163
- * // Get default database client
164
- * const defaultClient = getDbClient();
165
- *
166
- * @example
167
- * // Get specific database client by name
168
- * const postgresClient = getDbClient('myPostgresDb');
169
- * const mysqlClient = getDbClient('myMysqlDb');
170
- *
171
- * @example
172
- * // Handle error when client is not found
173
- * try {
174
- * const client = getDbClient('nonExistentDb');
175
- * } catch (error) {
176
- * console.error('Database client not found:', error.message);
177
- * }
178
- */
179
- export const getAllDbClients = (): Record<string, IDatabaseClient> => {
180
- return dbClients
181
- }