@dbcube/query-builder 5.2.2 → 5.2.4
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 +130 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +70 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +130 -13
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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 \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"]}
|
|
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 /**\r\n * Atomic batch: every write queued in the callback runs inside ONE\r\n * transaction with a SINGLE engine round-trip (begin/commit included).\r\n * The callback is synchronous — writes are collected, not awaited.\r\n * Any failure rolls back everything.\r\n *\r\n * This is the fastest way to run a sequence of writes atomically.\r\n * For transactions that need to READ intermediate results, use\r\n * `transaction()` (interactive) instead. Triggers/computed fields do\r\n * not run in batch mode.\r\n *\r\n * @example\r\n * await db.batch(b => {\r\n * b.table('accounts').where('id', '=', 1).decrement('balance', 200);\r\n * b.table('accounts').where('id', '=', 2).increment('balance', 200);\r\n * });\r\n */\r\n async batch(builder: (b: Database) => void): Promise<MutationInfo[][]> {\r\n const ops: DML[] = [];\r\n const collector = new Database(this.name);\r\n collector.engine = this.engine;\r\n collector.computedFields = this.computedFields;\r\n collector.triggers = this.triggers;\r\n (collector as any)._collectInto = ops;\r\n builder(collector);\r\n if (ops.length === 0) return [];\r\n\r\n const response = await this.engine.executeBatch(ops);\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 return response.data as MutationInfo[][];\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 const t = new Table<T>(this, this.name, tableName, this.engine, this.computedFields, this.triggers, this.txId);\r\n const sink = (this as any)._collectInto;\r\n if (sink) t._batchSink = sink;\r\n return t;\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 /** En modo batch (db.batch) las escrituras se encolan aquí en vez de\r\n * ejecutarse: toda la transacción viaja al engine en UN solo cruce. */\r\n _batchSink: DML[] | null = null;\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 // Lazy: sin triggers configurados (el caso común) no se construye el\r\n // runner — db.table() está en el hot path de cada query\r\n this.trigger = triggers.length > 0 ? new Trigger(instance, databaseName, triggers) : (null as any);\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 // Hot path: la query más frecuente de cualquier app. Sin computed\r\n // fields, triggers ni relaciones pendientes no hay nada que preparar —\r\n // un DML literal evita la cadena de clones (~0.3-0.5ms por llamada).\r\n if (this.computedFields.length === 0 && this.relations.length === 0 && !this._mutable) {\r\n const dml: DML = {\r\n type: 'select',\r\n database: this.dml.database,\r\n table: this.dml.table,\r\n columns: ['*'],\r\n distinct: false,\r\n joins: [],\r\n where: [{ column, operator: '=', value, type: 'AND', isGroup: false }],\r\n orderBy: [],\r\n groupBy: [],\r\n limit: 1,\r\n offset: null,\r\n data: null,\r\n aggregation: null,\r\n having: [],\r\n };\r\n const response = await this.engine.executeDml(dml, this.txId ?? undefined);\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 return (response.data?.[0] as T) || null;\r\n }\r\n\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 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 // Modo batch: encolar y salir (los triggers/computes no aplican en batch)\r\n if (this._batchSink) {\r\n this._batchSink.push({ ...this.dml, type: 'insert', data });\r\n return undefined as any;\r\n }\r\n\r\n // Hot path: sin triggers ni computed fields no hay nada que orquestar —\r\n // ejecutar directo sin la cadena de clones ni getResponse\r\n if (this.triggers.length === 0 && this.computedFields.length === 0) {\r\n const dml: DML = { ...this.dml, type: 'insert', data };\r\n const response = await this.engine.executeDml(dml, this.txId ?? undefined);\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 return (response.data ?? data) as T[];\r\n }\r\n\r\n const clone = this.clone();\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 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 (this.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 if (this._batchSink) {\r\n this._batchSink.push({ ...this.dml, type: 'update', data });\r\n return undefined as any;\r\n }\r\n\r\n if (this.triggers.length === 0 && this.computedFields.length === 0) {\r\n const dml: DML = { ...this.dml, type: 'update', data };\r\n const response = await this.engine.executeDml(dml, this.txId ?? undefined);\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 return response.data as MutationInfo[];\r\n }\r\n\r\n const clone = this.clone();\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 if (this.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 if (this._batchSink) {\r\n this._batchSink.push({ ...this.dml, type: 'delete', data: null });\r\n return undefined as any;\r\n }\r\n\r\n if (this.triggers.length === 0 && this.computedFields.length === 0) {\r\n const dml: DML = { ...this.dml, type: 'delete', data: null };\r\n const response = await this.engine.executeDml(dml, this.txId ?? undefined);\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 return response.data as MutationInfo[];\r\n }\r\n\r\n const clone = this.clone();\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 if (this.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 const data = { ...extra, [column]: { $inc: Number(amount) } };\r\n\r\n if (this._batchSink) {\r\n this._batchSink.push({ ...this.dml, type: 'update', data });\r\n return undefined as any;\r\n }\r\n\r\n if (this.triggers.length === 0 && this.computedFields.length === 0) {\r\n const dml: DML = { ...this.dml, type: 'update', data };\r\n const response = await this.engine.executeDml(dml, this.txId ?? undefined);\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 return response.data as MutationInfo[];\r\n }\r\n\r\n const clone = this.clone();\r\n clone.dml.type = 'update';\r\n clone.dml.data = data;\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 ? this.trigger.get('before' + type) : undefined;\r\n const after = this.trigger ? this.trigger.get('after' + type) : undefined;\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._batchSink = this._batchSink; // el modo batch sobrevive a la cadena de where()\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 // Los frames pueden venir como `at (path:line:col)` o, en código async,\r\n // como `at async path:line:col` (sin paréntesis). El `(?:async )?` evita\r\n // que el \"async \" quede pegado al path y rompa la lectura del archivo.\r\n const match = relevantStackLine.match(/\\((.*):(\\d+):(\\d+)\\)/) ||\r\n relevantStackLine.match(/at (?:async )?(.*):(\\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.4",
|
|
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.4"
|
|
58
58
|
},
|
|
59
59
|
"files": [
|
|
60
60
|
"dist/**/*"
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "^25.9.3",
|
|
68
68
|
"dts-bundle-generator": "^9.5.1",
|
|
69
|
-
"rollup": "^4.
|
|
69
|
+
"rollup": "^4.62.0",
|
|
70
70
|
"tsup": "^8.5.1",
|
|
71
71
|
"typescript": "^6.0.3"
|
|
72
72
|
}
|