@starbemtech/star-db-query-builder 1.1.0 → 1.3.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 (88) hide show
  1. package/.github/workflows/publish.yml +118 -0
  2. package/ARCHITECTURE.md +313 -0
  3. package/CHANGELOG.md +67 -0
  4. package/README.md +1275 -210
  5. package/coverage/base.css +224 -0
  6. package/coverage/block-navigation.js +87 -0
  7. package/coverage/favicon.png +0 -0
  8. package/coverage/index.html +131 -0
  9. package/coverage/lcov-report/base.css +224 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +131 -0
  13. package/coverage/lcov-report/mysqlClient.ts.html +685 -0
  14. package/coverage/lcov-report/pgClient.ts.html +823 -0
  15. package/coverage/lcov-report/prettify.css +1 -0
  16. package/coverage/lcov-report/prettify.js +2 -0
  17. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  18. package/coverage/lcov-report/sorter.js +210 -0
  19. package/coverage/lcov.info +533 -0
  20. package/coverage/mysqlClient.ts.html +685 -0
  21. package/coverage/pgClient.ts.html +823 -0
  22. package/coverage/prettify.css +1 -0
  23. package/coverage/prettify.js +2 -0
  24. package/coverage/sort-arrow-sprite.png +0 -0
  25. package/coverage/sorter.js +210 -0
  26. package/dist/index.d.ts +5 -4
  27. package/dist/index.js +1 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/src/core/repository.d.ts +374 -0
  30. package/dist/src/core/repository.js +677 -0
  31. package/dist/src/core/repository.js.map +1 -0
  32. package/dist/src/{default → core}/types.d.ts +8 -0
  33. package/dist/src/{default → core}/types.js.map +1 -1
  34. package/dist/src/core/utils.d.ts +133 -0
  35. package/dist/src/{default → core}/utils.js +167 -0
  36. package/dist/src/core/utils.js.map +1 -0
  37. package/dist/src/db/IDatabaseClient.d.ts +10 -1
  38. package/dist/src/db/initDb.d.ts +120 -1
  39. package/dist/src/db/initDb.js +119 -0
  40. package/dist/src/db/initDb.js.map +1 -1
  41. package/dist/src/db/mysqlClient.d.ts +23 -1
  42. package/dist/src/db/mysqlClient.js +115 -0
  43. package/dist/src/db/mysqlClient.js.map +1 -1
  44. package/dist/src/db/pgClient.d.ts +22 -1
  45. package/dist/src/db/pgClient.js +127 -0
  46. package/dist/src/db/pgClient.js.map +1 -1
  47. package/dist/src/monitor/monitor.d.ts +6 -1
  48. package/dist/src/monitor/monitor.js +5 -0
  49. package/dist/src/monitor/monitor.js.map +1 -1
  50. package/dist/src/setupTests.d.ts +26 -0
  51. package/dist/src/setupTests.js +43 -0
  52. package/dist/src/setupTests.js.map +1 -0
  53. package/docs/INDEX.md +145 -0
  54. package/docs/methods/findFirst.md +394 -0
  55. package/docs/methods/findMany.md +587 -0
  56. package/docs/methods/insert.md +536 -0
  57. package/docs/methods/insertMany.md +627 -0
  58. package/docs/methods/joins.md +781 -0
  59. package/docs/methods/rawQuery.md +284 -0
  60. package/docs/methods/transactions.md +737 -0
  61. package/eslint.config.mjs +77 -0
  62. package/index.ts +5 -4
  63. package/jest.config.ts +23 -28
  64. package/package.json +53 -30
  65. package/scripts/release.sh +123 -0
  66. package/src/core/repository.ts +865 -0
  67. package/src/{default → core}/types.ts +10 -1
  68. package/src/{default → core}/utils.ts +168 -0
  69. package/src/db/IDatabaseClient.ts +11 -1
  70. package/src/db/__tests__/mysqlClient.test.ts +262 -0
  71. package/src/db/__tests__/pgClient.test.ts +260 -0
  72. package/src/db/initDb.ts +120 -1
  73. package/src/db/mysqlClient.ts +119 -3
  74. package/src/db/pgClient.ts +131 -3
  75. package/src/monitor/monitor.ts +5 -0
  76. package/src/setupTests.ts +45 -0
  77. package/tsconfig.test.json +21 -0
  78. package/.eslintignore +0 -4
  79. package/.eslintrc.json +0 -32
  80. package/dist/.eslintrc.json +0 -32
  81. package/dist/src/default/genericRepository.d.ts +0 -28
  82. package/dist/src/default/genericRepository.js +0 -284
  83. package/dist/src/default/genericRepository.js.map +0 -1
  84. package/dist/src/default/utils.d.ts +0 -9
  85. package/dist/src/default/utils.js.map +0 -1
  86. package/index.d.ts +0 -60
  87. package/src/default/genericRepository.ts +0 -461
  88. /package/dist/src/{default → core}/types.js +0 -0
