UNPKG

qeasy

Version:

Query Easy: Simple SQL helper like Mongoose for MySQL/MariaDB

255 lines (192 loc) 6.8 kB
const { checkConnection } = require("../dbConnection/db"); const { validateIdentifier } = require("../validator/validateIdentifier"); exports.insert = async (table, data) => { try { /** @type {import('mysql2/promise').Pool} */ const pool = checkConnection(); let query; validateIdentifier(table, "table"); const columns = Object.keys(data); const values = Object.values(data); const questionParams = values.map(() => "?").join(", "); query = `INSERT INTO ${table} (${columns}) VALUES (${questionParams})`; const [result] = await pool.execute(query, values); return result; } catch (err) { console.error("QEasy Insert Error:", err.message); throw err; } }; exports.findWithJoins = async (options) => { try { const pool = checkConnection(); validateIdentifier(options.table, "table"); if (options.selectedColumns && Array.isArray(options.selectedColumns)) { options.selectedColumns.forEach((col) => { const parts = col.split("."); if (parts.length === 2) { validateIdentifier(parts[0], "table"); validateIdentifier(parts[1], "column"); } else { validateIdentifier(parts[0], "column"); } }); } const columnsPart = options.selectedColumns && options.selectedColumns.length > 0 ? options.selectedColumns.join(", ") : "*"; const aliasPart = options.as ? ` AS \`${options.as}\`` : ""; let query = `SELECT ${columnsPart} FROM \`${options.table}\`${aliasPart}`; if (options.joins && Array.isArray(options.joins)) { options.joins.forEach((join) => { const validJoinTypes = ["INNER", "LEFT", "RIGHT"]; const joinType = join.type && validJoinTypes.includes(join.type.toUpperCase()) ? join.type.toUpperCase() : "INNER"; validateIdentifier(join.table, "table"); const alias = join.as ? ` AS \`${join.as}\`` : ""; const leftKey = Object.keys(join.on)[0]; const rightKey = Object.values(join.on)[0]; const left = leftKey.split("."); const right = rightKey.split("."); validateIdentifier(left[0], "table"); validateIdentifier(left[1], "column"); validateIdentifier(right[0], "table"); validateIdentifier(right[1], "column"); const onClause = `\`${left[0]}\`.\`${left[1]}\` = \`${right[0]}\`.\`${right[1]}\``; query += ` ${joinType} JOIN \`${join.table}\`${alias} ON ${onClause}`; }); } let params = []; if (options.where && Array.isArray(options.where)) { const conditions = []; for (const cond of options.where) { const parts = cond.column.split("."); validateIdentifier(parts[0], "table"); validateIdentifier(parts[1], "column"); const op = cond.operator || "="; conditions.push(`\`${parts[0]}\`.\`${parts[1]}\` ${op} ?`); params.push(cond.value); } if (conditions.length > 0) { query += ` WHERE ${conditions.join(" AND ")}`; } } // ORDER BY if (options.orderBy && Array.isArray(options.orderBy)) { const orderParts = []; for (const order of options.orderBy) { const parts = order.column.split("."); validateIdentifier(parts[0], "table"); validateIdentifier(parts[1], "column"); const dir = order.direction && order.direction.toUpperCase() === "DESC" ? "DESC" : "ASC"; orderParts.push(`\`${parts[0]}\`.\`${parts[1]}\` ${dir}`); } if (orderParts.length > 0) { query += ` ORDER BY ${orderParts.join(", ")}`; } } // LIMIT if (options.limit && Number.isInteger(options.limit)) { query += ` LIMIT ?`; params.push(options.limit); } // OFFSET if (options.offset && Number.isInteger(options.offset)) { query += ` OFFSET ?`; params.push(options.offset); } console.log("Final SQL:", query); const [rows] = await pool.execute(query , params); return rows; } catch (err) { console.error("QEasy Select Error:", err.message); throw err; } }; /** @param {string} table */ exports.findAll = async (table) => { try { const pool = checkConnection(); validateIdentifier(table, "table"); query = `SELECT * FROM \`${table}\``; const [result] = await pool.execute(query); return result; } catch (error) { console.error("QEasy FindAll Error :", err.message); throw err; } }; /** @param {string} table @param {string} idField @param {string|number} id @returns {Promise<object|null>} */ exports.findById = async (table, idField, id) => { try { const pool = checkConnection(); validateIdentifier(table, "table"); validateIdentifier(idField, "idField"); const query = `SELECT * FROM \`${table}\` WHERE \`${idField}\` = ?`; const [result] = await pool.execute(query, [id]); if (result.length === 0) { return []; } return result[0]; } catch (err) { console.error("QEasy FindById Error :", err.message); throw err; } }; /** * @param {string} table * @param {string} idField * @param {string | number} id * @param {object | string} data * @returns {Promise<object|null>} */ exports.findByIdAndUpdate = async (table, idField, id, data) => { try { const pool = checkConnection(); let updateSubQueries; validateIdentifier(table, "table"); validateIdentifier(idField, "idField"); const columns = Object.keys(data); const values = Object.values(data); updateSubQueries = columns.map((col) => `\`${col}\` = ?`).join(` ,`); const params = [...values, id]; query = `UPDATE \`${table}\` SET ${updateSubQueries} WHERE \`${idField}\` = ?`; const [result] = await pool.execute(query, params); return result; } catch (err) { console.error("QEasy Update Error:", err.message); throw err; } }; /** * @param {string} table * @param {string} idField * @param {string|number} id * @returns {Promise<object>} */ exports.findByIdAndDelete = async (table, idField, id) => { try { const pool = checkConnection(); validateIdentifier(table, "table"); validateIdentifier(idField, "idField"); const query = `DELETE FROM \`${table}\` WHERE \`${idField}\` = ?`; const [result] = await pool.execute(query, [id]); return result; } catch (err) { console.error("QEasy Delete Error:", err.message); throw err; } };