Archivo mysql.js contiene la conexión a MySQL.
Código
const mysql = require("mysql"); const mysqlConnection = mysql.createConnection({ host: "localhost", port: 3306, user: "root", password: "", database: "", }); mysqlConnection.connect((err) => { if (err) { console.error("[DB] No se pudo conectar con MYSQL", err); } else { console.log("[DB] Conectado con MYSQL", mysqlConnection.threadId); } }); module.exports = mysqlConnection;
Archivo con la clase principal. Implementa las 5 funciones básicas de CRUD+L = Create/Crear, Read/Leer, Update/Modificar, Delete/Borrar, List/Listar
Código
const MySQL = require("./mysql"); function list(table) { return new Promise(async (resolve, reject) => { const sql = `SELECT * FROM ${table}`; await MySQL.query(sql, (err, results) => { if (err) { console.error("[DB]", err); return reject({ message: err, code: 401 }); } return resolve(results); }); }); } function get(table, id) { return new Promise(async (resolve, reject) => { const sql = `SELECT * FROM ${table} WHERE id=${id}`; await MySQL.query(sql, (err, results) => { if (err) { console.error("[DB]", err); return reject({ message: err, code: 401 }); } return resolve(results); }); }); } function insert(table, data) { return new Promise(async (resolve, reject) => { try { const fields = Object.keys(data); const values = Object.values(data); if (fields.length === 0) { return reject({ message: "Faltan datos", code: 400 }); } const sql = `INSERT INTO ${table} (${fields}) VALUES (${values.map( (h) => `'${h}'` )})`; await MySQL.query(sql, async (err, results) => { if (err) return reject({ message: err.message, code: 400 }); const insertedData = await get(table, results.insertId); return resolve(insertedData); }); } catch (error) { return reject(error); } }); } function update(table, id, data) { return new Promise(async (resolve, reject) => { try { const fields = Object.keys(data); const values = Object.values(data); if (fields.length === 0) { return reject({ message: "Faltan datos", code: 400 }); } const sql = `UPDATE ${table} SET ? WHERE id=${id}`; const beforeUpdate = await get(table, id); await MySQL.query(sql, data, async (err, results) => { if (err) return reject({ message: err.message, code: 400 }); const updateData = await get(table, id); return resolve({ ...results, beforeUpdate, updateData }); }); } catch (error) { return reject(error); } }); } function remove(table, id) { return new Promise(async (resolve, reject) => { try { const beforeUpdate = await get(table, id); if (beforeUpdate.length === 0) return reject({ message: `El elemento ${id} no existe`, code: 403 }); const sql = `DELETE FROM ${table} WHERE id=${id} LIMIT 1`; await MySQL.query(sql, async (err, results) => { if (err) return reject({ message: err.message, code: 400 }); return resolve({ ...results, beforeUpdate }); }); } catch (error) { return reject(error); } }); } module.exports = { list, get, insert, update, remove, };
Esta clase no tiene ningún tipo de validación, eso se debería hacer en otra capa, como por ejemplo en el controlador con @hapi/joi.
Para usarse simplemente debe importarse este modulo desde otro e invocar a la función CRUDL, por ejemplo
Ejemplo de Uso
Código
const db = require("./db.js"); // suponiendo que el archivo anterior se llame "db.js y // ademas este ubicado en el mismo directorio que el presente codigo. // Usar como funcion asincrona que debuelve un resultado o un error // Operacion CRUDL: Listar la tabla 'usuarios' completa // SIEMPRE dentro de una funcion async async function getUsers(){ const myUsers = await db.get('usuarios') return await db.get('usuarios') // return await db.get('usuarios') } console.log(getUsers()) // O usar como funciones que devuelven promesas, y gestionarla con then/cath: // Operacion CRUDL: (D) Borrar el registro de la tabla 'usuarios' cuyo id sea igual a '666' db.remove('usuarios', 666)//Borrar usuario con id 666 .then(users=>{ // Se borro el usuario, hacer algo console.log(`Se borro el user 666`) }) .catch(error=>{ console.log(error) })
Por ultimo, como tambien hago frontend, una cosa muy util es poder deshacer cualquier accion con un solo click, por cuestiones de UX/UI es una forma muy poderosa de fidelizar al usuario.
Por eso en las consultas 'remove' y 'update' se devuelve un objeto beforeUpdate y updateData
Código
"beforeUpdate": [ { "id": 14, "nombre": "Departamento de Coordinacion y Gestion Cooperativa", "responsable": "" } ]
Eso es muy util para revertir la ejecucion de la queri con un simple boton o 'call to action' como tiene gmail.