@hedhog/pagination 0.0.16 → 0.0.18

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