@@ -0,0 +1,677 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.beginTransaction = exports.withTransaction = exports.rawQuery = exports.joins = exports.deleteMany = exports.deleteOne = exports.updateMany = exports.update = exports.insertMany = exports.insert = exports.findMany = exports.findFirst = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const utils_1 = require("./utils");
6
+ /**
7
+ * Finds the first record in the specified table
8
+ *
9
+ * This function retrieves the first record from the specified table based on the provided
10
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
11
+ *
12
+ * @template T - The type of the record to be returned
13
+ * @param params - Query parameters including table name, database client, select fields, where conditions, group by, order by, and limit
14
+ * @returns Promise<T | null> - The first record or null if no record is found
15
+ *
16
+ * @throws {Error} When table name is not provided
17
+ * @throws {Error} When database client is not provided
18
+ *
19
+ * @example
20
+ * const firstRecord = await findFirst({
21
+ * tableName: 'users',
22
+ * dbClient: dbClient,
23
+ * select: ['id', 'name', 'email'],
24
+ * where: { status: 'active' },
25
+ * groupBy: ['status'],
26
+ * orderBy: [{ field: 'created_at', direction: 'DESC' }],
27
+ * })
28
+ *
29
+ * @example
30
+ * const firstRecord = await findFirst({
31
+ * tableName: 'users',
32
+ * dbClient: dbClient,
33
+ * select: ['id', 'name', 'email'],
34
+ * where: { status: 'active' },
35
+ * groupBy: ['status'],
36
+ * orderBy: [{ field: 'created_at', direction: 'DESC' }],
37
+ * })
38
+ */
39
+ const findFirst = async ({ tableName, dbClient, select, where, groupBy, orderBy, }) => {
40
+ if (!tableName)
41
+ throw new Error('Table name is required');
42
+ if (!dbClient)
43
+ throw new Error('DB client is required');
44
+ const fields = (0, utils_1.createSelectFields)(select, dbClient.clientType);
45
+ const [whereClause, params] = (0, utils_1.createWhereClause)(where, 1, dbClient.clientType);
46
+ const orderByClause = (0, utils_1.createOrderByClause)(orderBy);
47
+ const groupByClause = (0, utils_1.createGroupByClause)(groupBy);
48
+ const rows = await dbClient.query(`SELECT ${fields} FROM ${tableName}
49
+ ${whereClause.length > 7 ? whereClause : ''}
50
+ ${groupByClause}
51
+ ${orderByClause}
52
+ `, params);
53
+ return rows[0] || null;
54
+ };
55
+ exports.findFirst = findFirst;
56
+ /**
57
+ * Finds multiple records in the specified table
58
+ *
59
+ * This function retrieves multiple records from the specified table based on the provided
60
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
61
+ *
62
+ * @template T - The type of the records to be returned
63
+ * @param params - Query parameters including table name, database client, select fields, where conditions, group by, order by, limit, and offset
64
+ * @returns Promise<T[]> - The records found in the table
65
+ *
66
+ * @throws {Error} When table name is not provided
67
+ * @throws {Error} When database client is not provided
68
+ *
69
+ * @example
70
+ * const records = await findMany({
71
+ * tableName: 'users',
72
+ * dbClient: dbClient,
73
+ * select: ['id', 'name', 'email'],
74
+ * where: { status: 'active' },
75
+ * groupBy: ['status'],
76
+ * orderBy: [{ field: 'created_at', direction: 'DESC' }],
77
+ * limit: 10,
78
+ * offset: 0,
79
+ * unaccent: true,
80
+ * })
81
+ */
82
+ const findMany = async ({ tableName, dbClient, select, where, groupBy, orderBy, limit, offset, unaccent, }) => {
83
+ if (!tableName)
84
+ throw new Error('Table name is required');
85
+ if (!dbClient)
86
+ throw new Error('DB client is required');
87
+ const fields = (0, utils_1.createSelectFields)(select, dbClient.clientType);
88
+ const [whereClause, params] = (0, utils_1.createWhereClause)(where, 1, dbClient.clientType, unaccent);
89
+ const orderByClause = (0, utils_1.createOrderByClause)(orderBy);
90
+ const groupByClause = (0, utils_1.createGroupByClause)(groupBy);
91
+ const limitClause = (0, utils_1.createLimitClause)(limit);
92
+ const offsetClause = (0, utils_1.createOffsetClause)(offset);
93
+ const rows = await dbClient.query(`SELECT ${fields} FROM ${tableName}
94
+ ${whereClause.length > 7 ? whereClause : ''}
95
+ ${groupByClause}
96
+ ${orderByClause}
97
+ ${limitClause}
98
+ ${offsetClause}
99
+ `, params);
100
+ return rows || [];
101
+ };
102
+ exports.findMany = findMany;
103
+ /**
104
+ * Inserts a new record into the specified table
105
+ *
106
+ * This function inserts a new record into the specified table based on the provided
107
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
108
+ *
109
+ * @template P - The type of the data to be inserted
110
+ * @template R - The type of the record to be returned
111
+ * @param params - Query parameters including table name, database client, data to be inserted, and optional returning fields
112
+ * @returns Promise<R> - The inserted record
113
+ *
114
+ * @throws {Error} When table name is not provided
115
+ * @throws {Error} When database client is not provided
116
+ * @throws {Error} When data object is not provided
117
+ *
118
+ * @example
119
+ * const insertedRecord = await insert({
120
+ * tableName: 'users',
121
+ * dbClient: dbClient,
122
+ * data: { name: 'John Doe', email: 'john.doe@example.com' },
123
+ * returning: ['id', 'name', 'email'],
124
+ * })
125
+ */
126
+ const insert = async ({ tableName, dbClient, data, returning, }) => {
127
+ if (!tableName)
128
+ throw new Error('Table name is required');
129
+ if (!dbClient)
130
+ throw new Error('DB client is required');
131
+ if (!data)
132
+ throw new Error('Data object is required');
133
+ const keys = dbClient.clientType === 'pg'
134
+ ? Object.keys(data).map((key) => key === 'authorization' ? `"${key}"` : key)
135
+ : Object.keys(data);
136
+ const values = Object.values(data);
137
+ keys.unshift('id');
138
+ const generatedUUID = (0, uuid_1.v4)();
139
+ values.unshift(generatedUUID);
140
+ keys.push('updated_at');
141
+ values.push(new Date());
142
+ const placeholders = (0, utils_1.generatePlaceholders)(keys, dbClient.clientType);
143
+ let query = `INSERT INTO ${tableName} (${keys.join(', ')}) VALUES (${placeholders})`;
144
+ if (dbClient.clientType === 'pg') {
145
+ if (returning && returning.length > 0) {
146
+ query += ` RETURNING ${(0, utils_1.createSelectFields)(returning, dbClient.clientType)}`;
147
+ }
148
+ }
149
+ const inserted = await dbClient.query(query, values);
150
+ if (dbClient.clientType === 'mysql') {
151
+ const rows = await dbClient.query(`SELECT ${returning && returning.length > 0
152
+ ? (0, utils_1.createSelectFields)(returning, dbClient.clientType)
153
+ : '*'} FROM ${tableName}
154
+ WHERE
155
+ id = ?
156
+ `, [generatedUUID]);
157
+ return rows[0];
158
+ }
159
+ return inserted[0];
160
+ };
161
+ exports.insert = insert;
162
+ /**
163
+ * Inserts multiple records into the specified table
164
+ *
165
+ * This function inserts multiple records into the specified table based on the provided
166
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
167
+ *
168
+ * @template P - The type of the data to be inserted
169
+ * @template R - The type of the record to be returned
170
+ * @param params - Query parameters including table name, database client, data to be inserted, and optional returning fields
171
+ * @returns Promise<R[]> - The inserted records
172
+ *
173
+ * @throws {Error} When table name is not provided
174
+ * @throws {Error} When database client is not provided
175
+ * @throws {Error} When data array is not provided or empty
176
+ *
177
+ * @example
178
+ * const insertedRecords = await insertMany({
179
+ * tableName: 'users',
180
+ * dbClient: dbClient,
181
+ * data: [{ name: 'John Doe', email: 'john.doe@example.com' }, { name: 'Jane Doe', email: 'jane.doe@example.com' }],
182
+ * returning: ['id', 'name', 'email'],
183
+ * })
184
+ */
185
+ const insertMany = async ({ tableName, dbClient, data, returning, }) => {
186
+ if (!tableName)
187
+ throw new Error('Table name is required');
188
+ if (!dbClient)
189
+ throw new Error('DB client is required');
190
+ if (!data || data.length === 0)
191
+ throw new Error('Data array is required and cannot be empty');
192
+ const firstItem = data[0];
193
+ const keys = dbClient.clientType === 'pg'
194
+ ? Object.keys(firstItem).map((key) => key === 'authorization' ? `"${key}"` : key)
195
+ : Object.keys(firstItem);
196
+ const allKeys = ['id', ...keys, 'updated_at'];
197
+ let query = `INSERT INTO ${tableName} (${allKeys.join(', ')}) VALUES `;
198
+ const allValues = [];
199
+ const valueRows = [];
200
+ const generatedIds = [];
201
+ data.forEach((item, rowIndex) => {
202
+ const values = Object.values(item);
203
+ const generatedUUID = (0, uuid_1.v4)();
204
+ generatedIds.push(generatedUUID);
205
+ const currentValues = [generatedUUID, ...values, new Date()];
206
+ allValues.push(...currentValues);
207
+ // Generate unique placeholders for each row
208
+ if (dbClient.clientType === 'pg') {
209
+ const startIndex = rowIndex * allKeys.length + 1;
210
+ const placeholders = allKeys
211
+ .map((_, index) => `$${startIndex + index}`)
212
+ .join(', ');
213
+ valueRows.push(`(${placeholders})`);
214
+ }
215
+ else {
216
+ const placeholders = allKeys.map(() => '?').join(', ');
217
+ valueRows.push(`(${placeholders})`);
218
+ }
219
+ });
220
+ query += valueRows.join(', ');
221
+ if (dbClient.clientType === 'pg') {
222
+ if (returning && returning.length > 0) {
223
+ query += ` RETURNING ${(0, utils_1.createSelectFields)(returning, dbClient.clientType)}`;
224
+ }
225
+ }
226
+ const inserted = await dbClient.query(query, allValues);
227
+ if (dbClient.clientType === 'mysql') {
228
+ const placeholders = generatedIds.map(() => '?').join(', ');
229
+ const rows = await dbClient.query(`SELECT ${returning && returning.length > 0
230
+ ? (0, utils_1.createSelectFields)(returning, dbClient.clientType)
231
+ : '*'} FROM ${tableName}
232
+ WHERE id IN (${placeholders})
233
+ ORDER BY FIELD(id, ${placeholders})
234
+ `, [...generatedIds, ...generatedIds]);
235
+ return rows;
236
+ }
237
+ return inserted;
238
+ };
239
+ exports.insertMany = insertMany;
240
+ /**
241
+ * Updates a record in the specified table
242
+ *
243
+ * This function updates a record in the specified table based on the provided
244
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
245
+ *
246
+ * @template P - The type of the data to be updated
247
+ * @template R - The type of the record to be returned
248
+ * @param params - Query parameters including table name, database client, ID of the record to be updated, data to be updated, and optional returning fields
249
+ * @returns Promise<R | void> - The updated record or void if no record is found
250
+ *
251
+ * @throws {Error} When table name is not provided
252
+ * @throws {Error} When database client is not provided
253
+ * @throws {Error} When ID is not provided
254
+ *
255
+ * @example
256
+ * const updatedRecord = await update({
257
+ * tableName: 'users',
258
+ * dbClient: dbClient,
259
+ * id: '123',
260
+ * data: { name: 'John Doe', email: 'john.doe@example.com' },
261
+ * returning: ['id', 'name', 'email'],
262
+ * })
263
+ */
264
+ const update = async ({ tableName, dbClient, id, data, returning, }) => {
265
+ if (!tableName)
266
+ throw new Error('Table name is required');
267
+ if (!dbClient)
268
+ throw new Error('DB client is required');
269
+ if (!id)
270
+ throw new Error('ID is required');
271
+ if (!data)
272
+ throw new Error('Data object is required');
273
+ const keys = Object.keys(data);
274
+ const values = Object.values(data);
275
+ const setClause = (0, utils_1.generateSetClause)(keys, dbClient.clientType);
276
+ let query = `UPDATE ${tableName} SET ${setClause} WHERE id = '${id}'`;
277
+ if (dbClient.clientType === 'pg') {
278
+ if (returning && returning.length > 0) {
279
+ query += ` RETURNING ${(0, utils_1.createSelectFields)(returning, dbClient.clientType)}`;
280
+ }
281
+ }
282
+ const updated = await dbClient.query(query, values);
283
+ if (dbClient.clientType === 'mysql') {
284
+ const rows = await dbClient.query(`SELECT ${returning && returning.length > 0
285
+ ? (0, utils_1.createSelectFields)(returning, dbClient.clientType)
286
+ : '*'} FROM ${tableName}
287
+ WHERE
288
+ id = ?
289
+ `, [id]);
290
+ return rows[0];
291
+ }
292
+ return updated[0];
293
+ };
294
+ exports.update = update;
295
+ /**
296
+ * Updates multiple records in the specified table
297
+ *
298
+ * This function updates multiple records in the specified table based on the provided
299
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
300
+ *
301
+ * @template P - The type of the data to be updated
302
+ * @template R - The type of the record to be returned
303
+ * @param params - Query parameters including table name, database client, data to be updated, where conditions, and optional returning fields
304
+ * @returns Promise<R[]> - The updated records
305
+ *
306
+ * @throws {Error} When table name is not provided
307
+ * @throws {Error} When database client is not provided
308
+ * @throws {Error} When data object is not provided
309
+ * @throws {Error} When where condition is not provided
310
+ *
311
+ * @example
312
+ * const updatedRecords = await updateMany({
313
+ * tableName: 'users',
314
+ * dbClient: dbClient,
315
+ * data: { name: 'John Doe', email: 'john.doe@example.com' },
316
+ * where: { status: 'active' },
317
+ * returning: ['id', 'name', 'email'],
318
+ * })
319
+ */
320
+ const updateMany = async ({ tableName, dbClient, data, where, returning, }) => {
321
+ if (!tableName)
322
+ throw new Error('Table name is required');
323
+ if (!dbClient)
324
+ throw new Error('DB client is required');
325
+ if (!data)
326
+ throw new Error('Data object is required');
327
+ if (!where)
328
+ throw new Error('Where condition is required');
329
+ const keys = Object.keys(data);
330
+ const values = Object.values(data);
331
+ // Generate SET clause with correct placeholders
332
+ const setClause = keys
333
+ .map((key, index) => dbClient.clientType === 'pg' ? `${key} = $${index + 1}` : `${key} = ?`)
334
+ .join(', ');
335
+ // Generate WHERE clause with placeholders starting after SET values
336
+ const [whereClause, whereParams] = (0, utils_1.createWhereClause)(where, values.length + 1, dbClient.clientType);
337
+ let query = `UPDATE ${tableName} SET ${setClause} ${whereClause}`;
338
+ if (dbClient.clientType === 'pg') {
339
+ if (returning && returning.length > 0) {
340
+ query += ` RETURNING ${(0, utils_1.createSelectFields)(returning, dbClient.clientType)}`;
341
+ }
342
+ }
343
+ const updated = await dbClient.query(query, [...values, ...whereParams]);
344
+ if (dbClient.clientType === 'mysql') {
345
+ // For MySQL, we need to fetch the updated records separately
346
+ // since MySQL doesn't support RETURNING clause
347
+ const rows = await dbClient.query(`SELECT ${returning && returning.length > 0
348
+ ? (0, utils_1.createSelectFields)(returning, dbClient.clientType)
349
+ : '*'} FROM ${tableName}
350
+ ${whereClause}
351
+ `, whereParams);
352
+ return rows;
353
+ }
354
+ return updated;
355
+ };
356
+ exports.updateMany = updateMany;
357
+ /**
358
+ * Deletes a record from the specified table
359
+ *
360
+ * This function deletes a record from the specified table based on the provided
361
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
362
+ *
363
+ * @template T - The type of the record to be deleted
364
+ * @param params - Query parameters including table name, database client, ID of the record to be deleted, and optional permanently flag
365
+ * @returns Promise<void> - Resolves when the record is deleted
366
+ *
367
+ * @throws {Error} When table name is not provided
368
+ * @throws {Error} When database client is not provided
369
+ * @throws {Error} When ID is not provided
370
+ *
371
+ * @example
372
+ * await deleteOne({
373
+ * tableName: 'users',
374
+ * dbClient: dbClient,
375
+ * id: '123',
376
+ * permanently: true,
377
+ * })
378
+ */
379
+ const deleteOne = async ({ tableName, dbClient, id, permanently = false, }) => {
380
+ if (!tableName)
381
+ throw new Error('Table name is required');
382
+ if (!dbClient)
383
+ throw new Error('DB client is required');
384
+ if (!id)
385
+ throw new Error('ID is required');
386
+ await dbClient.query(permanently
387
+ ? `DELETE FROM ${tableName} WHERE id = ${dbClient.clientType === 'pg' ? '$1' : '?'}`
388
+ : `UPDATE ${tableName} SET status = 'deleted' WHERE id = ${dbClient.clientType === 'pg' ? '$1' : '?'}`, [id]);
389
+ };
390
+ exports.deleteOne = deleteOne;
391
+ /**
392
+ * Deletes multiple records from the specified table
393
+ *
394
+ * This function deletes multiple records from the specified table based on the provided
395
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
396
+ *
397
+ * @template T - The type of the record to be deleted
398
+ * @param params - Query parameters including table name, database client, IDs of the records to be deleted, field to be used for deletion, and optional permanently flag
399
+ * @returns Promise<void> - Resolves when the records are deleted
400
+ *
401
+ * @throws {Error} When table name is not provided
402
+ * @throws {Error} When database client is not provided
403
+ * @throws {Error} When IDs are not provided or empty
404
+ * @throws {Error} When field is not provided
405
+ *
406
+ * @example
407
+ * await deleteMany({
408
+ * tableName: 'users',
409
+ * dbClient: dbClient,
410
+ * ids: ['123', '456', '789'],
411
+ * field: 'id',
412
+ * permanently: true,
413
+ * })
414
+ */
415
+ const deleteMany = async ({ tableName, dbClient, ids, field = 'id', permanently = false, }) => {
416
+ if (!tableName)
417
+ throw new Error('Table name is required');
418
+ if (!dbClient)
419
+ throw new Error('DB client is required');
420
+ if (!ids || ids.length === 0)
421
+ throw new Error('IDs are required and cannot be empty');
422
+ if (!field)
423
+ throw new Error('Field is required');
424
+ const placeholders = dbClient.clientType === 'pg'
425
+ ? ids.map((_, index) => `$${index + 1}`).join(', ')
426
+ : ids.map(() => '?').join(', ');
427
+ const query = permanently
428
+ ? `DELETE FROM ${tableName} WHERE ${field} IN (${placeholders})`
429
+ : `UPDATE ${tableName} SET status = 'deleted' WHERE ${field} IN (${placeholders})`;
430
+ await dbClient.query(query, ids);
431
+ };
432
+ exports.deleteMany = deleteMany;
433
+ /**
434
+ * Joins multiple tables in the specified table
435
+ *
436
+ * This function joins multiple tables in the specified table based on the provided
437
+ * query parameters. It constructs the SQL query, executes it, and returns the result.
438
+ *
439
+ * @template T - The type of the record to be joined
440
+ * @param params - Query parameters including table name, database client, select fields, joins, where conditions, group by, order by, limit, and offset
441
+ * @returns Promise<T[]> - The records found in the joined tables
442
+ *
443
+ * @throws {Error} When table name is not provided
444
+ * @throws {Error} When database client is not provided
445
+ * @throws {Error} When select fields are not provided
446
+ * @throws {Error} When joins are not provided
447
+ *
448
+ * @example
449
+ * const records = await joins({
450
+ * tableName: 'users',
451
+ * dbClient: dbClient,
452
+ * select: ['id', 'name', 'email'],
453
+ * joins: [{ type: 'INNER', table: 'orders', on: 'users.id = orders.user_id' }],
454
+ * where: { status: 'active' },
455
+ * groupBy: ['status'],
456
+ * orderBy: [{ field: 'created_at', direction: 'DESC' }],
457
+ * limit: 10,
458
+ * offset: 0,
459
+ * unaccent: true,
460
+ * })
461
+ */
462
+ const joins = async ({ tableName, dbClient, select, joins, where, groupBy, orderBy, limit, offset, unaccent, }) => {
463
+ if (!tableName)
464
+ throw new Error('Table name is required');
465
+ if (!dbClient)
466
+ throw new Error('DB client is required');
467
+ const fields = Array.isArray(select) ? select : [];
468
+ const selectFields = (0, utils_1.createSelectFields)(fields, dbClient.clientType);
469
+ const [whereClause, params] = (0, utils_1.createWhereClause)(where, 1, dbClient.clientType, unaccent);
470
+ const groupByClause = (0, utils_1.createGroupByClause)(groupBy);
471
+ const orderByClause = (0, utils_1.createOrderByClause)(orderBy);
472
+ const limitClause = (0, utils_1.createLimitClause)(limit);
473
+ const offsetClause = (0, utils_1.createOffsetClause)(offset);
474
+ const queryBuilder = {
475
+ select: [selectFields],
476
+ from: tableName,
477
+ joins: joins,
478
+ where: whereClause,
479
+ groupBy: [groupByClause],
480
+ orderBy: orderByClause,
481
+ limit: limitClause,
482
+ offset: offsetClause,
483
+ };
484
+ const queryString = await buildQuery(queryBuilder);
485
+ const rows = await dbClient.query(queryString, params);
486
+ return rows;
487
+ };
488
+ exports.joins = joins;
489
+ /**
490
+ * Executa uma query SQL raw diretamente no banco de dados
491
+ * @param params - Parâmetros da query raw
492
+ * @returns Promise com o resultado da query
493
+ *
494
+ * @example
495
+ * // Query simples sem parâmetros
496
+ * const users = await rawQuery({
497
+ * dbClient,
498
+ * sql: 'SELECT * FROM users WHERE active = true'
499
+ * })
500
+ *
501
+ * @example
502
+ * // Query com parâmetros
503
+ * const user = await rawQuery({
504
+ * dbClient,
505
+ * sql: 'SELECT * FROM users WHERE id = ? AND email = ?',
506
+ * params: ['user-id', 'user@example.com']
507
+ * })
508
+ *
509
+ * @example
510
+ * // Query de agregação
511
+ * const stats = await rawQuery({
512
+ * dbClient,
513
+ * sql: `
514
+ * SELECT
515
+ * COUNT(*) as total_users,
516
+ * AVG(age) as avg_age,
517
+ * MAX(created_at) as last_created
518
+ * FROM users
519
+ * WHERE created_at >= ?
520
+ * `,
521
+ * params: [new Date('2023-01-01')]
522
+ * })
523
+ */
524
+ const rawQuery = async ({ dbClient, sql, params = [], }) => {
525
+ if (!dbClient)
526
+ throw new Error('DB client is required');
527
+ if (!sql || typeof sql !== 'string')
528
+ throw new Error('SQL query is required and must be a string');
529
+ try {
530
+ const result = await dbClient.query(sql, params);
531
+ return result;
532
+ }
533
+ catch (error) {
534
+ throw new Error(`Raw query execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
535
+ }
536
+ };
537
+ exports.rawQuery = rawQuery;
538
+ /**
539
+ * Builds a query string from the provided query parameters
540
+ *
541
+ * This function builds a query string from the provided query parameters. It constructs the SQL query, executes it, and returns the result.
542
+ *
543
+ * @param params - Query parameters including select fields, from table, joins, where conditions, group by, order by, limit, and offset
544
+ * @returns Promise<string> - The query string
545
+ *
546
+ * @example
547
+ * const queryString = await buildQuery({
548
+ * select: ['id', 'name', 'email'],
549
+ * from: 'users',
550
+ * joins: [{ type: 'INNER', table: 'orders', on: 'users.id = orders.user_id' }],
551
+ * where: { status: 'active' },
552
+ * groupBy: ['status'],
553
+ * orderBy: [{ field: 'created_at', direction: 'DESC' }],
554
+ * limit: 10,
555
+ * offset: 0,
556
+ * })
557
+ */
558
+ async function buildQuery(params) {
559
+ let queryString = `SELECT ${params.select.join(', ')} FROM ${params.from}`;
560
+ if (params.joins) {
561
+ for (const join of params.joins) {
562
+ queryString += ` ${join.type} JOIN ${join.table} ON ${join.on}`;
563
+ }
564
+ }
565
+ if (params.where) {
566
+ queryString += `${params.where}`;
567
+ }
568
+ if (params.groupBy) {
569
+ queryString += `${params.groupBy}`;
570
+ }
571
+ if (params.orderBy) {
572
+ queryString += `${params.orderBy}`;
573
+ }
574
+ if (params.limit) {
575
+ queryString += `${params.limit}`;
576
+ }
577
+ if (params.offset) {
578
+ queryString += `${params.offset}`;
579
+ }
580
+ return queryString;
581
+ }
582
+ /**
583
+ * Executes a function within a database transaction
584
+ * @param dbClient - Database client instance
585
+ * @param transactionFn - Function to execute within the transaction
586
+ * @returns Promise with the result of the transaction function
587
+ *
588
+ * @example
589
+ * // Simple transaction
590
+ * const result = await withTransaction(dbClient, async (tx) => {
591
+ * const user = await insert({
592
+ * tableName: 'users',
593
+ * dbClient: tx,
594
+ * data: { name: 'John', email: 'john@example.com' }
595
+ * })
596
+ *
597
+ * await insert({
598
+ * tableName: 'user_profiles',
599
+ * dbClient: tx,
600
+ * data: { user_id: user.id, bio: 'Hello world' }
601
+ * })
602
+ *
603
+ * return user
604
+ * })
605
+ *
606
+ * @example
607
+ * // Transaction with error handling
608
+ * try {
609
+ * const result = await withTransaction(dbClient, async (tx) => {
610
+ * // Multiple operations that must succeed or fail together
611
+ * const order = await insert({
612
+ * tableName: 'orders',
613
+ * dbClient: tx,
614
+ * data: { user_id: 'user-123', total: 100 }
615
+ * })
616
+ *
617
+ * await update({
618
+ * tableName: 'users',
619
+ * dbClient: tx,
620
+ * id: 'user-123',
621
+ * data: { last_order_id: order.id }
622
+ * })
623
+ *
624
+ * return order
625
+ * })
626
+ * } catch (error) {
627
+ * // Transaction was automatically rolled back
628
+ * console.error('Transaction failed:', error)
629
+ * }
630
+ */
631
+ const withTransaction = async (dbClient, transactionFn) => {
632
+ const transaction = await dbClient.beginTransaction();
633
+ try {
634
+ const result = await transactionFn(transaction);
635
+ await transaction.commit();
636
+ return result;
637
+ }
638
+ catch (error) {
639
+ await transaction.rollback();
640
+ throw error;
641
+ }
642
+ };
643
+ exports.withTransaction = withTransaction;
644
+ /**
645
+ * Creates a transaction client for manual transaction management
646
+ * @param dbClient - Database client instance
647
+ * @returns Promise with the transaction client
648
+ *
649
+ * @example
650
+ * // Manual transaction management
651
+ * const transaction = await beginTransaction(dbClient)
652
+ *
653
+ * try {
654
+ * const user = await insert({
655
+ * tableName: 'users',
656
+ * dbClient: transaction,
657
+ * data: { name: 'John', email: 'john@example.com' }
658
+ * })
659
+ *
660
+ * await insert({
661
+ * tableName: 'user_profiles',
662
+ * dbClient: transaction,
663
+ * data: { user_id: user.id, bio: 'Hello world' }
664
+ * })
665
+ *
666
+ * await transaction.commit()
667
+ * return user
668
+ * } catch (error) {
669
+ * await transaction.rollback()
670
+ * throw error
671
+ * }
672
+ */
673
+ const beginTransaction = async (dbClient) => {
674
+ return dbClient.beginTransaction();
675
+ };
676
+ exports.beginTransaction = beginTransaction;
677
+ //# sourceMappingURL=repository.js.map