UNPKG

agnostic-query

Version:

Type-safe fluent builder for portable query schemas. Runtime-agnostic, database-agnostic — the same QuerySchema drives Drizzle, Kysely, db0, or raw SQL.

67 lines (66 loc) 2.28 kB
import { isComparisonWhere } from "../core/where.js"; //#region src/sql/common.ts const quoteIdent = (s) => `"${s.replace(/"/g, "\"\"")}"`; const buildWhere = (where, fieldToStr, placeholderForIndex, startIndex = 1) => { if (where.op === "not") { const inner = buildWhere(where.condition, fieldToStr, placeholderForIndex, startIndex); if (!inner) return; return { sql: `NOT (${inner.sql})`, params: inner.params }; } if (where.op === "and" || where.op === "or") { let idx = startIndex; const parts = where.conditions.map((c) => { const res = buildWhere(c, fieldToStr, placeholderForIndex, idx); if (res) idx = idx + res.params.length; return res; }).filter((c) => c !== void 0); if (parts.length === 0) return; const joiner = ` ${where.op.toUpperCase()} `; const sql = parts.map((p) => p.sql).join(joiner); return { sql: parts.length > 1 ? `(${sql})` : sql, params: parts.flatMap((p) => p.params) }; } if (!isComparisonWhere(where)) return; const fieldStr = fieldToStr(where.field); if (where.op === "in") return { sql: `${fieldStr} IN (${where.values.map((_, i) => placeholderForIndex(i + startIndex)).join(", ")})`, params: where.values }; if (where.op === "is null") return { sql: `${fieldStr} IS NULL`, params: [] }; return { sql: `${fieldStr} ${where.op} ${placeholderForIndex(startIndex)}`, params: [where.value] }; }; const toSqlOrderBy = (orderBy, fieldToStr) => { if (!orderBy) return; return { sql: orderBy.map((c) => `${fieldToStr(c.field)} ${c.direction.toUpperCase()}`).join(", "), params: [] }; }; const _toSql = (json, fieldToStr, buildWhereFn) => { if (!json.table) throw new Error("Table name is required"); const where = json.where ? buildWhereFn(json.where) : void 0; const orderBy = json.orderBy?.length ? toSqlOrderBy(json.orderBy, fieldToStr) : void 0; return { sql: [ `SELECT * FROM ${quoteIdent(json.table)}`, where ? `WHERE ${where.sql}` : "", orderBy ? `ORDER BY ${orderBy.sql}` : "", json.limit !== void 0 ? `LIMIT ${json.limit}` : "", json.offset !== void 0 ? `OFFSET ${json.offset}` : "" ].filter(Boolean).join(" "), params: [...where?.params ?? [], ...orderBy?.params ?? []] }; }; //#endregion export { _toSql, buildWhere, quoteIdent, toSqlOrderBy };