@hed-hog/api-pagination 0.0.1 → 0.0.3

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 (68) hide show
  1. package/dist/databases/abstract.database.js +36 -67
  2. package/dist/databases/abstract.database.js.map +1 -1
  3. package/dist/databases/mysql.database.js +5 -0
  4. package/dist/databases/mysql.database.js.map +1 -1
  5. package/dist/databases/postgres.database.js +5 -0
  6. package/dist/databases/postgres.database.js.map +1 -1
  7. package/dist/decorator/pagination.decorator.d.ts +1 -1
  8. package/dist/decorator/pagination.decorator.js +5 -1
  9. package/dist/decorator/pagination.decorator.js.map +1 -1
  10. package/dist/dto/pagination.dto.js +6 -0
  11. package/dist/dto/pagination.dto.js.map +1 -1
  12. package/dist/pagination.service.js +6 -9
  13. package/dist/pagination.service.js.map +1 -1
  14. package/package.json +5 -5
  15. package/src/constants/pagination.constants.d.ts.map +1 -0
  16. package/src/constants/pagination.constants.js +6 -0
  17. package/src/constants/pagination.constants.js.map +1 -0
  18. package/src/databases/abstract.database.d.ts.map +1 -0
  19. package/src/databases/abstract.database.js +655 -0
  20. package/src/databases/abstract.database.js.map +1 -0
  21. package/src/databases/database.d.ts.map +1 -0
  22. package/src/databases/database.factory.d.ts.map +1 -0
  23. package/src/databases/database.factory.js +20 -0
  24. package/src/databases/database.factory.js.map +1 -0
  25. package/src/databases/database.js +9 -0
  26. package/src/databases/database.js.map +1 -0
  27. package/src/databases/index.d.ts.map +1 -0
  28. package/src/databases/index.js +20 -0
  29. package/src/databases/index.js.map +1 -0
  30. package/src/databases/mysql.database.d.ts.map +1 -0
  31. package/src/databases/mysql.database.js +22 -0
  32. package/src/databases/mysql.database.js.map +1 -0
  33. package/src/databases/postgres.database.d.ts.map +1 -0
  34. package/src/databases/postgres.database.js +22 -0
  35. package/src/databases/postgres.database.js.map +1 -0
  36. package/src/decorator/pagination.decorator.d.ts.map +1 -0
  37. package/src/decorator/pagination.decorator.js +58 -0
  38. package/src/decorator/pagination.decorator.js.map +1 -0
  39. package/src/dto/pagination.dto.d.ts.map +1 -0
  40. package/src/dto/pagination.dto.js +58 -0
  41. package/src/dto/pagination.dto.js.map +1 -0
  42. package/src/enums/patination.enums.d.ts.map +1 -0
  43. package/src/enums/patination.enums.js +17 -0
  44. package/src/enums/patination.enums.js.map +1 -0
  45. package/src/index.d.ts.map +1 -0
  46. package/src/index.js +23 -0
  47. package/src/index.js.map +1 -0
  48. package/src/pagination.module.d.ts.map +1 -0
  49. package/src/pagination.module.js +22 -0
  50. package/src/pagination.module.js.map +1 -0
  51. package/src/pagination.service.d.ts.map +1 -0
  52. package/src/pagination.service.js +252 -0
  53. package/src/pagination.service.js.map +1 -0
  54. package/src/types/pagination.types.d.ts.map +1 -0
  55. package/src/types/pagination.types.js +3 -0
  56. package/src/types/pagination.types.js.map +1 -0
  57. package/src/types/query-option.d.ts.map +1 -0
  58. package/src/types/query-option.js +3 -0
  59. package/src/types/query-option.js.map +1 -0
  60. package/src/types/relation-n2n-result.d.ts.map +1 -0
  61. package/src/types/relation-n2n-result.js +3 -0
  62. package/src/types/relation-n2n-result.js.map +1 -0
  63. package/src/types/transaction-queries.d.ts.map +1 -0
  64. package/src/types/transaction-queries.js +3 -0
  65. package/src/types/transaction-queries.js.map +1 -0
  66. package/tsconfig.json +0 -3
  67. package/tsconfig.production.json +2 -40
  68. package/tsconfig.production.tsbuildinfo +1 -0
