@starbemtech/star-db-query-builder 1.3.0 → 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 +81 -46
  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 +17 -2
  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 +28 -20
  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,200 +0,0 @@
1
- import { Pool, PoolConnection } from 'mysql2/promise'
2
- import promiseRetry from 'promise-retry'
3
- import { IDatabaseClient, ITransactionClient } from './IDatabaseClient'
4
- import { RetryOptions } from '../core/types'
5
- import { monitor, MonitorEvents } from '../monitor/monitor'
6
-
7
- const transientErrorCodes = new Set([
8
- 'ECONNRESET',
9
- 'ETIMEDOUT',
10
- 'PROTOCOL_CONNECTION_LOST',
11
- 'ECONNREFUSED',
12
- ])
13
-
14
- /**
15
- * Checks if the given error is a transient error that can be retried
16
- *
17
- * Transient errors are temporary network or connection issues that typically
18
- * resolve themselves and can be safely retried. This function checks if the
19
- * error code matches known transient error patterns for MySQL connections.
20
- *
21
- * @param error - The error object to check
22
- * @returns boolean - True if the error is transient and can be retried, false otherwise
23
- *
24
- * @example
25
- * try {
26
- * const result = await pool.execute(sql, params);
27
- * } catch (error) {
28
- * if (isTransientError(error)) {
29
- * // Retry the operation
30
- * console.log('Transient error detected, retrying...');
31
- * } else {
32
- * // Handle permanent error
33
- * throw error;
34
- * }
35
- * }
36
- */
37
- function isTransientError(error: any): boolean {
38
- return error && error.code && transientErrorCodes.has(error.code)
39
- }
40
-
41
- /**
42
- * Creates a MySQL database client
43
- *
44
- * This function initializes a MySQL database client with the provided pool configuration
45
- * and optional retry options. It sets up monitoring for connection events and query operations.
46
- *
47
- * @param pool - The MySQL pool instance
48
- * @param retryOptions - Optional retry options for failed queries
49
- * @returns IDatabaseClient - The MySQL database client instance
50
- *
51
- * @example
52
- * const mysqlClient = createMysqlClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
53
- *
54
- * @example
55
- * const mysqlClient = createMysqlClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
56
- *
57
- * @example
58
- * const mysqlClient = createMysqlClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
59
- *
60
- * @example
61
- * const mysqlClient = createMysqlClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
62
- */
63
- export const createMysqlClient = (
64
- pool: Pool,
65
- retryOptions?: RetryOptions
66
- ): IDatabaseClient => {
67
- monitor.emit(MonitorEvents.CONNECTION_CREATED, {
68
- clientType: 'mysql',
69
- poolOptions: pool.config,
70
- })
71
-
72
- return {
73
- clientType: 'mysql',
74
- query: async <T>(sql: string, params?: any[]): Promise<T> => {
75
- return promiseRetry(async (retry, attempt) => {
76
- const startTime = Date.now()
77
- try {
78
- monitor.emit(MonitorEvents.QUERY_START, {
79
- clientType: 'mysql',
80
- sql,
81
- params,
82
- attempt,
83
- })
84
-
85
- const [rows] = await pool.execute(sql, params)
86
-
87
- const elapsedTime = Date.now() - startTime
88
- monitor.emit(MonitorEvents.QUERY_END, {
89
- clientType: 'mysql',
90
- sql,
91
- params,
92
- attempt,
93
- elapsedTime,
94
- })
95
-
96
- return rows as unknown as T
97
- } catch (error: any) {
98
- const elapsedTime = Date.now() - startTime
99
- monitor.emit(MonitorEvents.QUERY_ERROR, {
100
- clientType: 'mysql',
101
- sql,
102
- params,
103
- attempt,
104
- elapsedTime,
105
- error,
106
- })
107
-
108
- if (isTransientError(error)) {
109
- console.warn(
110
- `MySQL query attempt ${attempt} failed, retrying...`,
111
- error
112
- )
113
- monitor.emit(MonitorEvents.RETRY_ATTEMPT, {
114
- clientType: 'mysql',
115
- sql,
116
- params,
117
- attempt,
118
- error,
119
- })
120
-
121
- return retry(error)
122
- }
123
-
124
- throw error
125
- }
126
- }, retryOptions)
127
- },
128
- beginTransaction: async (): Promise<ITransactionClient> => {
129
- const connection: PoolConnection = await pool.getConnection()
130
-
131
- try {
132
- await connection.beginTransaction()
133
-
134
- return {
135
- query: async <T>(sql: string, params?: any[]): Promise<T> => {
136
- const startTime = Date.now()
137
- try {
138
- monitor.emit(MonitorEvents.QUERY_START, {
139
- clientType: 'mysql',
140
- sql,
141
- params,
142
- attempt: 1,
143
- inTransaction: true,
144
- })
145
-
146
- const [rows] = await connection.execute(sql, params)
147
-
148
- const elapsedTime = Date.now() - startTime
149
- monitor.emit(MonitorEvents.QUERY_END, {
150
- clientType: 'mysql',
151
- sql,
152
- params,
153
- attempt: 1,
154
- elapsedTime,
155
- inTransaction: true,
156
- })
157
-
158
- return rows as unknown as T
159
- } catch (error) {
160
- const elapsedTime = Date.now() - startTime
161
- monitor.emit(MonitorEvents.QUERY_ERROR, {
162
- clientType: 'mysql',
163
- sql,
164
- params,
165
- attempt: 1,
166
- elapsedTime,
167
- error,
168
- inTransaction: true,
169
- })
170
- throw error
171
- }
172
- },
173
- commit: async (): Promise<void> => {
174
- try {
175
- await connection.commit()
176
- monitor.emit(MonitorEvents.TRANSACTION_COMMIT, {
177
- clientType: 'mysql',
178
- })
179
- } finally {
180
- connection.release()
181
- }
182
- },
183
- rollback: async (): Promise<void> => {
184
- try {
185
- await connection.rollback()
186
- monitor.emit(MonitorEvents.TRANSACTION_ROLLBACK, {
187
- clientType: 'mysql',
188
- })
189
- } finally {
190
- connection.release()
191
- }
192
- },
193
- }
194
- } catch (error) {
195
- connection.release()
196
- throw error
197
- }
198
- },
199
- }
200
- }
@@ -1,246 +0,0 @@
1
- import { Pool, PoolConfig, PoolClient } from 'pg'
2
- import promiseRetry from 'promise-retry'
3
- import { IDatabaseClient, ITransactionClient } from './IDatabaseClient'
4
- import { RetryOptions } from '../core/types'
5
- import { monitor, MonitorEvents } from '../monitor/monitor'
6
-
7
- const transientErrorCodes = new Set(['ECONNRESET', 'ETIMEDOUT', 'ECONNREFUSED'])
8
-
9
- /**
10
- * Checks if the given error is a transient error that can be retried
11
- *
12
- * Transient errors are temporary network or connection issues that typically
13
- * resolve themselves and can be safely retried. This function checks if the
14
- * error code matches known transient error patterns for PostgreSQL connections.
15
- *
16
- * @param error - The error object to check
17
- * @returns boolean - True if the error is transient and can be retried, false otherwise
18
- *
19
- * @example
20
- * try {
21
- * const result = await pool.query(sql, params);
22
- * } catch (error) {
23
- * if (isTransientError(error)) {
24
- * // Retry the operation
25
- * console.log('Transient error detected, retrying...');
26
- * } else {
27
- * // Handle permanent error
28
- * throw error;
29
- * }
30
- * }
31
- */
32
- function isTransientError(error: any): boolean {
33
- return error && error.code && transientErrorCodes.has(error.code)
34
- }
35
-
36
- /**
37
- * Ensures that the unaccent extension is installed in the PostgreSQL database
38
- *
39
- * This function checks if the unaccent extension is installed in the database
40
- * and installs it if it is not. It also emits a connection created event to
41
- * the monitor.
42
- *
43
- * @param pool - The PostgreSQL pool instance
44
- * @returns Promise<void> - Resolves when the unaccent extension is installed or already exists
45
- *
46
- * @example
47
- * await ensureUnaccentExtension(pool);
48
- */
49
- async function ensureUnaccentExtension(pool: Pool): Promise<void> {
50
- try {
51
- const checkResult = await pool.query(`
52
- SELECT 1 FROM pg_extension WHERE extname = 'unaccent'
53
- `)
54
-
55
- if (checkResult.rows.length === 0) {
56
- await pool.query('CREATE EXTENSION IF NOT EXISTS unaccent')
57
-
58
- monitor.emit(MonitorEvents.CONNECTION_CREATED, {
59
- clientType: 'pg',
60
- extension: 'unaccent',
61
- status: 'installed',
62
- })
63
-
64
- console.info(
65
- '@starbemtech/star-db-query-builder: Extensão unaccent instalada com sucesso.'
66
- )
67
- }
68
- } catch (error) {
69
- monitor.emit(MonitorEvents.QUERY_ERROR, {
70
- clientType: 'pg',
71
- action: 'install_unaccent',
72
- error,
73
- })
74
- throw new Error(
75
- `@starbemtech/star-db-query-builder: Não foi possível instalar a extensão unaccent:
76
- ${error}`
77
- )
78
- }
79
- }
80
-
81
- /**
82
- * Creates a PostgreSQL database client
83
- *
84
- * This function initializes a PostgreSQL database client with the provided pool configuration
85
- * and optional retry options. It sets up monitoring for connection events and query operations.
86
- *
87
- * @param pool - The PostgreSQL pool instance
88
- * @param retryOptions - Optional retry options for failed queries
89
- * @param poolConfig - Optional pool configuration
90
- * @param installUnaccentExtension - Optional flag to install unaccent extension
91
- * @returns IDatabaseClient - The PostgreSQL database client instance
92
- *
93
- * @example
94
- * const pgClient = await createPgClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
95
- *
96
- * @example
97
- * const pgClient = await createPgClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
98
- *
99
- * @example
100
- * const pgClient = await createPgClient(pool, { retries: 3, factor: 2, minTimeout: 1000 });
101
- */
102
- export const createPgClient = async (
103
- pool: Pool,
104
- retryOptions?: RetryOptions,
105
- poolConfig?: PoolConfig,
106
- installUnaccentExtension?: boolean
107
- ): Promise<IDatabaseClient> => {
108
- if (installUnaccentExtension) {
109
- await ensureUnaccentExtension(pool)
110
- }
111
-
112
- monitor.emit(MonitorEvents.CONNECTION_CREATED, {
113
- clientType: 'pg',
114
- poolOptions: poolConfig,
115
- })
116
-
117
- return {
118
- clientType: 'pg',
119
- query: async <T>(sql: string, params?: any[]): Promise<T> => {
120
- return promiseRetry(async (retry, attempt) => {
121
- const startTime = Date.now()
122
- try {
123
- monitor.emit(MonitorEvents.QUERY_START, {
124
- clientType: 'pg',
125
- sql,
126
- params,
127
- attempt,
128
- })
129
-
130
- const { rows } = await pool.query(sql, params)
131
-
132
- const elapsedTime = Date.now() - startTime
133
- monitor.emit(MonitorEvents.QUERY_END, {
134
- clientType: 'pg',
135
- sql,
136
- params,
137
- attempt,
138
- elapsedTime,
139
- })
140
-
141
- return rows as unknown as T
142
- } catch (error) {
143
- const elapsedTime = Date.now() - startTime
144
- monitor.emit(MonitorEvents.QUERY_ERROR, {
145
- clientType: 'pg',
146
- sql,
147
- params,
148
- attempt,
149
- elapsedTime,
150
- error,
151
- })
152
-
153
- if (isTransientError(error)) {
154
- console.warn(
155
- `Postgres query attempt ${attempt} failed, retrying...`,
156
- error
157
- )
158
-
159
- monitor.emit(MonitorEvents.RETRY_ATTEMPT, {
160
- clientType: 'pg',
161
- sql,
162
- params,
163
- attempt,
164
- error,
165
- })
166
-
167
- return retry(error)
168
- }
169
-
170
- throw error
171
- }
172
- }, retryOptions)
173
- },
174
- beginTransaction: async (): Promise<ITransactionClient> => {
175
- const client: PoolClient = await pool.connect()
176
-
177
- try {
178
- await client.query('BEGIN')
179
-
180
- return {
181
- query: async <T>(sql: string, params?: any[]): Promise<T> => {
182
- const startTime = Date.now()
183
- try {
184
- monitor.emit(MonitorEvents.QUERY_START, {
185
- clientType: 'pg',
186
- sql,
187
- params,
188
- attempt: 1,
189
- inTransaction: true,
190
- })
191
-
192
- const { rows } = await client.query(sql, params)
193
-
194
- const elapsedTime = Date.now() - startTime
195
- monitor.emit(MonitorEvents.QUERY_END, {
196
- clientType: 'pg',
197
- sql,
198
- params,
199
- attempt: 1,
200
- elapsedTime,
201
- inTransaction: true,
202
- })
203
-
204
- return rows as unknown as T
205
- } catch (error) {
206
- const elapsedTime = Date.now() - startTime
207
- monitor.emit(MonitorEvents.QUERY_ERROR, {
208
- clientType: 'pg',
209
- sql,
210
- params,
211
- attempt: 1,
212
- elapsedTime,
213
- error,
214
- inTransaction: true,
215
- })
216
- throw error
217
- }
218
- },
219
- commit: async (): Promise<void> => {
220
- try {
221
- await client.query('COMMIT')
222
- monitor.emit(MonitorEvents.TRANSACTION_COMMIT, {
223
- clientType: 'pg',
224
- })
225
- } finally {
226
- client.release()
227
- }
228
- },
229
- rollback: async (): Promise<void> => {
230
- try {
231
- await client.query('ROLLBACK')
232
- monitor.emit(MonitorEvents.TRANSACTION_ROLLBACK, {
233
- clientType: 'pg',
234
- })
235
- } finally {
236
- client.release()
237
- }
238
- },
239
- }
240
- } catch (error) {
241
- client.release()
242
- throw error
243
- }
244
- },
245
- }
246
- }
@@ -1,16 +0,0 @@
1
- import { EventEmitter } from 'stream'
2
-
3
- /**
4
- * Monitor events
5
- */
6
- export enum MonitorEvents {
7
- CONNECTION_CREATED = 'connection_created',
8
- QUERY_START = 'query_start',
9
- QUERY_END = 'query_end',
10
- QUERY_ERROR = 'query_error',
11
- RETRY_ATTEMPT = 'retry_attempt',
12
- TRANSACTION_COMMIT = 'transaction_commit',
13
- TRANSACTION_ROLLBACK = 'transaction_rollback',
14
- }
15
-
16
- export const monitor = new EventEmitter()
package/src/setupTests.ts DELETED
@@ -1,45 +0,0 @@
1
- // Jest setup file for star-db-query-builder tests
2
-
3
- // Mock console methods to reduce noise in tests
4
- const originalConsole = { ...console }
5
-
6
- beforeAll(() => {
7
- // Suppress console.log, console.warn, and console.error during tests
8
- jest.spyOn(console, 'log').mockImplementation(() => {})
9
- jest.spyOn(console, 'warn').mockImplementation(() => {})
10
- jest.spyOn(console, 'error').mockImplementation(() => {})
11
- })
12
-
13
- afterAll(() => {
14
- // Restore original console methods
15
- console.log = originalConsole.log
16
- console.warn = originalConsole.warn
17
- console.error = originalConsole.error
18
- })
19
-
20
- // Export test utilities for use in test files
21
- export const testUtils = {
22
- // Helper to create mock database client
23
- createMockDbClient: (clientType: 'pg' | 'mysql' = 'pg') => ({
24
- clientType,
25
- query: jest.fn(),
26
- connect: jest.fn(),
27
- end: jest.fn(),
28
- }),
29
-
30
- // Helper to create sample data
31
- createSampleUser: () => ({
32
- id: '123e4567-e89b-12d3-a456-426614174000',
33
- name: 'John Doe',
34
- email: 'john.doe@example.com',
35
- status: 'active',
36
- created_at: new Date('2023-01-01'),
37
- updated_at: new Date('2023-01-01'),
38
- }),
39
-
40
- // Helper to create sample conditions
41
- createSampleConditions: () => ({
42
- status: { operator: '=', value: 'active' },
43
- email: { operator: 'ILIKE', value: '%example.com' },
44
- }),
45
- }
@@ -1,21 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "types": [
5
- "jest",
6
- "node"
7
- ],
8
- "esModuleInterop": true,
9
- "allowSyntheticDefaultImports": true
10
- },
11
- "include": [
12
- "src/**/*",
13
- "**/*.test.ts",
14
- "**/*.spec.ts",
15
- "jest.config.ts"
16
- ],
17
- "exclude": [
18
- "dist",
19
- "node_modules"
20
- ]
21
- }