import dbHandler from "../db-handler"; import _ from "lodash"; import type { APIResponseObject, SQLInsertGenValueType, ServerQueryParam, } from "../../types"; import sqlGenerator from "../../utils/sql-generator"; type Params< Schema extends { [k: string]: any } = { [k: string]: any }, Table extends string = string, > = { table: Table; data: Schema; query?: ServerQueryParam; targetId?: number | string; }; function quoteIdentifier(identifier: string): string { return `\`${identifier.replace(/`/g, "``")}\``; } export default async function DbUpdate< Schema extends { [k: string]: any } = { [k: string]: any }, Table extends string = string, >({ table, data, query, targetId, }: Params): Promise { let sqlObj: ReturnType = { string: "", values: [] }; try { let finalQuery = query || {}; if (targetId) { finalQuery = _.merge, ServerQueryParam>( finalQuery, { query: { id: { value: String(targetId), }, }, }, ); } const sqlQueryObj = sqlGenerator({ tableName: quoteIdentifier(table), genObject: finalQuery, }); const whereClause = sqlQueryObj.string.match(/WHERE .*/)?.[0]; if (!whereClause) { return { success: false, msg: `No WHERE clause`, }; } let values: SQLInsertGenValueType[] = []; let sql = `UPDATE ${quoteIdentifier(table)} SET`; const finalData: { [k: string]: SQLInsertGenValueType } = { updated_at: Date.now(), ...data, }; const keys = Object.keys(finalData); for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (!key) continue; const isLast = i == keys.length - 1; sql += ` ${quoteIdentifier(key)}=?`; values.push(finalData[key] ?? null); if (!isLast) { sql += `,`; } } sql += ` ${whereClause}`; values = [...values, ...sqlQueryObj.values]; sqlObj.string = sql; sqlObj.values = values as any[]; const res = await dbHandler({ query: sql, values: values as any, }); if (!res.success) { return { success: false, msg: "Database update failed", debug: { sqlObj, }, }; } const singleRes = res.single_res as any; return { success: Boolean(singleRes?.affectedRows || singleRes?.changedRows), postInsertReturn: { affectedRows: Number(singleRes?.affectedRows), insertId: Number(singleRes?.insertId), }, debug: { sqlObj, }, }; } catch (error: any) { return { success: false, error: error.message, debug: { sqlObj, }, }; } }