@@ -0,0 +1,655 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AbstractDatabase = void 0;
37
+ const typeorm_1 = require("typeorm");
38
+ const database_1 = require("./database");
39
+ const PlatformTools_1 = require("typeorm/platform/PlatformTools");
40
+ class AbstractDatabase {
41
+ type;
42
+ host;
43
+ user;
44
+ password;
45
+ database;
46
+ port;
47
+ client = null;
48
+ foreignKeys = {};
49
+ foreignKeysByTable = {};
50
+ primaryKeys = {};
51
+ columnNameFromRelation = {};
52
+ relationN2N = {};
53
+ relation1N = {};
54
+ columnComment = {};
55
+ tableHasColumnOrder = {};
56
+ eventEmitter = new PlatformTools_1.EventEmitter();
57
+ autoClose = true;
58
+ constructor(type, host, user, password, database, port) {
59
+ this.type = type;
60
+ this.host = host;
61
+ this.user = user;
62
+ this.password = password;
63
+ this.database = database;
64
+ this.port = port;
65
+ }
66
+ getDataSource() {
67
+ return new typeorm_1.DataSource({
68
+ type: this.type,
69
+ host: this.host,
70
+ port: this.port,
71
+ username: this.user,
72
+ password: this.password,
73
+ database: this.database,
74
+ synchronize: true,
75
+ logging: false,
76
+ entities: [],
77
+ subscribers: [],
78
+ migrations: [],
79
+ });
80
+ }
81
+ disableAutoClose() {
82
+ this.autoClose = false;
83
+ }
84
+ close() {
85
+ return this.client?.end();
86
+ }
87
+ on(event, listener) {
88
+ return this.eventEmitter.on(event, listener);
89
+ }
90
+ getArrayType(values) {
91
+ return [...new Set(values.map((value) => typeof value))][0];
92
+ }
93
+ getWhereWithIn(columnName, operator, values) {
94
+ switch (this.type) {
95
+ case database_1.Database.POSTGRES:
96
+ if (operator === 'in') {
97
+ return `${this.getColumnNameWithScaping(columnName)} = ANY(?::${this.getArrayType(values) === 'number' ? 'int' : 'text'}[])`;
98
+ }
99
+ else {
100
+ return `${this.getColumnNameWithScaping(columnName)} <> ALL(?::${this.getArrayType(values) === 'number' ? 'int' : 'text'}[])`;
101
+ }
102
+ case database_1.Database.MYSQL:
103
+ return `${this.getColumnNameWithScaping(columnName)} ${operator === 'in' ? 'IN' : 'NOT IN'}(${values.map((value) => AbstractDatabase.addSimpleQuotes(value)).join(', ')})`;
104
+ }
105
+ }
106
+ static addSimpleQuotes(value) {
107
+ if (typeof value === 'string') {
108
+ return `'${value}'`;
109
+ }
110
+ return value;
111
+ }
112
+ replacePlaceholders(query) {
113
+ let index = 1;
114
+ return query.replace(/\?/g, () => {
115
+ return `$${index++}`;
116
+ });
117
+ }
118
+ getColumnNameWithScaping(columnName) {
119
+ switch (this.type) {
120
+ case database_1.Database.POSTGRES:
121
+ return `"${columnName}"`;
122
+ case database_1.Database.MYSQL:
123
+ return `\`${columnName}\``;
124
+ }
125
+ }
126
+ getLimit(offset, limit) {
127
+ switch (this.type) {
128
+ case database_1.Database.POSTGRES:
129
+ return `LIMIT ${offset} OFFSET ${limit}`;
130
+ case database_1.Database.MYSQL:
131
+ return `LIMIT ${offset}, ${limit}`;
132
+ }
133
+ }
134
+ getTableNameFromQuery(query) {
135
+ const match = query.match(/INSERT INTO\s+([`"]?[\w-]+[`"]?)/i);
136
+ if (match && match[1]) {
137
+ return match[1].replace(/[`"]/g, '');
138
+ }
139
+ return null;
140
+ }
141
+ async hasTableColumnOrder(tableName) {
142
+ if (this.tableHasColumnOrder[tableName]) {
143
+ return this.tableHasColumnOrder[tableName];
144
+ }
145
+ return (this.tableHasColumnOrder[tableName] =
146
+ (await this.getColumnComment(tableName, 'order')) === 'order');
147
+ }
148
+ async getColumnComment(tableName, columnName) {
149
+ if (this.columnComment[`${tableName}.${columnName}`]) {
150
+ return this.columnComment[`${tableName}.${columnName}`];
151
+ }
152
+ switch (this.type) {
153
+ case database_1.Database.POSTGRES:
154
+ const resultPg = await this.query(`SELECT a.attname AS column_name,
155
+ col_description(a.attrelid, a.attnum) AS column_comment
156
+ FROM pg_class AS c
157
+ JOIN pg_attribute AS a ON a.attrelid = c.oid
158
+ WHERE c.relname = ?
159
+ AND a.attname = ?;`, [tableName, columnName]);
160
+ return resultPg.length > 0
161
+ ? (this.columnComment[`${tableName}.${columnName}`] =
162
+ resultPg[0].column_comment)
163
+ : '';
164
+ case database_1.Database.MYSQL:
165
+ const resultMysql = await this.query(`SELECT COLUMN_NAME, COLUMN_COMMENT
166
+ FROM information_schema.COLUMNS
167
+ WHERE TABLE_NAME = ?
168
+ AND COLUMN_NAME = ?;`, [tableName, columnName]);
169
+ return resultMysql.length > 0
170
+ ? (this.columnComment[`${tableName}.${columnName}`] =
171
+ resultMysql[0].COLUMN_COMMENT)
172
+ : '';
173
+ }
174
+ }
175
+ async getTableNameFromForeignKey(tableName, foreignKey) {
176
+ if (this.foreignKeys[`${tableName}.${foreignKey}`]) {
177
+ return this.foreignKeys[`${tableName}.${foreignKey}`];
178
+ }
179
+ switch (this.type) {
180
+ case database_1.Database.POSTGRES:
181
+ const resultPg = await this.query(`SELECT
182
+ ccu.table_name
183
+ FROM
184
+ information_schema.table_constraints AS tc
185
+ JOIN information_schema.key_column_usage AS kcu
186
+ ON tc.constraint_name = kcu.constraint_name
187
+ AND tc.table_schema = kcu.table_schema
188
+ JOIN information_schema.constraint_column_usage AS ccu
189
+ ON ccu.constraint_name = tc.constraint_name
190
+ AND ccu.table_schema = tc.table_schema
191
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = ? AND kcu.column_name = ?;`, [tableName, foreignKey]);
192
+ if (resultPg.length === 0) {
193
+ throw new Error(`Foreign key ${tableName}.${foreignKey} not found in database.`);
194
+ }
195
+ return (this.foreignKeys[`${tableName}.${foreignKey}`] =
196
+ resultPg[0].table_name);
197
+ case database_1.Database.MYSQL:
198
+ const resultMysql = await this.query(`SELECT kcu.REFERENCED_TABLE_NAME as table_name
199
+ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
200
+ JOIN information_schema.table_constraints AS tc
201
+ ON tc.constraint_name = kcu.constraint_name
202
+ AND tc.table_schema = kcu.table_schema
203
+ WHERE kcu.TABLE_NAME = ? AND kcu.COLUMN_NAME = ? AND tc.CONSTRAINT_TYPE = 'FOREIGN KEY'`, [tableName, foreignKey]);
204
+ if (resultMysql.length === 0) {
205
+ throw new Error(`Foreign key ${tableName}.${foreignKey} not found in database.`);
206
+ }
207
+ return (this.foreignKeys[`${tableName}.${foreignKey}`] =
208
+ resultMysql[0].table_name);
209
+ }
210
+ }
211
+ shouldHandleReturning(options) {
212
+ return options?.returning !== undefined;
213
+ }
214
+ isReturningSingleField(options) {
215
+ return (options?.returning instanceof Array && options.returning.length === 1);
216
+ }
217
+ isReturningIdWithoutPrimaryKeys(options) {
218
+ return options?.returning === 'id' && !options.primaryKeys;
219
+ }
220
+ isMissingPrimaryKeys(options) {
221
+ return !options?.primaryKeys;
222
+ }
223
+ hasPrimaryKeys(options) {
224
+ return typeof options?.primaryKeys === 'string';
225
+ }
226
+ hasReturning(options) {
227
+ return typeof options?.returning === 'string';
228
+ }
229
+ formatOptions(options) {
230
+ if (options && this.shouldHandleReturning(options)) {
231
+ if (this.isReturningSingleField(options)) {
232
+ options.returning = options.returning[0];
233
+ }
234
+ if (this.isReturningIdWithoutPrimaryKeys(options)) {
235
+ options.primaryKeys = options.returning;
236
+ }
237
+ if (this.isMissingPrimaryKeys(options)) {
238
+ throw new Error('Primary key is required when using returning.');
239
+ }
240
+ if (this.hasPrimaryKeys(options)) {
241
+ options.primaryKeys = [options.primaryKeys];
242
+ }
243
+ if (this.hasReturning(options)) {
244
+ options.returning = [options.returning];
245
+ }
246
+ }
247
+ return options;
248
+ }
249
+ addReturningToQuery(query, options) {
250
+ if (this.type === database_1.Database.POSTGRES &&
251
+ this.shouldHandleReturning(options)) {
252
+ return `${query} RETURNING ${(options?.returning).join(', ')}`;
253
+ }
254
+ return query;
255
+ }
256
+ async getResult(query, result, options) {
257
+ switch (this.type) {
258
+ case database_1.Database.POSTGRES:
259
+ return result.rows;
260
+ case database_1.Database.MYSQL:
261
+ result = result[0];
262
+ if (this.shouldHandleReturning(options)) {
263
+ const resultArray = [
264
+ {
265
+ id: result.insertId,
266
+ },
267
+ ];
268
+ result = resultArray;
269
+ if ((Array.isArray(options?.returning) &&
270
+ options.returning.length > 1) ||
271
+ (options?.returning?.length === 1 &&
272
+ options?.primaryKeys &&
273
+ options?.returning[0] !== options?.primaryKeys[0])) {
274
+ const where = (options?.primaryKeys ?? [])
275
+ .map((pk) => `${pk} = ?`)
276
+ .join(' AND ');
277
+ const selectReturningQuery = `SELECT ${(options?.returning).join(', ')} FROM ${this.getTableNameFromQuery(query)} WHERE ${where}`;
278
+ const returningResult = await this.client.query(selectReturningQuery, [resultArray[0].id]);
279
+ result = returningResult;
280
+ }
281
+ }
282
+ else if (result?.insertId) {
283
+ result = [
284
+ {
285
+ id: result.insertId,
286
+ },
287
+ ];
288
+ }
289
+ return result;
290
+ }
291
+ }
292
+ async getClient() {
293
+ switch (this.type) {
294
+ case database_1.Database.POSTGRES:
295
+ const { Client } = await Promise.resolve().then(() => __importStar(require('pg')));
296
+ this.client = new Client({
297
+ host: this.host,
298
+ user: this.user,
299
+ password: this.password,
300
+ database: this.database,
301
+ port: this.port,
302
+ });
303
+ await this.client.connect();
304
+ return this.client;
305
+ case database_1.Database.MYSQL:
306
+ const mysql = await Promise.resolve().then(() => __importStar(require('mysql2/promise')));
307
+ this.client = await mysql.createConnection({
308
+ host: this.host,
309
+ user: this.user,
310
+ password: this.password,
311
+ database: this.database,
312
+ port: this.port,
313
+ });
314
+ return this.client;
315
+ }
316
+ }
317
+ async testDatabaseConnection() {
318
+ try {
319
+ switch (this.type) {
320
+ case database_1.Database.POSTGRES:
321
+ case database_1.Database.MYSQL:
322
+ await this.query('SELECT NOW()');
323
+ break;
324
+ }
325
+ }
326
+ catch (error) {
327
+ return false;
328
+ }
329
+ return true;
330
+ }
331
+ async getPrimaryKeys(tableName) {
332
+ if (this.primaryKeys[tableName]) {
333
+ return this.primaryKeys[tableName];
334
+ }
335
+ let primaryKeys = [];
336
+ switch (this.type) {
337
+ case database_1.Database.POSTGRES:
338
+ const resultPg = await this.query(`SELECT column_name
339
+ FROM information_schema.table_constraints tc
340
+ JOIN information_schema.key_column_usage kcu
341
+ ON tc.constraint_name = kcu.constraint_name
342
+ WHERE constraint_type = 'PRIMARY KEY'
343
+ AND tc.table_name = ?`, [tableName]);
344
+ primaryKeys = resultPg.map((row) => row.column_name);
345
+ if (primaryKeys.length > 0) {
346
+ this.primaryKeys[tableName] = primaryKeys;
347
+ }
348
+ return primaryKeys;
349
+ case database_1.Database.MYSQL:
350
+ const resultMysql = await this.query(`SELECT COLUMN_NAME
351
+ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
352
+ WHERE TABLE_NAME = ? AND CONSTRAINT_NAME = 'PRIMARY'`, [tableName]);
353
+ primaryKeys = resultMysql.map((row) => row.COLUMN_NAME);
354
+ if (primaryKeys.length > 0) {
355
+ this.primaryKeys[tableName] = primaryKeys;
356
+ }
357
+ return primaryKeys;
358
+ }
359
+ }
360
+ async getForeignKeys(tableName) {
361
+ if (this.foreignKeysByTable[tableName]) {
362
+ return this.foreignKeysByTable[tableName];
363
+ }
364
+ switch (this.type) {
365
+ case database_1.Database.POSTGRES:
366
+ const resultPg = await this.query(`SELECT kcu.column_name
367
+ FROM
368
+ information_schema.table_constraints AS tc
369
+ JOIN information_schema.key_column_usage AS kcu
370
+ ON tc.constraint_name = kcu.constraint_name
371
+ AND tc.table_schema = kcu.table_schema
372
+ JOIN information_schema.constraint_column_usage AS ccu
373
+ ON ccu.constraint_name = tc.constraint_name
374
+ AND ccu.table_schema = tc.table_schema
375
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = ?;`, [tableName]);
376
+ return (this.foreignKeysByTable[tableName] = resultPg.map((row) => row.column_name));
377
+ case database_1.Database.MYSQL:
378
+ const resultMysql = await this.query(`SELECT COLUMN_NAME
379
+ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
380
+ WHERE TABLE_NAME = ? AND CONSTRAINT_NAME != 'PRIMARY'`, [tableName]);
381
+ return (this.foreignKeysByTable[tableName] = resultMysql.map((row) => row.COLUMN_NAME));
382
+ }
383
+ }
384
+ async getColumnNameFromRelation(tableNameOrigin, tableNameDestination) {
385
+ if (this.columnNameFromRelation[`${tableNameOrigin}.${tableNameDestination}`]) {
386
+ return this.columnNameFromRelation[`${tableNameOrigin}.${tableNameDestination}`];
387
+ }
388
+ switch (this.type) {
389
+ case database_1.Database.POSTGRES:
390
+ const resultPg = await this.query(`SELECT
391
+ tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name
392
+ FROM
393
+ information_schema.table_constraints AS tc
394
+ JOIN information_schema.key_column_usage AS kcu
395
+ ON tc.constraint_name = kcu.constraint_name
396
+ AND tc.table_schema = kcu.table_schema
397
+ JOIN information_schema.constraint_column_usage AS ccu
398
+ ON ccu.constraint_name = tc.constraint_name
399
+ AND ccu.table_schema = tc.table_schema
400
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND ccu.table_name = ? AND tc.table_name = ?;`, [tableNameOrigin, tableNameDestination]);
401
+ if (!resultPg.length) {
402
+ throw new Error(`Foreign key ${tableNameOrigin}.${tableNameDestination} not found in database. [getColumnNameFromRelation]`);
403
+ }
404
+ return (this.columnNameFromRelation[`${tableNameOrigin}.${tableNameDestination}`] = resultPg[0].column_name);
405
+ case database_1.Database.MYSQL:
406
+ const resultMysql = await this.query(`SELECT
407
+ TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
408
+ FROM
409
+ INFORMATION_SCHEMA.KEY_COLUMN_USAGE
410
+ WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME = ? AND TABLE_NAME = ?;`, [tableNameOrigin, tableNameDestination]);
411
+ if (!resultMysql.length) {
412
+ throw new Error(`Foreign key ${tableNameOrigin}.${tableNameDestination} not found in database. [getColumnNameFromRelation]`);
413
+ }
414
+ return (this.columnNameFromRelation[`${tableNameOrigin}.${tableNameDestination}`] = resultMysql[0].COLUMN_NAME);
415
+ default:
416
+ throw new Error(`Unsupported database type: ${this.type}`);
417
+ }
418
+ }
419
+ async getRelation1N(tableNameOrigin, tableNameDestination) {
420
+ if (this.relation1N[`${tableNameOrigin}.${tableNameDestination}`]) {
421
+ return this.relation1N[`${tableNameOrigin}.${tableNameDestination}`];
422
+ }
423
+ switch (this.type) {
424
+ case database_1.Database.POSTGRES:
425
+ const resultPg = await this.query(`SELECT
426
+ tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name
427
+ FROM
428
+ information_schema.table_constraints AS tc
429
+ JOIN information_schema.key_column_usage AS kcu
430
+ ON tc.constraint_name = kcu.constraint_name
431
+ AND tc.table_schema = kcu.table_schema
432
+ JOIN information_schema.constraint_column_usage AS ccu
433
+ ON ccu.constraint_name = tc.constraint_name
434
+ AND ccu.table_schema = tc.table_schema
435
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND ccu.table_name = ? AND tc.table_name = ?;`, [tableNameOrigin, tableNameDestination]);
436
+ if (!resultPg.length) {
437
+ throw new Error(`Foreign key ${tableNameOrigin}.${tableNameDestination} not found in database. [getRelation1N]`);
438
+ }
439
+ return (this.relation1N[`${tableNameOrigin}.${tableNameDestination}`] =
440
+ resultPg[0].column_name);
441
+ case database_1.Database.MYSQL:
442
+ const resultMysql = await this.query(`SELECT
443
+ TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
444
+ FROM
445
+ INFORMATION_SCHEMA.KEY_COLUMN_USAGE
446
+ WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME = ? AND TABLE_NAME = ?;`, [tableNameOrigin, tableNameDestination]);
447
+ if (!resultMysql.length) {
448
+ throw new Error(`Foreign key ${tableNameOrigin}.${tableNameDestination} not found in database. [getRelation1N]`);
449
+ }
450
+ return (this.relation1N[`${tableNameOrigin}.${tableNameDestination}`] =
451
+ resultMysql[0].COLUMN_NAME);
452
+ }
453
+ }
454
+ async getRelationN2N(tableNameOrigin, tableNameDestination) {
455
+ if (this.relationN2N[`${tableNameOrigin}.${tableNameDestination}`]) {
456
+ return this.relationN2N[`${tableNameOrigin}.${tableNameDestination}`];
457
+ }
458
+ let tableNameIntermediate = '';
459
+ let columnNameOrigin = '';
460
+ let columnNameDestination = '';
461
+ let primaryKeyDestination = '';
462
+ switch (this.type) {
463
+ case database_1.Database.POSTGRES:
464
+ const resultPg1 = await this.query(`SELECT
465
+ tc.table_name, kcu.column_name
466
+ FROM
467
+ information_schema.table_constraints AS tc
468
+ JOIN information_schema.key_column_usage AS kcu
469
+ ON tc.constraint_name = kcu.constraint_name
470
+ AND tc.table_schema = kcu.table_schema
471
+ JOIN information_schema.constraint_column_usage AS ccu
472
+ ON ccu.constraint_name = tc.constraint_name
473
+ AND ccu.table_schema = tc.table_schema
474
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND ccu.table_name = ?;`, [tableNameOrigin]);
475
+ for (const row of resultPg1) {
476
+ const resultPg2 = await this.query(`SELECT
477
+ tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name
478
+ FROM
479
+ information_schema.table_constraints AS tc
480
+ JOIN information_schema.key_column_usage AS kcu
481
+ ON tc.constraint_name = kcu.constraint_name
482
+ AND tc.table_schema = kcu.table_schema
483
+ JOIN information_schema.constraint_column_usage AS ccu
484
+ ON ccu.constraint_name = tc.constraint_name
485
+ AND ccu.table_schema = tc.table_schema
486
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = ?;`, [row['table_name']]);
487
+ for (const row2 of resultPg2) {
488
+ if (row2['foreign_table_name'] === tableNameDestination) {
489
+ tableNameIntermediate = row['table_name'];
490
+ columnNameOrigin = row['column_name'];
491
+ columnNameDestination = row2['column_name'];
492
+ primaryKeyDestination = row2['foreign_column_name'];
493
+ break;
494
+ }
495
+ }
496
+ }
497
+ return (this.relationN2N[`${tableNameOrigin}.${tableNameDestination}`] =
498
+ {
499
+ tableNameIntermediate,
500
+ columnNameOrigin,
501
+ columnNameDestination,
502
+ primaryKeyDestination,
503
+ });
504
+ case database_1.Database.MYSQL:
505
+ const resultMysql1 = await this.query(`SELECT
506
+ kcu.TABLE_NAME,
507
+ kcu.COLUMN_NAME,
508
+ kcu.REFERENCED_TABLE_NAME AS foreign_table_name,
509
+ kcu.REFERENCED_COLUMN_NAME AS foreign_column_name
510
+ FROM
511
+ information_schema.KEY_COLUMN_USAGE AS kcu
512
+ WHERE
513
+ kcu.REFERENCED_TABLE_NAME = ?
514
+ AND kcu.TABLE_SCHEMA = DATABASE();`, [tableNameOrigin]);
515
+ for (const row of resultMysql1) {
516
+ const resultMysql2 = await this.query(`SELECT
517
+ kcu.TABLE_NAME,
518
+ kcu.COLUMN_NAME,
519
+ kcu.REFERENCED_TABLE_NAME AS foreign_table_name,
520
+ kcu.REFERENCED_COLUMN_NAME AS foreign_column_name
521
+ FROM
522
+ information_schema.KEY_COLUMN_USAGE AS kcu
523
+ WHERE
524
+ kcu.TABLE_NAME = ?
525
+ AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
526
+ AND kcu.TABLE_SCHEMA = DATABASE();`, [row['TABLE_NAME']]);
527
+ for (const row2 of resultMysql2) {
528
+ if (row2['foreign_table_name'] === tableNameDestination) {
529
+ tableNameIntermediate = row['TABLE_NAME'];
530
+ columnNameOrigin = row['COLUMN_NAME'];
531
+ columnNameDestination = row2['COLUMN_NAME'];
532
+ primaryKeyDestination = row2['foreign_column_name'];
533
+ break;
534
+ }
535
+ }
536
+ }
537
+ return (this.relationN2N[`${tableNameOrigin}.${tableNameDestination}`] =
538
+ {
539
+ tableNameIntermediate,
540
+ columnNameOrigin,
541
+ columnNameDestination,
542
+ primaryKeyDestination,
543
+ });
544
+ default:
545
+ throw new Error(`Unsupported database type: ${this.type}`);
546
+ }
547
+ }
548
+ static parseQueryValue(value) {
549
+ switch (typeof value) {
550
+ case 'number':
551
+ case 'boolean':
552
+ return value;
553
+ default:
554
+ return `'${value}'`;
555
+ }
556
+ }
557
+ static objectToWhereClause(obj) {
558
+ let whereClause = '';
559
+ for (const key in obj) {
560
+ if (typeof obj[key] === 'object') {
561
+ whereClause += `${key} ${obj[key].operator} ${AbstractDatabase.parseQueryValue(obj[key].value)}`;
562
+ }
563
+ else {
564
+ whereClause += `${key} = ${AbstractDatabase.parseQueryValue(obj[key])}`;
565
+ }
566
+ }
567
+ return whereClause;
568
+ }
569
+ async transaction(queries) {
570
+ this.eventEmitter.emit('transaction', { queries });
571
+ if (!this.client) {
572
+ await this.getClient();
573
+ }
574
+ const results = [];
575
+ for (let i = 0; i < queries.length; i++) {
576
+ queries[i].options = this.formatOptions(queries[i].options);
577
+ queries[i].query = this.addReturningToQuery(queries[i].query, queries[i].options);
578
+ }
579
+ try {
580
+ switch (this.type) {
581
+ case database_1.Database.POSTGRES:
582
+ await this.client.query('BEGIN');
583
+ for (const { query, values, options } of queries) {
584
+ const resultPg = await this.client.query(this.replacePlaceholders(query), values);
585
+ results.push(this.getResult(query, resultPg, options));
586
+ }
587
+ await this.client.query('COMMIT');
588
+ break;
589
+ case database_1.Database.MYSQL:
590
+ await this.client.beginTransaction();
591
+ for (const { query, values, options } of queries) {
592
+ const resultMySQL = await this.client.query(query, values);
593
+ results.push(this.getResult(query, resultMySQL, options));
594
+ }
595
+ await this.client.commit();
596
+ break;
597
+ }
598
+ }
599
+ catch (error) {
600
+ switch (this.type) {
601
+ case database_1.Database.POSTGRES:
602
+ await this.client.query('ROLLBACK');
603
+ break;
604
+ case database_1.Database.MYSQL:
605
+ await this.client.rollback();
606
+ break;
607
+ }
608
+ throw error;
609
+ }
610
+ finally {
611
+ if (this.autoClose) {
612
+ await this.client?.end();
613
+ this.client = null;
614
+ }
615
+ }
616
+ return results;
617
+ }
618
+ async query(query, values, options) {
619
+ this.eventEmitter.emit('query', { query, values, options });
620
+ if (!this.client) {
621
+ await this.getClient();
622
+ }
623
+ let result;
624
+ options = this.formatOptions(options);
625
+ query = this.addReturningToQuery(query, options);
626
+ try {
627
+ switch (this.type) {
628
+ case database_1.Database.POSTGRES:
629
+ result = await this.client.query(this.replacePlaceholders(query), values);
630
+ break;
631
+ case database_1.Database.MYSQL:
632
+ result = await this.client.query(query, values);
633
+ break;
634
+ }
635
+ }
636
+ catch (error) {
637
+ console.error({
638
+ error,
639
+ query,
640
+ values,
641
+ options,
642
+ });
643
+ this.eventEmitter.emit('error', { error, query, values, options });
644
+ }
645
+ result = await this.getResult(query, result, options);
646
+ this.eventEmitter.emit('query', { result });
647
+ if (this.autoClose) {
648
+ await this.client?.end();
649
+ this.client = null;
650
+ }
651
+ return result;
652
+ }
653
+ }
654
+ exports.AbstractDatabase = AbstractDatabase;
655
+ //# sourceMappingURL=abstract.database.js.map