First upload

This commit is contained in:
2026-03-17 14:12:37 +01:00
commit c857900860
46 changed files with 3343 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
// import mariadb from 'mariadb';
import * as mariadb from 'mariadb';
// Fix para BigInt en la serialización JSON (necesario para IDs grandes en MariaDB)
BigInt.prototype.toJSON = function () {
return this.toString();
};
// Configuración del Pool
export const pool = mariadb.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: 'Reale',
connectionLimit: 20,
timezone: 'Z',
insertIdAsNumber: true
});
// Helper para escapar identificadores (tablas/columnas)
const b = (id) => `\`${id.replace(/`/g, '``')}\``;
export class Database {
constructor(connector) {
/** @type {mariadb.Pool | mariadb.PoolConnection} */
this.connector = connector;
}
async insert(table, data) {
const rows = Array.isArray(data) ? data : [data];
if (!rows.length) return null;
const fields = Object.keys(rows[0]);
const query = `INSERT INTO ${b(table)} (${fields.map(b).join(',')}) VALUES (${fields.map(() => '?').join(',')})`;
return this.connector.batch(query, rows.map(r => fields.map(f => r[f])));
}
async update(table, data, where) {
const fields = Object.keys(data);
const wFields = Object.keys(where);
const query = `UPDATE ${b(table)} SET ${fields.map(f => `${b(f)}=?`).join(',')} WHERE ${wFields.map(f => `${b(f)}=?`).join(' AND ')}`;
return this.connector.query(query, [...fields.map(f => data[f]), ...wFields.map(f => where[f])]);
}
async upsert(table, data, ignore = false) {
const rows = Array.isArray(data) ? data : [data];
if (!rows.length) return null;
const fields = Object.keys(rows[0]);
const set = fields.filter(f => f !== 'id').map(f => `${b(f)}=VALUES(${b(f)})`).join(',');
const query = `INSERT ${ignore ? 'IGNORE' : ''} INTO ${b(table)} (${fields.map(b).join(',')}) VALUES (${fields.map(() => '?').join(',')}) ON DUPLICATE KEY UPDATE ${set}`;
return this.connector.batch(query, rows.map(r => fields.map(f => r[f])));
}
async delete(table, where) {
const keys = Object.keys(where);
if (!keys.length) throw new Error('Delete requiere condiciones');
return this.connector.query(`DELETE FROM ${b(table)} WHERE ${keys.map(k => `${b(k)}=?`).join(' AND ')}`, keys.map(k => where[k]));
}
async select(table, where = {}, opts = { limit: 5000, order: null }) {
const keys = Object.keys(where);
let sqlStr = `SELECT * FROM ${b(table)}`;
if (keys.length) sqlStr += ` WHERE ${keys.map(k => `${b(k)}=?`).join(' AND ')}`;
if (opts.order) sqlStr += ` ORDER BY ${b(opts.order)}`;
return this.connector.query(sqlStr + ` LIMIT ${opts.limit}`, keys.map(k => where[k]));
}
async one(table, where) {
const res = await this.select(table, where, { limit: 1 });
return res[0] || null;
}
async count(table, where = {}) {
const keys = Object.keys(where);
let sqlStr = `SELECT COUNT(*) as total FROM ${b(table)}`;
if (keys.length) sqlStr += ` WHERE ${keys.map(k => `${b(k)}=?`).join(' AND ')}`;
const res = await this.connector.query(sqlStr, keys.map(k => where[k]));
return Number(res[0].total);
}
async search(table, fields, term, limit = 1000) {
if (!fields.length || !term) return [];
const where = fields.map(f => `${b(f)} LIKE ?`).join(' OR ');
return this.connector.query(`SELECT * FROM ${b(table)} WHERE ${where} LIMIT ${limit}`, fields.map(() => `%${term}%`));
}
async unique(table, fields, where = {}) {
const f = Array.isArray(fields) ? fields.map(b).join(',') : b(fields);
const keys = Object.keys(where);
let sqlStr = `SELECT DISTINCT ${f} FROM ${b(table)}`;
if (keys.length) sqlStr += ` WHERE ${keys.map(k => `${b(k)}=?`).join(' AND ')}`;
const sort = Array.isArray(fields) ? b(fields[0]) : f;
return this.connector.query(sqlStr + ` ORDER BY ${sort} ASC`, keys.map(k => where[k]));
}
async raw(query, data = {}) {
const params = [];
const sqlStr = query.replace(/:(\w+)/g, (_, key) => {
params.push(data[key]);
return '?';
});
return this.connector.query(sqlStr, params);
}
}
/**
* Lógica de Transacciones
*/
export const trx = async (opts, actions) => {
const tasks = Array.isArray(opts) ? opts : [opts];
const conn = await pool.getConnection();
try {
await conn.beginTransaction();
const transactionDb = new Database(conn);
const results = {};
for (const item of tasks) {
if (typeof actions[item.action] !== 'function') {
throw new Error(`Acción ${item.action} no existe`);
}
results[item.action] = await actions[item.action](transactionDb, item);
}
await conn.commit();
return results;
} catch (err) {
console.error('Error en la transacción:', err);
await conn.rollback();
throw err;
} finally {
if (conn) conn.release();
}
};
// Exportamos la instancia principal vinculada al Pool
export const db = new Database(pool);