UNPKG

@dudousxd/nestjs-filter-drizzle

Version:

Drizzle ORM adapter for @dudousxd/nestjs-filter.

68 lines • 3.59 kB
import type { ColumnFilter } from '@dudousxd/nestjs-filter'; import { Column, type SQL } from 'drizzle-orm'; /** The SQL dialect a query renders for — decides LIKE/ILIKE, casts and escapes. */ export type DrizzleDialect = 'postgres' | 'mysql' | 'sqlite'; /** * What an operator compares: a real column (its type drives value coercion and * the `isEmpty` shape) or a developer-provided SQL expression (a computed field, * a correlated aggregate subquery). */ export type OperatorTarget = Column | SQL; /** * Coerces a client value to what the column's driver encoder expects. * * Drizzle binds a comparison value THROUGH the column (`mapToDriverValue`), so * a value of the wrong JS type is not merely compared loosely — it can break * the encoder: a `timestamp` column in `mode: 'date'` calls `.toISOString()` on * whatever it is handed, and a SQLite boolean encodes the string `'false'` as * truthy `1`. Query strings and decoded cursors deliver exactly those strings. * Values that do not parse are passed through untouched (the database then * reports the mismatch, rather than this layer inventing a value). */ export declare function coerceValue(column: Column, value: unknown): unknown; /** * Builds a LIKE predicate. The pattern is always a bound parameter, already * escaped with {@link escapeLike} (backslash escapes). Postgres and MySQL treat * backslash as the default LIKE escape; SQLite has NO default escape character, * so the clause is spelled out there — without it `%` in user input would still * be a wildcard. * * Case-insensitive matching uses `ILIKE` on Postgres (index-friendly with a * trigram index) and `lower(x) LIKE lower(p)` elsewhere. */ export declare function likeCondition(target: OperatorTarget, pattern: string, dialect: DrizzleDialect, opts?: { caseInsensitive?: boolean; negate?: boolean; }): SQL; /** * Translates ONE `ColumnFilter` operator into a drizzle SQL condition over * `target`. Every client value is a bound parameter (drizzle's `eq`/`gt`/… * bind through the column's encoder); nothing client-supplied is inlined. * * `isEmpty`/`isNotEmpty` compare against `''` only for string columns — `col = * ''` on a date or integer column is a type error on Postgres/MySQL — and * collapse to the NULL check everywhere else. */ export declare function buildOperatorCondition(target: OperatorTarget, filter: ColumnFilter, dialect: DrizzleDialect, /** * For an expression target whose values are those of a known column (a * `MIN`/`MAX` over a child column), bind comparison values through that * column's encoder — so a date compares as the column stores dates (an epoch * integer on SQLite, a timestamp on Postgres) rather than as a raw JS value. */ encoder?: Column): SQL; /** * Resolves a leaf filter to its condition — the adapter supplies this, since it * knows how to reach a field (a root column, or a relation path that needs an * `EXISTS` subquery). Returning `undefined` drops the leaf (an unresolvable * field never reaches SQL). */ export type LeafResolver = (filter: ColumnFilter) => SQL | undefined; /** * Folds a list of `ColumnFilter`s (with arbitrarily nested `AND`/`OR`) into one * condition: top-level entries are ANDed; a node contributes * `base AND (...AND) AND (OR₁ OR OR₂ …)`, the same grouping the MikroORM * adapter emits. A pure group node (no `field`) contributes only its children. */ export declare function buildColumnFiltersCondition(filters: ColumnFilter[], leaf: LeafResolver): SQL | undefined; //# sourceMappingURL=operator-resolver.d.ts.map