@dbcube/query-builder 5.2.1 → 5.2.2
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.
- package/dist/index.cjs +19 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +19 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -80,10 +80,13 @@ var Trigger = class {
|
|
|
80
80
|
delete require2.cache[require2.resolve(pathFile)];
|
|
81
81
|
} catch {
|
|
82
82
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
try {
|
|
84
|
+
const triggerModule = require2(pathFile);
|
|
85
|
+
const dataProcess = triggerModule.default || triggerModule;
|
|
86
|
+
await dataProcess({ db: this.instance, oldData: row, newData: row });
|
|
87
|
+
} finally {
|
|
88
|
+
interceptor.restore();
|
|
89
|
+
}
|
|
87
90
|
return interceptor;
|
|
88
91
|
}
|
|
89
92
|
return null;
|
|
@@ -583,6 +586,7 @@ var Table = class _Table {
|
|
|
583
586
|
column,
|
|
584
587
|
alias: "count"
|
|
585
588
|
};
|
|
589
|
+
clone.dml.orderBy = [];
|
|
586
590
|
clone.dml.columns = [`COUNT(${column}) AS count`];
|
|
587
591
|
clone.dml.data = null;
|
|
588
592
|
clone.dml.limit = null;
|
|
@@ -616,6 +620,7 @@ var Table = class _Table {
|
|
|
616
620
|
column,
|
|
617
621
|
alias: "sum"
|
|
618
622
|
};
|
|
623
|
+
clone.dml.orderBy = [];
|
|
619
624
|
clone.dml.columns = [`SUM(${column}) AS sum`];
|
|
620
625
|
clone.dml.data = null;
|
|
621
626
|
clone.dml.limit = 1;
|
|
@@ -648,6 +653,7 @@ var Table = class _Table {
|
|
|
648
653
|
column,
|
|
649
654
|
alias: "avg"
|
|
650
655
|
};
|
|
656
|
+
clone.dml.orderBy = [];
|
|
651
657
|
clone.dml.columns = [`AVG(${column}) AS avg`];
|
|
652
658
|
clone.dml.data = null;
|
|
653
659
|
clone.dml.limit = 1;
|
|
@@ -680,6 +686,7 @@ var Table = class _Table {
|
|
|
680
686
|
column,
|
|
681
687
|
alias: "max"
|
|
682
688
|
};
|
|
689
|
+
clone.dml.orderBy = [];
|
|
683
690
|
clone.dml.columns = [`MAX(${column}) AS max`];
|
|
684
691
|
clone.dml.data = null;
|
|
685
692
|
clone.dml.limit = 1;
|
|
@@ -712,6 +719,7 @@ var Table = class _Table {
|
|
|
712
719
|
column,
|
|
713
720
|
alias: "min"
|
|
714
721
|
};
|
|
722
|
+
clone.dml.orderBy = [];
|
|
715
723
|
clone.dml.columns = [`MIN(${column}) AS min`];
|
|
716
724
|
clone.dml.data = null;
|
|
717
725
|
clone.dml.limit = 1;
|
|
@@ -1284,6 +1292,7 @@ var Table = class _Table {
|
|
|
1284
1292
|
const localDML = dml ? dml : this.dml;
|
|
1285
1293
|
const computedFieldsNeeded = [];
|
|
1286
1294
|
let dependeciesArrray = [];
|
|
1295
|
+
const requestedColumns = new Set(localDML.columns ?? []);
|
|
1287
1296
|
if (this.computedFields.length > 0) {
|
|
1288
1297
|
let columns = localDML.columns;
|
|
1289
1298
|
for (const field of localDML.columns) {
|
|
@@ -1313,6 +1322,7 @@ var Table = class _Table {
|
|
|
1313
1322
|
if (response.status != 200) {
|
|
1314
1323
|
interceptor?.discard();
|
|
1315
1324
|
returnFormattedError(response.status, response.message);
|
|
1325
|
+
throw new Error(String(response.message));
|
|
1316
1326
|
}
|
|
1317
1327
|
await interceptor?.commit();
|
|
1318
1328
|
arrayResult = response.data;
|
|
@@ -1321,6 +1331,7 @@ var Table = class _Table {
|
|
|
1321
1331
|
const response = await this.engine.executeDml(newDML, this.txId ?? void 0);
|
|
1322
1332
|
if (response.status != 200) {
|
|
1323
1333
|
returnFormattedError(response.status, response.message);
|
|
1334
|
+
throw new Error(String(response.message));
|
|
1324
1335
|
}
|
|
1325
1336
|
const interceptor = await this.trigger.execute("after" + type, data);
|
|
1326
1337
|
await interceptor?.commit();
|
|
@@ -1330,6 +1341,7 @@ var Table = class _Table {
|
|
|
1330
1341
|
const response = await this.engine.executeDml(localDML, this.txId ?? void 0);
|
|
1331
1342
|
if (response.status != 200) {
|
|
1332
1343
|
returnFormattedError(response.status, response.message);
|
|
1344
|
+
throw new Error(String(response.message));
|
|
1333
1345
|
}
|
|
1334
1346
|
arrayResult = response.data;
|
|
1335
1347
|
}
|
|
@@ -1337,14 +1349,16 @@ var Table = class _Table {
|
|
|
1337
1349
|
const response = await this.engine.executeDml(localDML, this.txId ?? void 0);
|
|
1338
1350
|
if (response.status != 200) {
|
|
1339
1351
|
returnFormattedError(response.status, response.message);
|
|
1352
|
+
throw new Error(String(response.message));
|
|
1340
1353
|
}
|
|
1341
1354
|
arrayResult = response.data;
|
|
1342
1355
|
}
|
|
1343
1356
|
if (computedFieldsNeeded.length > 0) {
|
|
1344
1357
|
let newDataset = import_core2.ComputedFieldProcessor.computedFields(arrayResult, computedFieldsNeeded);
|
|
1358
|
+
const toRemove = dependeciesArrray.filter((key) => !requestedColumns.has(key));
|
|
1345
1359
|
const result = newDataset.map((obj) => {
|
|
1346
1360
|
const newObj = { ...obj };
|
|
1347
|
-
|
|
1361
|
+
toRemove.forEach((key) => delete newObj[key]);
|
|
1348
1362
|
return newObj;
|
|
1349
1363
|
});
|
|
1350
1364
|
return result;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lib/Database.ts","../src/lib/Trigger.ts"],"sourcesContent":["import { Table, Database } from './lib/Database';\nimport type {\n ComputedFieldConfig,\n DatabaseRecord,\n MutationInfo,\n PaginatedResult,\n RelationOptions,\n TriggerConfig,\n WhereCallback,\n} from './@types/Database';\n\nexport default Database;\nexport {\n Table,\n Database,\n type ComputedFieldConfig,\n type DatabaseRecord,\n type MutationInfo,\n type PaginatedResult,\n type RelationOptions,\n type TriggerConfig,\n type WhereCallback\n};\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { randomUUID } from 'crypto';\r\nimport { QueryEngine, ComputedFieldProcessor, TriggerProcessor } from \"@dbcube/core\";\r\nimport { ComputedFieldConfig, DatabaseRecord, DML, MutationInfo, PaginatedResult, RelationOptions, TriggerConfig, WhereCallback, WhereCondition } from \"../@types/Database\";\r\nimport { Trigger } from './Trigger';\r\n\r\n/**\r\n * Main class to handle MySQL database connections and queries.\r\n * Implements the Singleton pattern to ensure a single instance of the connection pool.\r\n */\r\nexport class Database {\r\n private name: string;\r\n private engine: QueryEngine;\r\n private computedFields: ComputedFieldConfig[];\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n\r\n constructor(name: string) {\r\n this.name = name;\r\n const engine = new QueryEngine(name);\r\n this.engine = engine;\r\n this.computedFields = [];\r\n this.triggers = [];\r\n }\r\n\r\n /**\r\n * Executes raw SQL (MySQL/PostgreSQL/SQLite) or a raw command document (MongoDB)\r\n * with bound parameters. The escape hatch for anything the builder doesn't cover.\r\n *\r\n * @example\r\n * const rows = await db.raw('SELECT * FROM users WHERE age > ?', [25]);\r\n * await db.raw('CREATE INDEX idx_users_email ON users(email)');\r\n */\r\n async raw<R = DatabaseRecord>(query: string, params: unknown[] = []): Promise<R[]> {\r\n const response = await this.engine.rawQuery(query, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Runs a callback inside a database transaction. Everything executed through\r\n * the received connection is committed atomically; any thrown error rolls\r\n * the whole transaction back.\r\n *\r\n * Requires daemon mode (enabled by default with an up-to-date query-engine).\r\n *\r\n * @example\r\n * await db.transaction(async (trx) => {\r\n * await trx.table('accounts').where('id', '=', 1).update({ balance: 50 });\r\n * await trx.table('accounts').where('id', '=', 2).update({ balance: 150 });\r\n * });\r\n */\r\n async transaction<T>(callback: (trx: Database) => Promise<T>): Promise<T> {\r\n const txId: string = await this.engine.beginTransaction();\r\n\r\n const trx = new Database(this.name);\r\n trx.engine = this.engine;\r\n trx.computedFields = this.computedFields;\r\n trx.triggers = this.triggers;\r\n trx.txId = txId;\r\n\r\n try {\r\n const result = await callback(trx);\r\n await this.engine.commitTransaction(txId);\r\n return result;\r\n } catch (error) {\r\n try {\r\n await this.engine.rollbackTransaction(txId);\r\n } catch (rollbackError: any) {\r\n // El error original manda, pero un rollback fallido no puede\r\n // pasar en silencio: la transacción puede seguir reteniendo\r\n // locks hasta que el daemon la expire por inactividad.\r\n console.error(\r\n `[dbcube] Rollback of transaction ${txId} failed: ${rollbackError?.message ?? rollbackError}`\r\n );\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async useComputes(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayComputedFields = await ComputedFieldProcessor.getComputedFields(this.name);\r\n newDatabase.setComputedFields(arrayComputedFields);\r\n return newDatabase;\r\n }\r\n\r\n async useTriggers(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayTriggers = await TriggerProcessor.getTriggers(this.name);\r\n newDatabase.setTriggers(arrayTriggers);\r\n return newDatabase;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n const response = await this.engine.run('query_engine', [\r\n '--action', 'connect',\r\n ]);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n await this.engine.run('query_engine', [\r\n '--action', 'disconnect',\r\n ]);\r\n }\r\n\r\n /**\r\n * Creates and returns a new instance of `Table` for the specified table.\r\n * This method is used to start building queries for a specific table.\r\n * It provides a fluent interface for common database operations like select, insert, update, and delete.\r\n *\r\n * @param {string} tableName - The name of the table to query.\r\n * @returns {Table} - Returns a new instance of `Table` for the specified table.\r\n *\r\n * @example\r\n * // Select all records from a table\r\n * const users = await db.table('users').get();\r\n * \r\n * // Select records with conditions\r\n * const activeUsers = await db.table('users')\r\n * .where('status', '=', 'active')\r\n * .orderBy('created_at', 'DESC')\r\n * .limit(10)\r\n * .get();\r\n * \r\n * // Insert records\r\n * await db.table('users').insert([\r\n * { name: 'John', email: 'john@example.com', age: 30 }\r\n * ]);\r\n * \r\n * // Update records\r\n * await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ status: 'inactive' });\r\n * \r\n * // Delete records\r\n * await db.table('users')\r\n * .where('status', '=', 'deleted')\r\n * .delete();\r\n * \r\n * // Access column management\r\n * const columns = await db.table('users').columns().get();\r\n */\r\n table<T extends DatabaseRecord = DatabaseRecord>(tableName: string): Table<T> {\r\n return new Table<T>(this, this.name, tableName, this.engine, this.computedFields, this.triggers, this.txId);\r\n }\r\n\r\n private setComputedFields(computedFields: ComputedFieldConfig[]){\r\n this.computedFields = computedFields;\r\n }\r\n\r\n private setTriggers(triggers: TriggerConfig[]){\r\n this.triggers = triggers;\r\n }\r\n}\r\n\r\n/**\r\n * Class to build and execute SQL queries for a specific table.\r\n * Supports operations like SELECT, INSERT, UPDATE, DELETE, and more.\r\n *\r\n * Generic over the row shape: `db.table<User>('users').get()` resolves to\r\n * `Promise<User[]>`. Pair it with the interfaces emitted by `dbcube generate`.\r\n */\r\nexport class Table<T extends DatabaseRecord = DatabaseRecord> {\r\n private engine: QueryEngine;\r\n private nextType: 'AND' | 'OR' = 'AND';\r\n private dml: DML;\r\n private computedFields: ComputedFieldConfig[] = [];\r\n private trigger: Trigger;\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n private relations: { name: string; options: RelationOptions }[] = [];\r\n /** Builders de grupo mutan en sitio (ver clone()) */\r\n private _mutable = false;\r\n\r\n private instance: Database;\r\n\r\n constructor(instance: Database, databaseName: string, tableName: string, engine: QueryEngine, computedFields: ComputedFieldConfig[] = [], triggers: TriggerConfig[] = [], txId: string | null = null) {\r\n this.engine = engine;\r\n this.instance = instance;\r\n this.computedFields = computedFields;\r\n this.triggers = triggers;\r\n this.trigger = new Trigger(instance, databaseName, triggers);\r\n this.nextType = 'AND';\r\n this.txId = txId;\r\n\r\n this.dml = {\r\n type: 'select',\r\n database: databaseName,\r\n table: tableName,\r\n columns: ['*'],\r\n distinct: false,\r\n joins: [],\r\n where: [],\r\n orderBy: [],\r\n groupBy: [],\r\n limit: null,\r\n offset: null,\r\n data: null,\r\n aggregation: null,\r\n having: []\r\n };\r\n }\r\n\r\n /**\r\n * Specifies the columns to select in a SELECT query.\r\n *\r\n * @param {string[]} fields - Array of column names to select. If empty, selects all columns.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').select(['id', 'name']).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n select(fields: string[] = []): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = fields.length > 0 ? fields : ['*'];\r\n clone.dml.aggregation = null;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).get();\r\n * const nullUsers = await db.table('users').where('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n where(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n where(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n where(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an OR WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).orWhere('name', '=', 'Jane').get();\r\n * const nullUsers = await db.table('users').where('active', '=', true).orWhere('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n orWhere(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n orWhere(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n orWhere(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'OR',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a grouped WHERE condition to the query.\r\n *\r\n * @param {WhereCallback} callback - A callback function that receives a new Table instance to build the grouped conditions.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereGroup(query => {\r\n * query.where('age', '>', 25).orWhere('name', '=', 'Jane');\r\n * }).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereGroup(callback: WhereCallback): Table<T> {\r\n const clone = this.clone();\r\n const groupQuery = new Table(this.instance, clone.dml.database, clone.dml.table, clone.engine);\r\n // El callback encadena sin usar el valor de retorno; el builder del\r\n // grupo debe mutar en sitio o las condiciones se perderían en clones\r\n groupQuery._mutable = true;\r\n callback(groupQuery);\r\n\r\n clone.dml.where.push({\r\n type: clone.nextType,\r\n isGroup: true,\r\n conditions: groupQuery.dml.where as WhereCondition[]\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n or(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'OR';\r\n return clone;\r\n }\r\n\r\n and(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE BETWEEN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {[any, any]} values - A tuple with two values representing the range.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereBetween('age', [20, 30]).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereBetween(column: string, values: [any, any]): Table<T> {\r\n const clone = this.clone();\r\n const [value1, value2] = values;\r\n if (value1 !== undefined && value2 !== undefined) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'BETWEEN',\r\n value: [value1, value2],\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {any[]} values - An array of values to match.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereIn('id', [1, 2]).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n whereIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNull('email').get();\r\n * console.log(users); // [{ id: 3, name: 'Alice', email: null }]\r\n */\r\n whereNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NOT NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotNull('email').get();\r\n * console.log(users); // [{ id: 1, name: 'John', email: 'john@example.com' }]\r\n */\r\n whereNotNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NOT NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').join('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }]\r\n */\r\n join(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'INNER',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a LEFT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').leftJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: 2, name: 'Jane', order_id: null }]\r\n */\r\n leftJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'LEFT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a RIGHT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').rightJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: null, name: null, order_id: 102 }]\r\n */\r\n rightJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'RIGHT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an ORDER BY clause to the query.\r\n *\r\n * @param {string} column - The column to order by.\r\n * @param {'ASC' | 'DESC'} direction - The sorting direction ('ASC' or 'DESC').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').orderBy('name', 'ASC').get();\r\n * console.log(users); // [{ id: 2, name: 'Jane' }, { id: 1, name: 'John' }]\r\n */\r\n orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): Table<T> {\r\n const clone = this.clone();\r\n const validDirections: ('ASC' | 'DESC')[] = ['ASC', 'DESC'];\r\n if (validDirections.includes(direction.toUpperCase() as 'ASC' | 'DESC')) {\r\n clone.dml.orderBy.push({\r\n column,\r\n direction: direction.toUpperCase() as 'ASC' | 'DESC'\r\n });\r\n } else {\r\n throw new Error(`Invalid direction: ${direction}. Use 'ASC' or 'DESC'.`);\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a GROUP BY clause to the query.\r\n *\r\n * @param {string} column - The column to group by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').groupBy('age').get();\r\n * console.log(users); // [{ age: 30, count: 1 }, { age: 25, count: 1 }]\r\n */\r\n groupBy(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.groupBy.push(column);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a DISTINCT clause to the query.\r\n *\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').distinct().select(['name']).get();\r\n * console.log(users); // [{ name: 'John' }, { name: 'Jane' }]\r\n */\r\n distinct(): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.distinct = true;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a COUNT clause to the query.\r\n *\r\n * @param {string} column - The column to count (default is '*').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const count = await db.table('users').count().first();\r\n * console.log(count); // { count: 2 }\r\n */\r\n async count(column: string = '*'): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'COUNT',\r\n column,\r\n alias: 'count'\r\n }\r\n clone.dml.columns = [`COUNT(${column}) AS count`];\r\n clone.dml.data = null;\r\n clone.dml.limit = null; // Remover limit para contar todos\r\n clone.dml.offset = null; // Remover offset también\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.count;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a SUM clause to the query.\r\n *\r\n * @param {string} column - The column to sum.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const totalAge = await db.table('users').sum('age').first();\r\n * console.log(totalAge); // { sum: 55 }\r\n */\r\n async sum(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'SUM',\r\n column,\r\n alias: 'sum'\r\n }\r\n clone.dml.columns = [`SUM(${column}) AS sum`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.sum;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds an AVG clause to the query.\r\n *\r\n * @param {string} column - The column to calculate the average.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const avgAge = await db.table('users').avg('age').first();\r\n * console.log(avgAge); // { avg: 27.5 }\r\n */\r\n async avg(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'AVG',\r\n column,\r\n alias: 'avg'\r\n }\r\n clone.dml.columns = [`AVG(${column}) AS avg`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.avg;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MAX clause to the query.\r\n *\r\n * @param {string} column - The column to find the maximum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const maxAge = await db.table('users').max('age').first();\r\n * console.log(maxAge); // { max: 30 }\r\n */\r\n async max(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MAX',\r\n column,\r\n alias: 'max'\r\n }\r\n clone.dml.columns = [`MAX(${column}) AS max`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.max;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MIN clause to the query.\r\n *\r\n * @param {string} column - The column to find the minimum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const minAge = await db.table('users').min('age').first();\r\n * console.log(minAge); // { min: 25 }\r\n */\r\n async min(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MIN',\r\n column,\r\n alias: 'min'\r\n }\r\n clone.dml.columns = [`MIN(${column}) AS min`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.min;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the column names of the table.\r\n * For SQL databases (MySQL, PostgreSQL, SQLite), returns a simple array of column names.\r\n * For MongoDB, returns a hierarchical structure with nested documents.\r\n *\r\n * @returns {Promise<string[] | any>} - Returns an array of column names for SQL databases,\r\n * or a hierarchical structure for MongoDB.\r\n *\r\n * @example\r\n * // SQL databases (MySQL, PostgreSQL, SQLite)\r\n * const columns = await db.table('users').columns();\r\n * console.log(columns); // ['id', 'name', 'email', 'age', 'created_at']\r\n *\r\n * @example\r\n * // MongoDB\r\n * const structure = await db.table('users').columns();\r\n * console.log(structure);\r\n * // {\r\n * // columns: ['id', 'name', 'profile'],\r\n * // submenu: {\r\n * // profile: {\r\n * // columns: ['age', 'city'],\r\n * // submenu: {}\r\n * // }\r\n * // }\r\n * // }\r\n */\r\n async columns(): Promise<string[] | any> {\r\n const clone = this.clone();\r\n clone.dml.type = 'columns';\r\n clone.dml.columns = [];\r\n clone.dml.where = [];\r\n clone.dml.orderBy = [];\r\n clone.dml.groupBy = [];\r\n clone.dml.limit = null;\r\n clone.dml.offset = null;\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n\r\n try {\r\n const result = await clone.getResponse();\r\n\r\n if (Array.isArray(result) && result.length > 0) {\r\n // Verificar si es MongoDB (estructura jerárquica)\r\n if (result[0].columns && result[0].submenu !== undefined) {\r\n // MongoDB: devolver la estructura completa\r\n return result[0];\r\n }\r\n\r\n // SQL databases: transformar a array simple de strings\r\n return result.map((row: any) => row.column_name || row.Field || row.name);\r\n }\r\n\r\n return [];\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a LIMIT clause to the query.\r\n *\r\n * @param {number} number - The maximum number of rows to return.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n limit(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.limit = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds pagination to the query using LIMIT and OFFSET.\r\n *\r\n * @param {number} number - The page number (starting from 1).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).page(2).get();\r\n * console.log(users); // [{ id: 2, name: 'Jane', age: 25 }]\r\n */\r\n page(number: number): Table<T> {\r\n const clone = this.clone();\r\n const pageNum = Number(number);\r\n if (clone.dml.limit) {\r\n clone.dml.offset = (pageNum - 1) * clone.dml.limit;\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Executes the query and returns all matching rows.\r\n *\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of rows.\r\n *\r\n * @example\r\n * const users = await db.table('users').get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n async get(): Promise<T[]> {\r\n try {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n const result = await clone.getResponse();\r\n if (this.relations.length > 0 && Array.isArray(result)) {\r\n return await this.attachRelations(result) as T[];\r\n }\r\n return result as T[];\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Executes the query and returns the first matching row.\r\n *\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').first();\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async first(): Promise<T | null> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Finds a row by a specific column value.\r\n *\r\n * @param {any} value - The value to search for.\r\n * @param {string} column - The column to search in (default is 'id').\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first matching row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').find(1);\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async find(value: string | number, column: string = 'id'): Promise<T | null> {\r\n // where() is immutable: reassign the clone or the condition is lost\r\n const clone = this.clone().where(column, '=', value);\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Inserts one or more rows into the table.\r\n *\r\n * @param {DatabaseRecord[]} data - An array of objects representing the rows to insert.\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of the inserted rows.\r\n *\r\n * @example\r\n * const newUsers = await db.table('users').insert([\r\n * { name: 'Alice', age: 28 },\r\n * { name: 'Bob', age: 32 }\r\n * ]);\r\n * console.log(newUsers); // [{ id: 3, name: 'Alice', age: 28 }, { id: 4, name: 'Bob', age: 32 }]\r\n */\r\n async insert(data: Partial<T>[]): Promise<T[]> {\r\n const clone = this.clone();\r\n if (!Array.isArray(data)) {\r\n throw new Error('The insert method requires an array of objects with key-value pairs.');\r\n }\r\n\r\n if (!data.every(item => typeof item === 'object' && item !== null)) {\r\n throw new Error('The array must contain only valid objects.');\r\n }\r\n\r\n clone.dml.type = 'insert';\r\n clone.dml.data = data;\r\n\r\n const result = await clone.getResponse(clone.dml, 'Add');\r\n\r\n return result ?? data;\r\n }\r\n\r\n /**\r\n * Updates rows in the table based on the defined conditions.\r\n *\r\n * @param {DatabaseRecord} data - An object with key-value pairs representing the fields to update.\r\n * @returns {Promise<any>} - Returns the result of the update operation.\r\n *\r\n * @example\r\n * const result = await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ name: 'John Updated', age: 31 });\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async update(data: Partial<T>): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (typeof data !== 'object' || Array.isArray(data)) {\r\n throw new Error('The update method requires an object with key-value pairs.');\r\n }\r\n\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an update.');\r\n }\r\n\r\n clone.dml.type = 'update';\r\n clone.dml.data = data;\r\n\r\n return clone.getResponse(clone.dml, 'Update');\r\n }\r\n\r\n /**\r\n * Deletes rows from the table based on the defined conditions.\r\n *\r\n * @returns {Promise<any>} - Returns the result of the delete operation.\r\n *\r\n * @example\r\n * const result = await db.table('users').where('id', '=', 1).delete();\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async delete(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform a delete.');\r\n }\r\n\r\n clone.dml.type = 'delete';\r\n\r\n const deleteData = await clone.getResponse(clone.dml, 'Delete');\r\n return deleteData;\r\n }\r\n\r\n /**\r\n * Adds a WHERE NOT IN condition to the query.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotIn('status', ['banned', 'deleted']).get();\r\n */\r\n whereNotIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'NOT IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Sets an explicit OFFSET for the query (alternative to page()).\r\n *\r\n * @example\r\n * const rows = await db.table('logs').orderBy('id', 'ASC').limit(50).offset(100).get();\r\n */\r\n offset(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.offset = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Appends raw expressions to the SELECT list (aggregates, functions, aliases).\r\n * Combine with groupBy() and having() for per-group metrics.\r\n *\r\n * @example\r\n * const stats = await db.table('orders')\r\n * .select(['user_id'])\r\n * .selectRaw(['COUNT(*) AS order_count', 'SUM(amount) AS total'])\r\n * .groupBy('user_id')\r\n * .having('order_count', '>', 5)\r\n * .get();\r\n */\r\n selectRaw(expressions: string[]): Table<T> {\r\n const clone = this.clone();\r\n if (clone.dml.columns.length === 1 && clone.dml.columns[0] === '*') {\r\n clone.dml.columns = [...expressions];\r\n } else {\r\n clone.dml.columns = [...clone.dml.columns, ...expressions];\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a HAVING condition (filters grouped results).\r\n *\r\n * @example\r\n * .groupBy('user_id').having('COUNT(*)', '>', 5)\r\n */\r\n having(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.having = clone.dml.having ?? [];\r\n clone.dml.having.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'AND',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Checks if at least one row matches the current conditions.\r\n * Cheaper than first(): selects a constant with LIMIT 1.\r\n *\r\n * @example\r\n * const taken = await db.table('users').where('email', '=', email).exists();\r\n */\r\n async exists(): Promise<boolean> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = ['1 AS dbcube_exists'];\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n clone.dml.offset = null;\r\n const result = await clone.getResponse();\r\n return Array.isArray(result) && result.length > 0;\r\n }\r\n\r\n /**\r\n * Fetches one page of results plus pagination metadata in a single call.\r\n * Runs the page query and the total count with the same conditions.\r\n *\r\n * @example\r\n * const { items, total, totalPages, hasNext } = await db.table('products')\r\n * .where('published', '=', true)\r\n * .orderBy('id', 'ASC')\r\n * .paginate(2, 25);\r\n */\r\n async paginate(page: number = 1, perPage: number = 20): Promise<PaginatedResult<T>> {\r\n const pageNum = Math.max(1, Number(page));\r\n const size = Math.max(1, Number(perPage));\r\n\r\n const itemsQuery = this.limit(size).page(pageNum);\r\n const [items, total] = await Promise.all([\r\n itemsQuery.get(),\r\n this.count()\r\n ]);\r\n\r\n const totalNum = Number(total);\r\n const totalPages = Math.ceil(totalNum / size);\r\n return {\r\n items,\r\n page: pageNum,\r\n perPage: size,\r\n total: totalNum,\r\n totalPages,\r\n hasNext: pageNum < totalPages,\r\n hasPrev: pageNum > 1,\r\n };\r\n }\r\n\r\n /**\r\n * Processes all matching rows in batches of `size`, keeping memory flat.\r\n * Return `false` from the callback to stop early.\r\n *\r\n * @example\r\n * await db.table('logs').orderBy('id', 'ASC').chunk(500, async (rows) => {\r\n * await processBatch(rows);\r\n * });\r\n */\r\n async chunk(size: number, callback: (rows: T[], page: number) => Promise<void | boolean> | void | boolean): Promise<void> {\r\n const batchSize = Math.max(1, Number(size));\r\n let page = 1;\r\n while (true) {\r\n const rows = await this.limit(batchSize).page(page).get();\r\n if (rows.length === 0) break;\r\n const result = await callback(rows, page);\r\n if (result === false) break;\r\n if (rows.length < batchSize) break;\r\n page++;\r\n }\r\n }\r\n\r\n /**\r\n * Atomically increments a numeric column: `SET col = col + amount`.\r\n * Requires at least one WHERE condition. Extra fields can be updated in the same statement.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).increment('stock', 3);\r\n * await db.table('posts').where('id', '=', 1).increment('views', 1, { last_viewed_at: new Date().toISOString() });\r\n */\r\n async increment(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an increment.');\r\n }\r\n clone.dml.type = 'update';\r\n clone.dml.data = { ...extra, [column]: { $inc: Number(amount) } };\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Atomically decrements a numeric column: `SET col = col - amount`.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).decrement('stock', 1);\r\n */\r\n async decrement(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n return this.increment(column, -Math.abs(Number(amount)), extra);\r\n }\r\n\r\n /**\r\n * Deletes ALL rows from the table. The only write operation allowed\r\n * without a WHERE — the destructive intent is explicit in the name.\r\n *\r\n * @example\r\n * await db.table('temp_imports').truncate();\r\n */\r\n async truncate(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n clone.dml.type = 'delete';\r\n clone.dml.where = [];\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Inserts rows, updating them instead when a conflict occurs on the given keys.\r\n * MySQL → ON DUPLICATE KEY UPDATE · PostgreSQL/SQLite → ON CONFLICT ... DO UPDATE.\r\n *\r\n * @param data Rows to insert.\r\n * @param conflictKeys Column(s) with the UNIQUE/PK constraint that triggers the update.\r\n * @param updateColumns Columns to overwrite on conflict (defaults to every non-conflict column).\r\n *\r\n * @example\r\n * await db.table('settings').upsert(\r\n * [{ key: 'theme', value: 'dark' }],\r\n * ['key']\r\n * );\r\n */\r\n async upsert(data: Partial<T>[], conflictKeys: string[], updateColumns?: string[]): Promise<MutationInfo[]> {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n throw new Error('The upsert method requires a non-empty array of objects.');\r\n }\r\n if (!Array.isArray(conflictKeys) || conflictKeys.length === 0) {\r\n throw new Error('The upsert method requires at least one conflict key column.');\r\n }\r\n\r\n const motor: string = this.engine?.getConfig?.()?.type ?? 'mysql';\r\n\r\n const table = this.dml.table;\r\n const columns = Object.keys(data[0]);\r\n const targets = updateColumns ?? columns.filter(c => !conflictKeys.includes(c));\r\n\r\n // Único método que arma la operación en JS: validar identificadores\r\n // porque las claves de los objetos pueden venir de input externo\r\n assertValidIdentifier(table, 'table');\r\n for (const c of columns) assertValidIdentifier(c, 'column');\r\n for (const c of conflictKeys) assertValidIdentifier(c, 'conflict key');\r\n for (const c of targets) assertValidIdentifier(c, 'update column');\r\n\r\n if (motor === 'mongodb') {\r\n // Comando `update` nativo con upsert:true por fila — misma semántica\r\n // que ON CONFLICT: matchea por conflictKeys, actualiza solo targets,\r\n // y al insertar escribe la fila completa.\r\n const updates = data.map(row => {\r\n const q: Record<string, unknown> = {};\r\n for (const k of conflictKeys) q[k] = row[k];\r\n\r\n const set: Record<string, unknown> = {};\r\n for (const c of targets) if (c in row) set[c] = row[c];\r\n\r\n const setOnInsert: Record<string, unknown> = {};\r\n for (const c of columns) {\r\n if (!targets.includes(c) && !conflictKeys.includes(c)) setOnInsert[c] = row[c];\r\n }\r\n if (!('uuid' in row)) setOnInsert['uuid'] = randomUUID();\r\n\r\n const u: Record<string, unknown> = {};\r\n if (Object.keys(set).length) u['$set'] = set;\r\n if (Object.keys(setOnInsert).length) u['$setOnInsert'] = setOnInsert;\r\n\r\n return { q, u, upsert: true, multi: false };\r\n });\r\n\r\n const command = JSON.stringify({ update: table, updates });\r\n const response = await this.engine.rawQuery(command, [], this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n const quote = (id: string) => motor === 'mysql' ? `\\`${id}\\`` : `\"${id}\"`;\r\n\r\n const params: any[] = [];\r\n const placeholder = () => motor === 'postgres' || motor === 'postgresql'\r\n ? `$${params.length}`\r\n : '?';\r\n\r\n const rowsSql = data.map(row => {\r\n const cells = columns.map(col => {\r\n params.push(row[col] === undefined ? null : row[col]);\r\n return placeholder();\r\n });\r\n return `(${cells.join(', ')})`;\r\n }).join(', ');\r\n\r\n const colsSql = columns.map(quote).join(', ');\r\n let sql: string;\r\n\r\n if (motor === 'mysql') {\r\n const updates = targets.map(c => `${quote(c)} = VALUES(${quote(c)})`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON DUPLICATE KEY UPDATE ${updates}`;\r\n } else {\r\n const conflict = conflictKeys.map(quote).join(', ');\r\n const updates = targets.map(c => `${quote(c)} = excluded.${quote(c)}`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON CONFLICT (${conflict}) DO UPDATE SET ${updates}`;\r\n }\r\n\r\n if (motor === 'sqlite') {\r\n // SQLite pool schema sync: ensure every pooled connection sees constraints\r\n // created moments ago (e.g. a UNIQUE index added right before this upsert).\r\n await this.engine.rawQuery('SELECT name FROM sqlite_master LIMIT 1', [], this.txId ?? undefined);\r\n }\r\n const response = await this.engine.rawQuery(sql, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Declares a relation to eager-load with the results of get().\r\n * Relations are resolved from `foreign` definitions in your .cube files,\r\n * or explicitly via options. Loads each relation with ONE batched query\r\n * (whereIn) — no N+1.\r\n *\r\n * @example\r\n * // hasMany: orders.user_id → users.id (auto-detected from orders.table.cube)\r\n * const users = await db.table('users').with('orders').get();\r\n * // users[0].orders === [{...}, {...}]\r\n *\r\n * // belongsTo: posts.author_id → users.id, attached as a single object\r\n * const posts = await db.table('posts')\r\n * .with('author', { table: 'users', foreignKey: 'author_id', type: 'one' })\r\n * .get();\r\n */\r\n with(relation: string, options: RelationOptions = {}): Table<T> {\r\n const clone = this.clone();\r\n clone.relations.push({ name: relation, options });\r\n return clone;\r\n }\r\n\r\n private async attachRelations(rows: DatabaseRecord[]): Promise<DatabaseRecord[]> {\r\n if (rows.length === 0 || this.relations.length === 0) return rows;\r\n\r\n for (const { name, options } of this.relations) {\r\n const relatedTable = options.table ?? name;\r\n const cubeMeta = loadCubeRelations();\r\n\r\n // Detect direction + keys from .cube foreign metadata when not explicit\r\n let type = options.type;\r\n let foreignKey = options.foreignKey;\r\n let localKey = options.localKey ?? 'id';\r\n\r\n if (!foreignKey || !type) {\r\n const childFks = cubeMeta[relatedTable]?.foreigns ?? [];\r\n const ownFks = cubeMeta[this.dml.table]?.foreigns ?? [];\r\n const childToParent = childFks.find(fk => fk.table === this.dml.table);\r\n const parentToChild = ownFks.find(fk => fk.table === relatedTable);\r\n\r\n if (childToParent) {\r\n // hasMany: the related table points at us\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? childToParent.column_name;\r\n localKey = options.localKey ?? childToParent.column;\r\n } else if (parentToChild) {\r\n // belongsTo: we point at the related table\r\n type = type ?? 'one';\r\n foreignKey = foreignKey ?? parentToChild.column_name;\r\n localKey = options.localKey ?? parentToChild.column;\r\n } else {\r\n // Heuristic fallback: <singular-parent>_id on the child table\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? `${singularize(this.dml.table)}_id`;\r\n }\r\n }\r\n\r\n const relatedQuery = new Table(this.instance, this.dml.database, relatedTable, this.engine, this.computedFields, this.triggers, this.txId);\r\n\r\n if (type === 'one') {\r\n // belongsTo: FK lives on THIS table, match related.localKey\r\n const fkValues = [...new Set(rows.map(r => r[foreignKey!]).filter(v => v !== null && v !== undefined))];\r\n const related = fkValues.length > 0\r\n ? await relatedQuery.whereIn(localKey, fkValues).get()\r\n : [];\r\n const index = new Map(related.map(r => [r[localKey], r]));\r\n for (const row of rows) {\r\n row[name] = index.get(row[foreignKey!]) ?? null;\r\n }\r\n } else {\r\n // hasMany: FK lives on the RELATED table, match this.localKey\r\n const ids = [...new Set(rows.map(r => r[localKey]).filter(v => v !== null && v !== undefined))];\r\n const related = ids.length > 0\r\n ? await relatedQuery.whereIn(foreignKey!, ids).get()\r\n : [];\r\n const groups = new Map<any, DatabaseRecord[]>();\r\n for (const rel of related) {\r\n const key = rel[foreignKey!];\r\n if (!groups.has(key)) groups.set(key, []);\r\n groups.get(key)!.push(rel);\r\n }\r\n for (const row of rows) {\r\n row[name] = groups.get(row[localKey]) ?? [];\r\n }\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n private async getResponse(dml: any = null, type: any = null): Promise<any> {\r\n const localDML = dml ? dml : this.dml;\r\n const computedFieldsNeeded: any[] = [];\r\n let dependeciesArrray: any[] = [];\r\n\r\n if (this.computedFields.length > 0) {\r\n let columns = localDML.columns;\r\n\r\n for (const field of localDML.columns) {\r\n const computedField = this.computedFields.find(cf => cf.column === field);\r\n\r\n if (computedField) {\r\n computedFieldsNeeded.push(computedField);\r\n // Add dependencies to real fields\r\n const dependencies = ComputedFieldProcessor.extractDependencies(computedField.instruction);\r\n dependeciesArrray = [...dependeciesArrray, ...dependencies];\r\n columns = Array.from(new Set([...columns, ...dependencies]));\r\n columns = columns.filter((col: string) => col != field);\r\n }\r\n }\r\n localDML.columns = columns;\r\n }\r\n\r\n let arrayResult = [];\r\n if (type) {\r\n const beffore = this.trigger.get('before' + type);\r\n const after = this.trigger.get('after' + type);\r\n if (this.triggers.length > 0 && (beffore || after)) {\r\n const dataset = localDML.data;\r\n for (let index = 0; index < dataset.length; index++) {\r\n const data = dataset[index];\r\n const newDML = { ...localDML, data: [data] };\r\n if (beffore) {\r\n const interceptor = await this.trigger.execute('before' + type, data);\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n interceptor?.discard();\r\n returnFormattedError(response.status, response.message);\r\n }\r\n await interceptor?.commit();\r\n arrayResult = response.data;\r\n }\r\n if (after) {\r\n\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n const interceptor = await this.trigger.execute('after' + type, data);\r\n await interceptor?.commit();\r\n }\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n\r\n if (computedFieldsNeeded.length > 0) {\r\n let newDataset: any = ComputedFieldProcessor.computedFields(arrayResult, computedFieldsNeeded);\r\n const result = newDataset.map((obj: any) => {\r\n const newObj = { ...obj };\r\n dependeciesArrray.forEach(key => delete newObj[key]);\r\n return newObj;\r\n });\r\n return result;\r\n }\r\n return arrayResult;\r\n }\r\n\r\n private clone(): Table<T> {\r\n // Los builders de grupo (whereGroup) son mutables: el callback encadena\r\n // sin usar el valor de retorno, así que clonar perdería las condiciones\r\n if (this._mutable) return this;\r\n const cloned = Object.create(Object.getPrototypeOf(this));\r\n cloned.engine = this.engine;\r\n cloned.instance = this.instance;\r\n cloned.nextType = this.nextType;\r\n cloned.computedFields = this.computedFields;\r\n cloned.trigger = this.trigger;\r\n cloned.triggers = this.triggers;\r\n cloned.txId = this.txId;\r\n cloned.relations = [...this.relations];\r\n\r\n cloned.dml = {\r\n ...this.dml,\r\n columns: [...this.dml.columns],\r\n joins: [...this.dml.joins],\r\n where: [...this.dml.where],\r\n orderBy: [...this.dml.orderBy],\r\n groupBy: [...this.dml.groupBy],\r\n having: [...(this.dml.having ?? [])],\r\n // Clonar propiedades que faltaban para evitar mutación compartida\r\n data: this.dml.data ? (Array.isArray(this.dml.data) ? [...this.dml.data] : { ...this.dml.data }) : null,\r\n aggregation: this.dml.aggregation ? { ...this.dml.aggregation } : null\r\n };\r\n return cloned;\r\n }\r\n\r\n}\r\n\r\n// ---- Cube relation metadata (cached scan of dbcube/*.table.cube) ----\r\n\r\ninterface CubeForeign {\r\n column_name: string; // FK column on the owning table\r\n table: string; // referenced table\r\n column: string; // referenced column\r\n}\r\n\r\nlet cubeRelationsCache: Record<string, { foreigns: CubeForeign[] }> | null = null;\r\n\r\nfunction loadCubeRelations(): Record<string, { foreigns: CubeForeign[] }> {\r\n if (cubeRelationsCache) return cubeRelationsCache;\r\n const result: Record<string, { foreigns: CubeForeign[] }> = {};\r\n\r\n const scanDir = (dir: string) => {\r\n let entries: fs.Dirent[];\r\n try {\r\n entries = fs.readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const entry of entries) {\r\n const full = path.join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n if (entry.name !== 'node_modules' && entry.name !== 'triggers' && entry.name !== 'logs') {\r\n scanDir(full);\r\n }\r\n } else if (entry.name.endsWith('.table.cube')) {\r\n try {\r\n const content = fs.readFileSync(full, 'utf8');\r\n const nameMatch = content.match(/@meta\\s*\\(\\s*\\{[\\s\\S]*?name\\s*:\\s*\"([^\"]+)\"/);\r\n const tableName = nameMatch ? nameMatch[1] : path.basename(entry.name, '.table.cube');\r\n\r\n const foreigns: CubeForeign[] = [];\r\n const colRegex = /(\\w+)\\s*:\\s*\\{(?:[^{}]|\\{[^{}]*\\})*?foreign\\s*:\\s*\\{([^}]*)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = colRegex.exec(content)) !== null) {\r\n const fkTable = m[2].match(/table\\s*:\\s*\"([^\"]+)\"/);\r\n const fkColumn = m[2].match(/column\\s*:\\s*\"([^\"]+)\"/);\r\n if (fkTable) {\r\n foreigns.push({\r\n column_name: m[1],\r\n table: fkTable[1],\r\n column: fkColumn ? fkColumn[1] : 'id',\r\n });\r\n }\r\n }\r\n result[tableName] = { foreigns };\r\n } catch { /* unreadable cube — skip */ }\r\n }\r\n }\r\n };\r\n\r\n scanDir(path.join(process.cwd(), 'dbcube'));\r\n cubeRelationsCache = result;\r\n return result;\r\n}\r\n\r\nfunction assertValidIdentifier(name: string, kind: string): void {\r\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\r\n throw new Error(`Invalid ${kind} name: '${name}'. Only letters, numbers and underscore are allowed.`);\r\n }\r\n}\r\n\r\nfunction singularize(word: string): string {\r\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\r\n if (word.endsWith('ses')) return word.slice(0, -2);\r\n if (word.endsWith('s') && !word.endsWith('ss')) return word.slice(0, -1);\r\n return word;\r\n}\r\n\r\nfunction returnFormattedError(status: number, message: string) {\r\n const RESET = '\\x1b[0m';\r\n const RED = '\\x1b[31m';\r\n const YELLOW = '\\x1b[33m';\r\n const BOLD = '\\x1b[1m';\r\n const CYAN = '\\x1b[36m';\r\n const GRAY = '\\x1b[90m';\r\n const UNDERLINE = '\\x1b[4m';\r\n const MAGENTA = '\\x1b[35m';\r\n\r\n let output = '';\r\n let help = '';\r\n const color = status === 600 ? YELLOW : RED;\r\n\r\n\r\n if (message.includes(\"[help]\")) {\r\n const parts = message.split(\"[help]\");\r\n output += `\\n${RED}${BOLD}${parts[0]}${RESET}`;\r\n help += `\\n${MAGENTA}${BOLD}[help]${RESET} ${GRAY}${parts[1]}${RESET}\\n`;\r\n } else {\r\n output += `\\n${color}${BOLD}${message}${RESET}\\n`;\r\n }\r\n\r\n const err = new Error();\r\n const stackLines = err.stack?.split('\\n') || [];\r\n\r\n // Buscamos la primera línea del stack fuera de node_modules\r\n const relevantStackLine = stackLines.find(line =>\r\n line.includes('.js:') && !line.includes('node_modules')\r\n );\r\n\r\n if (relevantStackLine) {\r\n const match = relevantStackLine.match(/\\((.*):(\\d+):(\\d+)\\)/) ||\r\n relevantStackLine.match(/at (.*):(\\d+):(\\d+)/);\r\n\r\n if (match) {\r\n const [, filePath, lineStr, columnStr] = match;\r\n const lineNum = parseInt(lineStr, 10);\r\n const errorLocation = `${filePath}:${lineStr}:${columnStr}`;\r\n\r\n // Leemos el archivo y sacamos las líneas relevantes\r\n try {\r\n const codeLines = fs.readFileSync(filePath, 'utf-8').split('\\n');\r\n const start = Math.max(0, lineNum - 3);\r\n const end = Math.min(codeLines.length, lineNum + 2);\r\n\r\n output += `\\n${CYAN}${BOLD}[code] ${RESET}${YELLOW} ${UNDERLINE}${errorLocation}${RESET}\\n`;\r\n\r\n for (let i = start; i < end; i++) {\r\n const line = codeLines[i];\r\n const lineLabel = `${i + 1}`.padStart(4, ' ');\r\n const pointer = i + 1 === lineNum ? `${RED}<-${RESET}` : ' ';\r\n output += `${GRAY}${lineLabel}${RESET} ${pointer} ${line}\\n`;\r\n }\r\n } catch (err) {\r\n output += `${YELLOW}⚠️ No se pudo leer el archivo de origen: ${filePath}${RESET}\\n`;\r\n output += `\\n${CYAN}${BOLD}Stack Trace:${RESET}\\n${stackLines.slice(2).join('\\n')}\\n`;\r\n }\r\n }\r\n }\r\n output += help;\r\n console.error(output);\r\n}\r\n\r\nexport default Database;\r\n","import path from \"path\";\nimport { FileLogger, InterceptController } from \"@dbcube/core\";\nimport { createRequire } from 'module';\nimport type { TriggerConfig } from \"../@types/Database\";\n\n/**\n * Runtime triggers: user-defined JS functions (from .trigger.cube files) that\n * run in the application process around each write. Because they execute in\n * the write-path (not as DB-side triggers), they behave identically across\n * MySQL, PostgreSQL, SQLite and MongoDB, and fire exactly once per operation\n * regardless of how many service instances share the database.\n */\nexport class Trigger {\n private triggers: TriggerConfig[];\n private databaseName: string;\n private instance: unknown;\n\n constructor(instance: unknown, databaseName: string, metadata: TriggerConfig[]) {\n this.triggers = metadata;\n this.databaseName = databaseName;\n this.instance = instance;\n }\n\n get(type: string): TriggerConfig | undefined {\n return this.triggers.find((tr) => tr.type === type);\n }\n\n async execute(type: string, row: Record<string, unknown>): Promise<InterceptController | null> {\n const trigger = this.triggers.find((tr) => tr.type === type);\n if (trigger) {\n const logFilePath = path.resolve(\n process.cwd(),\n 'dbcube',\n 'logs',\n 'triggers',\n this.databaseName,\n `${trigger.table_ref}_${trigger.type}.log`\n );\n\n const interceptor = FileLogger.interceptConsole(logFilePath, {\n keepOriginal: false,\n useBuffer: true\n });\n const pathFile = path.resolve(process.cwd(), 'dbcube', 'triggers', `${trigger.database_ref}_${trigger.table_ref}_${trigger.type}.js`);\n // Use __filename for CJS, process.cwd() for ESM\n const requireUrl = typeof __filename !== 'undefined' ? __filename : process.cwd();\n const require = createRequire(requireUrl);\n // Clear require cache to ensure fresh load\n try {\n delete require.cache[require.resolve(pathFile)];\n } catch { /* bundled environments may not expose a resolvable cache */ }\n const triggerModule = require(pathFile);\n const dataProcess = triggerModule.default || triggerModule;\n await dataProcess({ db: this.instance, oldData: row, newData: row });\n interceptor.restore();\n return interceptor;\n }\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,gBAAe;AACf,IAAAA,eAAiB;AACjB,oBAA2B;AAC3B,IAAAC,eAAsE;;;ACHtE,kBAAiB;AACjB,kBAAgD;AAChD,oBAA8B;AAUvB,IAAM,UAAN,MAAc;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,UAAmB,cAAsB,UAA2B;AAC5E,SAAK,WAAW;AAChB,SAAK,eAAe;AACpB,SAAK,WAAW;AAAA,EACpB;AAAA,EAEA,IAAI,MAAyC;AACzC,WAAO,KAAK,SAAS,KAAK,CAAC,OAAO,GAAG,SAAS,IAAI;AAAA,EACtD;AAAA,EAEA,MAAM,QAAQ,MAAc,KAAmE;AAC3F,UAAM,UAAU,KAAK,SAAS,KAAK,CAAC,OAAO,GAAG,SAAS,IAAI;AAC3D,QAAI,SAAS;AACT,YAAM,cAAc,YAAAC,QAAK;AAAA,QACrB,QAAQ,IAAI;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,GAAG,QAAQ,SAAS,IAAI,QAAQ,IAAI;AAAA,MACxC;AAEA,YAAM,cAAc,uBAAW,iBAAiB,aAAa;AAAA,QACzD,cAAc;AAAA,QACd,WAAW;AAAA,MACf,CAAC;AACD,YAAM,WAAW,YAAAA,QAAK,QAAQ,QAAQ,IAAI,GAAG,UAAU,YAAY,GAAG,QAAQ,YAAY,IAAI,QAAQ,SAAS,IAAI,QAAQ,IAAI,KAAK;AAEpI,YAAM,aAAa,OAAO,eAAe,cAAc,aAAa,QAAQ,IAAI;AAChF,YAAMC,eAAU,6BAAc,UAAU;AAExC,UAAI;AACA,eAAOA,SAAQ,MAAMA,SAAQ,QAAQ,QAAQ,CAAC;AAAA,MAClD,QAAQ;AAAA,MAA+D;AACvE,YAAM,gBAAgBA,SAAQ,QAAQ;AACtC,YAAM,cAAc,cAAc,WAAW;AAC7C,YAAM,YAAY,EAAE,IAAI,KAAK,UAAU,SAAS,KAAK,SAAS,IAAI,CAAC;AACnE,kBAAY,QAAQ;AACpB,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AACJ;;;ADhDO,IAAM,WAAN,MAAM,UAAS;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAsB;AAAA,EAE9B,YAAY,MAAc;AACtB,SAAK,OAAO;AACZ,UAAM,SAAS,IAAI,yBAAY,IAAI;AACnC,SAAK,SAAS;AACd,SAAK,iBAAiB,CAAC;AACvB,SAAK,WAAW,CAAC;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,IAAwB,OAAe,SAAoB,CAAC,GAAiB;AAC/E,UAAM,WAAW,MAAM,KAAK,OAAO,SAAS,OAAO,QAAQ,KAAK,QAAQ,MAAS;AACjF,QAAI,SAAS,UAAU,KAAK;AACxB,2BAAqB,SAAS,QAAQ,SAAS,OAAO;AACtD,YAAM,IAAI,MAAM,SAAS,OAAO;AAAA,IACpC;AACA,WAAO,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,YAAe,UAAqD;AACtE,UAAM,OAAe,MAAM,KAAK,OAAO,iBAAiB;AAExD,UAAM,MAAM,IAAI,UAAS,KAAK,IAAI;AAClC,QAAI,SAAS,KAAK;AAClB,QAAI,iBAAiB,KAAK;AAC1B,QAAI,WAAW,KAAK;AACpB,QAAI,OAAO;AAEX,QAAI;AACA,YAAM,SAAS,MAAM,SAAS,GAAG;AACjC,YAAM,KAAK,OAAO,kBAAkB,IAAI;AACxC,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,UAAI;AACA,cAAM,KAAK,OAAO,oBAAoB,IAAI;AAAA,MAC9C,SAAS,eAAoB;AAIzB,gBAAQ;AAAA,UACJ,oCAAoC,IAAI,YAAY,eAAe,WAAW,aAAa;AAAA,QAC/F;AAAA,MACJ;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA,EAEA,MAAM,cAAiC;AACnC,UAAM,cAAc,IAAI,UAAS,KAAK,IAAI;AAC1C,UAAM,sBAAsB,MAAM,oCAAuB,kBAAkB,KAAK,IAAI;AACpF,gBAAY,kBAAkB,mBAAmB;AACjD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,cAAiC;AACnC,UAAM,cAAc,IAAI,UAAS,KAAK,IAAI;AAC1C,UAAM,gBAAgB,MAAM,8BAAiB,YAAY,KAAK,IAAI;AAClE,gBAAY,YAAY,aAAa;AACrC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,UAAyB;AAC3B,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,gBAAgB;AAAA,MACnD;AAAA,MAAY;AAAA,IAChB,CAAC;AACD,QAAI,SAAS,UAAU,KAAK;AACxB,2BAAqB,SAAS,QAAQ,SAAS,OAAO;AAAA,IAC1D;AAAA,EACJ;AAAA,EAEA,MAAM,aAA4B;AAC9B,UAAM,KAAK,OAAO,IAAI,gBAAgB;AAAA,MAClC;AAAA,MAAY;AAAA,IAChB,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuCA,MAAiD,WAA6B;AAC1E,WAAO,IAAI,MAAS,MAAM,KAAK,MAAM,WAAW,KAAK,QAAQ,KAAK,gBAAgB,KAAK,UAAU,KAAK,IAAI;AAAA,EAC9G;AAAA,EAEQ,kBAAkB,gBAAsC;AAC5D,SAAK,iBAAiB;AAAA,EAC1B;AAAA,EAEQ,YAAY,UAA0B;AAC1C,SAAK,WAAW;AAAA,EACpB;AACJ;AASO,IAAM,QAAN,MAAM,OAAiD;AAAA,EAClD;AAAA,EACA,WAAyB;AAAA,EACzB;AAAA,EACA,iBAAwC,CAAC;AAAA,EACzC;AAAA,EACA;AAAA,EACA,OAAsB;AAAA,EACtB,YAA0D,CAAC;AAAA;AAAA,EAE3D,WAAW;AAAA,EAEX;AAAA,EAER,YAAY,UAAoB,cAAsB,WAAmB,QAAqB,iBAAwC,CAAC,GAAG,WAA4B,CAAC,GAAG,OAAsB,MAAM;AAClM,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,iBAAiB;AACtB,SAAK,WAAW;AAChB,SAAK,UAAU,IAAI,QAAQ,UAAU,cAAc,QAAQ;AAC3D,SAAK,WAAW;AAChB,SAAK,OAAO;AAEZ,SAAK,MAAM;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS,CAAC,GAAG;AAAA,MACb,UAAU;AAAA,MACV,OAAO,CAAC;AAAA,MACR,OAAO,CAAC;AAAA,MACR,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ,CAAC;AAAA,IACb;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,SAAmB,CAAC,GAAa;AACpC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,UAAU,OAAO,SAAS,IAAI,SAAS,CAAC,GAAG;AACrD,UAAM,IAAI,cAAc;AACxB,WAAO;AAAA,EACX;AAAA,EAiBA,MAAM,QAAgB,UAAkB,OAAuB;AAC3D,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AACD,UAAM,WAAW;AACjB,WAAO;AAAA,EACX;AAAA,EAiBA,QAAQ,QAAgB,UAAkB,OAAuB;AAC7D,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAW,UAAmC;AAC1C,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,IAAI,OAAM,KAAK,UAAU,MAAM,IAAI,UAAU,MAAM,IAAI,OAAO,MAAM,MAAM;AAG7F,eAAW,WAAW;AACtB,aAAS,UAAU;AAEnB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB,MAAM,MAAM;AAAA,MACZ,SAAS;AAAA,MACT,YAAY,WAAW,IAAI;AAAA,IAC/B,CAAC;AACD,UAAM,WAAW;AACjB,WAAO;AAAA,EACX;AAAA,EAEA,KAAe;AACX,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,WAAW;AACjB,WAAO;AAAA,EACX;AAAA,EAEA,MAAgB;AACZ,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,WAAW;AACjB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,QAAgB,QAA8B;AACvD,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,CAAC,QAAQ,MAAM,IAAI;AACzB,QAAI,WAAW,UAAa,WAAW,QAAW;AAC9C,YAAM,IAAI,MAAM,KAAK;AAAA,QACjB;AAAA,QACA,UAAU;AAAA,QACV,OAAO,CAAC,QAAQ,MAAM;AAAA,QACtB,MAAM,MAAM;AAAA,QACZ,SAAS;AAAA,MACb,CAAC;AACD,YAAM,WAAW;AAAA,IACrB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,QAAgB,QAAyB;AAC7C,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AAC5C,YAAM,IAAI,MAAM,KAAK;AAAA,QACjB;AAAA,QACA,UAAU;AAAA,QACV,OAAO;AAAA,QACP,MAAM,MAAM;AAAA,QACZ,SAAS;AAAA,MACb,CAAC;AACD,YAAM,WAAW;AAAA,IACrB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,UAAU,QAA0B;AAChC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB;AAAA,MACA,UAAU;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AACD,UAAM,WAAW;AACjB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,aAAa,QAA0B;AACnC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB;AAAA,MACA,UAAU;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AACD,UAAM,WAAW;AACjB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,KAAK,OAAe,SAAiB,UAAkB,SAA2B;AAC9E,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB,MAAM;AAAA,MACN;AAAA,MACA,IAAI;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,IACJ,CAAC;AACD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,SAAS,OAAe,SAAiB,UAAkB,SAA2B;AAClF,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB,MAAM;AAAA,MACN;AAAA,MACA,IAAI;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,IACJ,CAAC;AACD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UAAU,OAAe,SAAiB,UAAkB,SAA2B;AACnF,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,MAAM,KAAK;AAAA,MACjB,MAAM;AAAA,MACN;AAAA,MACA,IAAI;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,IACJ,CAAC;AACD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,QAAgB,YAA4B,OAAiB;AACjE,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,kBAAsC,CAAC,OAAO,MAAM;AAC1D,QAAI,gBAAgB,SAAS,UAAU,YAAY,CAAmB,GAAG;AACrE,YAAM,IAAI,QAAQ,KAAK;AAAA,QACnB;AAAA,QACA,WAAW,UAAU,YAAY;AAAA,MACrC,CAAC;AAAA,IACL,OAAO;AACH,YAAM,IAAI,MAAM,sBAAsB,SAAS,wBAAwB;AAAA,IAC3E;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAQ,QAA0B;AAC9B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,QAAQ,KAAK,MAAM;AAC7B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,WAAqB;AACjB,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,WAAW;AACrB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MAAM,SAAiB,KAAsB;AAC/C,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,IACX;AACA,UAAM,IAAI,UAAU,CAAC,SAAS,MAAM,YAAY;AAChD,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,QAAQ;AAClB,UAAM,IAAI,SAAS;AACnB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,OAAO,CAAC,KAAK;AACzB,UAAI,KAAK;AACL,eAAO,IAAI;AAAA,MACf;AACA,aAAO;AAAA,IACX,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IAAI,QAAiC;AACvC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,IACX;AACA,UAAM,IAAI,UAAU,CAAC,OAAO,MAAM,UAAU;AAC5C,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,QAAQ;AAClB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,OAAO,CAAC,KAAK;AACzB,UAAI,KAAK;AACL,eAAO,IAAI;AAAA,MACf;AACA,aAAO;AAAA,IACX,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IAAI,QAAiC;AACvC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,IACX;AACA,UAAM,IAAI,UAAU,CAAC,OAAO,MAAM,UAAU;AAC5C,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,QAAQ;AAClB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,OAAO,CAAC,KAAK;AACzB,UAAI,KAAK;AACL,eAAO,IAAI;AAAA,MACf;AACA,aAAO;AAAA,IACX,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IAAI,QAAiC;AACvC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,IACX;AACA,UAAM,IAAI,UAAU,CAAC,OAAO,MAAM,UAAU;AAC5C,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,QAAQ;AAClB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,OAAO,CAAC,KAAK;AACzB,UAAI,KAAK;AACL,eAAO,IAAI;AAAA,MACf;AACA,aAAO;AAAA,IACX,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IAAI,QAAiC;AACvC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,IACX;AACA,UAAM,IAAI,UAAU,CAAC,OAAO,MAAM,UAAU;AAC5C,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,QAAQ;AAClB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,OAAO,CAAC,KAAK;AACzB,UAAI,KAAK;AACL,eAAO,IAAI;AAAA,MACf;AACA,aAAO;AAAA,IACX,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,MAAM,UAAmC;AACrC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,UAAU,CAAC;AACrB,UAAM,IAAI,QAAQ,CAAC;AACnB,UAAM,IAAI,UAAU,CAAC;AACrB,UAAM,IAAI,UAAU,CAAC;AACrB,UAAM,IAAI,QAAQ;AAClB,UAAM,IAAI,SAAS;AACnB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AAExB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AAEvC,UAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AAE5C,YAAI,OAAO,CAAC,EAAE,WAAW,OAAO,CAAC,EAAE,YAAY,QAAW;AAEtD,iBAAO,OAAO,CAAC;AAAA,QACnB;AAGA,eAAO,OAAO,IAAI,CAAC,QAAa,IAAI,eAAe,IAAI,SAAS,IAAI,IAAI;AAAA,MAC5E;AAEA,aAAO,CAAC;AAAA,IACZ,SAAS,OAAO;AACZ,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QAA0B;AAC5B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,QAAQ,OAAO,MAAM;AAC/B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,KAAK,QAA0B;AAC3B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,UAAU,OAAO,MAAM;AAC7B,QAAI,MAAM,IAAI,OAAO;AACjB,YAAM,IAAI,UAAU,UAAU,KAAK,MAAM,IAAI;AAAA,IACjD;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MAAoB;AACtB,QAAI;AACA,YAAM,QAAQ,KAAK,MAAM;AACzB,YAAM,IAAI,OAAO;AACjB,YAAM,IAAI,OAAO;AACjB,YAAM,IAAI,cAAc;AACxB,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,UAAI,KAAK,UAAU,SAAS,KAAK,MAAM,QAAQ,MAAM,GAAG;AACpD,eAAO,MAAM,KAAK,gBAAgB,MAAM;AAAA,MAC5C;AACA,aAAO;AAAA,IACX,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAA2B;AAC7B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AACxB,UAAM,IAAI,QAAQ;AAClB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,aAAO,OAAO,CAAC,KAAK;AAAA,IACxB,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,KAAK,OAAwB,SAAiB,MAAyB;AAEzE,UAAM,QAAQ,KAAK,MAAM,EAAE,MAAM,QAAQ,KAAK,KAAK;AACnD,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AACxB,UAAM,IAAI,QAAQ;AAClB,QAAI;AACA,YAAM,SAAS,MAAM,MAAM,YAAY;AACvC,aAAO,OAAO,CAAC,KAAK;AAAA,IACxB,SACO,OAAO;AACV,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,OAAO,MAAkC;AAC3C,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACtB,YAAM,IAAI,MAAM,sEAAsE;AAAA,IAC1F;AAEA,QAAI,CAAC,KAAK,MAAM,UAAQ,OAAO,SAAS,YAAY,SAAS,IAAI,GAAG;AAChE,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAChE;AAEA,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,OAAO;AAEjB,UAAM,SAAS,MAAM,MAAM,YAAY,MAAM,KAAK,KAAK;AAEvD,WAAO,UAAU;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OAAO,MAA2C;AACpD,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GAAG;AACjD,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAChF;AAEA,QAAI,MAAM,IAAI,MAAM,WAAW,GAAG;AAC9B,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACzF;AAEA,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,OAAO;AAEjB,WAAO,MAAM,YAAY,MAAM,KAAK,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SAAkC;AACpC,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,MAAM,IAAI,MAAM,WAAW,GAAG;AAC9B,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACxF;AAEA,UAAM,IAAI,OAAO;AAEjB,UAAM,aAAa,MAAM,MAAM,YAAY,MAAM,KAAK,QAAQ;AAC9D,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,QAAgB,QAAyB;AAChD,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AAC5C,YAAM,IAAI,MAAM,KAAK;AAAA,QACjB;AAAA,QACA,UAAU;AAAA,QACV,OAAO;AAAA,QACP,MAAM,MAAM;AAAA,QACZ,SAAS;AAAA,MACb,CAAC;AACD,YAAM,WAAW;AAAA,IACrB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAA0B;AAC7B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,SAAS,OAAO,MAAM;AAChC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,UAAU,aAAiC;AACvC,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,MAAM,IAAI,QAAQ,WAAW,KAAK,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK;AAChE,YAAM,IAAI,UAAU,CAAC,GAAG,WAAW;AAAA,IACvC,OAAO;AACH,YAAM,IAAI,UAAU,CAAC,GAAG,MAAM,IAAI,SAAS,GAAG,WAAW;AAAA,IAC7D;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAAgB,UAAkB,OAAuB;AAC5D,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,SAAS,MAAM,IAAI,UAAU,CAAC;AACxC,UAAM,IAAI,OAAO,KAAK;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAA2B;AAC7B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,UAAU,CAAC,oBAAoB;AACzC,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,cAAc;AACxB,UAAM,IAAI,QAAQ;AAClB,UAAM,IAAI,SAAS;AACnB,UAAM,SAAS,MAAM,MAAM,YAAY;AACvC,WAAO,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,SAAS,OAAe,GAAG,UAAkB,IAAiC;AAChF,UAAM,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC;AACxC,UAAM,OAAO,KAAK,IAAI,GAAG,OAAO,OAAO,CAAC;AAExC,UAAM,aAAa,KAAK,MAAM,IAAI,EAAE,KAAK,OAAO;AAChD,UAAM,CAAC,OAAO,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,MACrC,WAAW,IAAI;AAAA,MACf,KAAK,MAAM;AAAA,IACf,CAAC;AAED,UAAM,WAAW,OAAO,KAAK;AAC7B,UAAM,aAAa,KAAK,KAAK,WAAW,IAAI;AAC5C,WAAO;AAAA,MACH;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA,MACP;AAAA,MACA,SAAS,UAAU;AAAA,MACnB,SAAS,UAAU;AAAA,IACvB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MAAM,MAAc,UAAgG;AACtH,UAAM,YAAY,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC;AAC1C,QAAI,OAAO;AACX,WAAO,MAAM;AACT,YAAM,OAAO,MAAM,KAAK,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE,IAAI;AACxD,UAAI,KAAK,WAAW,EAAG;AACvB,YAAM,SAAS,MAAM,SAAS,MAAM,IAAI;AACxC,UAAI,WAAW,MAAO;AACtB,UAAI,KAAK,SAAS,UAAW;AAC7B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UAAU,QAAgB,SAAiB,GAAG,QAAoB,CAAC,GAA4B;AACjG,UAAM,QAAQ,KAAK,MAAM;AACzB,QAAI,MAAM,IAAI,MAAM,WAAW,GAAG;AAC9B,YAAM,IAAI,MAAM,wEAAwE;AAAA,IAC5F;AACA,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,EAAE,MAAM,OAAO,MAAM,EAAE,EAAE;AAChE,WAAO,MAAM,YAAY;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,QAAgB,SAAiB,GAAG,QAAoB,CAAC,GAA4B;AACjG,WAAO,KAAK,UAAU,QAAQ,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAoC;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,QAAQ,CAAC;AACnB,WAAO,MAAM,YAAY;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,OAAO,MAAoB,cAAwB,eAAmD;AACxG,QAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GAAG;AAC3C,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC9E;AACA,QAAI,CAAC,MAAM,QAAQ,YAAY,KAAK,aAAa,WAAW,GAAG;AAC3D,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAClF;AAEA,UAAM,QAAgB,KAAK,QAAQ,YAAY,GAAG,QAAQ;AAE1D,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC;AACnC,UAAM,UAAU,iBAAiB,QAAQ,OAAO,OAAK,CAAC,aAAa,SAAS,CAAC,CAAC;AAI9E,0BAAsB,OAAO,OAAO;AACpC,eAAW,KAAK,QAAS,uBAAsB,GAAG,QAAQ;AAC1D,eAAW,KAAK,aAAc,uBAAsB,GAAG,cAAc;AACrE,eAAW,KAAK,QAAS,uBAAsB,GAAG,eAAe;AAEjE,QAAI,UAAU,WAAW;AAIrB,YAAM,UAAU,KAAK,IAAI,SAAO;AAC5B,cAAM,IAA6B,CAAC;AACpC,mBAAW,KAAK,aAAc,GAAE,CAAC,IAAI,IAAI,CAAC;AAE1C,cAAM,MAA+B,CAAC;AACtC,mBAAW,KAAK,QAAS,KAAI,KAAK,IAAK,KAAI,CAAC,IAAI,IAAI,CAAC;AAErD,cAAM,cAAuC,CAAC;AAC9C,mBAAW,KAAK,SAAS;AACrB,cAAI,CAAC,QAAQ,SAAS,CAAC,KAAK,CAAC,aAAa,SAAS,CAAC,EAAG,aAAY,CAAC,IAAI,IAAI,CAAC;AAAA,QACjF;AACA,YAAI,EAAE,UAAU,KAAM,aAAY,MAAM,QAAI,0BAAW;AAEvD,cAAM,IAA6B,CAAC;AACpC,YAAI,OAAO,KAAK,GAAG,EAAE,OAAQ,GAAE,MAAM,IAAI;AACzC,YAAI,OAAO,KAAK,WAAW,EAAE,OAAQ,GAAE,cAAc,IAAI;AAEzD,eAAO,EAAE,GAAG,GAAG,QAAQ,MAAM,OAAO,MAAM;AAAA,MAC9C,CAAC;AAED,YAAM,UAAU,KAAK,UAAU,EAAE,QAAQ,OAAO,QAAQ,CAAC;AACzD,YAAMC,YAAW,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,KAAK,QAAQ,MAAS;AAC/E,UAAIA,UAAS,UAAU,KAAK;AACxB,6BAAqBA,UAAS,QAAQA,UAAS,OAAO;AACtD,cAAM,IAAI,MAAMA,UAAS,OAAO;AAAA,MACpC;AACA,aAAOA,UAAS;AAAA,IACpB;AAEA,UAAM,QAAQ,CAAC,OAAe,UAAU,UAAU,KAAK,EAAE,OAAO,IAAI,EAAE;AAEtE,UAAM,SAAgB,CAAC;AACvB,UAAM,cAAc,MAAM,UAAU,cAAc,UAAU,eACtD,IAAI,OAAO,MAAM,KACjB;AAEN,UAAM,UAAU,KAAK,IAAI,SAAO;AAC5B,YAAM,QAAQ,QAAQ,IAAI,SAAO;AAC7B,eAAO,KAAK,IAAI,GAAG,MAAM,SAAY,OAAO,IAAI,GAAG,CAAC;AACpD,eAAO,YAAY;AAAA,MACvB,CAAC;AACD,aAAO,IAAI,MAAM,KAAK,IAAI,CAAC;AAAA,IAC/B,CAAC,EAAE,KAAK,IAAI;AAEZ,UAAM,UAAU,QAAQ,IAAI,KAAK,EAAE,KAAK,IAAI;AAC5C,QAAI;AAEJ,QAAI,UAAU,SAAS;AACnB,YAAM,UAAU,QAAQ,IAAI,OAAK,GAAG,MAAM,CAAC,CAAC,aAAa,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,IAAI;AAC/E,YAAM,eAAe,MAAM,KAAK,CAAC,KAAK,OAAO,YAAY,OAAO,4BAA4B,OAAO;AAAA,IACvG,OAAO;AACH,YAAM,WAAW,aAAa,IAAI,KAAK,EAAE,KAAK,IAAI;AAClD,YAAM,UAAU,QAAQ,IAAI,OAAK,GAAG,MAAM,CAAC,CAAC,eAAe,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,IAAI;AAChF,YAAM,eAAe,MAAM,KAAK,CAAC,KAAK,OAAO,YAAY,OAAO,iBAAiB,QAAQ,mBAAmB,OAAO;AAAA,IACvH;AAEA,QAAI,UAAU,UAAU;AAGpB,YAAM,KAAK,OAAO,SAAS,0CAA0C,CAAC,GAAG,KAAK,QAAQ,MAAS;AAAA,IACnG;AACA,UAAM,WAAW,MAAM,KAAK,OAAO,SAAS,KAAK,QAAQ,KAAK,QAAQ,MAAS;AAC/E,QAAI,SAAS,UAAU,KAAK;AACxB,2BAAqB,SAAS,QAAQ,SAAS,OAAO;AACtD,YAAM,IAAI,MAAM,SAAS,OAAO;AAAA,IACpC;AACA,WAAO,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,KAAK,UAAkB,UAA2B,CAAC,GAAa;AAC5D,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,UAAU,KAAK,EAAE,MAAM,UAAU,QAAQ,CAAC;AAChD,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,gBAAgB,MAAmD;AAC7E,QAAI,KAAK,WAAW,KAAK,KAAK,UAAU,WAAW,EAAG,QAAO;AAE7D,eAAW,EAAE,MAAM,QAAQ,KAAK,KAAK,WAAW;AAC5C,YAAM,eAAe,QAAQ,SAAS;AACtC,YAAM,WAAW,kBAAkB;AAGnC,UAAI,OAAO,QAAQ;AACnB,UAAI,aAAa,QAAQ;AACzB,UAAI,WAAW,QAAQ,YAAY;AAEnC,UAAI,CAAC,cAAc,CAAC,MAAM;AACtB,cAAM,WAAW,SAAS,YAAY,GAAG,YAAY,CAAC;AACtD,cAAM,SAAS,SAAS,KAAK,IAAI,KAAK,GAAG,YAAY,CAAC;AACtD,cAAM,gBAAgB,SAAS,KAAK,QAAM,GAAG,UAAU,KAAK,IAAI,KAAK;AACrE,cAAM,gBAAgB,OAAO,KAAK,QAAM,GAAG,UAAU,YAAY;AAEjE,YAAI,eAAe;AAEf,iBAAO,QAAQ;AACf,uBAAa,cAAc,cAAc;AACzC,qBAAW,QAAQ,YAAY,cAAc;AAAA,QACjD,WAAW,eAAe;AAEtB,iBAAO,QAAQ;AACf,uBAAa,cAAc,cAAc;AACzC,qBAAW,QAAQ,YAAY,cAAc;AAAA,QACjD,OAAO;AAEH,iBAAO,QAAQ;AACf,uBAAa,cAAc,GAAG,YAAY,KAAK,IAAI,KAAK,CAAC;AAAA,QAC7D;AAAA,MACJ;AAEA,YAAM,eAAe,IAAI,OAAM,KAAK,UAAU,KAAK,IAAI,UAAU,cAAc,KAAK,QAAQ,KAAK,gBAAgB,KAAK,UAAU,KAAK,IAAI;AAEzI,UAAI,SAAS,OAAO;AAEhB,cAAM,WAAW,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,OAAK,EAAE,UAAW,CAAC,EAAE,OAAO,OAAK,MAAM,QAAQ,MAAM,MAAS,CAAC,CAAC;AACtG,cAAM,UAAU,SAAS,SAAS,IAC5B,MAAM,aAAa,QAAQ,UAAU,QAAQ,EAAE,IAAI,IACnD,CAAC;AACP,cAAM,QAAQ,IAAI,IAAI,QAAQ,IAAI,OAAK,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;AACxD,mBAAW,OAAO,MAAM;AACpB,cAAI,IAAI,IAAI,MAAM,IAAI,IAAI,UAAW,CAAC,KAAK;AAAA,QAC/C;AAAA,MACJ,OAAO;AAEH,cAAM,MAAM,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,OAAK,EAAE,QAAQ,CAAC,EAAE,OAAO,OAAK,MAAM,QAAQ,MAAM,MAAS,CAAC,CAAC;AAC9F,cAAM,UAAU,IAAI,SAAS,IACvB,MAAM,aAAa,QAAQ,YAAa,GAAG,EAAE,IAAI,IACjD,CAAC;AACP,cAAM,SAAS,oBAAI,IAA2B;AAC9C,mBAAW,OAAO,SAAS;AACvB,gBAAM,MAAM,IAAI,UAAW;AAC3B,cAAI,CAAC,OAAO,IAAI,GAAG,EAAG,QAAO,IAAI,KAAK,CAAC,CAAC;AACxC,iBAAO,IAAI,GAAG,EAAG,KAAK,GAAG;AAAA,QAC7B;AACA,mBAAW,OAAO,MAAM;AACpB,cAAI,IAAI,IAAI,OAAO,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC;AAAA,QAC9C;AAAA,MACJ;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,YAAY,MAAW,MAAM,OAAY,MAAoB;AACvE,UAAM,WAAW,MAAM,MAAM,KAAK;AAClC,UAAM,uBAA8B,CAAC;AACrC,QAAI,oBAA2B,CAAC;AAEhC,QAAI,KAAK,eAAe,SAAS,GAAG;AAChC,UAAI,UAAU,SAAS;AAEvB,iBAAW,SAAS,SAAS,SAAS;AAClC,cAAM,gBAAgB,KAAK,eAAe,KAAK,QAAM,GAAG,WAAW,KAAK;AAExE,YAAI,eAAe;AACf,+BAAqB,KAAK,aAAa;AAEvC,gBAAM,eAAe,oCAAuB,oBAAoB,cAAc,WAAW;AACzF,8BAAoB,CAAC,GAAG,mBAAmB,GAAG,YAAY;AAC1D,oBAAU,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;AAC3D,oBAAU,QAAQ,OAAO,CAAC,QAAgB,OAAO,KAAK;AAAA,QAC1D;AAAA,MACJ;AACA,eAAS,UAAU;AAAA,IACvB;AAEA,QAAI,cAAc,CAAC;AACnB,QAAI,MAAM;AACN,YAAM,UAAU,KAAK,QAAQ,IAAI,WAAW,IAAI;AAChD,YAAM,QAAQ,KAAK,QAAQ,IAAI,UAAU,IAAI;AAC7C,UAAI,KAAK,SAAS,SAAS,MAAM,WAAW,QAAQ;AAChD,cAAM,UAAU,SAAS;AACzB,iBAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS;AACjD,gBAAM,OAAO,QAAQ,KAAK;AAC1B,gBAAM,SAAS,EAAE,GAAG,UAAU,MAAM,CAAC,IAAI,EAAE;AAC3C,cAAI,SAAS;AACT,kBAAM,cAAc,MAAM,KAAK,QAAQ,QAAQ,WAAW,MAAM,IAAI;AACpE,kBAAM,WAAW,MAAM,KAAK,OAAO,WAAW,QAAQ,KAAK,QAAQ,MAAS;AAE5E,gBAAI,SAAS,UAAU,KAAK;AACxB,2BAAa,QAAQ;AACrB,mCAAqB,SAAS,QAAQ,SAAS,OAAO;AAAA,YAC1D;AACA,kBAAM,aAAa,OAAO;AAC1B,0BAAc,SAAS;AAAA,UAC3B;AACA,cAAI,OAAO;AAEP,kBAAM,WAAW,MAAM,KAAK,OAAO,WAAW,QAAQ,KAAK,QAAQ,MAAS;AAE5E,gBAAI,SAAS,UAAU,KAAK;AACxB,mCAAqB,SAAS,QAAQ,SAAS,OAAO;AAAA,YAC1D;AACA,kBAAM,cAAc,MAAM,KAAK,QAAQ,QAAQ,UAAU,MAAM,IAAI;AACnE,kBAAM,aAAa,OAAO;AAAA,UAC9B;AAAA,QACJ;AAAA,MACJ,OAAO;AACH,cAAM,WAAW,MAAM,KAAK,OAAO,WAAW,UAAU,KAAK,QAAQ,MAAS;AAE9E,YAAI,SAAS,UAAU,KAAK;AACxB,+BAAqB,SAAS,QAAQ,SAAS,OAAO;AAAA,QAC1D;AAEA,sBAAc,SAAS;AAAA,MAC3B;AAAA,IACJ,OAAO;AACH,YAAM,WAAW,MAAM,KAAK,OAAO,WAAW,UAAU,KAAK,QAAQ,MAAS;AAE9E,UAAI,SAAS,UAAU,KAAK;AACxB,6BAAqB,SAAS,QAAQ,SAAS,OAAO;AAAA,MAC1D;AAEA,oBAAc,SAAS;AAAA,IAC3B;AAEA,QAAI,qBAAqB,SAAS,GAAG;AACjC,UAAI,aAAkB,oCAAuB,eAAe,aAAa,oBAAoB;AAC7F,YAAM,SAAS,WAAW,IAAI,CAAC,QAAa;AACxC,cAAM,SAAS,EAAE,GAAG,IAAI;AACxB,0BAAkB,QAAQ,SAAO,OAAO,OAAO,GAAG,CAAC;AACnD,eAAO;AAAA,MACX,CAAC;AACD,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,QAAkB;AAGtB,QAAI,KAAK,SAAU,QAAO;AAC1B,UAAM,SAAS,OAAO,OAAO,OAAO,eAAe,IAAI,CAAC;AACxD,WAAO,SAAS,KAAK;AACrB,WAAO,WAAW,KAAK;AACvB,WAAO,WAAW,KAAK;AACvB,WAAO,iBAAiB,KAAK;AAC7B,WAAO,UAAU,KAAK;AACtB,WAAO,WAAW,KAAK;AACvB,WAAO,OAAO,KAAK;AACnB,WAAO,YAAY,CAAC,GAAG,KAAK,SAAS;AAErC,WAAO,MAAM;AAAA,MACT,GAAG,KAAK;AAAA,MACR,SAAS,CAAC,GAAG,KAAK,IAAI,OAAO;AAAA,MAC7B,OAAO,CAAC,GAAG,KAAK,IAAI,KAAK;AAAA,MACzB,OAAO,CAAC,GAAG,KAAK,IAAI,KAAK;AAAA,MACzB,SAAS,CAAC,GAAG,KAAK,IAAI,OAAO;AAAA,MAC7B,SAAS,CAAC,GAAG,KAAK,IAAI,OAAO;AAAA,MAC7B,QAAQ,CAAC,GAAI,KAAK,IAAI,UAAU,CAAC,CAAE;AAAA;AAAA,MAEnC,MAAM,KAAK,IAAI,OAAQ,MAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,IAAI,EAAE,GAAG,KAAK,IAAI,KAAK,IAAK;AAAA,MACnG,aAAa,KAAK,IAAI,cAAc,EAAE,GAAG,KAAK,IAAI,YAAY,IAAI;AAAA,IACtE;AACA,WAAO;AAAA,EACX;AAEJ;AAUA,IAAI,qBAAyE;AAE7E,SAAS,oBAAiE;AACtE,MAAI,mBAAoB,QAAO;AAC/B,QAAM,SAAsD,CAAC;AAE7D,QAAM,UAAU,CAAC,QAAgB;AAC7B,QAAI;AACJ,QAAI;AACA,gBAAU,UAAAC,QAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACzD,QAAQ;AACJ;AAAA,IACJ;AACA,eAAW,SAAS,SAAS;AACzB,YAAM,OAAO,aAAAC,QAAK,KAAK,KAAK,MAAM,IAAI;AACtC,UAAI,MAAM,YAAY,GAAG;AACrB,YAAI,MAAM,SAAS,kBAAkB,MAAM,SAAS,cAAc,MAAM,SAAS,QAAQ;AACrF,kBAAQ,IAAI;AAAA,QAChB;AAAA,MACJ,WAAW,MAAM,KAAK,SAAS,aAAa,GAAG;AAC3C,YAAI;AACA,gBAAM,UAAU,UAAAD,QAAG,aAAa,MAAM,MAAM;AAC5C,gBAAM,YAAY,QAAQ,MAAM,6CAA6C;AAC7E,gBAAM,YAAY,YAAY,UAAU,CAAC,IAAI,aAAAC,QAAK,SAAS,MAAM,MAAM,aAAa;AAEpF,gBAAM,WAA0B,CAAC;AACjC,gBAAM,WAAW;AACjB,cAAI;AACJ,kBAAQ,IAAI,SAAS,KAAK,OAAO,OAAO,MAAM;AAC1C,kBAAM,UAAU,EAAE,CAAC,EAAE,MAAM,uBAAuB;AAClD,kBAAM,WAAW,EAAE,CAAC,EAAE,MAAM,wBAAwB;AACpD,gBAAI,SAAS;AACT,uBAAS,KAAK;AAAA,gBACV,aAAa,EAAE,CAAC;AAAA,gBAChB,OAAO,QAAQ,CAAC;AAAA,gBAChB,QAAQ,WAAW,SAAS,CAAC,IAAI;AAAA,cACrC,CAAC;AAAA,YACL;AAAA,UACJ;AACA,iBAAO,SAAS,IAAI,EAAE,SAAS;AAAA,QACnC,QAAQ;AAAA,QAA+B;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ;AAEA,UAAQ,aAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,QAAQ,CAAC;AAC1C,uBAAqB;AACrB,SAAO;AACX;AAEA,SAAS,sBAAsB,MAAc,MAAoB;AAC7D,MAAI,CAAC,2BAA2B,KAAK,IAAI,GAAG;AACxC,UAAM,IAAI,MAAM,WAAW,IAAI,WAAW,IAAI,sDAAsD;AAAA,EACxG;AACJ;AAEA,SAAS,YAAY,MAAsB;AACvC,MAAI,KAAK,SAAS,KAAK,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE,IAAI;AACrD,MAAI,KAAK,SAAS,KAAK,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AACjD,MAAI,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,SAAS,IAAI,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AACvE,SAAO;AACX;AAEA,SAAS,qBAAqB,QAAgB,SAAiB;AAC3D,QAAM,QAAQ;AACd,QAAM,MAAM;AACZ,QAAM,SAAS;AACf,QAAM,OAAO;AACb,QAAM,OAAO;AACb,QAAM,OAAO;AACb,QAAM,YAAY;AAClB,QAAM,UAAU;AAEhB,MAAI,SAAS;AACb,MAAI,OAAO;AACX,QAAM,QAAQ,WAAW,MAAM,SAAS;AAGxC,MAAI,QAAQ,SAAS,QAAQ,GAAG;AAC5B,UAAM,QAAQ,QAAQ,MAAM,QAAQ;AACpC,cAAU;AAAA,EAAK,GAAG,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,KAAK;AAC5C,YAAQ;AAAA,EAAK,OAAO,GAAG,IAAI,SAAS,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,KAAK;AAAA;AAAA,EACxE,OAAO;AACH,cAAU;AAAA,EAAK,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK;AAAA;AAAA,EACjD;AAEA,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,aAAa,IAAI,OAAO,MAAM,IAAI,KAAK,CAAC;AAG9C,QAAM,oBAAoB,WAAW;AAAA,IAAK,UACtC,KAAK,SAAS,MAAM,KAAK,CAAC,KAAK,SAAS,cAAc;AAAA,EAC1D;AAEA,MAAI,mBAAmB;AACnB,UAAM,QAAQ,kBAAkB,MAAM,sBAAsB,KACxD,kBAAkB,MAAM,qBAAqB;AAEjD,QAAI,OAAO;AACP,YAAM,CAAC,EAAE,UAAU,SAAS,SAAS,IAAI;AACzC,YAAM,UAAU,SAAS,SAAS,EAAE;AACpC,YAAM,gBAAgB,GAAG,QAAQ,IAAI,OAAO,IAAI,SAAS;AAGzD,UAAI;AACA,cAAM,YAAY,UAAAD,QAAG,aAAa,UAAU,OAAO,EAAE,MAAM,IAAI;AAC/D,cAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,CAAC;AACrC,cAAM,MAAM,KAAK,IAAI,UAAU,QAAQ,UAAU,CAAC;AAElD,kBAAU;AAAA,EAAK,IAAI,GAAG,IAAI,UAAU,KAAK,GAAG,MAAM,IAAI,SAAS,GAAG,aAAa,GAAG,KAAK;AAAA;AAEvF,iBAAS,IAAI,OAAO,IAAI,KAAK,KAAK;AAC9B,gBAAM,OAAO,UAAU,CAAC;AACxB,gBAAM,YAAY,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,GAAG;AAC5C,gBAAM,UAAU,IAAI,MAAM,UAAU,GAAG,GAAG,KAAK,KAAK,KAAK;AACzD,oBAAU,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,OAAO,IAAI,IAAI;AAAA;AAAA,QAC5D;AAAA,MACJ,SAASE,MAAK;AACV,kBAAU,GAAG,MAAM,sDAA4C,QAAQ,GAAG,KAAK;AAAA;AAC/E,kBAAU;AAAA,EAAK,IAAI,GAAG,IAAI,eAAe,KAAK;AAAA,EAAK,WAAW,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA,MACrF;AAAA,IACJ;AAAA,EACJ;AACA,YAAU;AACV,UAAQ,MAAM,MAAM;AACxB;;;ADtkDA,IAAO,gBAAQ;","names":["import_path","import_core","path","require","response","fs","path","err"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/Database.ts","../src/lib/Trigger.ts"],"sourcesContent":["import { Table, Database } from './lib/Database';\nimport type {\n ComputedFieldConfig,\n DatabaseRecord,\n MutationInfo,\n PaginatedResult,\n RelationOptions,\n TriggerConfig,\n WhereCallback,\n} from './@types/Database';\n\nexport default Database;\nexport {\n Table,\n Database,\n type ComputedFieldConfig,\n type DatabaseRecord,\n type MutationInfo,\n type PaginatedResult,\n type RelationOptions,\n type TriggerConfig,\n type WhereCallback\n};\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { randomUUID } from 'crypto';\r\nimport { QueryEngine, ComputedFieldProcessor, TriggerProcessor } from \"@dbcube/core\";\r\nimport { ComputedFieldConfig, DatabaseRecord, DML, MutationInfo, PaginatedResult, RelationOptions, TriggerConfig, WhereCallback, WhereCondition } from \"../@types/Database\";\r\nimport { Trigger } from './Trigger';\r\n\r\n/**\r\n * Main class to handle MySQL database connections and queries.\r\n * Implements the Singleton pattern to ensure a single instance of the connection pool.\r\n */\r\nexport class Database {\r\n private name: string;\r\n private engine: QueryEngine;\r\n private computedFields: ComputedFieldConfig[];\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n\r\n constructor(name: string) {\r\n this.name = name;\r\n const engine = new QueryEngine(name);\r\n this.engine = engine;\r\n this.computedFields = [];\r\n this.triggers = [];\r\n }\r\n\r\n /**\r\n * Executes raw SQL (MySQL/PostgreSQL/SQLite) or a raw command document (MongoDB)\r\n * with bound parameters. The escape hatch for anything the builder doesn't cover.\r\n *\r\n * @example\r\n * const rows = await db.raw('SELECT * FROM users WHERE age > ?', [25]);\r\n * await db.raw('CREATE INDEX idx_users_email ON users(email)');\r\n */\r\n async raw<R = DatabaseRecord>(query: string, params: unknown[] = []): Promise<R[]> {\r\n const response = await this.engine.rawQuery(query, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Runs a callback inside a database transaction. Everything executed through\r\n * the received connection is committed atomically; any thrown error rolls\r\n * the whole transaction back.\r\n *\r\n * Requires daemon mode (enabled by default with an up-to-date query-engine).\r\n *\r\n * @example\r\n * await db.transaction(async (trx) => {\r\n * await trx.table('accounts').where('id', '=', 1).update({ balance: 50 });\r\n * await trx.table('accounts').where('id', '=', 2).update({ balance: 150 });\r\n * });\r\n */\r\n async transaction<T>(callback: (trx: Database) => Promise<T>): Promise<T> {\r\n const txId: string = await this.engine.beginTransaction();\r\n\r\n const trx = new Database(this.name);\r\n trx.engine = this.engine;\r\n trx.computedFields = this.computedFields;\r\n trx.triggers = this.triggers;\r\n trx.txId = txId;\r\n\r\n try {\r\n const result = await callback(trx);\r\n await this.engine.commitTransaction(txId);\r\n return result;\r\n } catch (error) {\r\n try {\r\n await this.engine.rollbackTransaction(txId);\r\n } catch (rollbackError: any) {\r\n // El error original manda, pero un rollback fallido no puede\r\n // pasar en silencio: la transacción puede seguir reteniendo\r\n // locks hasta que el daemon la expire por inactividad.\r\n console.error(\r\n `[dbcube] Rollback of transaction ${txId} failed: ${rollbackError?.message ?? rollbackError}`\r\n );\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async useComputes(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayComputedFields = await ComputedFieldProcessor.getComputedFields(this.name);\r\n newDatabase.setComputedFields(arrayComputedFields);\r\n return newDatabase;\r\n }\r\n\r\n async useTriggers(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayTriggers = await TriggerProcessor.getTriggers(this.name);\r\n newDatabase.setTriggers(arrayTriggers);\r\n return newDatabase;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n const response = await this.engine.run('query_engine', [\r\n '--action', 'connect',\r\n ]);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n await this.engine.run('query_engine', [\r\n '--action', 'disconnect',\r\n ]);\r\n }\r\n\r\n /**\r\n * Creates and returns a new instance of `Table` for the specified table.\r\n * This method is used to start building queries for a specific table.\r\n * It provides a fluent interface for common database operations like select, insert, update, and delete.\r\n *\r\n * @param {string} tableName - The name of the table to query.\r\n * @returns {Table} - Returns a new instance of `Table` for the specified table.\r\n *\r\n * @example\r\n * // Select all records from a table\r\n * const users = await db.table('users').get();\r\n * \r\n * // Select records with conditions\r\n * const activeUsers = await db.table('users')\r\n * .where('status', '=', 'active')\r\n * .orderBy('created_at', 'DESC')\r\n * .limit(10)\r\n * .get();\r\n * \r\n * // Insert records\r\n * await db.table('users').insert([\r\n * { name: 'John', email: 'john@example.com', age: 30 }\r\n * ]);\r\n * \r\n * // Update records\r\n * await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ status: 'inactive' });\r\n * \r\n * // Delete records\r\n * await db.table('users')\r\n * .where('status', '=', 'deleted')\r\n * .delete();\r\n * \r\n * // Access column management\r\n * const columns = await db.table('users').columns().get();\r\n */\r\n table<T extends DatabaseRecord = DatabaseRecord>(tableName: string): Table<T> {\r\n return new Table<T>(this, this.name, tableName, this.engine, this.computedFields, this.triggers, this.txId);\r\n }\r\n\r\n private setComputedFields(computedFields: ComputedFieldConfig[]){\r\n this.computedFields = computedFields;\r\n }\r\n\r\n private setTriggers(triggers: TriggerConfig[]){\r\n this.triggers = triggers;\r\n }\r\n}\r\n\r\n/**\r\n * Class to build and execute SQL queries for a specific table.\r\n * Supports operations like SELECT, INSERT, UPDATE, DELETE, and more.\r\n *\r\n * Generic over the row shape: `db.table<User>('users').get()` resolves to\r\n * `Promise<User[]>`. Pair it with the interfaces emitted by `dbcube generate`.\r\n */\r\nexport class Table<T extends DatabaseRecord = DatabaseRecord> {\r\n private engine: QueryEngine;\r\n private nextType: 'AND' | 'OR' = 'AND';\r\n private dml: DML;\r\n private computedFields: ComputedFieldConfig[] = [];\r\n private trigger: Trigger;\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n private relations: { name: string; options: RelationOptions }[] = [];\r\n /** Builders de grupo mutan en sitio (ver clone()) */\r\n private _mutable = false;\r\n\r\n private instance: Database;\r\n\r\n constructor(instance: Database, databaseName: string, tableName: string, engine: QueryEngine, computedFields: ComputedFieldConfig[] = [], triggers: TriggerConfig[] = [], txId: string | null = null) {\r\n this.engine = engine;\r\n this.instance = instance;\r\n this.computedFields = computedFields;\r\n this.triggers = triggers;\r\n this.trigger = new Trigger(instance, databaseName, triggers);\r\n this.nextType = 'AND';\r\n this.txId = txId;\r\n\r\n this.dml = {\r\n type: 'select',\r\n database: databaseName,\r\n table: tableName,\r\n columns: ['*'],\r\n distinct: false,\r\n joins: [],\r\n where: [],\r\n orderBy: [],\r\n groupBy: [],\r\n limit: null,\r\n offset: null,\r\n data: null,\r\n aggregation: null,\r\n having: []\r\n };\r\n }\r\n\r\n /**\r\n * Specifies the columns to select in a SELECT query.\r\n *\r\n * @param {string[]} fields - Array of column names to select. If empty, selects all columns.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').select(['id', 'name']).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n select(fields: string[] = []): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = fields.length > 0 ? fields : ['*'];\r\n clone.dml.aggregation = null;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).get();\r\n * const nullUsers = await db.table('users').where('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n where(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n where(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n where(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an OR WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).orWhere('name', '=', 'Jane').get();\r\n * const nullUsers = await db.table('users').where('active', '=', true).orWhere('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n orWhere(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n orWhere(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n orWhere(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'OR',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a grouped WHERE condition to the query.\r\n *\r\n * @param {WhereCallback} callback - A callback function that receives a new Table instance to build the grouped conditions.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereGroup(query => {\r\n * query.where('age', '>', 25).orWhere('name', '=', 'Jane');\r\n * }).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereGroup(callback: WhereCallback): Table<T> {\r\n const clone = this.clone();\r\n const groupQuery = new Table(this.instance, clone.dml.database, clone.dml.table, clone.engine);\r\n // El callback encadena sin usar el valor de retorno; el builder del\r\n // grupo debe mutar en sitio o las condiciones se perderían en clones\r\n groupQuery._mutable = true;\r\n callback(groupQuery);\r\n\r\n clone.dml.where.push({\r\n type: clone.nextType,\r\n isGroup: true,\r\n conditions: groupQuery.dml.where as WhereCondition[]\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n or(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'OR';\r\n return clone;\r\n }\r\n\r\n and(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE BETWEEN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {[any, any]} values - A tuple with two values representing the range.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereBetween('age', [20, 30]).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereBetween(column: string, values: [any, any]): Table<T> {\r\n const clone = this.clone();\r\n const [value1, value2] = values;\r\n if (value1 !== undefined && value2 !== undefined) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'BETWEEN',\r\n value: [value1, value2],\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {any[]} values - An array of values to match.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereIn('id', [1, 2]).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n whereIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNull('email').get();\r\n * console.log(users); // [{ id: 3, name: 'Alice', email: null }]\r\n */\r\n whereNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NOT NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotNull('email').get();\r\n * console.log(users); // [{ id: 1, name: 'John', email: 'john@example.com' }]\r\n */\r\n whereNotNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NOT NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').join('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }]\r\n */\r\n join(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'INNER',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a LEFT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').leftJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: 2, name: 'Jane', order_id: null }]\r\n */\r\n leftJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'LEFT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a RIGHT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').rightJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: null, name: null, order_id: 102 }]\r\n */\r\n rightJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'RIGHT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an ORDER BY clause to the query.\r\n *\r\n * @param {string} column - The column to order by.\r\n * @param {'ASC' | 'DESC'} direction - The sorting direction ('ASC' or 'DESC').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').orderBy('name', 'ASC').get();\r\n * console.log(users); // [{ id: 2, name: 'Jane' }, { id: 1, name: 'John' }]\r\n */\r\n orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): Table<T> {\r\n const clone = this.clone();\r\n const validDirections: ('ASC' | 'DESC')[] = ['ASC', 'DESC'];\r\n if (validDirections.includes(direction.toUpperCase() as 'ASC' | 'DESC')) {\r\n clone.dml.orderBy.push({\r\n column,\r\n direction: direction.toUpperCase() as 'ASC' | 'DESC'\r\n });\r\n } else {\r\n throw new Error(`Invalid direction: ${direction}. Use 'ASC' or 'DESC'.`);\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a GROUP BY clause to the query.\r\n *\r\n * @param {string} column - The column to group by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').groupBy('age').get();\r\n * console.log(users); // [{ age: 30, count: 1 }, { age: 25, count: 1 }]\r\n */\r\n groupBy(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.groupBy.push(column);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a DISTINCT clause to the query.\r\n *\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').distinct().select(['name']).get();\r\n * console.log(users); // [{ name: 'John' }, { name: 'Jane' }]\r\n */\r\n distinct(): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.distinct = true;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a COUNT clause to the query.\r\n *\r\n * @param {string} column - The column to count (default is '*').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const count = await db.table('users').count().first();\r\n * console.log(count); // { count: 2 }\r\n */\r\n async count(column: string = '*'): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'COUNT',\r\n column,\r\n alias: 'count'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`COUNT(${column}) AS count`];\r\n clone.dml.data = null;\r\n clone.dml.limit = null; // Remover limit para contar todos\r\n clone.dml.offset = null; // Remover offset también\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.count;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a SUM clause to the query.\r\n *\r\n * @param {string} column - The column to sum.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const totalAge = await db.table('users').sum('age').first();\r\n * console.log(totalAge); // { sum: 55 }\r\n */\r\n async sum(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'SUM',\r\n column,\r\n alias: 'sum'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`SUM(${column}) AS sum`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.sum;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds an AVG clause to the query.\r\n *\r\n * @param {string} column - The column to calculate the average.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const avgAge = await db.table('users').avg('age').first();\r\n * console.log(avgAge); // { avg: 27.5 }\r\n */\r\n async avg(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'AVG',\r\n column,\r\n alias: 'avg'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`AVG(${column}) AS avg`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.avg;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MAX clause to the query.\r\n *\r\n * @param {string} column - The column to find the maximum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const maxAge = await db.table('users').max('age').first();\r\n * console.log(maxAge); // { max: 30 }\r\n */\r\n async max(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MAX',\r\n column,\r\n alias: 'max'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`MAX(${column}) AS max`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.max;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MIN clause to the query.\r\n *\r\n * @param {string} column - The column to find the minimum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const minAge = await db.table('users').min('age').first();\r\n * console.log(minAge); // { min: 25 }\r\n */\r\n async min(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MIN',\r\n column,\r\n alias: 'min'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`MIN(${column}) AS min`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.min;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the column names of the table.\r\n * For SQL databases (MySQL, PostgreSQL, SQLite), returns a simple array of column names.\r\n * For MongoDB, returns a hierarchical structure with nested documents.\r\n *\r\n * @returns {Promise<string[] | any>} - Returns an array of column names for SQL databases,\r\n * or a hierarchical structure for MongoDB.\r\n *\r\n * @example\r\n * // SQL databases (MySQL, PostgreSQL, SQLite)\r\n * const columns = await db.table('users').columns();\r\n * console.log(columns); // ['id', 'name', 'email', 'age', 'created_at']\r\n *\r\n * @example\r\n * // MongoDB\r\n * const structure = await db.table('users').columns();\r\n * console.log(structure);\r\n * // {\r\n * // columns: ['id', 'name', 'profile'],\r\n * // submenu: {\r\n * // profile: {\r\n * // columns: ['age', 'city'],\r\n * // submenu: {}\r\n * // }\r\n * // }\r\n * // }\r\n */\r\n async columns(): Promise<string[] | any> {\r\n const clone = this.clone();\r\n clone.dml.type = 'columns';\r\n clone.dml.columns = [];\r\n clone.dml.where = [];\r\n clone.dml.orderBy = [];\r\n clone.dml.groupBy = [];\r\n clone.dml.limit = null;\r\n clone.dml.offset = null;\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n\r\n try {\r\n const result = await clone.getResponse();\r\n\r\n if (Array.isArray(result) && result.length > 0) {\r\n // Verificar si es MongoDB (estructura jerárquica)\r\n if (result[0].columns && result[0].submenu !== undefined) {\r\n // MongoDB: devolver la estructura completa\r\n return result[0];\r\n }\r\n\r\n // SQL databases: transformar a array simple de strings\r\n return result.map((row: any) => row.column_name || row.Field || row.name);\r\n }\r\n\r\n return [];\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a LIMIT clause to the query.\r\n *\r\n * @param {number} number - The maximum number of rows to return.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n limit(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.limit = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds pagination to the query using LIMIT and OFFSET.\r\n *\r\n * @param {number} number - The page number (starting from 1).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).page(2).get();\r\n * console.log(users); // [{ id: 2, name: 'Jane', age: 25 }]\r\n */\r\n page(number: number): Table<T> {\r\n const clone = this.clone();\r\n const pageNum = Number(number);\r\n if (clone.dml.limit) {\r\n clone.dml.offset = (pageNum - 1) * clone.dml.limit;\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Executes the query and returns all matching rows.\r\n *\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of rows.\r\n *\r\n * @example\r\n * const users = await db.table('users').get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n async get(): Promise<T[]> {\r\n try {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n const result = await clone.getResponse();\r\n if (this.relations.length > 0 && Array.isArray(result)) {\r\n return await this.attachRelations(result) as T[];\r\n }\r\n return result as T[];\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Executes the query and returns the first matching row.\r\n *\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').first();\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async first(): Promise<T | null> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Finds a row by a specific column value.\r\n *\r\n * @param {any} value - The value to search for.\r\n * @param {string} column - The column to search in (default is 'id').\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first matching row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').find(1);\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async find(value: string | number, column: string = 'id'): Promise<T | null> {\r\n // where() is immutable: reassign the clone or the condition is lost\r\n const clone = this.clone().where(column, '=', value);\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Inserts one or more rows into the table.\r\n *\r\n * @param {DatabaseRecord[]} data - An array of objects representing the rows to insert.\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of the inserted rows.\r\n *\r\n * @example\r\n * const newUsers = await db.table('users').insert([\r\n * { name: 'Alice', age: 28 },\r\n * { name: 'Bob', age: 32 }\r\n * ]);\r\n * console.log(newUsers); // [{ id: 3, name: 'Alice', age: 28 }, { id: 4, name: 'Bob', age: 32 }]\r\n */\r\n async insert(data: Partial<T>[]): Promise<T[]> {\r\n const clone = this.clone();\r\n if (!Array.isArray(data)) {\r\n throw new Error('The insert method requires an array of objects with key-value pairs.');\r\n }\r\n\r\n if (!data.every(item => typeof item === 'object' && item !== null)) {\r\n throw new Error('The array must contain only valid objects.');\r\n }\r\n\r\n clone.dml.type = 'insert';\r\n clone.dml.data = data;\r\n\r\n const result = await clone.getResponse(clone.dml, 'Add');\r\n\r\n return result ?? data;\r\n }\r\n\r\n /**\r\n * Updates rows in the table based on the defined conditions.\r\n *\r\n * @param {DatabaseRecord} data - An object with key-value pairs representing the fields to update.\r\n * @returns {Promise<any>} - Returns the result of the update operation.\r\n *\r\n * @example\r\n * const result = await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ name: 'John Updated', age: 31 });\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async update(data: Partial<T>): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (typeof data !== 'object' || Array.isArray(data)) {\r\n throw new Error('The update method requires an object with key-value pairs.');\r\n }\r\n\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an update.');\r\n }\r\n\r\n clone.dml.type = 'update';\r\n clone.dml.data = data;\r\n\r\n return clone.getResponse(clone.dml, 'Update');\r\n }\r\n\r\n /**\r\n * Deletes rows from the table based on the defined conditions.\r\n *\r\n * @returns {Promise<any>} - Returns the result of the delete operation.\r\n *\r\n * @example\r\n * const result = await db.table('users').where('id', '=', 1).delete();\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async delete(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform a delete.');\r\n }\r\n\r\n clone.dml.type = 'delete';\r\n\r\n const deleteData = await clone.getResponse(clone.dml, 'Delete');\r\n return deleteData;\r\n }\r\n\r\n /**\r\n * Adds a WHERE NOT IN condition to the query.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotIn('status', ['banned', 'deleted']).get();\r\n */\r\n whereNotIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'NOT IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Sets an explicit OFFSET for the query (alternative to page()).\r\n *\r\n * @example\r\n * const rows = await db.table('logs').orderBy('id', 'ASC').limit(50).offset(100).get();\r\n */\r\n offset(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.offset = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Appends raw expressions to the SELECT list (aggregates, functions, aliases).\r\n * Combine with groupBy() and having() for per-group metrics.\r\n *\r\n * @example\r\n * const stats = await db.table('orders')\r\n * .select(['user_id'])\r\n * .selectRaw(['COUNT(*) AS order_count', 'SUM(amount) AS total'])\r\n * .groupBy('user_id')\r\n * .having('order_count', '>', 5)\r\n * .get();\r\n */\r\n selectRaw(expressions: string[]): Table<T> {\r\n const clone = this.clone();\r\n if (clone.dml.columns.length === 1 && clone.dml.columns[0] === '*') {\r\n clone.dml.columns = [...expressions];\r\n } else {\r\n clone.dml.columns = [...clone.dml.columns, ...expressions];\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a HAVING condition (filters grouped results).\r\n *\r\n * @example\r\n * .groupBy('user_id').having('COUNT(*)', '>', 5)\r\n */\r\n having(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.having = clone.dml.having ?? [];\r\n clone.dml.having.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'AND',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Checks if at least one row matches the current conditions.\r\n * Cheaper than first(): selects a constant with LIMIT 1.\r\n *\r\n * @example\r\n * const taken = await db.table('users').where('email', '=', email).exists();\r\n */\r\n async exists(): Promise<boolean> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = ['1 AS dbcube_exists'];\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n clone.dml.offset = null;\r\n const result = await clone.getResponse();\r\n return Array.isArray(result) && result.length > 0;\r\n }\r\n\r\n /**\r\n * Fetches one page of results plus pagination metadata in a single call.\r\n * Runs the page query and the total count with the same conditions.\r\n *\r\n * @example\r\n * const { items, total, totalPages, hasNext } = await db.table('products')\r\n * .where('published', '=', true)\r\n * .orderBy('id', 'ASC')\r\n * .paginate(2, 25);\r\n */\r\n async paginate(page: number = 1, perPage: number = 20): Promise<PaginatedResult<T>> {\r\n const pageNum = Math.max(1, Number(page));\r\n const size = Math.max(1, Number(perPage));\r\n\r\n const itemsQuery = this.limit(size).page(pageNum);\r\n const [items, total] = await Promise.all([\r\n itemsQuery.get(),\r\n this.count()\r\n ]);\r\n\r\n const totalNum = Number(total);\r\n const totalPages = Math.ceil(totalNum / size);\r\n return {\r\n items,\r\n page: pageNum,\r\n perPage: size,\r\n total: totalNum,\r\n totalPages,\r\n hasNext: pageNum < totalPages,\r\n hasPrev: pageNum > 1,\r\n };\r\n }\r\n\r\n /**\r\n * Processes all matching rows in batches of `size`, keeping memory flat.\r\n * Return `false` from the callback to stop early.\r\n *\r\n * @example\r\n * await db.table('logs').orderBy('id', 'ASC').chunk(500, async (rows) => {\r\n * await processBatch(rows);\r\n * });\r\n */\r\n async chunk(size: number, callback: (rows: T[], page: number) => Promise<void | boolean> | void | boolean): Promise<void> {\r\n const batchSize = Math.max(1, Number(size));\r\n let page = 1;\r\n while (true) {\r\n const rows = await this.limit(batchSize).page(page).get();\r\n if (rows.length === 0) break;\r\n const result = await callback(rows, page);\r\n if (result === false) break;\r\n if (rows.length < batchSize) break;\r\n page++;\r\n }\r\n }\r\n\r\n /**\r\n * Atomically increments a numeric column: `SET col = col + amount`.\r\n * Requires at least one WHERE condition. Extra fields can be updated in the same statement.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).increment('stock', 3);\r\n * await db.table('posts').where('id', '=', 1).increment('views', 1, { last_viewed_at: new Date().toISOString() });\r\n */\r\n async increment(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an increment.');\r\n }\r\n clone.dml.type = 'update';\r\n clone.dml.data = { ...extra, [column]: { $inc: Number(amount) } };\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Atomically decrements a numeric column: `SET col = col - amount`.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).decrement('stock', 1);\r\n */\r\n async decrement(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n return this.increment(column, -Math.abs(Number(amount)), extra);\r\n }\r\n\r\n /**\r\n * Deletes ALL rows from the table. The only write operation allowed\r\n * without a WHERE — the destructive intent is explicit in the name.\r\n *\r\n * @example\r\n * await db.table('temp_imports').truncate();\r\n */\r\n async truncate(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n clone.dml.type = 'delete';\r\n clone.dml.where = [];\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Inserts rows, updating them instead when a conflict occurs on the given keys.\r\n * MySQL → ON DUPLICATE KEY UPDATE · PostgreSQL/SQLite → ON CONFLICT ... DO UPDATE.\r\n *\r\n * @param data Rows to insert.\r\n * @param conflictKeys Column(s) with the UNIQUE/PK constraint that triggers the update.\r\n * @param updateColumns Columns to overwrite on conflict (defaults to every non-conflict column).\r\n *\r\n * @example\r\n * await db.table('settings').upsert(\r\n * [{ key: 'theme', value: 'dark' }],\r\n * ['key']\r\n * );\r\n */\r\n async upsert(data: Partial<T>[], conflictKeys: string[], updateColumns?: string[]): Promise<MutationInfo[]> {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n throw new Error('The upsert method requires a non-empty array of objects.');\r\n }\r\n if (!Array.isArray(conflictKeys) || conflictKeys.length === 0) {\r\n throw new Error('The upsert method requires at least one conflict key column.');\r\n }\r\n\r\n const motor: string = this.engine?.getConfig?.()?.type ?? 'mysql';\r\n\r\n const table = this.dml.table;\r\n const columns = Object.keys(data[0]);\r\n const targets = updateColumns ?? columns.filter(c => !conflictKeys.includes(c));\r\n\r\n // Único método que arma la operación en JS: validar identificadores\r\n // porque las claves de los objetos pueden venir de input externo\r\n assertValidIdentifier(table, 'table');\r\n for (const c of columns) assertValidIdentifier(c, 'column');\r\n for (const c of conflictKeys) assertValidIdentifier(c, 'conflict key');\r\n for (const c of targets) assertValidIdentifier(c, 'update column');\r\n\r\n if (motor === 'mongodb') {\r\n // Comando `update` nativo con upsert:true por fila — misma semántica\r\n // que ON CONFLICT: matchea por conflictKeys, actualiza solo targets,\r\n // y al insertar escribe la fila completa.\r\n const updates = data.map(row => {\r\n const q: Record<string, unknown> = {};\r\n for (const k of conflictKeys) q[k] = row[k];\r\n\r\n const set: Record<string, unknown> = {};\r\n for (const c of targets) if (c in row) set[c] = row[c];\r\n\r\n const setOnInsert: Record<string, unknown> = {};\r\n for (const c of columns) {\r\n if (!targets.includes(c) && !conflictKeys.includes(c)) setOnInsert[c] = row[c];\r\n }\r\n if (!('uuid' in row)) setOnInsert['uuid'] = randomUUID();\r\n\r\n const u: Record<string, unknown> = {};\r\n if (Object.keys(set).length) u['$set'] = set;\r\n if (Object.keys(setOnInsert).length) u['$setOnInsert'] = setOnInsert;\r\n\r\n return { q, u, upsert: true, multi: false };\r\n });\r\n\r\n const command = JSON.stringify({ update: table, updates });\r\n const response = await this.engine.rawQuery(command, [], this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n const quote = (id: string) => motor === 'mysql' ? `\\`${id}\\`` : `\"${id}\"`;\r\n\r\n const params: any[] = [];\r\n const placeholder = () => motor === 'postgres' || motor === 'postgresql'\r\n ? `$${params.length}`\r\n : '?';\r\n\r\n const rowsSql = data.map(row => {\r\n const cells = columns.map(col => {\r\n params.push(row[col] === undefined ? null : row[col]);\r\n return placeholder();\r\n });\r\n return `(${cells.join(', ')})`;\r\n }).join(', ');\r\n\r\n const colsSql = columns.map(quote).join(', ');\r\n let sql: string;\r\n\r\n if (motor === 'mysql') {\r\n const updates = targets.map(c => `${quote(c)} = VALUES(${quote(c)})`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON DUPLICATE KEY UPDATE ${updates}`;\r\n } else {\r\n const conflict = conflictKeys.map(quote).join(', ');\r\n const updates = targets.map(c => `${quote(c)} = excluded.${quote(c)}`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON CONFLICT (${conflict}) DO UPDATE SET ${updates}`;\r\n }\r\n\r\n if (motor === 'sqlite') {\r\n // SQLite pool schema sync: ensure every pooled connection sees constraints\r\n // created moments ago (e.g. a UNIQUE index added right before this upsert).\r\n await this.engine.rawQuery('SELECT name FROM sqlite_master LIMIT 1', [], this.txId ?? undefined);\r\n }\r\n const response = await this.engine.rawQuery(sql, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Declares a relation to eager-load with the results of get().\r\n * Relations are resolved from `foreign` definitions in your .cube files,\r\n * or explicitly via options. Loads each relation with ONE batched query\r\n * (whereIn) — no N+1.\r\n *\r\n * @example\r\n * // hasMany: orders.user_id → users.id (auto-detected from orders.table.cube)\r\n * const users = await db.table('users').with('orders').get();\r\n * // users[0].orders === [{...}, {...}]\r\n *\r\n * // belongsTo: posts.author_id → users.id, attached as a single object\r\n * const posts = await db.table('posts')\r\n * .with('author', { table: 'users', foreignKey: 'author_id', type: 'one' })\r\n * .get();\r\n */\r\n with(relation: string, options: RelationOptions = {}): Table<T> {\r\n const clone = this.clone();\r\n clone.relations.push({ name: relation, options });\r\n return clone;\r\n }\r\n\r\n private async attachRelations(rows: DatabaseRecord[]): Promise<DatabaseRecord[]> {\r\n if (rows.length === 0 || this.relations.length === 0) return rows;\r\n\r\n for (const { name, options } of this.relations) {\r\n const relatedTable = options.table ?? name;\r\n const cubeMeta = loadCubeRelations();\r\n\r\n // Detect direction + keys from .cube foreign metadata when not explicit\r\n let type = options.type;\r\n let foreignKey = options.foreignKey;\r\n let localKey = options.localKey ?? 'id';\r\n\r\n if (!foreignKey || !type) {\r\n const childFks = cubeMeta[relatedTable]?.foreigns ?? [];\r\n const ownFks = cubeMeta[this.dml.table]?.foreigns ?? [];\r\n const childToParent = childFks.find(fk => fk.table === this.dml.table);\r\n const parentToChild = ownFks.find(fk => fk.table === relatedTable);\r\n\r\n if (childToParent) {\r\n // hasMany: the related table points at us\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? childToParent.column_name;\r\n localKey = options.localKey ?? childToParent.column;\r\n } else if (parentToChild) {\r\n // belongsTo: we point at the related table\r\n type = type ?? 'one';\r\n foreignKey = foreignKey ?? parentToChild.column_name;\r\n localKey = options.localKey ?? parentToChild.column;\r\n } else {\r\n // Heuristic fallback: <singular-parent>_id on the child table\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? `${singularize(this.dml.table)}_id`;\r\n }\r\n }\r\n\r\n const relatedQuery = new Table(this.instance, this.dml.database, relatedTable, this.engine, this.computedFields, this.triggers, this.txId);\r\n\r\n if (type === 'one') {\r\n // belongsTo: FK lives on THIS table, match related.localKey\r\n const fkValues = [...new Set(rows.map(r => r[foreignKey!]).filter(v => v !== null && v !== undefined))];\r\n const related = fkValues.length > 0\r\n ? await relatedQuery.whereIn(localKey, fkValues).get()\r\n : [];\r\n const index = new Map(related.map(r => [r[localKey], r]));\r\n for (const row of rows) {\r\n row[name] = index.get(row[foreignKey!]) ?? null;\r\n }\r\n } else {\r\n // hasMany: FK lives on the RELATED table, match this.localKey\r\n const ids = [...new Set(rows.map(r => r[localKey]).filter(v => v !== null && v !== undefined))];\r\n const related = ids.length > 0\r\n ? await relatedQuery.whereIn(foreignKey!, ids).get()\r\n : [];\r\n const groups = new Map<any, DatabaseRecord[]>();\r\n for (const rel of related) {\r\n const key = rel[foreignKey!];\r\n if (!groups.has(key)) groups.set(key, []);\r\n groups.get(key)!.push(rel);\r\n }\r\n for (const row of rows) {\r\n row[name] = groups.get(row[localKey]) ?? [];\r\n }\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n private async getResponse(dml: any = null, type: any = null): Promise<any> {\r\n const localDML = dml ? dml : this.dml;\r\n const computedFieldsNeeded: any[] = [];\r\n let dependeciesArrray: any[] = [];\r\n // Columnas pedidas por el usuario ANTES de inyectar dependencias de\r\n // computed fields: las dependencias solo se eliminan del resultado si\r\n // el usuario NO las pidió explícitamente\r\n const requestedColumns = new Set<string>(localDML.columns ?? []);\r\n\r\n if (this.computedFields.length > 0) {\r\n let columns = localDML.columns;\r\n\r\n for (const field of localDML.columns) {\r\n const computedField = this.computedFields.find(cf => cf.column === field);\r\n\r\n if (computedField) {\r\n computedFieldsNeeded.push(computedField);\r\n // Add dependencies to real fields\r\n const dependencies = ComputedFieldProcessor.extractDependencies(computedField.instruction);\r\n dependeciesArrray = [...dependeciesArrray, ...dependencies];\r\n columns = Array.from(new Set([...columns, ...dependencies]));\r\n columns = columns.filter((col: string) => col != field);\r\n }\r\n }\r\n localDML.columns = columns;\r\n }\r\n\r\n let arrayResult = [];\r\n if (type) {\r\n const beffore = this.trigger.get('before' + type);\r\n const after = this.trigger.get('after' + type);\r\n if (this.triggers.length > 0 && (beffore || after)) {\r\n const dataset = localDML.data;\r\n for (let index = 0; index < dataset.length; index++) {\r\n const data = dataset[index];\r\n const newDML = { ...localDML, data: [data] };\r\n if (beffore) {\r\n const interceptor = await this.trigger.execute('before' + type, data);\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n interceptor?.discard();\r\n returnFormattedError(response.status, response.message);\r\n // Un fallo del engine DEBE propagarse: resolver en\r\n // silencio haría creer al caller que la escritura\r\n // ocurrió (pérdida de datos invisible)\r\n throw new Error(String(response.message));\r\n }\r\n await interceptor?.commit();\r\n arrayResult = response.data;\r\n }\r\n if (after) {\r\n\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(String(response.message));\r\n }\r\n const interceptor = await this.trigger.execute('after' + type, data);\r\n await interceptor?.commit();\r\n }\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(String(response.message));\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(String(response.message));\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n\r\n if (computedFieldsNeeded.length > 0) {\r\n let newDataset: any = ComputedFieldProcessor.computedFields(arrayResult, computedFieldsNeeded);\r\n const toRemove = dependeciesArrray.filter(key => !requestedColumns.has(key));\r\n const result = newDataset.map((obj: any) => {\r\n const newObj = { ...obj };\r\n toRemove.forEach(key => delete newObj[key]);\r\n return newObj;\r\n });\r\n return result;\r\n }\r\n return arrayResult;\r\n }\r\n\r\n private clone(): Table<T> {\r\n // Los builders de grupo (whereGroup) son mutables: el callback encadena\r\n // sin usar el valor de retorno, así que clonar perdería las condiciones\r\n if (this._mutable) return this;\r\n const cloned = Object.create(Object.getPrototypeOf(this));\r\n cloned.engine = this.engine;\r\n cloned.instance = this.instance;\r\n cloned.nextType = this.nextType;\r\n cloned.computedFields = this.computedFields;\r\n cloned.trigger = this.trigger;\r\n cloned.triggers = this.triggers;\r\n cloned.txId = this.txId;\r\n cloned.relations = [...this.relations];\r\n\r\n cloned.dml = {\r\n ...this.dml,\r\n columns: [...this.dml.columns],\r\n joins: [...this.dml.joins],\r\n where: [...this.dml.where],\r\n orderBy: [...this.dml.orderBy],\r\n groupBy: [...this.dml.groupBy],\r\n having: [...(this.dml.having ?? [])],\r\n // Clonar propiedades que faltaban para evitar mutación compartida\r\n data: this.dml.data ? (Array.isArray(this.dml.data) ? [...this.dml.data] : { ...this.dml.data }) : null,\r\n aggregation: this.dml.aggregation ? { ...this.dml.aggregation } : null\r\n };\r\n return cloned;\r\n }\r\n\r\n}\r\n\r\n// ---- Cube relation metadata (cached scan of dbcube/*.table.cube) ----\r\n\r\ninterface CubeForeign {\r\n column_name: string; // FK column on the owning table\r\n table: string; // referenced table\r\n column: string; // referenced column\r\n}\r\n\r\nlet cubeRelationsCache: Record<string, { foreigns: CubeForeign[] }> | null = null;\r\n\r\nfunction loadCubeRelations(): Record<string, { foreigns: CubeForeign[] }> {\r\n if (cubeRelationsCache) return cubeRelationsCache;\r\n const result: Record<string, { foreigns: CubeForeign[] }> = {};\r\n\r\n const scanDir = (dir: string) => {\r\n let entries: fs.Dirent[];\r\n try {\r\n entries = fs.readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const entry of entries) {\r\n const full = path.join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n if (entry.name !== 'node_modules' && entry.name !== 'triggers' && entry.name !== 'logs') {\r\n scanDir(full);\r\n }\r\n } else if (entry.name.endsWith('.table.cube')) {\r\n try {\r\n const content = fs.readFileSync(full, 'utf8');\r\n const nameMatch = content.match(/@meta\\s*\\(\\s*\\{[\\s\\S]*?name\\s*:\\s*\"([^\"]+)\"/);\r\n const tableName = nameMatch ? nameMatch[1] : path.basename(entry.name, '.table.cube');\r\n\r\n const foreigns: CubeForeign[] = [];\r\n const colRegex = /(\\w+)\\s*:\\s*\\{(?:[^{}]|\\{[^{}]*\\})*?foreign\\s*:\\s*\\{([^}]*)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = colRegex.exec(content)) !== null) {\r\n const fkTable = m[2].match(/table\\s*:\\s*\"([^\"]+)\"/);\r\n const fkColumn = m[2].match(/column\\s*:\\s*\"([^\"]+)\"/);\r\n if (fkTable) {\r\n foreigns.push({\r\n column_name: m[1],\r\n table: fkTable[1],\r\n column: fkColumn ? fkColumn[1] : 'id',\r\n });\r\n }\r\n }\r\n result[tableName] = { foreigns };\r\n } catch { /* unreadable cube — skip */ }\r\n }\r\n }\r\n };\r\n\r\n scanDir(path.join(process.cwd(), 'dbcube'));\r\n cubeRelationsCache = result;\r\n return result;\r\n}\r\n\r\nfunction assertValidIdentifier(name: string, kind: string): void {\r\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\r\n throw new Error(`Invalid ${kind} name: '${name}'. Only letters, numbers and underscore are allowed.`);\r\n }\r\n}\r\n\r\nfunction singularize(word: string): string {\r\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\r\n if (word.endsWith('ses')) return word.slice(0, -2);\r\n if (word.endsWith('s') && !word.endsWith('ss')) return word.slice(0, -1);\r\n return word;\r\n}\r\n\r\nfunction returnFormattedError(status: number, message: string) {\r\n const RESET = '\\x1b[0m';\r\n const RED = '\\x1b[31m';\r\n const YELLOW = '\\x1b[33m';\r\n const BOLD = '\\x1b[1m';\r\n const CYAN = '\\x1b[36m';\r\n const GRAY = '\\x1b[90m';\r\n const UNDERLINE = '\\x1b[4m';\r\n const MAGENTA = '\\x1b[35m';\r\n\r\n let output = '';\r\n let help = '';\r\n const color = status === 600 ? YELLOW : RED;\r\n\r\n\r\n if (message.includes(\"[help]\")) {\r\n const parts = message.split(\"[help]\");\r\n output += `\\n${RED}${BOLD}${parts[0]}${RESET}`;\r\n help += `\\n${MAGENTA}${BOLD}[help]${RESET} ${GRAY}${parts[1]}${RESET}\\n`;\r\n } else {\r\n output += `\\n${color}${BOLD}${message}${RESET}\\n`;\r\n }\r\n\r\n const err = new Error();\r\n const stackLines = err.stack?.split('\\n') || [];\r\n\r\n // Buscamos la primera línea del stack fuera de node_modules\r\n const relevantStackLine = stackLines.find(line =>\r\n line.includes('.js:') && !line.includes('node_modules')\r\n );\r\n\r\n if (relevantStackLine) {\r\n const match = relevantStackLine.match(/\\((.*):(\\d+):(\\d+)\\)/) ||\r\n relevantStackLine.match(/at (.*):(\\d+):(\\d+)/);\r\n\r\n if (match) {\r\n const [, filePath, lineStr, columnStr] = match;\r\n const lineNum = parseInt(lineStr, 10);\r\n const errorLocation = `${filePath}:${lineStr}:${columnStr}`;\r\n\r\n // Leemos el archivo y sacamos las líneas relevantes\r\n try {\r\n const codeLines = fs.readFileSync(filePath, 'utf-8').split('\\n');\r\n const start = Math.max(0, lineNum - 3);\r\n const end = Math.min(codeLines.length, lineNum + 2);\r\n\r\n output += `\\n${CYAN}${BOLD}[code] ${RESET}${YELLOW} ${UNDERLINE}${errorLocation}${RESET}\\n`;\r\n\r\n for (let i = start; i < end; i++) {\r\n const line = codeLines[i];\r\n const lineLabel = `${i + 1}`.padStart(4, ' ');\r\n const pointer = i + 1 === lineNum ? `${RED}<-${RESET}` : ' ';\r\n output += `${GRAY}${lineLabel}${RESET} ${pointer} ${line}\\n`;\r\n }\r\n } catch (err) {\r\n output += `${YELLOW}⚠️ No se pudo leer el archivo de origen: ${filePath}${RESET}\\n`;\r\n output += `\\n${CYAN}${BOLD}Stack Trace:${RESET}\\n${stackLines.slice(2).join('\\n')}\\n`;\r\n }\r\n }\r\n }\r\n output += help;\r\n console.error(output);\r\n}\r\n\r\nexport default Database;\r\n","import path from \"path\";\nimport { FileLogger, InterceptController } from \"@dbcube/core\";\nimport { createRequire } from 'module';\nimport type { TriggerConfig } from \"../@types/Database\";\n\n/**\n * Runtime triggers: user-defined JS functions (from .trigger.cube files) that\n * run in the application process around each write. Because they execute in\n * the write-path (not as DB-side triggers), they behave identically across\n * MySQL, PostgreSQL, SQLite and MongoDB, and fire exactly once per operation\n * regardless of how many service instances share the database.\n */\nexport class Trigger {\n private triggers: TriggerConfig[];\n private databaseName: string;\n private instance: unknown;\n\n constructor(instance: unknown, databaseName: string, metadata: TriggerConfig[]) {\n this.triggers = metadata;\n this.databaseName = databaseName;\n this.instance = instance;\n }\n\n get(type: string): TriggerConfig | undefined {\n return this.triggers.find((tr) => tr.type === type);\n }\n\n async execute(type: string, row: Record<string, unknown>): Promise<InterceptController | null> {\n const trigger = this.triggers.find((tr) => tr.type === type);\n if (trigger) {\n const logFilePath = path.resolve(\n process.cwd(),\n 'dbcube',\n 'logs',\n 'triggers',\n this.databaseName,\n `${trigger.table_ref}_${trigger.type}.log`\n );\n\n const interceptor = FileLogger.interceptConsole(logFilePath, {\n keepOriginal: false,\n useBuffer: true\n });\n const pathFile = path.resolve(process.cwd(), 'dbcube', 'triggers', `${trigger.database_ref}_${trigger.table_ref}_${trigger.type}.js`);\n // Use __filename for CJS, process.cwd() for ESM\n const requireUrl = typeof __filename !== 'undefined' ? __filename : process.cwd();\n const require = createRequire(requireUrl);\n // Clear require cache to ensure fresh load\n try {\n delete require.cache[require.resolve(pathFile)];\n } catch { /* bundled environments may not expose a resolvable cache */ }\n try {\n const triggerModule = require(pathFile);\n const dataProcess = triggerModule.default || triggerModule;\n await dataProcess({ db: this.instance, oldData: row, newData: row });\n } finally {\n // Sin esto, un trigger que lanza deja el console secuestrado\n // para SIEMPRE y el error se vuelve invisible para la app\n interceptor.restore();\n }\n return interceptor;\n }\n return null;\n }\n}\n"],"mappings":"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","names":["import_path","import_core","path","require","response","fs","path","err"]}
|
package/dist/index.js
CHANGED
|
@@ -42,10 +42,13 @@ var Trigger = class {
|
|
|
42
42
|
delete require2.cache[require2.resolve(pathFile)];
|
|
43
43
|
} catch {
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
try {
|
|
46
|
+
const triggerModule = require2(pathFile);
|
|
47
|
+
const dataProcess = triggerModule.default || triggerModule;
|
|
48
|
+
await dataProcess({ db: this.instance, oldData: row, newData: row });
|
|
49
|
+
} finally {
|
|
50
|
+
interceptor.restore();
|
|
51
|
+
}
|
|
49
52
|
return interceptor;
|
|
50
53
|
}
|
|
51
54
|
return null;
|
|
@@ -545,6 +548,7 @@ var Table = class _Table {
|
|
|
545
548
|
column,
|
|
546
549
|
alias: "count"
|
|
547
550
|
};
|
|
551
|
+
clone.dml.orderBy = [];
|
|
548
552
|
clone.dml.columns = [`COUNT(${column}) AS count`];
|
|
549
553
|
clone.dml.data = null;
|
|
550
554
|
clone.dml.limit = null;
|
|
@@ -578,6 +582,7 @@ var Table = class _Table {
|
|
|
578
582
|
column,
|
|
579
583
|
alias: "sum"
|
|
580
584
|
};
|
|
585
|
+
clone.dml.orderBy = [];
|
|
581
586
|
clone.dml.columns = [`SUM(${column}) AS sum`];
|
|
582
587
|
clone.dml.data = null;
|
|
583
588
|
clone.dml.limit = 1;
|
|
@@ -610,6 +615,7 @@ var Table = class _Table {
|
|
|
610
615
|
column,
|
|
611
616
|
alias: "avg"
|
|
612
617
|
};
|
|
618
|
+
clone.dml.orderBy = [];
|
|
613
619
|
clone.dml.columns = [`AVG(${column}) AS avg`];
|
|
614
620
|
clone.dml.data = null;
|
|
615
621
|
clone.dml.limit = 1;
|
|
@@ -642,6 +648,7 @@ var Table = class _Table {
|
|
|
642
648
|
column,
|
|
643
649
|
alias: "max"
|
|
644
650
|
};
|
|
651
|
+
clone.dml.orderBy = [];
|
|
645
652
|
clone.dml.columns = [`MAX(${column}) AS max`];
|
|
646
653
|
clone.dml.data = null;
|
|
647
654
|
clone.dml.limit = 1;
|
|
@@ -674,6 +681,7 @@ var Table = class _Table {
|
|
|
674
681
|
column,
|
|
675
682
|
alias: "min"
|
|
676
683
|
};
|
|
684
|
+
clone.dml.orderBy = [];
|
|
677
685
|
clone.dml.columns = [`MIN(${column}) AS min`];
|
|
678
686
|
clone.dml.data = null;
|
|
679
687
|
clone.dml.limit = 1;
|
|
@@ -1246,6 +1254,7 @@ var Table = class _Table {
|
|
|
1246
1254
|
const localDML = dml ? dml : this.dml;
|
|
1247
1255
|
const computedFieldsNeeded = [];
|
|
1248
1256
|
let dependeciesArrray = [];
|
|
1257
|
+
const requestedColumns = new Set(localDML.columns ?? []);
|
|
1249
1258
|
if (this.computedFields.length > 0) {
|
|
1250
1259
|
let columns = localDML.columns;
|
|
1251
1260
|
for (const field of localDML.columns) {
|
|
@@ -1275,6 +1284,7 @@ var Table = class _Table {
|
|
|
1275
1284
|
if (response.status != 200) {
|
|
1276
1285
|
interceptor?.discard();
|
|
1277
1286
|
returnFormattedError(response.status, response.message);
|
|
1287
|
+
throw new Error(String(response.message));
|
|
1278
1288
|
}
|
|
1279
1289
|
await interceptor?.commit();
|
|
1280
1290
|
arrayResult = response.data;
|
|
@@ -1283,6 +1293,7 @@ var Table = class _Table {
|
|
|
1283
1293
|
const response = await this.engine.executeDml(newDML, this.txId ?? void 0);
|
|
1284
1294
|
if (response.status != 200) {
|
|
1285
1295
|
returnFormattedError(response.status, response.message);
|
|
1296
|
+
throw new Error(String(response.message));
|
|
1286
1297
|
}
|
|
1287
1298
|
const interceptor = await this.trigger.execute("after" + type, data);
|
|
1288
1299
|
await interceptor?.commit();
|
|
@@ -1292,6 +1303,7 @@ var Table = class _Table {
|
|
|
1292
1303
|
const response = await this.engine.executeDml(localDML, this.txId ?? void 0);
|
|
1293
1304
|
if (response.status != 200) {
|
|
1294
1305
|
returnFormattedError(response.status, response.message);
|
|
1306
|
+
throw new Error(String(response.message));
|
|
1295
1307
|
}
|
|
1296
1308
|
arrayResult = response.data;
|
|
1297
1309
|
}
|
|
@@ -1299,14 +1311,16 @@ var Table = class _Table {
|
|
|
1299
1311
|
const response = await this.engine.executeDml(localDML, this.txId ?? void 0);
|
|
1300
1312
|
if (response.status != 200) {
|
|
1301
1313
|
returnFormattedError(response.status, response.message);
|
|
1314
|
+
throw new Error(String(response.message));
|
|
1302
1315
|
}
|
|
1303
1316
|
arrayResult = response.data;
|
|
1304
1317
|
}
|
|
1305
1318
|
if (computedFieldsNeeded.length > 0) {
|
|
1306
1319
|
let newDataset = ComputedFieldProcessor.computedFields(arrayResult, computedFieldsNeeded);
|
|
1320
|
+
const toRemove = dependeciesArrray.filter((key) => !requestedColumns.has(key));
|
|
1307
1321
|
const result = newDataset.map((obj) => {
|
|
1308
1322
|
const newObj = { ...obj };
|
|
1309
|
-
|
|
1323
|
+
toRemove.forEach((key) => delete newObj[key]);
|
|
1310
1324
|
return newObj;
|
|
1311
1325
|
});
|
|
1312
1326
|
return result;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/Database.ts","../src/lib/Trigger.ts","../src/index.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport { randomUUID } from 'crypto';\r\nimport { QueryEngine, ComputedFieldProcessor, TriggerProcessor } from \"@dbcube/core\";\r\nimport { ComputedFieldConfig, DatabaseRecord, DML, MutationInfo, PaginatedResult, RelationOptions, TriggerConfig, WhereCallback, WhereCondition } from \"../@types/Database\";\r\nimport { Trigger } from './Trigger';\r\n\r\n/**\r\n * Main class to handle MySQL database connections and queries.\r\n * Implements the Singleton pattern to ensure a single instance of the connection pool.\r\n */\r\nexport class Database {\r\n private name: string;\r\n private engine: QueryEngine;\r\n private computedFields: ComputedFieldConfig[];\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n\r\n constructor(name: string) {\r\n this.name = name;\r\n const engine = new QueryEngine(name);\r\n this.engine = engine;\r\n this.computedFields = [];\r\n this.triggers = [];\r\n }\r\n\r\n /**\r\n * Executes raw SQL (MySQL/PostgreSQL/SQLite) or a raw command document (MongoDB)\r\n * with bound parameters. The escape hatch for anything the builder doesn't cover.\r\n *\r\n * @example\r\n * const rows = await db.raw('SELECT * FROM users WHERE age > ?', [25]);\r\n * await db.raw('CREATE INDEX idx_users_email ON users(email)');\r\n */\r\n async raw<R = DatabaseRecord>(query: string, params: unknown[] = []): Promise<R[]> {\r\n const response = await this.engine.rawQuery(query, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Runs a callback inside a database transaction. Everything executed through\r\n * the received connection is committed atomically; any thrown error rolls\r\n * the whole transaction back.\r\n *\r\n * Requires daemon mode (enabled by default with an up-to-date query-engine).\r\n *\r\n * @example\r\n * await db.transaction(async (trx) => {\r\n * await trx.table('accounts').where('id', '=', 1).update({ balance: 50 });\r\n * await trx.table('accounts').where('id', '=', 2).update({ balance: 150 });\r\n * });\r\n */\r\n async transaction<T>(callback: (trx: Database) => Promise<T>): Promise<T> {\r\n const txId: string = await this.engine.beginTransaction();\r\n\r\n const trx = new Database(this.name);\r\n trx.engine = this.engine;\r\n trx.computedFields = this.computedFields;\r\n trx.triggers = this.triggers;\r\n trx.txId = txId;\r\n\r\n try {\r\n const result = await callback(trx);\r\n await this.engine.commitTransaction(txId);\r\n return result;\r\n } catch (error) {\r\n try {\r\n await this.engine.rollbackTransaction(txId);\r\n } catch (rollbackError: any) {\r\n // El error original manda, pero un rollback fallido no puede\r\n // pasar en silencio: la transacción puede seguir reteniendo\r\n // locks hasta que el daemon la expire por inactividad.\r\n console.error(\r\n `[dbcube] Rollback of transaction ${txId} failed: ${rollbackError?.message ?? rollbackError}`\r\n );\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async useComputes(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayComputedFields = await ComputedFieldProcessor.getComputedFields(this.name);\r\n newDatabase.setComputedFields(arrayComputedFields);\r\n return newDatabase;\r\n }\r\n\r\n async useTriggers(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayTriggers = await TriggerProcessor.getTriggers(this.name);\r\n newDatabase.setTriggers(arrayTriggers);\r\n return newDatabase;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n const response = await this.engine.run('query_engine', [\r\n '--action', 'connect',\r\n ]);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n await this.engine.run('query_engine', [\r\n '--action', 'disconnect',\r\n ]);\r\n }\r\n\r\n /**\r\n * Creates and returns a new instance of `Table` for the specified table.\r\n * This method is used to start building queries for a specific table.\r\n * It provides a fluent interface for common database operations like select, insert, update, and delete.\r\n *\r\n * @param {string} tableName - The name of the table to query.\r\n * @returns {Table} - Returns a new instance of `Table` for the specified table.\r\n *\r\n * @example\r\n * // Select all records from a table\r\n * const users = await db.table('users').get();\r\n * \r\n * // Select records with conditions\r\n * const activeUsers = await db.table('users')\r\n * .where('status', '=', 'active')\r\n * .orderBy('created_at', 'DESC')\r\n * .limit(10)\r\n * .get();\r\n * \r\n * // Insert records\r\n * await db.table('users').insert([\r\n * { name: 'John', email: 'john@example.com', age: 30 }\r\n * ]);\r\n * \r\n * // Update records\r\n * await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ status: 'inactive' });\r\n * \r\n * // Delete records\r\n * await db.table('users')\r\n * .where('status', '=', 'deleted')\r\n * .delete();\r\n * \r\n * // Access column management\r\n * const columns = await db.table('users').columns().get();\r\n */\r\n table<T extends DatabaseRecord = DatabaseRecord>(tableName: string): Table<T> {\r\n return new Table<T>(this, this.name, tableName, this.engine, this.computedFields, this.triggers, this.txId);\r\n }\r\n\r\n private setComputedFields(computedFields: ComputedFieldConfig[]){\r\n this.computedFields = computedFields;\r\n }\r\n\r\n private setTriggers(triggers: TriggerConfig[]){\r\n this.triggers = triggers;\r\n }\r\n}\r\n\r\n/**\r\n * Class to build and execute SQL queries for a specific table.\r\n * Supports operations like SELECT, INSERT, UPDATE, DELETE, and more.\r\n *\r\n * Generic over the row shape: `db.table<User>('users').get()` resolves to\r\n * `Promise<User[]>`. Pair it with the interfaces emitted by `dbcube generate`.\r\n */\r\nexport class Table<T extends DatabaseRecord = DatabaseRecord> {\r\n private engine: QueryEngine;\r\n private nextType: 'AND' | 'OR' = 'AND';\r\n private dml: DML;\r\n private computedFields: ComputedFieldConfig[] = [];\r\n private trigger: Trigger;\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n private relations: { name: string; options: RelationOptions }[] = [];\r\n /** Builders de grupo mutan en sitio (ver clone()) */\r\n private _mutable = false;\r\n\r\n private instance: Database;\r\n\r\n constructor(instance: Database, databaseName: string, tableName: string, engine: QueryEngine, computedFields: ComputedFieldConfig[] = [], triggers: TriggerConfig[] = [], txId: string | null = null) {\r\n this.engine = engine;\r\n this.instance = instance;\r\n this.computedFields = computedFields;\r\n this.triggers = triggers;\r\n this.trigger = new Trigger(instance, databaseName, triggers);\r\n this.nextType = 'AND';\r\n this.txId = txId;\r\n\r\n this.dml = {\r\n type: 'select',\r\n database: databaseName,\r\n table: tableName,\r\n columns: ['*'],\r\n distinct: false,\r\n joins: [],\r\n where: [],\r\n orderBy: [],\r\n groupBy: [],\r\n limit: null,\r\n offset: null,\r\n data: null,\r\n aggregation: null,\r\n having: []\r\n };\r\n }\r\n\r\n /**\r\n * Specifies the columns to select in a SELECT query.\r\n *\r\n * @param {string[]} fields - Array of column names to select. If empty, selects all columns.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').select(['id', 'name']).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n select(fields: string[] = []): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = fields.length > 0 ? fields : ['*'];\r\n clone.dml.aggregation = null;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).get();\r\n * const nullUsers = await db.table('users').where('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n where(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n where(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n where(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an OR WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).orWhere('name', '=', 'Jane').get();\r\n * const nullUsers = await db.table('users').where('active', '=', true).orWhere('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n orWhere(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n orWhere(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n orWhere(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'OR',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a grouped WHERE condition to the query.\r\n *\r\n * @param {WhereCallback} callback - A callback function that receives a new Table instance to build the grouped conditions.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereGroup(query => {\r\n * query.where('age', '>', 25).orWhere('name', '=', 'Jane');\r\n * }).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereGroup(callback: WhereCallback): Table<T> {\r\n const clone = this.clone();\r\n const groupQuery = new Table(this.instance, clone.dml.database, clone.dml.table, clone.engine);\r\n // El callback encadena sin usar el valor de retorno; el builder del\r\n // grupo debe mutar en sitio o las condiciones se perderían en clones\r\n groupQuery._mutable = true;\r\n callback(groupQuery);\r\n\r\n clone.dml.where.push({\r\n type: clone.nextType,\r\n isGroup: true,\r\n conditions: groupQuery.dml.where as WhereCondition[]\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n or(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'OR';\r\n return clone;\r\n }\r\n\r\n and(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE BETWEEN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {[any, any]} values - A tuple with two values representing the range.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereBetween('age', [20, 30]).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereBetween(column: string, values: [any, any]): Table<T> {\r\n const clone = this.clone();\r\n const [value1, value2] = values;\r\n if (value1 !== undefined && value2 !== undefined) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'BETWEEN',\r\n value: [value1, value2],\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {any[]} values - An array of values to match.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereIn('id', [1, 2]).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n whereIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNull('email').get();\r\n * console.log(users); // [{ id: 3, name: 'Alice', email: null }]\r\n */\r\n whereNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NOT NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotNull('email').get();\r\n * console.log(users); // [{ id: 1, name: 'John', email: 'john@example.com' }]\r\n */\r\n whereNotNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NOT NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').join('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }]\r\n */\r\n join(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'INNER',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a LEFT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').leftJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: 2, name: 'Jane', order_id: null }]\r\n */\r\n leftJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'LEFT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a RIGHT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').rightJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: null, name: null, order_id: 102 }]\r\n */\r\n rightJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'RIGHT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an ORDER BY clause to the query.\r\n *\r\n * @param {string} column - The column to order by.\r\n * @param {'ASC' | 'DESC'} direction - The sorting direction ('ASC' or 'DESC').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').orderBy('name', 'ASC').get();\r\n * console.log(users); // [{ id: 2, name: 'Jane' }, { id: 1, name: 'John' }]\r\n */\r\n orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): Table<T> {\r\n const clone = this.clone();\r\n const validDirections: ('ASC' | 'DESC')[] = ['ASC', 'DESC'];\r\n if (validDirections.includes(direction.toUpperCase() as 'ASC' | 'DESC')) {\r\n clone.dml.orderBy.push({\r\n column,\r\n direction: direction.toUpperCase() as 'ASC' | 'DESC'\r\n });\r\n } else {\r\n throw new Error(`Invalid direction: ${direction}. Use 'ASC' or 'DESC'.`);\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a GROUP BY clause to the query.\r\n *\r\n * @param {string} column - The column to group by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').groupBy('age').get();\r\n * console.log(users); // [{ age: 30, count: 1 }, { age: 25, count: 1 }]\r\n */\r\n groupBy(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.groupBy.push(column);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a DISTINCT clause to the query.\r\n *\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').distinct().select(['name']).get();\r\n * console.log(users); // [{ name: 'John' }, { name: 'Jane' }]\r\n */\r\n distinct(): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.distinct = true;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a COUNT clause to the query.\r\n *\r\n * @param {string} column - The column to count (default is '*').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const count = await db.table('users').count().first();\r\n * console.log(count); // { count: 2 }\r\n */\r\n async count(column: string = '*'): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'COUNT',\r\n column,\r\n alias: 'count'\r\n }\r\n clone.dml.columns = [`COUNT(${column}) AS count`];\r\n clone.dml.data = null;\r\n clone.dml.limit = null; // Remover limit para contar todos\r\n clone.dml.offset = null; // Remover offset también\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.count;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a SUM clause to the query.\r\n *\r\n * @param {string} column - The column to sum.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const totalAge = await db.table('users').sum('age').first();\r\n * console.log(totalAge); // { sum: 55 }\r\n */\r\n async sum(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'SUM',\r\n column,\r\n alias: 'sum'\r\n }\r\n clone.dml.columns = [`SUM(${column}) AS sum`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.sum;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds an AVG clause to the query.\r\n *\r\n * @param {string} column - The column to calculate the average.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const avgAge = await db.table('users').avg('age').first();\r\n * console.log(avgAge); // { avg: 27.5 }\r\n */\r\n async avg(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'AVG',\r\n column,\r\n alias: 'avg'\r\n }\r\n clone.dml.columns = [`AVG(${column}) AS avg`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.avg;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MAX clause to the query.\r\n *\r\n * @param {string} column - The column to find the maximum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const maxAge = await db.table('users').max('age').first();\r\n * console.log(maxAge); // { max: 30 }\r\n */\r\n async max(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MAX',\r\n column,\r\n alias: 'max'\r\n }\r\n clone.dml.columns = [`MAX(${column}) AS max`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.max;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MIN clause to the query.\r\n *\r\n * @param {string} column - The column to find the minimum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const minAge = await db.table('users').min('age').first();\r\n * console.log(minAge); // { min: 25 }\r\n */\r\n async min(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MIN',\r\n column,\r\n alias: 'min'\r\n }\r\n clone.dml.columns = [`MIN(${column}) AS min`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.min;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the column names of the table.\r\n * For SQL databases (MySQL, PostgreSQL, SQLite), returns a simple array of column names.\r\n * For MongoDB, returns a hierarchical structure with nested documents.\r\n *\r\n * @returns {Promise<string[] | any>} - Returns an array of column names for SQL databases,\r\n * or a hierarchical structure for MongoDB.\r\n *\r\n * @example\r\n * // SQL databases (MySQL, PostgreSQL, SQLite)\r\n * const columns = await db.table('users').columns();\r\n * console.log(columns); // ['id', 'name', 'email', 'age', 'created_at']\r\n *\r\n * @example\r\n * // MongoDB\r\n * const structure = await db.table('users').columns();\r\n * console.log(structure);\r\n * // {\r\n * // columns: ['id', 'name', 'profile'],\r\n * // submenu: {\r\n * // profile: {\r\n * // columns: ['age', 'city'],\r\n * // submenu: {}\r\n * // }\r\n * // }\r\n * // }\r\n */\r\n async columns(): Promise<string[] | any> {\r\n const clone = this.clone();\r\n clone.dml.type = 'columns';\r\n clone.dml.columns = [];\r\n clone.dml.where = [];\r\n clone.dml.orderBy = [];\r\n clone.dml.groupBy = [];\r\n clone.dml.limit = null;\r\n clone.dml.offset = null;\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n\r\n try {\r\n const result = await clone.getResponse();\r\n\r\n if (Array.isArray(result) && result.length > 0) {\r\n // Verificar si es MongoDB (estructura jerárquica)\r\n if (result[0].columns && result[0].submenu !== undefined) {\r\n // MongoDB: devolver la estructura completa\r\n return result[0];\r\n }\r\n\r\n // SQL databases: transformar a array simple de strings\r\n return result.map((row: any) => row.column_name || row.Field || row.name);\r\n }\r\n\r\n return [];\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a LIMIT clause to the query.\r\n *\r\n * @param {number} number - The maximum number of rows to return.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n limit(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.limit = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds pagination to the query using LIMIT and OFFSET.\r\n *\r\n * @param {number} number - The page number (starting from 1).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).page(2).get();\r\n * console.log(users); // [{ id: 2, name: 'Jane', age: 25 }]\r\n */\r\n page(number: number): Table<T> {\r\n const clone = this.clone();\r\n const pageNum = Number(number);\r\n if (clone.dml.limit) {\r\n clone.dml.offset = (pageNum - 1) * clone.dml.limit;\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Executes the query and returns all matching rows.\r\n *\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of rows.\r\n *\r\n * @example\r\n * const users = await db.table('users').get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n async get(): Promise<T[]> {\r\n try {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n const result = await clone.getResponse();\r\n if (this.relations.length > 0 && Array.isArray(result)) {\r\n return await this.attachRelations(result) as T[];\r\n }\r\n return result as T[];\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Executes the query and returns the first matching row.\r\n *\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').first();\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async first(): Promise<T | null> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Finds a row by a specific column value.\r\n *\r\n * @param {any} value - The value to search for.\r\n * @param {string} column - The column to search in (default is 'id').\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first matching row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').find(1);\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async find(value: string | number, column: string = 'id'): Promise<T | null> {\r\n // where() is immutable: reassign the clone or the condition is lost\r\n const clone = this.clone().where(column, '=', value);\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Inserts one or more rows into the table.\r\n *\r\n * @param {DatabaseRecord[]} data - An array of objects representing the rows to insert.\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of the inserted rows.\r\n *\r\n * @example\r\n * const newUsers = await db.table('users').insert([\r\n * { name: 'Alice', age: 28 },\r\n * { name: 'Bob', age: 32 }\r\n * ]);\r\n * console.log(newUsers); // [{ id: 3, name: 'Alice', age: 28 }, { id: 4, name: 'Bob', age: 32 }]\r\n */\r\n async insert(data: Partial<T>[]): Promise<T[]> {\r\n const clone = this.clone();\r\n if (!Array.isArray(data)) {\r\n throw new Error('The insert method requires an array of objects with key-value pairs.');\r\n }\r\n\r\n if (!data.every(item => typeof item === 'object' && item !== null)) {\r\n throw new Error('The array must contain only valid objects.');\r\n }\r\n\r\n clone.dml.type = 'insert';\r\n clone.dml.data = data;\r\n\r\n const result = await clone.getResponse(clone.dml, 'Add');\r\n\r\n return result ?? data;\r\n }\r\n\r\n /**\r\n * Updates rows in the table based on the defined conditions.\r\n *\r\n * @param {DatabaseRecord} data - An object with key-value pairs representing the fields to update.\r\n * @returns {Promise<any>} - Returns the result of the update operation.\r\n *\r\n * @example\r\n * const result = await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ name: 'John Updated', age: 31 });\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async update(data: Partial<T>): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (typeof data !== 'object' || Array.isArray(data)) {\r\n throw new Error('The update method requires an object with key-value pairs.');\r\n }\r\n\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an update.');\r\n }\r\n\r\n clone.dml.type = 'update';\r\n clone.dml.data = data;\r\n\r\n return clone.getResponse(clone.dml, 'Update');\r\n }\r\n\r\n /**\r\n * Deletes rows from the table based on the defined conditions.\r\n *\r\n * @returns {Promise<any>} - Returns the result of the delete operation.\r\n *\r\n * @example\r\n * const result = await db.table('users').where('id', '=', 1).delete();\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async delete(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform a delete.');\r\n }\r\n\r\n clone.dml.type = 'delete';\r\n\r\n const deleteData = await clone.getResponse(clone.dml, 'Delete');\r\n return deleteData;\r\n }\r\n\r\n /**\r\n * Adds a WHERE NOT IN condition to the query.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotIn('status', ['banned', 'deleted']).get();\r\n */\r\n whereNotIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'NOT IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Sets an explicit OFFSET for the query (alternative to page()).\r\n *\r\n * @example\r\n * const rows = await db.table('logs').orderBy('id', 'ASC').limit(50).offset(100).get();\r\n */\r\n offset(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.offset = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Appends raw expressions to the SELECT list (aggregates, functions, aliases).\r\n * Combine with groupBy() and having() for per-group metrics.\r\n *\r\n * @example\r\n * const stats = await db.table('orders')\r\n * .select(['user_id'])\r\n * .selectRaw(['COUNT(*) AS order_count', 'SUM(amount) AS total'])\r\n * .groupBy('user_id')\r\n * .having('order_count', '>', 5)\r\n * .get();\r\n */\r\n selectRaw(expressions: string[]): Table<T> {\r\n const clone = this.clone();\r\n if (clone.dml.columns.length === 1 && clone.dml.columns[0] === '*') {\r\n clone.dml.columns = [...expressions];\r\n } else {\r\n clone.dml.columns = [...clone.dml.columns, ...expressions];\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a HAVING condition (filters grouped results).\r\n *\r\n * @example\r\n * .groupBy('user_id').having('COUNT(*)', '>', 5)\r\n */\r\n having(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.having = clone.dml.having ?? [];\r\n clone.dml.having.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'AND',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Checks if at least one row matches the current conditions.\r\n * Cheaper than first(): selects a constant with LIMIT 1.\r\n *\r\n * @example\r\n * const taken = await db.table('users').where('email', '=', email).exists();\r\n */\r\n async exists(): Promise<boolean> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = ['1 AS dbcube_exists'];\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n clone.dml.offset = null;\r\n const result = await clone.getResponse();\r\n return Array.isArray(result) && result.length > 0;\r\n }\r\n\r\n /**\r\n * Fetches one page of results plus pagination metadata in a single call.\r\n * Runs the page query and the total count with the same conditions.\r\n *\r\n * @example\r\n * const { items, total, totalPages, hasNext } = await db.table('products')\r\n * .where('published', '=', true)\r\n * .orderBy('id', 'ASC')\r\n * .paginate(2, 25);\r\n */\r\n async paginate(page: number = 1, perPage: number = 20): Promise<PaginatedResult<T>> {\r\n const pageNum = Math.max(1, Number(page));\r\n const size = Math.max(1, Number(perPage));\r\n\r\n const itemsQuery = this.limit(size).page(pageNum);\r\n const [items, total] = await Promise.all([\r\n itemsQuery.get(),\r\n this.count()\r\n ]);\r\n\r\n const totalNum = Number(total);\r\n const totalPages = Math.ceil(totalNum / size);\r\n return {\r\n items,\r\n page: pageNum,\r\n perPage: size,\r\n total: totalNum,\r\n totalPages,\r\n hasNext: pageNum < totalPages,\r\n hasPrev: pageNum > 1,\r\n };\r\n }\r\n\r\n /**\r\n * Processes all matching rows in batches of `size`, keeping memory flat.\r\n * Return `false` from the callback to stop early.\r\n *\r\n * @example\r\n * await db.table('logs').orderBy('id', 'ASC').chunk(500, async (rows) => {\r\n * await processBatch(rows);\r\n * });\r\n */\r\n async chunk(size: number, callback: (rows: T[], page: number) => Promise<void | boolean> | void | boolean): Promise<void> {\r\n const batchSize = Math.max(1, Number(size));\r\n let page = 1;\r\n while (true) {\r\n const rows = await this.limit(batchSize).page(page).get();\r\n if (rows.length === 0) break;\r\n const result = await callback(rows, page);\r\n if (result === false) break;\r\n if (rows.length < batchSize) break;\r\n page++;\r\n }\r\n }\r\n\r\n /**\r\n * Atomically increments a numeric column: `SET col = col + amount`.\r\n * Requires at least one WHERE condition. Extra fields can be updated in the same statement.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).increment('stock', 3);\r\n * await db.table('posts').where('id', '=', 1).increment('views', 1, { last_viewed_at: new Date().toISOString() });\r\n */\r\n async increment(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an increment.');\r\n }\r\n clone.dml.type = 'update';\r\n clone.dml.data = { ...extra, [column]: { $inc: Number(amount) } };\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Atomically decrements a numeric column: `SET col = col - amount`.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).decrement('stock', 1);\r\n */\r\n async decrement(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n return this.increment(column, -Math.abs(Number(amount)), extra);\r\n }\r\n\r\n /**\r\n * Deletes ALL rows from the table. The only write operation allowed\r\n * without a WHERE — the destructive intent is explicit in the name.\r\n *\r\n * @example\r\n * await db.table('temp_imports').truncate();\r\n */\r\n async truncate(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n clone.dml.type = 'delete';\r\n clone.dml.where = [];\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Inserts rows, updating them instead when a conflict occurs on the given keys.\r\n * MySQL → ON DUPLICATE KEY UPDATE · PostgreSQL/SQLite → ON CONFLICT ... DO UPDATE.\r\n *\r\n * @param data Rows to insert.\r\n * @param conflictKeys Column(s) with the UNIQUE/PK constraint that triggers the update.\r\n * @param updateColumns Columns to overwrite on conflict (defaults to every non-conflict column).\r\n *\r\n * @example\r\n * await db.table('settings').upsert(\r\n * [{ key: 'theme', value: 'dark' }],\r\n * ['key']\r\n * );\r\n */\r\n async upsert(data: Partial<T>[], conflictKeys: string[], updateColumns?: string[]): Promise<MutationInfo[]> {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n throw new Error('The upsert method requires a non-empty array of objects.');\r\n }\r\n if (!Array.isArray(conflictKeys) || conflictKeys.length === 0) {\r\n throw new Error('The upsert method requires at least one conflict key column.');\r\n }\r\n\r\n const motor: string = this.engine?.getConfig?.()?.type ?? 'mysql';\r\n\r\n const table = this.dml.table;\r\n const columns = Object.keys(data[0]);\r\n const targets = updateColumns ?? columns.filter(c => !conflictKeys.includes(c));\r\n\r\n // Único método que arma la operación en JS: validar identificadores\r\n // porque las claves de los objetos pueden venir de input externo\r\n assertValidIdentifier(table, 'table');\r\n for (const c of columns) assertValidIdentifier(c, 'column');\r\n for (const c of conflictKeys) assertValidIdentifier(c, 'conflict key');\r\n for (const c of targets) assertValidIdentifier(c, 'update column');\r\n\r\n if (motor === 'mongodb') {\r\n // Comando `update` nativo con upsert:true por fila — misma semántica\r\n // que ON CONFLICT: matchea por conflictKeys, actualiza solo targets,\r\n // y al insertar escribe la fila completa.\r\n const updates = data.map(row => {\r\n const q: Record<string, unknown> = {};\r\n for (const k of conflictKeys) q[k] = row[k];\r\n\r\n const set: Record<string, unknown> = {};\r\n for (const c of targets) if (c in row) set[c] = row[c];\r\n\r\n const setOnInsert: Record<string, unknown> = {};\r\n for (const c of columns) {\r\n if (!targets.includes(c) && !conflictKeys.includes(c)) setOnInsert[c] = row[c];\r\n }\r\n if (!('uuid' in row)) setOnInsert['uuid'] = randomUUID();\r\n\r\n const u: Record<string, unknown> = {};\r\n if (Object.keys(set).length) u['$set'] = set;\r\n if (Object.keys(setOnInsert).length) u['$setOnInsert'] = setOnInsert;\r\n\r\n return { q, u, upsert: true, multi: false };\r\n });\r\n\r\n const command = JSON.stringify({ update: table, updates });\r\n const response = await this.engine.rawQuery(command, [], this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n const quote = (id: string) => motor === 'mysql' ? `\\`${id}\\`` : `\"${id}\"`;\r\n\r\n const params: any[] = [];\r\n const placeholder = () => motor === 'postgres' || motor === 'postgresql'\r\n ? `$${params.length}`\r\n : '?';\r\n\r\n const rowsSql = data.map(row => {\r\n const cells = columns.map(col => {\r\n params.push(row[col] === undefined ? null : row[col]);\r\n return placeholder();\r\n });\r\n return `(${cells.join(', ')})`;\r\n }).join(', ');\r\n\r\n const colsSql = columns.map(quote).join(', ');\r\n let sql: string;\r\n\r\n if (motor === 'mysql') {\r\n const updates = targets.map(c => `${quote(c)} = VALUES(${quote(c)})`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON DUPLICATE KEY UPDATE ${updates}`;\r\n } else {\r\n const conflict = conflictKeys.map(quote).join(', ');\r\n const updates = targets.map(c => `${quote(c)} = excluded.${quote(c)}`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON CONFLICT (${conflict}) DO UPDATE SET ${updates}`;\r\n }\r\n\r\n if (motor === 'sqlite') {\r\n // SQLite pool schema sync: ensure every pooled connection sees constraints\r\n // created moments ago (e.g. a UNIQUE index added right before this upsert).\r\n await this.engine.rawQuery('SELECT name FROM sqlite_master LIMIT 1', [], this.txId ?? undefined);\r\n }\r\n const response = await this.engine.rawQuery(sql, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Declares a relation to eager-load with the results of get().\r\n * Relations are resolved from `foreign` definitions in your .cube files,\r\n * or explicitly via options. Loads each relation with ONE batched query\r\n * (whereIn) — no N+1.\r\n *\r\n * @example\r\n * // hasMany: orders.user_id → users.id (auto-detected from orders.table.cube)\r\n * const users = await db.table('users').with('orders').get();\r\n * // users[0].orders === [{...}, {...}]\r\n *\r\n * // belongsTo: posts.author_id → users.id, attached as a single object\r\n * const posts = await db.table('posts')\r\n * .with('author', { table: 'users', foreignKey: 'author_id', type: 'one' })\r\n * .get();\r\n */\r\n with(relation: string, options: RelationOptions = {}): Table<T> {\r\n const clone = this.clone();\r\n clone.relations.push({ name: relation, options });\r\n return clone;\r\n }\r\n\r\n private async attachRelations(rows: DatabaseRecord[]): Promise<DatabaseRecord[]> {\r\n if (rows.length === 0 || this.relations.length === 0) return rows;\r\n\r\n for (const { name, options } of this.relations) {\r\n const relatedTable = options.table ?? name;\r\n const cubeMeta = loadCubeRelations();\r\n\r\n // Detect direction + keys from .cube foreign metadata when not explicit\r\n let type = options.type;\r\n let foreignKey = options.foreignKey;\r\n let localKey = options.localKey ?? 'id';\r\n\r\n if (!foreignKey || !type) {\r\n const childFks = cubeMeta[relatedTable]?.foreigns ?? [];\r\n const ownFks = cubeMeta[this.dml.table]?.foreigns ?? [];\r\n const childToParent = childFks.find(fk => fk.table === this.dml.table);\r\n const parentToChild = ownFks.find(fk => fk.table === relatedTable);\r\n\r\n if (childToParent) {\r\n // hasMany: the related table points at us\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? childToParent.column_name;\r\n localKey = options.localKey ?? childToParent.column;\r\n } else if (parentToChild) {\r\n // belongsTo: we point at the related table\r\n type = type ?? 'one';\r\n foreignKey = foreignKey ?? parentToChild.column_name;\r\n localKey = options.localKey ?? parentToChild.column;\r\n } else {\r\n // Heuristic fallback: <singular-parent>_id on the child table\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? `${singularize(this.dml.table)}_id`;\r\n }\r\n }\r\n\r\n const relatedQuery = new Table(this.instance, this.dml.database, relatedTable, this.engine, this.computedFields, this.triggers, this.txId);\r\n\r\n if (type === 'one') {\r\n // belongsTo: FK lives on THIS table, match related.localKey\r\n const fkValues = [...new Set(rows.map(r => r[foreignKey!]).filter(v => v !== null && v !== undefined))];\r\n const related = fkValues.length > 0\r\n ? await relatedQuery.whereIn(localKey, fkValues).get()\r\n : [];\r\n const index = new Map(related.map(r => [r[localKey], r]));\r\n for (const row of rows) {\r\n row[name] = index.get(row[foreignKey!]) ?? null;\r\n }\r\n } else {\r\n // hasMany: FK lives on the RELATED table, match this.localKey\r\n const ids = [...new Set(rows.map(r => r[localKey]).filter(v => v !== null && v !== undefined))];\r\n const related = ids.length > 0\r\n ? await relatedQuery.whereIn(foreignKey!, ids).get()\r\n : [];\r\n const groups = new Map<any, DatabaseRecord[]>();\r\n for (const rel of related) {\r\n const key = rel[foreignKey!];\r\n if (!groups.has(key)) groups.set(key, []);\r\n groups.get(key)!.push(rel);\r\n }\r\n for (const row of rows) {\r\n row[name] = groups.get(row[localKey]) ?? [];\r\n }\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n private async getResponse(dml: any = null, type: any = null): Promise<any> {\r\n const localDML = dml ? dml : this.dml;\r\n const computedFieldsNeeded: any[] = [];\r\n let dependeciesArrray: any[] = [];\r\n\r\n if (this.computedFields.length > 0) {\r\n let columns = localDML.columns;\r\n\r\n for (const field of localDML.columns) {\r\n const computedField = this.computedFields.find(cf => cf.column === field);\r\n\r\n if (computedField) {\r\n computedFieldsNeeded.push(computedField);\r\n // Add dependencies to real fields\r\n const dependencies = ComputedFieldProcessor.extractDependencies(computedField.instruction);\r\n dependeciesArrray = [...dependeciesArrray, ...dependencies];\r\n columns = Array.from(new Set([...columns, ...dependencies]));\r\n columns = columns.filter((col: string) => col != field);\r\n }\r\n }\r\n localDML.columns = columns;\r\n }\r\n\r\n let arrayResult = [];\r\n if (type) {\r\n const beffore = this.trigger.get('before' + type);\r\n const after = this.trigger.get('after' + type);\r\n if (this.triggers.length > 0 && (beffore || after)) {\r\n const dataset = localDML.data;\r\n for (let index = 0; index < dataset.length; index++) {\r\n const data = dataset[index];\r\n const newDML = { ...localDML, data: [data] };\r\n if (beffore) {\r\n const interceptor = await this.trigger.execute('before' + type, data);\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n interceptor?.discard();\r\n returnFormattedError(response.status, response.message);\r\n }\r\n await interceptor?.commit();\r\n arrayResult = response.data;\r\n }\r\n if (after) {\r\n\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n const interceptor = await this.trigger.execute('after' + type, data);\r\n await interceptor?.commit();\r\n }\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n\r\n if (computedFieldsNeeded.length > 0) {\r\n let newDataset: any = ComputedFieldProcessor.computedFields(arrayResult, computedFieldsNeeded);\r\n const result = newDataset.map((obj: any) => {\r\n const newObj = { ...obj };\r\n dependeciesArrray.forEach(key => delete newObj[key]);\r\n return newObj;\r\n });\r\n return result;\r\n }\r\n return arrayResult;\r\n }\r\n\r\n private clone(): Table<T> {\r\n // Los builders de grupo (whereGroup) son mutables: el callback encadena\r\n // sin usar el valor de retorno, así que clonar perdería las condiciones\r\n if (this._mutable) return this;\r\n const cloned = Object.create(Object.getPrototypeOf(this));\r\n cloned.engine = this.engine;\r\n cloned.instance = this.instance;\r\n cloned.nextType = this.nextType;\r\n cloned.computedFields = this.computedFields;\r\n cloned.trigger = this.trigger;\r\n cloned.triggers = this.triggers;\r\n cloned.txId = this.txId;\r\n cloned.relations = [...this.relations];\r\n\r\n cloned.dml = {\r\n ...this.dml,\r\n columns: [...this.dml.columns],\r\n joins: [...this.dml.joins],\r\n where: [...this.dml.where],\r\n orderBy: [...this.dml.orderBy],\r\n groupBy: [...this.dml.groupBy],\r\n having: [...(this.dml.having ?? [])],\r\n // Clonar propiedades que faltaban para evitar mutación compartida\r\n data: this.dml.data ? (Array.isArray(this.dml.data) ? [...this.dml.data] : { ...this.dml.data }) : null,\r\n aggregation: this.dml.aggregation ? { ...this.dml.aggregation } : null\r\n };\r\n return cloned;\r\n }\r\n\r\n}\r\n\r\n// ---- Cube relation metadata (cached scan of dbcube/*.table.cube) ----\r\n\r\ninterface CubeForeign {\r\n column_name: string; // FK column on the owning table\r\n table: string; // referenced table\r\n column: string; // referenced column\r\n}\r\n\r\nlet cubeRelationsCache: Record<string, { foreigns: CubeForeign[] }> | null = null;\r\n\r\nfunction loadCubeRelations(): Record<string, { foreigns: CubeForeign[] }> {\r\n if (cubeRelationsCache) return cubeRelationsCache;\r\n const result: Record<string, { foreigns: CubeForeign[] }> = {};\r\n\r\n const scanDir = (dir: string) => {\r\n let entries: fs.Dirent[];\r\n try {\r\n entries = fs.readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const entry of entries) {\r\n const full = path.join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n if (entry.name !== 'node_modules' && entry.name !== 'triggers' && entry.name !== 'logs') {\r\n scanDir(full);\r\n }\r\n } else if (entry.name.endsWith('.table.cube')) {\r\n try {\r\n const content = fs.readFileSync(full, 'utf8');\r\n const nameMatch = content.match(/@meta\\s*\\(\\s*\\{[\\s\\S]*?name\\s*:\\s*\"([^\"]+)\"/);\r\n const tableName = nameMatch ? nameMatch[1] : path.basename(entry.name, '.table.cube');\r\n\r\n const foreigns: CubeForeign[] = [];\r\n const colRegex = /(\\w+)\\s*:\\s*\\{(?:[^{}]|\\{[^{}]*\\})*?foreign\\s*:\\s*\\{([^}]*)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = colRegex.exec(content)) !== null) {\r\n const fkTable = m[2].match(/table\\s*:\\s*\"([^\"]+)\"/);\r\n const fkColumn = m[2].match(/column\\s*:\\s*\"([^\"]+)\"/);\r\n if (fkTable) {\r\n foreigns.push({\r\n column_name: m[1],\r\n table: fkTable[1],\r\n column: fkColumn ? fkColumn[1] : 'id',\r\n });\r\n }\r\n }\r\n result[tableName] = { foreigns };\r\n } catch { /* unreadable cube — skip */ }\r\n }\r\n }\r\n };\r\n\r\n scanDir(path.join(process.cwd(), 'dbcube'));\r\n cubeRelationsCache = result;\r\n return result;\r\n}\r\n\r\nfunction assertValidIdentifier(name: string, kind: string): void {\r\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\r\n throw new Error(`Invalid ${kind} name: '${name}'. Only letters, numbers and underscore are allowed.`);\r\n }\r\n}\r\n\r\nfunction singularize(word: string): string {\r\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\r\n if (word.endsWith('ses')) return word.slice(0, -2);\r\n if (word.endsWith('s') && !word.endsWith('ss')) return word.slice(0, -1);\r\n return word;\r\n}\r\n\r\nfunction returnFormattedError(status: number, message: string) {\r\n const RESET = '\\x1b[0m';\r\n const RED = '\\x1b[31m';\r\n const YELLOW = '\\x1b[33m';\r\n const BOLD = '\\x1b[1m';\r\n const CYAN = '\\x1b[36m';\r\n const GRAY = '\\x1b[90m';\r\n const UNDERLINE = '\\x1b[4m';\r\n const MAGENTA = '\\x1b[35m';\r\n\r\n let output = '';\r\n let help = '';\r\n const color = status === 600 ? YELLOW : RED;\r\n\r\n\r\n if (message.includes(\"[help]\")) {\r\n const parts = message.split(\"[help]\");\r\n output += `\\n${RED}${BOLD}${parts[0]}${RESET}`;\r\n help += `\\n${MAGENTA}${BOLD}[help]${RESET} ${GRAY}${parts[1]}${RESET}\\n`;\r\n } else {\r\n output += `\\n${color}${BOLD}${message}${RESET}\\n`;\r\n }\r\n\r\n const err = new Error();\r\n const stackLines = err.stack?.split('\\n') || [];\r\n\r\n // Buscamos la primera línea del stack fuera de node_modules\r\n const relevantStackLine = stackLines.find(line =>\r\n line.includes('.js:') && !line.includes('node_modules')\r\n );\r\n\r\n if (relevantStackLine) {\r\n const match = relevantStackLine.match(/\\((.*):(\\d+):(\\d+)\\)/) ||\r\n relevantStackLine.match(/at (.*):(\\d+):(\\d+)/);\r\n\r\n if (match) {\r\n const [, filePath, lineStr, columnStr] = match;\r\n const lineNum = parseInt(lineStr, 10);\r\n const errorLocation = `${filePath}:${lineStr}:${columnStr}`;\r\n\r\n // Leemos el archivo y sacamos las líneas relevantes\r\n try {\r\n const codeLines = fs.readFileSync(filePath, 'utf-8').split('\\n');\r\n const start = Math.max(0, lineNum - 3);\r\n const end = Math.min(codeLines.length, lineNum + 2);\r\n\r\n output += `\\n${CYAN}${BOLD}[code] ${RESET}${YELLOW} ${UNDERLINE}${errorLocation}${RESET}\\n`;\r\n\r\n for (let i = start; i < end; i++) {\r\n const line = codeLines[i];\r\n const lineLabel = `${i + 1}`.padStart(4, ' ');\r\n const pointer = i + 1 === lineNum ? `${RED}<-${RESET}` : ' ';\r\n output += `${GRAY}${lineLabel}${RESET} ${pointer} ${line}\\n`;\r\n }\r\n } catch (err) {\r\n output += `${YELLOW}⚠️ No se pudo leer el archivo de origen: ${filePath}${RESET}\\n`;\r\n output += `\\n${CYAN}${BOLD}Stack Trace:${RESET}\\n${stackLines.slice(2).join('\\n')}\\n`;\r\n }\r\n }\r\n }\r\n output += help;\r\n console.error(output);\r\n}\r\n\r\nexport default Database;\r\n","import path from \"path\";\nimport { FileLogger, InterceptController } from \"@dbcube/core\";\nimport { createRequire } from 'module';\nimport type { TriggerConfig } from \"../@types/Database\";\n\n/**\n * Runtime triggers: user-defined JS functions (from .trigger.cube files) that\n * run in the application process around each write. Because they execute in\n * the write-path (not as DB-side triggers), they behave identically across\n * MySQL, PostgreSQL, SQLite and MongoDB, and fire exactly once per operation\n * regardless of how many service instances share the database.\n */\nexport class Trigger {\n private triggers: TriggerConfig[];\n private databaseName: string;\n private instance: unknown;\n\n constructor(instance: unknown, databaseName: string, metadata: TriggerConfig[]) {\n this.triggers = metadata;\n this.databaseName = databaseName;\n this.instance = instance;\n }\n\n get(type: string): TriggerConfig | undefined {\n return this.triggers.find((tr) => tr.type === type);\n }\n\n async execute(type: string, row: Record<string, unknown>): Promise<InterceptController | null> {\n const trigger = this.triggers.find((tr) => tr.type === type);\n if (trigger) {\n const logFilePath = path.resolve(\n process.cwd(),\n 'dbcube',\n 'logs',\n 'triggers',\n this.databaseName,\n `${trigger.table_ref}_${trigger.type}.log`\n );\n\n const interceptor = FileLogger.interceptConsole(logFilePath, {\n keepOriginal: false,\n useBuffer: true\n });\n const pathFile = path.resolve(process.cwd(), 'dbcube', 'triggers', `${trigger.database_ref}_${trigger.table_ref}_${trigger.type}.js`);\n // Use __filename for CJS, process.cwd() for ESM\n const requireUrl = typeof __filename !== 'undefined' ? __filename : process.cwd();\n const require = createRequire(requireUrl);\n // Clear require cache to ensure fresh load\n try {\n delete require.cache[require.resolve(pathFile)];\n } catch { /* bundled environments may not expose a resolvable cache */ }\n const triggerModule = require(pathFile);\n const dataProcess = triggerModule.default || triggerModule;\n await dataProcess({ db: this.instance, oldData: row, newData: row });\n interceptor.restore();\n return interceptor;\n }\n return null;\n }\n}\n","import { Table, Database } from './lib/Database';\nimport type {\n ComputedFieldConfig,\n DatabaseRecord,\n MutationInfo,\n PaginatedResult,\n RelationOptions,\n TriggerConfig,\n WhereCallback,\n} from './@types/Database';\n\nexport default Database;\nexport {\n Table,\n Database,\n type ComputedFieldConfig,\n type DatabaseRecord,\n type MutationInfo,\n type PaginatedResult,\n type RelationOptions,\n type TriggerConfig,\n type WhereCallback\n};\n"],"mappings":"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","names":["path","require","response","path","err"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/Database.ts","../src/lib/Trigger.ts","../src/index.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport { randomUUID } from 'crypto';\r\nimport { QueryEngine, ComputedFieldProcessor, TriggerProcessor } from \"@dbcube/core\";\r\nimport { ComputedFieldConfig, DatabaseRecord, DML, MutationInfo, PaginatedResult, RelationOptions, TriggerConfig, WhereCallback, WhereCondition } from \"../@types/Database\";\r\nimport { Trigger } from './Trigger';\r\n\r\n/**\r\n * Main class to handle MySQL database connections and queries.\r\n * Implements the Singleton pattern to ensure a single instance of the connection pool.\r\n */\r\nexport class Database {\r\n private name: string;\r\n private engine: QueryEngine;\r\n private computedFields: ComputedFieldConfig[];\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n\r\n constructor(name: string) {\r\n this.name = name;\r\n const engine = new QueryEngine(name);\r\n this.engine = engine;\r\n this.computedFields = [];\r\n this.triggers = [];\r\n }\r\n\r\n /**\r\n * Executes raw SQL (MySQL/PostgreSQL/SQLite) or a raw command document (MongoDB)\r\n * with bound parameters. The escape hatch for anything the builder doesn't cover.\r\n *\r\n * @example\r\n * const rows = await db.raw('SELECT * FROM users WHERE age > ?', [25]);\r\n * await db.raw('CREATE INDEX idx_users_email ON users(email)');\r\n */\r\n async raw<R = DatabaseRecord>(query: string, params: unknown[] = []): Promise<R[]> {\r\n const response = await this.engine.rawQuery(query, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Runs a callback inside a database transaction. Everything executed through\r\n * the received connection is committed atomically; any thrown error rolls\r\n * the whole transaction back.\r\n *\r\n * Requires daemon mode (enabled by default with an up-to-date query-engine).\r\n *\r\n * @example\r\n * await db.transaction(async (trx) => {\r\n * await trx.table('accounts').where('id', '=', 1).update({ balance: 50 });\r\n * await trx.table('accounts').where('id', '=', 2).update({ balance: 150 });\r\n * });\r\n */\r\n async transaction<T>(callback: (trx: Database) => Promise<T>): Promise<T> {\r\n const txId: string = await this.engine.beginTransaction();\r\n\r\n const trx = new Database(this.name);\r\n trx.engine = this.engine;\r\n trx.computedFields = this.computedFields;\r\n trx.triggers = this.triggers;\r\n trx.txId = txId;\r\n\r\n try {\r\n const result = await callback(trx);\r\n await this.engine.commitTransaction(txId);\r\n return result;\r\n } catch (error) {\r\n try {\r\n await this.engine.rollbackTransaction(txId);\r\n } catch (rollbackError: any) {\r\n // El error original manda, pero un rollback fallido no puede\r\n // pasar en silencio: la transacción puede seguir reteniendo\r\n // locks hasta que el daemon la expire por inactividad.\r\n console.error(\r\n `[dbcube] Rollback of transaction ${txId} failed: ${rollbackError?.message ?? rollbackError}`\r\n );\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async useComputes(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayComputedFields = await ComputedFieldProcessor.getComputedFields(this.name);\r\n newDatabase.setComputedFields(arrayComputedFields);\r\n return newDatabase;\r\n }\r\n\r\n async useTriggers(): Promise<Database> {\r\n const newDatabase = new Database(this.name); \r\n const arrayTriggers = await TriggerProcessor.getTriggers(this.name);\r\n newDatabase.setTriggers(arrayTriggers);\r\n return newDatabase;\r\n }\r\n\r\n async connect(): Promise<void> {\r\n const response = await this.engine.run('query_engine', [\r\n '--action', 'connect',\r\n ]);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n await this.engine.run('query_engine', [\r\n '--action', 'disconnect',\r\n ]);\r\n }\r\n\r\n /**\r\n * Creates and returns a new instance of `Table` for the specified table.\r\n * This method is used to start building queries for a specific table.\r\n * It provides a fluent interface for common database operations like select, insert, update, and delete.\r\n *\r\n * @param {string} tableName - The name of the table to query.\r\n * @returns {Table} - Returns a new instance of `Table` for the specified table.\r\n *\r\n * @example\r\n * // Select all records from a table\r\n * const users = await db.table('users').get();\r\n * \r\n * // Select records with conditions\r\n * const activeUsers = await db.table('users')\r\n * .where('status', '=', 'active')\r\n * .orderBy('created_at', 'DESC')\r\n * .limit(10)\r\n * .get();\r\n * \r\n * // Insert records\r\n * await db.table('users').insert([\r\n * { name: 'John', email: 'john@example.com', age: 30 }\r\n * ]);\r\n * \r\n * // Update records\r\n * await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ status: 'inactive' });\r\n * \r\n * // Delete records\r\n * await db.table('users')\r\n * .where('status', '=', 'deleted')\r\n * .delete();\r\n * \r\n * // Access column management\r\n * const columns = await db.table('users').columns().get();\r\n */\r\n table<T extends DatabaseRecord = DatabaseRecord>(tableName: string): Table<T> {\r\n return new Table<T>(this, this.name, tableName, this.engine, this.computedFields, this.triggers, this.txId);\r\n }\r\n\r\n private setComputedFields(computedFields: ComputedFieldConfig[]){\r\n this.computedFields = computedFields;\r\n }\r\n\r\n private setTriggers(triggers: TriggerConfig[]){\r\n this.triggers = triggers;\r\n }\r\n}\r\n\r\n/**\r\n * Class to build and execute SQL queries for a specific table.\r\n * Supports operations like SELECT, INSERT, UPDATE, DELETE, and more.\r\n *\r\n * Generic over the row shape: `db.table<User>('users').get()` resolves to\r\n * `Promise<User[]>`. Pair it with the interfaces emitted by `dbcube generate`.\r\n */\r\nexport class Table<T extends DatabaseRecord = DatabaseRecord> {\r\n private engine: QueryEngine;\r\n private nextType: 'AND' | 'OR' = 'AND';\r\n private dml: DML;\r\n private computedFields: ComputedFieldConfig[] = [];\r\n private trigger: Trigger;\r\n private triggers: TriggerConfig[];\r\n private txId: string | null = null;\r\n private relations: { name: string; options: RelationOptions }[] = [];\r\n /** Builders de grupo mutan en sitio (ver clone()) */\r\n private _mutable = false;\r\n\r\n private instance: Database;\r\n\r\n constructor(instance: Database, databaseName: string, tableName: string, engine: QueryEngine, computedFields: ComputedFieldConfig[] = [], triggers: TriggerConfig[] = [], txId: string | null = null) {\r\n this.engine = engine;\r\n this.instance = instance;\r\n this.computedFields = computedFields;\r\n this.triggers = triggers;\r\n this.trigger = new Trigger(instance, databaseName, triggers);\r\n this.nextType = 'AND';\r\n this.txId = txId;\r\n\r\n this.dml = {\r\n type: 'select',\r\n database: databaseName,\r\n table: tableName,\r\n columns: ['*'],\r\n distinct: false,\r\n joins: [],\r\n where: [],\r\n orderBy: [],\r\n groupBy: [],\r\n limit: null,\r\n offset: null,\r\n data: null,\r\n aggregation: null,\r\n having: []\r\n };\r\n }\r\n\r\n /**\r\n * Specifies the columns to select in a SELECT query.\r\n *\r\n * @param {string[]} fields - Array of column names to select. If empty, selects all columns.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').select(['id', 'name']).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n select(fields: string[] = []): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = fields.length > 0 ? fields : ['*'];\r\n clone.dml.aggregation = null;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).get();\r\n * const nullUsers = await db.table('users').where('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n where(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n where(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n where(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an OR WHERE condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<', 'IS NULL', 'IS NOT NULL').\r\n * @param {any} value - The value to compare against (optional for IS NULL/IS NOT NULL).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').where('age', '>', 25).orWhere('name', '=', 'Jane').get();\r\n * const nullUsers = await db.table('users').where('active', '=', true).orWhere('email', 'IS NULL').get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n orWhere(column: string, operator: 'IS NULL' | 'IS NOT NULL'): Table<T>;\r\n orWhere(column: string, operator: '=' | '!=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN', value: any): Table<T>;\r\n orWhere(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'OR',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a grouped WHERE condition to the query.\r\n *\r\n * @param {WhereCallback} callback - A callback function that receives a new Table instance to build the grouped conditions.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereGroup(query => {\r\n * query.where('age', '>', 25).orWhere('name', '=', 'Jane');\r\n * }).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereGroup(callback: WhereCallback): Table<T> {\r\n const clone = this.clone();\r\n const groupQuery = new Table(this.instance, clone.dml.database, clone.dml.table, clone.engine);\r\n // El callback encadena sin usar el valor de retorno; el builder del\r\n // grupo debe mutar en sitio o las condiciones se perderían en clones\r\n groupQuery._mutable = true;\r\n callback(groupQuery);\r\n\r\n clone.dml.where.push({\r\n type: clone.nextType,\r\n isGroup: true,\r\n conditions: groupQuery.dml.where as WhereCondition[]\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n or(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'OR';\r\n return clone;\r\n }\r\n\r\n and(): Table<T> {\r\n const clone = this.clone();\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE BETWEEN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {[any, any]} values - A tuple with two values representing the range.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereBetween('age', [20, 30]).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }, { id: 2, name: 'Jane', age: 25 }]\r\n */\r\n whereBetween(column: string, values: [any, any]): Table<T> {\r\n const clone = this.clone();\r\n const [value1, value2] = values;\r\n if (value1 !== undefined && value2 !== undefined) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'BETWEEN',\r\n value: [value1, value2],\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IN condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @param {any[]} values - An array of values to match.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereIn('id', [1, 2]).get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n whereIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNull('email').get();\r\n * console.log(users); // [{ id: 3, name: 'Alice', email: null }]\r\n */\r\n whereNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a WHERE IS NOT NULL condition to the query.\r\n *\r\n * @param {string} column - The column to filter by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotNull('email').get();\r\n * console.log(users); // [{ id: 1, name: 'John', email: 'john@example.com' }]\r\n */\r\n whereNotNull(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.where.push({\r\n column,\r\n operator: 'IS NOT NULL',\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').join('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }]\r\n */\r\n join(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'INNER',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a LEFT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').leftJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: 2, name: 'Jane', order_id: null }]\r\n */\r\n leftJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'LEFT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a RIGHT JOIN clause to the query.\r\n *\r\n * @param {string} table - The table to join.\r\n * @param {string} column1 - The column from the current table.\r\n * @param {string} operator - The comparison operator (e.g., '=', '>', '<').\r\n * @param {string} column2 - The column from the joined table.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').rightJoin('orders', 'users.id', '=', 'orders.user_id').get();\r\n * console.log(users); // [{ id: 1, name: 'John', order_id: 101 }, { id: null, name: null, order_id: 102 }]\r\n */\r\n rightJoin(table: string, column1: string, operator: string, column2: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.joins.push({\r\n type: 'RIGHT',\r\n table,\r\n on: {\r\n column1,\r\n operator,\r\n column2\r\n }\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds an ORDER BY clause to the query.\r\n *\r\n * @param {string} column - The column to order by.\r\n * @param {'ASC' | 'DESC'} direction - The sorting direction ('ASC' or 'DESC').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').orderBy('name', 'ASC').get();\r\n * console.log(users); // [{ id: 2, name: 'Jane' }, { id: 1, name: 'John' }]\r\n */\r\n orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): Table<T> {\r\n const clone = this.clone();\r\n const validDirections: ('ASC' | 'DESC')[] = ['ASC', 'DESC'];\r\n if (validDirections.includes(direction.toUpperCase() as 'ASC' | 'DESC')) {\r\n clone.dml.orderBy.push({\r\n column,\r\n direction: direction.toUpperCase() as 'ASC' | 'DESC'\r\n });\r\n } else {\r\n throw new Error(`Invalid direction: ${direction}. Use 'ASC' or 'DESC'.`);\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a GROUP BY clause to the query.\r\n *\r\n * @param {string} column - The column to group by.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').groupBy('age').get();\r\n * console.log(users); // [{ age: 30, count: 1 }, { age: 25, count: 1 }]\r\n */\r\n groupBy(column: string): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.groupBy.push(column);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a DISTINCT clause to the query.\r\n *\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').distinct().select(['name']).get();\r\n * console.log(users); // [{ name: 'John' }, { name: 'Jane' }]\r\n */\r\n distinct(): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.distinct = true;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a COUNT clause to the query.\r\n *\r\n * @param {string} column - The column to count (default is '*').\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const count = await db.table('users').count().first();\r\n * console.log(count); // { count: 2 }\r\n */\r\n async count(column: string = '*'): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'COUNT',\r\n column,\r\n alias: 'count'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`COUNT(${column}) AS count`];\r\n clone.dml.data = null;\r\n clone.dml.limit = null; // Remover limit para contar todos\r\n clone.dml.offset = null; // Remover offset también\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.count;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a SUM clause to the query.\r\n *\r\n * @param {string} column - The column to sum.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const totalAge = await db.table('users').sum('age').first();\r\n * console.log(totalAge); // { sum: 55 }\r\n */\r\n async sum(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'SUM',\r\n column,\r\n alias: 'sum'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`SUM(${column}) AS sum`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.sum;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds an AVG clause to the query.\r\n *\r\n * @param {string} column - The column to calculate the average.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const avgAge = await db.table('users').avg('age').first();\r\n * console.log(avgAge); // { avg: 27.5 }\r\n */\r\n async avg(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'AVG',\r\n column,\r\n alias: 'avg'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`AVG(${column}) AS avg`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.avg;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MAX clause to the query.\r\n *\r\n * @param {string} column - The column to find the maximum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const maxAge = await db.table('users').max('age').first();\r\n * console.log(maxAge); // { max: 30 }\r\n */\r\n async max(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MAX',\r\n column,\r\n alias: 'max'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`MAX(${column}) AS max`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.max;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a MIN clause to the query.\r\n *\r\n * @param {string} column - The column to find the minimum value.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const minAge = await db.table('users').min('age').first();\r\n * console.log(minAge); // { min: 25 }\r\n */\r\n async min(column: string): Promise<number> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.aggregation = {\r\n type: 'MIN',\r\n column,\r\n alias: 'min'\r\n }\r\n \r\n clone.dml.orderBy = []; // un agregado escalar no ordena; Postgres rechaza ORDER BY de columnas no agrupadas\r\nclone.dml.columns = [`MIN(${column}) AS min`];\r\n clone.dml.data = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n const res = result[0] || null;\r\n if (res) {\r\n return res.min;\r\n }\r\n return 0;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the column names of the table.\r\n * For SQL databases (MySQL, PostgreSQL, SQLite), returns a simple array of column names.\r\n * For MongoDB, returns a hierarchical structure with nested documents.\r\n *\r\n * @returns {Promise<string[] | any>} - Returns an array of column names for SQL databases,\r\n * or a hierarchical structure for MongoDB.\r\n *\r\n * @example\r\n * // SQL databases (MySQL, PostgreSQL, SQLite)\r\n * const columns = await db.table('users').columns();\r\n * console.log(columns); // ['id', 'name', 'email', 'age', 'created_at']\r\n *\r\n * @example\r\n * // MongoDB\r\n * const structure = await db.table('users').columns();\r\n * console.log(structure);\r\n * // {\r\n * // columns: ['id', 'name', 'profile'],\r\n * // submenu: {\r\n * // profile: {\r\n * // columns: ['age', 'city'],\r\n * // submenu: {}\r\n * // }\r\n * // }\r\n * // }\r\n */\r\n async columns(): Promise<string[] | any> {\r\n const clone = this.clone();\r\n clone.dml.type = 'columns';\r\n clone.dml.columns = [];\r\n clone.dml.where = [];\r\n clone.dml.orderBy = [];\r\n clone.dml.groupBy = [];\r\n clone.dml.limit = null;\r\n clone.dml.offset = null;\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n\r\n try {\r\n const result = await clone.getResponse();\r\n\r\n if (Array.isArray(result) && result.length > 0) {\r\n // Verificar si es MongoDB (estructura jerárquica)\r\n if (result[0].columns && result[0].submenu !== undefined) {\r\n // MongoDB: devolver la estructura completa\r\n return result[0];\r\n }\r\n\r\n // SQL databases: transformar a array simple de strings\r\n return result.map((row: any) => row.column_name || row.Field || row.name);\r\n }\r\n\r\n return [];\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a LIMIT clause to the query.\r\n *\r\n * @param {number} number - The maximum number of rows to return.\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).get();\r\n * console.log(users); // [{ id: 1, name: 'John', age: 30 }]\r\n */\r\n limit(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.limit = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds pagination to the query using LIMIT and OFFSET.\r\n *\r\n * @param {number} number - The page number (starting from 1).\r\n * @returns {Table} - Returns the current instance of Table for method chaining.\r\n *\r\n * @example\r\n * const users = await db.table('users').limit(1).page(2).get();\r\n * console.log(users); // [{ id: 2, name: 'Jane', age: 25 }]\r\n */\r\n page(number: number): Table<T> {\r\n const clone = this.clone();\r\n const pageNum = Number(number);\r\n if (clone.dml.limit) {\r\n clone.dml.offset = (pageNum - 1) * clone.dml.limit;\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Executes the query and returns all matching rows.\r\n *\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of rows.\r\n *\r\n * @example\r\n * const users = await db.table('users').get();\r\n * console.log(users); // [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\r\n */\r\n async get(): Promise<T[]> {\r\n try {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n const result = await clone.getResponse();\r\n if (this.relations.length > 0 && Array.isArray(result)) {\r\n return await this.attachRelations(result) as T[];\r\n }\r\n return result as T[];\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Executes the query and returns the first matching row.\r\n *\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').first();\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async first(): Promise<T | null> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Finds a row by a specific column value.\r\n *\r\n * @param {any} value - The value to search for.\r\n * @param {string} column - The column to search in (default is 'id').\r\n * @returns {Promise<DatabaseRecord | null>} - Returns the first matching row or null if no rows match.\r\n *\r\n * @example\r\n * const user = await db.table('users').find(1);\r\n * console.log(user); // { id: 1, name: 'John' }\r\n */\r\n async find(value: string | number, column: string = 'id'): Promise<T | null> {\r\n // where() is immutable: reassign the clone or the condition is lost\r\n const clone = this.clone().where(column, '=', value);\r\n clone.dml.type = 'select';\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n try {\r\n const result = await clone.getResponse();\r\n return result[0] || null;\r\n }\r\n catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Inserts one or more rows into the table.\r\n *\r\n * @param {DatabaseRecord[]} data - An array of objects representing the rows to insert.\r\n * @returns {Promise<DatabaseRecord[]>} - Returns an array of the inserted rows.\r\n *\r\n * @example\r\n * const newUsers = await db.table('users').insert([\r\n * { name: 'Alice', age: 28 },\r\n * { name: 'Bob', age: 32 }\r\n * ]);\r\n * console.log(newUsers); // [{ id: 3, name: 'Alice', age: 28 }, { id: 4, name: 'Bob', age: 32 }]\r\n */\r\n async insert(data: Partial<T>[]): Promise<T[]> {\r\n const clone = this.clone();\r\n if (!Array.isArray(data)) {\r\n throw new Error('The insert method requires an array of objects with key-value pairs.');\r\n }\r\n\r\n if (!data.every(item => typeof item === 'object' && item !== null)) {\r\n throw new Error('The array must contain only valid objects.');\r\n }\r\n\r\n clone.dml.type = 'insert';\r\n clone.dml.data = data;\r\n\r\n const result = await clone.getResponse(clone.dml, 'Add');\r\n\r\n return result ?? data;\r\n }\r\n\r\n /**\r\n * Updates rows in the table based on the defined conditions.\r\n *\r\n * @param {DatabaseRecord} data - An object with key-value pairs representing the fields to update.\r\n * @returns {Promise<any>} - Returns the result of the update operation.\r\n *\r\n * @example\r\n * const result = await db.table('users')\r\n * .where('id', '=', 1)\r\n * .update({ name: 'John Updated', age: 31 });\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async update(data: Partial<T>): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (typeof data !== 'object' || Array.isArray(data)) {\r\n throw new Error('The update method requires an object with key-value pairs.');\r\n }\r\n\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an update.');\r\n }\r\n\r\n clone.dml.type = 'update';\r\n clone.dml.data = data;\r\n\r\n return clone.getResponse(clone.dml, 'Update');\r\n }\r\n\r\n /**\r\n * Deletes rows from the table based on the defined conditions.\r\n *\r\n * @returns {Promise<any>} - Returns the result of the delete operation.\r\n *\r\n * @example\r\n * const result = await db.table('users').where('id', '=', 1).delete();\r\n * console.log(result); // { affectedRows: 1 }\r\n */\r\n async delete(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform a delete.');\r\n }\r\n\r\n clone.dml.type = 'delete';\r\n\r\n const deleteData = await clone.getResponse(clone.dml, 'Delete');\r\n return deleteData;\r\n }\r\n\r\n /**\r\n * Adds a WHERE NOT IN condition to the query.\r\n *\r\n * @example\r\n * const users = await db.table('users').whereNotIn('status', ['banned', 'deleted']).get();\r\n */\r\n whereNotIn(column: string, values: any[]): Table<T> {\r\n const clone = this.clone();\r\n if (Array.isArray(values) && values.length > 0) {\r\n clone.dml.where.push({\r\n column,\r\n operator: 'NOT IN',\r\n value: values,\r\n type: clone.nextType,\r\n isGroup: false\r\n });\r\n clone.nextType = 'AND';\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Sets an explicit OFFSET for the query (alternative to page()).\r\n *\r\n * @example\r\n * const rows = await db.table('logs').orderBy('id', 'ASC').limit(50).offset(100).get();\r\n */\r\n offset(number: number): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.offset = Number(number);\r\n return clone;\r\n }\r\n\r\n /**\r\n * Appends raw expressions to the SELECT list (aggregates, functions, aliases).\r\n * Combine with groupBy() and having() for per-group metrics.\r\n *\r\n * @example\r\n * const stats = await db.table('orders')\r\n * .select(['user_id'])\r\n * .selectRaw(['COUNT(*) AS order_count', 'SUM(amount) AS total'])\r\n * .groupBy('user_id')\r\n * .having('order_count', '>', 5)\r\n * .get();\r\n */\r\n selectRaw(expressions: string[]): Table<T> {\r\n const clone = this.clone();\r\n if (clone.dml.columns.length === 1 && clone.dml.columns[0] === '*') {\r\n clone.dml.columns = [...expressions];\r\n } else {\r\n clone.dml.columns = [...clone.dml.columns, ...expressions];\r\n }\r\n return clone;\r\n }\r\n\r\n /**\r\n * Adds a HAVING condition (filters grouped results).\r\n *\r\n * @example\r\n * .groupBy('user_id').having('COUNT(*)', '>', 5)\r\n */\r\n having(column: string, operator: string, value?: any): Table<T> {\r\n const clone = this.clone();\r\n clone.dml.having = clone.dml.having ?? [];\r\n clone.dml.having.push({\r\n column,\r\n operator,\r\n value,\r\n type: 'AND',\r\n isGroup: false\r\n });\r\n return clone;\r\n }\r\n\r\n /**\r\n * Checks if at least one row matches the current conditions.\r\n * Cheaper than first(): selects a constant with LIMIT 1.\r\n *\r\n * @example\r\n * const taken = await db.table('users').where('email', '=', email).exists();\r\n */\r\n async exists(): Promise<boolean> {\r\n const clone = this.clone();\r\n clone.dml.type = 'select';\r\n clone.dml.columns = ['1 AS dbcube_exists'];\r\n clone.dml.data = null;\r\n clone.dml.aggregation = null;\r\n clone.dml.limit = 1;\r\n clone.dml.offset = null;\r\n const result = await clone.getResponse();\r\n return Array.isArray(result) && result.length > 0;\r\n }\r\n\r\n /**\r\n * Fetches one page of results plus pagination metadata in a single call.\r\n * Runs the page query and the total count with the same conditions.\r\n *\r\n * @example\r\n * const { items, total, totalPages, hasNext } = await db.table('products')\r\n * .where('published', '=', true)\r\n * .orderBy('id', 'ASC')\r\n * .paginate(2, 25);\r\n */\r\n async paginate(page: number = 1, perPage: number = 20): Promise<PaginatedResult<T>> {\r\n const pageNum = Math.max(1, Number(page));\r\n const size = Math.max(1, Number(perPage));\r\n\r\n const itemsQuery = this.limit(size).page(pageNum);\r\n const [items, total] = await Promise.all([\r\n itemsQuery.get(),\r\n this.count()\r\n ]);\r\n\r\n const totalNum = Number(total);\r\n const totalPages = Math.ceil(totalNum / size);\r\n return {\r\n items,\r\n page: pageNum,\r\n perPage: size,\r\n total: totalNum,\r\n totalPages,\r\n hasNext: pageNum < totalPages,\r\n hasPrev: pageNum > 1,\r\n };\r\n }\r\n\r\n /**\r\n * Processes all matching rows in batches of `size`, keeping memory flat.\r\n * Return `false` from the callback to stop early.\r\n *\r\n * @example\r\n * await db.table('logs').orderBy('id', 'ASC').chunk(500, async (rows) => {\r\n * await processBatch(rows);\r\n * });\r\n */\r\n async chunk(size: number, callback: (rows: T[], page: number) => Promise<void | boolean> | void | boolean): Promise<void> {\r\n const batchSize = Math.max(1, Number(size));\r\n let page = 1;\r\n while (true) {\r\n const rows = await this.limit(batchSize).page(page).get();\r\n if (rows.length === 0) break;\r\n const result = await callback(rows, page);\r\n if (result === false) break;\r\n if (rows.length < batchSize) break;\r\n page++;\r\n }\r\n }\r\n\r\n /**\r\n * Atomically increments a numeric column: `SET col = col + amount`.\r\n * Requires at least one WHERE condition. Extra fields can be updated in the same statement.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).increment('stock', 3);\r\n * await db.table('posts').where('id', '=', 1).increment('views', 1, { last_viewed_at: new Date().toISOString() });\r\n */\r\n async increment(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n if (clone.dml.where.length === 0) {\r\n throw new Error('You must specify at least one WHERE condition to perform an increment.');\r\n }\r\n clone.dml.type = 'update';\r\n clone.dml.data = { ...extra, [column]: { $inc: Number(amount) } };\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Atomically decrements a numeric column: `SET col = col - amount`.\r\n *\r\n * @example\r\n * await db.table('products').where('id', '=', 5).decrement('stock', 1);\r\n */\r\n async decrement(column: string, amount: number = 1, extra: Partial<T> = {}): Promise<MutationInfo[]> {\r\n return this.increment(column, -Math.abs(Number(amount)), extra);\r\n }\r\n\r\n /**\r\n * Deletes ALL rows from the table. The only write operation allowed\r\n * without a WHERE — the destructive intent is explicit in the name.\r\n *\r\n * @example\r\n * await db.table('temp_imports').truncate();\r\n */\r\n async truncate(): Promise<MutationInfo[]> {\r\n const clone = this.clone();\r\n clone.dml.type = 'delete';\r\n clone.dml.where = [];\r\n return clone.getResponse();\r\n }\r\n\r\n /**\r\n * Inserts rows, updating them instead when a conflict occurs on the given keys.\r\n * MySQL → ON DUPLICATE KEY UPDATE · PostgreSQL/SQLite → ON CONFLICT ... DO UPDATE.\r\n *\r\n * @param data Rows to insert.\r\n * @param conflictKeys Column(s) with the UNIQUE/PK constraint that triggers the update.\r\n * @param updateColumns Columns to overwrite on conflict (defaults to every non-conflict column).\r\n *\r\n * @example\r\n * await db.table('settings').upsert(\r\n * [{ key: 'theme', value: 'dark' }],\r\n * ['key']\r\n * );\r\n */\r\n async upsert(data: Partial<T>[], conflictKeys: string[], updateColumns?: string[]): Promise<MutationInfo[]> {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n throw new Error('The upsert method requires a non-empty array of objects.');\r\n }\r\n if (!Array.isArray(conflictKeys) || conflictKeys.length === 0) {\r\n throw new Error('The upsert method requires at least one conflict key column.');\r\n }\r\n\r\n const motor: string = this.engine?.getConfig?.()?.type ?? 'mysql';\r\n\r\n const table = this.dml.table;\r\n const columns = Object.keys(data[0]);\r\n const targets = updateColumns ?? columns.filter(c => !conflictKeys.includes(c));\r\n\r\n // Único método que arma la operación en JS: validar identificadores\r\n // porque las claves de los objetos pueden venir de input externo\r\n assertValidIdentifier(table, 'table');\r\n for (const c of columns) assertValidIdentifier(c, 'column');\r\n for (const c of conflictKeys) assertValidIdentifier(c, 'conflict key');\r\n for (const c of targets) assertValidIdentifier(c, 'update column');\r\n\r\n if (motor === 'mongodb') {\r\n // Comando `update` nativo con upsert:true por fila — misma semántica\r\n // que ON CONFLICT: matchea por conflictKeys, actualiza solo targets,\r\n // y al insertar escribe la fila completa.\r\n const updates = data.map(row => {\r\n const q: Record<string, unknown> = {};\r\n for (const k of conflictKeys) q[k] = row[k];\r\n\r\n const set: Record<string, unknown> = {};\r\n for (const c of targets) if (c in row) set[c] = row[c];\r\n\r\n const setOnInsert: Record<string, unknown> = {};\r\n for (const c of columns) {\r\n if (!targets.includes(c) && !conflictKeys.includes(c)) setOnInsert[c] = row[c];\r\n }\r\n if (!('uuid' in row)) setOnInsert['uuid'] = randomUUID();\r\n\r\n const u: Record<string, unknown> = {};\r\n if (Object.keys(set).length) u['$set'] = set;\r\n if (Object.keys(setOnInsert).length) u['$setOnInsert'] = setOnInsert;\r\n\r\n return { q, u, upsert: true, multi: false };\r\n });\r\n\r\n const command = JSON.stringify({ update: table, updates });\r\n const response = await this.engine.rawQuery(command, [], this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n const quote = (id: string) => motor === 'mysql' ? `\\`${id}\\`` : `\"${id}\"`;\r\n\r\n const params: any[] = [];\r\n const placeholder = () => motor === 'postgres' || motor === 'postgresql'\r\n ? `$${params.length}`\r\n : '?';\r\n\r\n const rowsSql = data.map(row => {\r\n const cells = columns.map(col => {\r\n params.push(row[col] === undefined ? null : row[col]);\r\n return placeholder();\r\n });\r\n return `(${cells.join(', ')})`;\r\n }).join(', ');\r\n\r\n const colsSql = columns.map(quote).join(', ');\r\n let sql: string;\r\n\r\n if (motor === 'mysql') {\r\n const updates = targets.map(c => `${quote(c)} = VALUES(${quote(c)})`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON DUPLICATE KEY UPDATE ${updates}`;\r\n } else {\r\n const conflict = conflictKeys.map(quote).join(', ');\r\n const updates = targets.map(c => `${quote(c)} = excluded.${quote(c)}`).join(', ');\r\n sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON CONFLICT (${conflict}) DO UPDATE SET ${updates}`;\r\n }\r\n\r\n if (motor === 'sqlite') {\r\n // SQLite pool schema sync: ensure every pooled connection sees constraints\r\n // created moments ago (e.g. a UNIQUE index added right before this upsert).\r\n await this.engine.rawQuery('SELECT name FROM sqlite_master LIMIT 1', [], this.txId ?? undefined);\r\n }\r\n const response = await this.engine.rawQuery(sql, params, this.txId ?? undefined);\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(response.message);\r\n }\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Declares a relation to eager-load with the results of get().\r\n * Relations are resolved from `foreign` definitions in your .cube files,\r\n * or explicitly via options. Loads each relation with ONE batched query\r\n * (whereIn) — no N+1.\r\n *\r\n * @example\r\n * // hasMany: orders.user_id → users.id (auto-detected from orders.table.cube)\r\n * const users = await db.table('users').with('orders').get();\r\n * // users[0].orders === [{...}, {...}]\r\n *\r\n * // belongsTo: posts.author_id → users.id, attached as a single object\r\n * const posts = await db.table('posts')\r\n * .with('author', { table: 'users', foreignKey: 'author_id', type: 'one' })\r\n * .get();\r\n */\r\n with(relation: string, options: RelationOptions = {}): Table<T> {\r\n const clone = this.clone();\r\n clone.relations.push({ name: relation, options });\r\n return clone;\r\n }\r\n\r\n private async attachRelations(rows: DatabaseRecord[]): Promise<DatabaseRecord[]> {\r\n if (rows.length === 0 || this.relations.length === 0) return rows;\r\n\r\n for (const { name, options } of this.relations) {\r\n const relatedTable = options.table ?? name;\r\n const cubeMeta = loadCubeRelations();\r\n\r\n // Detect direction + keys from .cube foreign metadata when not explicit\r\n let type = options.type;\r\n let foreignKey = options.foreignKey;\r\n let localKey = options.localKey ?? 'id';\r\n\r\n if (!foreignKey || !type) {\r\n const childFks = cubeMeta[relatedTable]?.foreigns ?? [];\r\n const ownFks = cubeMeta[this.dml.table]?.foreigns ?? [];\r\n const childToParent = childFks.find(fk => fk.table === this.dml.table);\r\n const parentToChild = ownFks.find(fk => fk.table === relatedTable);\r\n\r\n if (childToParent) {\r\n // hasMany: the related table points at us\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? childToParent.column_name;\r\n localKey = options.localKey ?? childToParent.column;\r\n } else if (parentToChild) {\r\n // belongsTo: we point at the related table\r\n type = type ?? 'one';\r\n foreignKey = foreignKey ?? parentToChild.column_name;\r\n localKey = options.localKey ?? parentToChild.column;\r\n } else {\r\n // Heuristic fallback: <singular-parent>_id on the child table\r\n type = type ?? 'many';\r\n foreignKey = foreignKey ?? `${singularize(this.dml.table)}_id`;\r\n }\r\n }\r\n\r\n const relatedQuery = new Table(this.instance, this.dml.database, relatedTable, this.engine, this.computedFields, this.triggers, this.txId);\r\n\r\n if (type === 'one') {\r\n // belongsTo: FK lives on THIS table, match related.localKey\r\n const fkValues = [...new Set(rows.map(r => r[foreignKey!]).filter(v => v !== null && v !== undefined))];\r\n const related = fkValues.length > 0\r\n ? await relatedQuery.whereIn(localKey, fkValues).get()\r\n : [];\r\n const index = new Map(related.map(r => [r[localKey], r]));\r\n for (const row of rows) {\r\n row[name] = index.get(row[foreignKey!]) ?? null;\r\n }\r\n } else {\r\n // hasMany: FK lives on the RELATED table, match this.localKey\r\n const ids = [...new Set(rows.map(r => r[localKey]).filter(v => v !== null && v !== undefined))];\r\n const related = ids.length > 0\r\n ? await relatedQuery.whereIn(foreignKey!, ids).get()\r\n : [];\r\n const groups = new Map<any, DatabaseRecord[]>();\r\n for (const rel of related) {\r\n const key = rel[foreignKey!];\r\n if (!groups.has(key)) groups.set(key, []);\r\n groups.get(key)!.push(rel);\r\n }\r\n for (const row of rows) {\r\n row[name] = groups.get(row[localKey]) ?? [];\r\n }\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n private async getResponse(dml: any = null, type: any = null): Promise<any> {\r\n const localDML = dml ? dml : this.dml;\r\n const computedFieldsNeeded: any[] = [];\r\n let dependeciesArrray: any[] = [];\r\n // Columnas pedidas por el usuario ANTES de inyectar dependencias de\r\n // computed fields: las dependencias solo se eliminan del resultado si\r\n // el usuario NO las pidió explícitamente\r\n const requestedColumns = new Set<string>(localDML.columns ?? []);\r\n\r\n if (this.computedFields.length > 0) {\r\n let columns = localDML.columns;\r\n\r\n for (const field of localDML.columns) {\r\n const computedField = this.computedFields.find(cf => cf.column === field);\r\n\r\n if (computedField) {\r\n computedFieldsNeeded.push(computedField);\r\n // Add dependencies to real fields\r\n const dependencies = ComputedFieldProcessor.extractDependencies(computedField.instruction);\r\n dependeciesArrray = [...dependeciesArrray, ...dependencies];\r\n columns = Array.from(new Set([...columns, ...dependencies]));\r\n columns = columns.filter((col: string) => col != field);\r\n }\r\n }\r\n localDML.columns = columns;\r\n }\r\n\r\n let arrayResult = [];\r\n if (type) {\r\n const beffore = this.trigger.get('before' + type);\r\n const after = this.trigger.get('after' + type);\r\n if (this.triggers.length > 0 && (beffore || after)) {\r\n const dataset = localDML.data;\r\n for (let index = 0; index < dataset.length; index++) {\r\n const data = dataset[index];\r\n const newDML = { ...localDML, data: [data] };\r\n if (beffore) {\r\n const interceptor = await this.trigger.execute('before' + type, data);\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n interceptor?.discard();\r\n returnFormattedError(response.status, response.message);\r\n // Un fallo del engine DEBE propagarse: resolver en\r\n // silencio haría creer al caller que la escritura\r\n // ocurrió (pérdida de datos invisible)\r\n throw new Error(String(response.message));\r\n }\r\n await interceptor?.commit();\r\n arrayResult = response.data;\r\n }\r\n if (after) {\r\n\r\n const response = await this.engine.executeDml(newDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(String(response.message));\r\n }\r\n const interceptor = await this.trigger.execute('after' + type, data);\r\n await interceptor?.commit();\r\n }\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(String(response.message));\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n } else {\r\n const response = await this.engine.executeDml(localDML, this.txId ?? undefined);\r\n\r\n if (response.status != 200) {\r\n returnFormattedError(response.status, response.message);\r\n throw new Error(String(response.message));\r\n }\r\n\r\n arrayResult = response.data;\r\n }\r\n\r\n if (computedFieldsNeeded.length > 0) {\r\n let newDataset: any = ComputedFieldProcessor.computedFields(arrayResult, computedFieldsNeeded);\r\n const toRemove = dependeciesArrray.filter(key => !requestedColumns.has(key));\r\n const result = newDataset.map((obj: any) => {\r\n const newObj = { ...obj };\r\n toRemove.forEach(key => delete newObj[key]);\r\n return newObj;\r\n });\r\n return result;\r\n }\r\n return arrayResult;\r\n }\r\n\r\n private clone(): Table<T> {\r\n // Los builders de grupo (whereGroup) son mutables: el callback encadena\r\n // sin usar el valor de retorno, así que clonar perdería las condiciones\r\n if (this._mutable) return this;\r\n const cloned = Object.create(Object.getPrototypeOf(this));\r\n cloned.engine = this.engine;\r\n cloned.instance = this.instance;\r\n cloned.nextType = this.nextType;\r\n cloned.computedFields = this.computedFields;\r\n cloned.trigger = this.trigger;\r\n cloned.triggers = this.triggers;\r\n cloned.txId = this.txId;\r\n cloned.relations = [...this.relations];\r\n\r\n cloned.dml = {\r\n ...this.dml,\r\n columns: [...this.dml.columns],\r\n joins: [...this.dml.joins],\r\n where: [...this.dml.where],\r\n orderBy: [...this.dml.orderBy],\r\n groupBy: [...this.dml.groupBy],\r\n having: [...(this.dml.having ?? [])],\r\n // Clonar propiedades que faltaban para evitar mutación compartida\r\n data: this.dml.data ? (Array.isArray(this.dml.data) ? [...this.dml.data] : { ...this.dml.data }) : null,\r\n aggregation: this.dml.aggregation ? { ...this.dml.aggregation } : null\r\n };\r\n return cloned;\r\n }\r\n\r\n}\r\n\r\n// ---- Cube relation metadata (cached scan of dbcube/*.table.cube) ----\r\n\r\ninterface CubeForeign {\r\n column_name: string; // FK column on the owning table\r\n table: string; // referenced table\r\n column: string; // referenced column\r\n}\r\n\r\nlet cubeRelationsCache: Record<string, { foreigns: CubeForeign[] }> | null = null;\r\n\r\nfunction loadCubeRelations(): Record<string, { foreigns: CubeForeign[] }> {\r\n if (cubeRelationsCache) return cubeRelationsCache;\r\n const result: Record<string, { foreigns: CubeForeign[] }> = {};\r\n\r\n const scanDir = (dir: string) => {\r\n let entries: fs.Dirent[];\r\n try {\r\n entries = fs.readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const entry of entries) {\r\n const full = path.join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n if (entry.name !== 'node_modules' && entry.name !== 'triggers' && entry.name !== 'logs') {\r\n scanDir(full);\r\n }\r\n } else if (entry.name.endsWith('.table.cube')) {\r\n try {\r\n const content = fs.readFileSync(full, 'utf8');\r\n const nameMatch = content.match(/@meta\\s*\\(\\s*\\{[\\s\\S]*?name\\s*:\\s*\"([^\"]+)\"/);\r\n const tableName = nameMatch ? nameMatch[1] : path.basename(entry.name, '.table.cube');\r\n\r\n const foreigns: CubeForeign[] = [];\r\n const colRegex = /(\\w+)\\s*:\\s*\\{(?:[^{}]|\\{[^{}]*\\})*?foreign\\s*:\\s*\\{([^}]*)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = colRegex.exec(content)) !== null) {\r\n const fkTable = m[2].match(/table\\s*:\\s*\"([^\"]+)\"/);\r\n const fkColumn = m[2].match(/column\\s*:\\s*\"([^\"]+)\"/);\r\n if (fkTable) {\r\n foreigns.push({\r\n column_name: m[1],\r\n table: fkTable[1],\r\n column: fkColumn ? fkColumn[1] : 'id',\r\n });\r\n }\r\n }\r\n result[tableName] = { foreigns };\r\n } catch { /* unreadable cube — skip */ }\r\n }\r\n }\r\n };\r\n\r\n scanDir(path.join(process.cwd(), 'dbcube'));\r\n cubeRelationsCache = result;\r\n return result;\r\n}\r\n\r\nfunction assertValidIdentifier(name: string, kind: string): void {\r\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\r\n throw new Error(`Invalid ${kind} name: '${name}'. Only letters, numbers and underscore are allowed.`);\r\n }\r\n}\r\n\r\nfunction singularize(word: string): string {\r\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\r\n if (word.endsWith('ses')) return word.slice(0, -2);\r\n if (word.endsWith('s') && !word.endsWith('ss')) return word.slice(0, -1);\r\n return word;\r\n}\r\n\r\nfunction returnFormattedError(status: number, message: string) {\r\n const RESET = '\\x1b[0m';\r\n const RED = '\\x1b[31m';\r\n const YELLOW = '\\x1b[33m';\r\n const BOLD = '\\x1b[1m';\r\n const CYAN = '\\x1b[36m';\r\n const GRAY = '\\x1b[90m';\r\n const UNDERLINE = '\\x1b[4m';\r\n const MAGENTA = '\\x1b[35m';\r\n\r\n let output = '';\r\n let help = '';\r\n const color = status === 600 ? YELLOW : RED;\r\n\r\n\r\n if (message.includes(\"[help]\")) {\r\n const parts = message.split(\"[help]\");\r\n output += `\\n${RED}${BOLD}${parts[0]}${RESET}`;\r\n help += `\\n${MAGENTA}${BOLD}[help]${RESET} ${GRAY}${parts[1]}${RESET}\\n`;\r\n } else {\r\n output += `\\n${color}${BOLD}${message}${RESET}\\n`;\r\n }\r\n\r\n const err = new Error();\r\n const stackLines = err.stack?.split('\\n') || [];\r\n\r\n // Buscamos la primera línea del stack fuera de node_modules\r\n const relevantStackLine = stackLines.find(line =>\r\n line.includes('.js:') && !line.includes('node_modules')\r\n );\r\n\r\n if (relevantStackLine) {\r\n const match = relevantStackLine.match(/\\((.*):(\\d+):(\\d+)\\)/) ||\r\n relevantStackLine.match(/at (.*):(\\d+):(\\d+)/);\r\n\r\n if (match) {\r\n const [, filePath, lineStr, columnStr] = match;\r\n const lineNum = parseInt(lineStr, 10);\r\n const errorLocation = `${filePath}:${lineStr}:${columnStr}`;\r\n\r\n // Leemos el archivo y sacamos las líneas relevantes\r\n try {\r\n const codeLines = fs.readFileSync(filePath, 'utf-8').split('\\n');\r\n const start = Math.max(0, lineNum - 3);\r\n const end = Math.min(codeLines.length, lineNum + 2);\r\n\r\n output += `\\n${CYAN}${BOLD}[code] ${RESET}${YELLOW} ${UNDERLINE}${errorLocation}${RESET}\\n`;\r\n\r\n for (let i = start; i < end; i++) {\r\n const line = codeLines[i];\r\n const lineLabel = `${i + 1}`.padStart(4, ' ');\r\n const pointer = i + 1 === lineNum ? `${RED}<-${RESET}` : ' ';\r\n output += `${GRAY}${lineLabel}${RESET} ${pointer} ${line}\\n`;\r\n }\r\n } catch (err) {\r\n output += `${YELLOW}⚠️ No se pudo leer el archivo de origen: ${filePath}${RESET}\\n`;\r\n output += `\\n${CYAN}${BOLD}Stack Trace:${RESET}\\n${stackLines.slice(2).join('\\n')}\\n`;\r\n }\r\n }\r\n }\r\n output += help;\r\n console.error(output);\r\n}\r\n\r\nexport default Database;\r\n","import path from \"path\";\nimport { FileLogger, InterceptController } from \"@dbcube/core\";\nimport { createRequire } from 'module';\nimport type { TriggerConfig } from \"../@types/Database\";\n\n/**\n * Runtime triggers: user-defined JS functions (from .trigger.cube files) that\n * run in the application process around each write. Because they execute in\n * the write-path (not as DB-side triggers), they behave identically across\n * MySQL, PostgreSQL, SQLite and MongoDB, and fire exactly once per operation\n * regardless of how many service instances share the database.\n */\nexport class Trigger {\n private triggers: TriggerConfig[];\n private databaseName: string;\n private instance: unknown;\n\n constructor(instance: unknown, databaseName: string, metadata: TriggerConfig[]) {\n this.triggers = metadata;\n this.databaseName = databaseName;\n this.instance = instance;\n }\n\n get(type: string): TriggerConfig | undefined {\n return this.triggers.find((tr) => tr.type === type);\n }\n\n async execute(type: string, row: Record<string, unknown>): Promise<InterceptController | null> {\n const trigger = this.triggers.find((tr) => tr.type === type);\n if (trigger) {\n const logFilePath = path.resolve(\n process.cwd(),\n 'dbcube',\n 'logs',\n 'triggers',\n this.databaseName,\n `${trigger.table_ref}_${trigger.type}.log`\n );\n\n const interceptor = FileLogger.interceptConsole(logFilePath, {\n keepOriginal: false,\n useBuffer: true\n });\n const pathFile = path.resolve(process.cwd(), 'dbcube', 'triggers', `${trigger.database_ref}_${trigger.table_ref}_${trigger.type}.js`);\n // Use __filename for CJS, process.cwd() for ESM\n const requireUrl = typeof __filename !== 'undefined' ? __filename : process.cwd();\n const require = createRequire(requireUrl);\n // Clear require cache to ensure fresh load\n try {\n delete require.cache[require.resolve(pathFile)];\n } catch { /* bundled environments may not expose a resolvable cache */ }\n try {\n const triggerModule = require(pathFile);\n const dataProcess = triggerModule.default || triggerModule;\n await dataProcess({ db: this.instance, oldData: row, newData: row });\n } finally {\n // Sin esto, un trigger que lanza deja el console secuestrado\n // para SIEMPRE y el error se vuelve invisible para la app\n interceptor.restore();\n }\n return interceptor;\n }\n return null;\n }\n}\n","import { Table, Database } from './lib/Database';\nimport type {\n ComputedFieldConfig,\n DatabaseRecord,\n MutationInfo,\n PaginatedResult,\n RelationOptions,\n TriggerConfig,\n WhereCallback,\n} from './@types/Database';\n\nexport default Database;\nexport {\n Table,\n Database,\n type ComputedFieldConfig,\n type DatabaseRecord,\n type MutationInfo,\n type PaginatedResult,\n type RelationOptions,\n type TriggerConfig,\n type WhereCallback\n};\n"],"mappings":"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","names":["path","require","response","path","err"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dbcube/query-builder",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.2",
|
|
4
4
|
"description": "The Dbcube Query Builder is a lightweight, flexible, and fluent library for building queries across multiple database engines, including MySQL, PostgreSQL, SQLite, and MongoDB, using JavaScript/Node.js. \nIts agnostic design allows you to generate data manipulation (DML) and data definition (DDL) operations with a clean, chainable syntax—without sacrificing power or expressiveness.\nIt’s designed to work seamlessly in both SQL and NoSQL environments, providing a consistent abstraction layer across different storage technologies while still leveraging the native capabilities of each engine.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@dbcube/core": "^5.2.
|
|
57
|
+
"@dbcube/core": "^5.2.2"
|
|
58
58
|
},
|
|
59
59
|
"files": [
|
|
60
60
|
"dist/**/*"
|