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.

72 lines (71 loc) 2.58 kB
import { isComparisonWhere } from "../core/where.js"; import { fieldToStr } from "../sql/pg.js"; import { and, arrayContained, arrayContains, arrayOverlaps, asc, desc, eq, gt, gte, ilike, inArray, isNull, like, lt, lte, not, or, sql } from "drizzle-orm"; //#region src/drizzle/pg.ts const opMap = { "=": eq, ">": gt, ">=": gte, "<": lt, "<=": lte, like, ilike }; const setOps = { "@>": arrayContains, "<@": arrayContained, "&&": arrayOverlaps }; const _toDrizzleWhere = (table, where) => { if (!where) return void 0; if (where.op === "not") { const subCondition = _toDrizzleWhere(table, where.condition); return subCondition ? not(subCondition) : void 0; } if (where.op === "and" || where.op === "or") { const conditions = where.conditions.map((c) => _toDrizzleWhere(table, c)).filter((c) => !!c); if (conditions.length === 0) return; return where.op === "and" ? and(...conditions) : or(...conditions); } if (!isComparisonWhere(where)) return; const [rootKey, ...segments] = where.field; const column = table[rootKey]; if (!column) { console.warn(`Field ${rootKey} does not exist on table`); return; } const target = segments.length === 0 ? column : sql.raw(fieldToStr(where.field)); if (where.op === "in") return inArray(target, where.values); if (where.op === "is null") return isNull(target); if (where.op in setOps) { const opFn = setOps[where.op]; if (!opFn) return; return opFn(target, where.value); } const opFn = opMap[where.op]; if (!opFn) return; return opFn(target, where.value); }; const toDrizzleWhere = (table, where, extraConditions) => { const whereConditions = _toDrizzleWhere(table, where); if (!extraConditions) return whereConditions; if (!whereConditions) return extraConditions; return and(extraConditions, whereConditions); }; const toDrizzleOrderBy = (table, orderBy) => { if (!orderBy) return []; return orderBy.map((c) => { const col = table[c.field[0]]; return (c.direction === "desc" ? desc : asc)(col); }); }; const toDrizzle = (db, table, querySchema) => { if (!querySchema) return db.select().from(table); const query = db.select().from(table).where(toDrizzleWhere(table, querySchema.where)).orderBy(...toDrizzleOrderBy(table, querySchema.orderBy)); if (querySchema.limit && querySchema.offset) return query.limit(querySchema.limit).offset(querySchema.offset); if (querySchema.limit) return query.limit(querySchema.limit); if (querySchema.offset) return query.offset(querySchema.offset); return query; }; //#endregion export { opMap, toDrizzle, toDrizzleOrderBy, toDrizzleWhere };