longcelot-sheet-db
Version:
Google Sheets-backed staging database adapter for Node.js with schema-first design
95 lines • 4.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildSelect = buildSelect;
exports.buildCount = buildCount;
exports.buildInsert = buildInsert;
exports.buildInsertMany = buildInsertMany;
exports.buildUpdate = buildUpdate;
exports.buildDelete = buildDelete;
function coerceParam(dialect, value) {
return typeof value === 'boolean' ? dialect.booleanLiteral(value) : value;
}
/**
* `WhereClause` (schema/types.ts) is an equality-map today — matching CRUDOperations'
* `matchesWhere()` semantics — so every condition here is a plain `AND`-chained `col = $n`.
*/
function buildWhereClause(dialect, options, startIndex) {
const conditions = [];
const params = [];
let idx = startIndex;
if (options.tenant) {
conditions.push(`${dialect.quoteIdent(options.tenant.column)} = ${dialect.placeholder(idx++)}`);
params.push(options.tenant.value);
}
if (options.softDeleteColumn && !options.includeDeleted) {
conditions.push(`${dialect.quoteIdent(options.softDeleteColumn)} IS NULL`);
}
if (options.where) {
for (const [key, value] of Object.entries(options.where)) {
conditions.push(`${dialect.quoteIdent(key)} = ${dialect.placeholder(idx++)}`);
params.push(coerceParam(dialect, value));
}
}
return { clause: conditions.length ? ` WHERE ${conditions.join(' AND ')}` : '', params, nextIndex: idx };
}
function buildSelect(dialect, table, options) {
const { clause, params } = buildWhereClause(dialect, options, 1);
let text = `SELECT * FROM ${dialect.quoteIdent(table)}${clause}`;
if (options.orderBy) {
text += ` ORDER BY ${dialect.quoteIdent(options.orderBy)} ${options.order === 'desc' ? 'DESC' : 'ASC'}`;
}
const limitOffset = dialect.limitOffsetClause(options.limit, options.offset);
if (limitOffset)
text += ` ${limitOffset}`;
return { text, params };
}
function buildCount(dialect, table, options) {
const { clause, params } = buildWhereClause(dialect, options, 1);
return { text: `SELECT COUNT(*) AS count FROM ${dialect.quoteIdent(table)}${clause}`, params };
}
function buildInsert(dialect, table, row) {
const columns = Object.keys(row);
const params = columns.map((col) => coerceParam(dialect, row[col]));
const placeholders = columns.map((_col, i) => dialect.placeholder(i + 1));
const text = `INSERT INTO ${dialect.quoteIdent(table)} (${columns
.map((c) => dialect.quoteIdent(c))
.join(', ')}) VALUES (${placeholders.join(', ')})`;
return { text, params };
}
function buildInsertMany(dialect, table, rows) {
if (rows.length === 0)
return { text: '', params: [] };
const columns = Object.keys(rows[0]);
const params = [];
let idx = 1;
const valueGroups = rows.map((row) => {
const placeholders = columns.map((col) => {
params.push(coerceParam(dialect, row[col]));
return dialect.placeholder(idx++);
});
return `(${placeholders.join(', ')})`;
});
const text = `INSERT INTO ${dialect.quoteIdent(table)} (${columns
.map((c) => dialect.quoteIdent(c))
.join(', ')}) VALUES ${valueGroups.join(', ')}`;
return { text, params };
}
/**
* No soft-delete filtering here — matches CRUDOperations.update(), which scans/updates
* regardless of `_deleted_at` (only findMany/findOne/count exclude soft-deleted rows by default).
*/
function buildUpdate(dialect, table, data, where, tenant) {
const setColumns = Object.keys(data);
const setParams = setColumns.map((col) => coerceParam(dialect, data[col]));
let idx = 1;
const setClause = setColumns.map((col) => `${dialect.quoteIdent(col)} = ${dialect.placeholder(idx++)}`).join(', ');
const { clause, params: whereParams } = buildWhereClause(dialect, { where, tenant }, idx);
const text = `UPDATE ${dialect.quoteIdent(table)} SET ${setClause}${clause}`;
return { text, params: [...setParams, ...whereParams] };
}
/** Real hard delete — only used when schema.softDelete is false; soft-delete routes through buildUpdate. */
function buildDelete(dialect, table, where, tenant) {
const { clause, params } = buildWhereClause(dialect, { where, tenant }, 1);
return { text: `DELETE FROM ${dialect.quoteIdent(table)}${clause}`, params };
}
//# sourceMappingURL=queryBuilder.js.map