bun-mariadb/src/lib/mariadb/db-select.ts

130 lines
3.4 KiB
TypeScript

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<Schema>;
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<Schema, Table>): Promise<APIResponseObject<Schema>> {
let sqlObj: ReturnType<typeof sqlGenerator> | null = null;
try {
let finalQuery = query || {};
if (targetId) {
finalQuery = _.merge<ServerQueryParam<any>, ServerQueryParam<any>>(
finalQuery,
{
query: {
id: {
value: String(targetId),
},
},
},
);
}
sqlObj = sqlGenerator({
tableName: quoteIdentifier(table),
genObject: finalQuery,
});
const res = await dbHandler<Schema>({
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<Schema> = {
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,
},
};
}
}