Port bun-mariadb schema guard, targetId fix, lazy init and tests

- schema: add --dry-run (sync in a rolled-back transaction) and require
  confirmation (or --yes) before dropping tables or columns; unapproved
  destructive changes are refused
- only rebuild tables whose CREATE TABLE statement changed
- always AND targetId with the query, regardless of searchOperator
- empty IN / NOT IN lists become 1 = 0 / 1 = 1
- initialize lazily on first call so importing never throws
- read CLI version from package.json, chmod CLI on compile, pin @types/bun
- add SQL generator, value and schema guard tests

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-14 03:00:29 +01:00
co-authored by Claude Opus 5.5
parent 87da436f81
commit 4e47bd8ce0
23 changed files with 649 additions and 172 deletions
+33 -3
View File
@@ -18,6 +18,11 @@ type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
tableName: string;
dbFullName?: string;
count?: boolean;
/**
* Restrict to a single row id. Always combined with AND, regardless of
* `searchOperator`.
*/
targetId?: number | string;
};
type Return = {
@@ -40,7 +45,12 @@ type Return = {
*/
export default function sqlGenerator<
T extends { [key: string]: any } = { [key: string]: any },
>({ tableName: passedTableName, genObject, count }: Param<T>): Return {
>({
tableName: passedTableName,
genObject,
count,
targetId,
}: Param<T>): Return {
const tableName = sqlIdent(passedTableName, "table name");
const finalQuery = genObject?.query ? genObject.query : undefined;
@@ -115,11 +125,31 @@ export default function sqlGenerator<
(str) => typeof str == "string",
);
let whereString = "";
const whereConditions: string[] = [];
if (cleanedUpSearchStr?.[0]) {
const stringOperator = sqlOperator(genObject?.searchOperator);
whereString = `WHERE ${cleanedUpSearchStr.join(` ${stringOperator} `)}`;
whereConditions.push(
`(${cleanedUpSearchStr.join(` ${stringOperator} `)})`,
);
}
if (targetId !== undefined && targetId !== null && targetId !== "") {
const id = Number(targetId);
if (!Number.isSafeInteger(id)) {
throw new Error(`Invalid targetId: ${JSON.stringify(targetId)}`);
}
whereConditions.push(`${genObject?.join ? `${tableName}.` : ""}id = ?`);
whereValues.push(id);
}
const whereString = whereConditions.length
? `WHERE ${whereConditions.join(" AND ")}`
: "";
if (whereString) {
queryString += ` ${whereString}`;
sqlSearhValues.push(...whereValues);
}