import dbHandler from "../db-handler"; import _ from "lodash"; import type { APIResponseObject, ServerQueryParam } from "../../types"; import sqlGenerator from "../../utils/sql-generator"; type Params< Schema extends { [k: string]: any } = { [k: string]: any }, Table extends string = string, > = { query?: ServerQueryParam; table: Table; count?: boolean; targetId?: number | string; }; function quoteIdentifier(identifier: string): string { return `\`${identifier.replace(/`/g, "``")}\``; } export default async function DbSelect< Schema extends { [k: string]: any } = { [k: string]: any }, Table extends string = string, >({ table, query, count, targetId, }: Params): Promise> { let sqlObj: ReturnType | null = null; try { let finalQuery = query || {}; if (targetId) { finalQuery = _.merge, ServerQueryParam>( finalQuery, { query: { id: { value: String(targetId), }, }, }, ); } sqlObj = sqlGenerator({ tableName: quoteIdentifier(table), genObject: finalQuery, }); const res = await dbHandler({ query: sqlObj.string, values: sqlObj.values as any, }); if (!res.success) { return { success: false, msg: "Database select failed", debug: { sqlObj, sql: sqlObj.string, }, }; } const batchRes = (res.payload || []) as Schema[]; let resp: APIResponseObject = { success: true, payload: batchRes, singleRes: batchRes[0], debug: { sqlObj, sql: sqlObj.string, }, }; if (count) { const countSqlObject = sqlGenerator({ tableName: quoteIdentifier(table), genObject: finalQuery, count, }); const countSql = `SELECT COUNT(*) AS count FROM (${countSqlObject.string}) AS c`; const countRes = await dbHandler<{ count: number }>({ query: countSql, values: countSqlObject.values as any, }); if (!countRes.success) { return { ...resp, success: false, msg: "Database count failed", debug: { ...resp.debug, count_sql: countSql, }, }; } const countRows = countRes.payload || []; const countVal = countRows[0]?.count ?? countRows[0]?.["COUNT(*)"]; resp = { ...resp, count: Number(countVal), debug: { ...resp.debug, count_sql: countSql, }, }; } return resp; } catch (error: any) { return { success: false, error: error.message, debug: { sqlObj, }, }; } }