UNPKG

@krishnapawar/kp-mysql-models

Version:

`kp-mysql-models` is a lightweight, easy-to-use, and promise-based Node.js ORM tool designed for MySQL. It simplifies database interactions by offering features like model-based query building, CRUD operations, and support for advanced queries such as joi

520 lines (490 loc) 16 kB
const { isLatest,isLimit,isCheck,isTable,isOne,isInt,isNotObject, isArray, isObject, isEmpty } = require('./supporterMethodes'); const getKeyValue = (data, setType = "WHERE") => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { setItem.push(`${key}='${value}'`); } return " " + setType + " " + setItem.toString(); }; const selectOption = (data, x) => { if (data?.select || x?._show) { return data?.select?.toString() ?? x._show.toString(); } return "*"; }; //where clause condition const whereAnd = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${key}='${value}'`); } else { setItem.push(`${key}='${value}'`); } } return `${setItem.toString()}`; }; const whereOr = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` OR ${key}='${value}'`); } else { setItem.push(`${key}='${value}'`); } } return `${setItem.toString()}`; }; const whereIs = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${key} IS ${value}`); } else { setItem.push(`${key} IS ${value}`); } } return `${setItem.toString()}`; }; const whereIsNull = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${value} IS NULL`); } else { setItem.push(`${value} IS NULL`); } } return `${setItem.toString()}`; }; const whereIsNotNull = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${value} IS NOT NULL`); } else { setItem.push(`${value} IS NOT NULL`); } } return `${setItem.toString()}`; }; const whereIn = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { const formattedValues = Array.isArray(value) ? value.map((v) => `'${v}'`).join(", ") : `'${value}'`; if (setItem.length > 0) { setItem.push(` AND ${key} IN (${formattedValues})`); } else { setItem.push(`${key} IN (${formattedValues})`); } } return ` ${setItem.join(" ")}`; }; const whereNotIn = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { const formattedValues = Array.isArray(value) ? value.map((v) => `'${v}'`).join(", ") : `'${value}'`; if (setItem.length > 0) { setItem.push(` AND ${key} NOT IN (${formattedValues})`); } else { setItem.push(`${key} NOT IN (${formattedValues})`); } } return `${setItem.join(" ")}`; }; const whereRaw = (data) => { if (isCheck(data)) return ""; return `${data}`; }; const onlyTrashed= (data) => { if (isCheck(data)) return ""; if (data === true ) return " deleted_at IS NOT NULL "; return ""; }; const whereClause = (data, resData) => { if (isCheck(data)) return ""; const clauses = [ whereNotIn(data.whereNotIn).replace(/,/g, ""), whereIn(data.whereIn), whereAnd(data.where).replace(/,/g, ""), whereOr(data.whereOr).replace(/,/g, ""), whereIs(data.whereIs).replace(/,/g, ""), connect(data, resData), whereRaw(data.whereRaw), onlyTrashed(data.onlyTrashed), whereIsNull(data.whereIsNull || data.whereNull), whereIsNotNull(data.whereIsNotNull || data.whereNotNull) ]; const validClauses = clauses.filter(clause => clause !== ""); if (validClauses.length === 0) return ""; return `WHERE ${validClauses.join(" AND ").replace(/( AND )? OR /g, " OR ")}`; }; // on clause condition const onAnd = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${key}=${value}`); } else { setItem.push(`${key}=${value}`); } } return `${setItem.toString()}`; }; const onOr = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` OR ${key}='${value}'`); } else { setItem.push(`${key}=${value}`); } } return `${setItem.toString()}`; }; const onIs = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${key} IS ${value}`); } else { setItem.push(`${key} IS ${value}`); } } return `${setItem.toString()}`; }; const onIn = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${key} IN (${value.toString()})`); } else { setItem.push(`${key} IN (${value.toString()})`); } } return ` ${setItem.toString()}`; }; const onNotIn = (data) => { if (isCheck(data)) return ""; let setItem = []; for (const [key, value] of Object.entries(data)) { if (setItem.length > 0) { setItem.push(` AND ${key} NOT IN (${value.toString()})`); } else { setItem.push(`${key} NOT IN (${value.toString()})`); } } return `${setItem.toString()}`; }; const onRaw = (data) => { if (isCheck(data)) return ""; return `${data}`; }; const onClause = (data) => { const clauses = [ onNotIn(data.onNotIn).replace(/,/g, ""), onIn(data.onIn), onAnd(data.on).replace(/,/g, ""), onOr(data.onOr).replace(/,/g, ""), onIs(data.onIs).replace(/,/g, ""), onRaw(data.onRaw) ]; const validClauses = clauses.filter(clause => clause !== ""); if (validClauses.length === 0) return ""; return `ON ${validClauses.join(" AND ").replace(/( AND )? OR /g, " OR ")}`; }; //end on const pagination = (data) => { if (isCheck(data)) return ""; if (isCheck(data.pagination) || data.pagination == NaN) return ""; if ( isLimit(data) == "" || (isCheck(data.pagination) && isLimit(data) == 0) ) return ""; return `OFFSET ${parseInt(data.pagination>=1 ? data.pagination-1:data.pagination) * parseInt(data.limit)}`; }; const paginationData = (totalData, data, page = 0) => { if (isCheck(totalData) && data.pagination < 0) return ""; let pageCountExce = totalData > 0 ? totalData / data.limit : 0; let totalPage = isInt(pageCountExce) == 0 ? pageCountExce : pageCountExce - isInt(pageCountExce) + 1; let currentPage = data.pagination>0?data.pagination:1; let pagelenth = []; for (let index = 1; index <= totalPage; index++) { pagelenth.push(index); } let pageDataLimit=data.limit; return {pageDataLimit, totalPage, totalData, currentPage, pagelenth }; }; const joinTable = (data) => { if (isEmpty(data)) return ""; if (!Array.isArray(data) && isObject(data) && Array.isArray(data.join)) { data = data.join; } else if (!Array.isArray(data)) { return ""; } let str = " "; for (const join of data) { if (isTable(join.table)) return ""; if ( join.type != undefined && join.type != null && joinType(join.type) != "" ) { str += ` ${joinType(join.type)} ${join.table} ${onClause(join)}`; } else { str += ` JOIN ${join.table} ${onClause(join)}`; } } return str; }; const withTable = (data) => { if (data !== undefined && isCheck(data) && data.length <= 0) return ""; let str = " "; for (const key in data) { if (Object.hasOwnProperty.call(data, key)) { const element = data[key]; for (const join of data[key]) { if (isTable(join.table)) return ""; if (key != undefined && key != null && joinType(key) != "") { str += ` ${joinType(key)} ${join.table} ${onClause(join)}`; } else { str += ` JOIN ${join.table} ${onClause(join)}`; } } } } return str; }; const withdata = (errThrow, resData, datas,dbcon=null) => { return new Promise((r,e)=>{ try { let db = dbcon ?? pool; if(isCheck(datas)) return r(resData); if (datas.with !== undefined && isCheck(datas.with) && datas.with.length <= 0) return r(resData); let totalKeyCount = 0; for (const _ in datas.with) { totalKeyCount++; } let keyIndex = 0; for (const key in datas.with) { let data = datas.with[key]; db.query( `SELECT ${selectOption(data)} FROM ${data.table} ${whereClause( data, resData )} ${isLatest(data)} ${isLimit(data)} ${pagination(data)}`, async(err, res) => { if (err) { return errThrow(err); } if (data!= undefined && !isOne(data) && (!isCheck(data.pagination) || data.pagination >= 0)) { db.query( `SELECT count(*) as totalData FROM ${data.table} ${whereClause( data, resData )} ${isLatest(data)}`, async(err, resp) => { if (err) { return errThrow(err); } let paginate = paginationData(resp[0].totalData, data); resData[key] = { res, paginate }; } ); } else if(isOne(data)) { if (isCheck(data.with)) { resData[key] = res.length>0 ? res[0]:{}; } else { resData[key] = res.length>0 ? await withdata(e, res[0], data,db):{}; } }else{ if (isCheck(data.with)) { resData[key] = res; } else { resData[key] = await withdata(e, res, data,db); } } keyIndex++; if (keyIndex === totalKeyCount) { return r(resData); } } ); } if (keyIndex === totalKeyCount) { return r(resData); } } catch (error) { return e(error); } }); }; const getDataWith = async (errThrow, resData, datas, dbcon = null) => { let db = dbcon ?? pool; const executeQuery = (query) => { return new Promise((resolve, reject) => { db.query(query, (err, res) => { if (err) return reject(err); resolve(res); }); }); }; const getTotalDataCount = async (data, resData) => { const [resp] = await executeQuery(`SELECT count(*) as totalData FROM ${data.table} ${whereClause(data, resData)} ${isLatest(data)}`); return resp.totalData; }; const processKey = async (key, data) => { const res = await executeQuery(`SELECT ${selectOption(data)} FROM ${data.table} ${whereClause(data, resData)} ${isLatest(data)} ${isLimit(data, isOne(data))} ${pagination(data)}`); if (!isOne(data) && (!isCheck(data.pagination) || data.pagination >= 0)) { const totalData = await getTotalDataCount(data, resData); const paginate = paginationData(totalData, data); resData[key] = { res, paginate }; } else if (isOne(data)) { if (isCheck(data.with)) { return resData[key] = res.length > 0 ? res[0] : {}; } else { return resData[key] = res.length > 0 ? await getDataWith(errThrow, res[0], data, db) : {}; } } else { if (isCheck(data.with)) { return resData[key] = res; } else { return resData[key] = await Promise.all(res.map(async (r) => await getDataWith(errThrow, r, data, db))); } } }; return new Promise(async (resolve, reject) => { try { if (isCheck(datas)) return resolve(resData); if (datas.with !== undefined && isCheck(datas.with) && datas.with.length <= 0) return resolve(resData); const keys = Object.keys(datas.with); for (const key of keys) { if(!isEmpty(datas.with[key])){ await processKey(key, datas.with[key]); } } return resolve(resData); } catch (error) { return errThrow(error); } }); }; const connect = (conn, resdata) => { if (isCheck(conn.connect) && isCheck(conn.hasOne) && isCheck(conn.belongsTo) && isCheck(conn.belongsToMany) && isCheck(conn.hasMany)) return ""; let str = ""; let tbcon = (conn.connect || conn.hasOne || conn.belongsTo || conn.hasMany || conn.belongsToMany); for (const key in tbcon) { let baseColumn = conn.connect ? (isCheck(resdata[key]) ? resdata[tbcon[key]] : resdata[key]) : resdata[tbcon[key]]; let column = conn.connect ? (isCheck(resdata[key])) ? key : tbcon[key] : key; const condition = isArray(tbcon) && !isObject(tbcon) ? `id = "${resdata[tbcon[key]]}" ` : `${column} = "${baseColumn}" `; str += str === "" ? condition : `AND ${condition}`; } return str; }; const joinType = (data) => { const joinMap = { belongsto: 'INNER JOIN', 'inner join': 'INNER JOIN', innerjoin: 'INNER JOIN', hasone: 'JOIN', join: 'JOIN', belongstomany: 'LEFT JOIN', 'left join': 'LEFT JOIN', leftjoin: 'LEFT JOIN', hasmany: 'RIGHT JOIN', 'right join': 'RIGHT JOIN', rightjoin: 'RIGHT JOIN', }; return joinMap[data.toLowerCase()] || ''; }; const addDeletedAt = (table, connection) => { if (isTable(table)) return reject(isTable(table)); return new Promise((resolve, reject) => { if (sqlConnect(connection)) { return reject(sqlConnect(connection)); } connection.query( `SHOW COLUMNS FROM ${table} LIKE "deleted_at"`, async (err, res) => { if (err) { return reject(err); } if (res.length > 0) return resolve(true); try { connection.query( `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '${table}' ORDER BY ORDINAL_POSITION DESC LIMIT 1`, (err1, colunm) => { if (err1) return reject(err1); if (colunm.length) { connection.query( `ALTER TABLE ${table} ADD deleted_at TIMESTAMP NULL DEFAULT NULL AFTER ${colunm[0].COLUMN_NAME}`, (err, res) => { if (err) { return reject(err); } return resolve(true); } ); } else { return resolve(false); } } ); } catch (error) { return reject(error); } } ); }); }; const sqlConnect = (pool) => { try { if (isCheck(pool) || isNotObject(pool)) { return "Error: Invalid or missing database connection. Please verify your database configuration."; } } catch (error) { return "Error: Unable to establish a database connection. Please check your database settings."; } }; module.exports={ addDeletedAt, sqlConnect, joinType, connect, getDataWith, withdata, withTable,joinTable,paginationData,pagination,onClause,onRaw,onNotIn, onIn,onIs,onOr,onAnd,whereClause,onlyTrashed,whereRaw,whereNotIn,whereIn,whereIs,whereOr,whereAnd, selectOption,getKeyValue, }