UNPKG

@dudousxd/nestjs-filter-clickhouse

Version:

ClickHouse adapter for @dudousxd/nestjs-filter: compiles structured filter input to parameterized ClickHouse SQL.

122 lines • 5.02 kB
import type { SchemaEntity } from '@dudousxd/nestjs-filter'; /** * A field of a ClickHouse table: a trusted SQL expression plus its ClickHouse type. * * - `type` — the ClickHouse type of the expression (`String`, `UInt64`, `Float64`, * `DateTime64(3, 'UTC')`, `LowCardinality(String)`, `Nullable(Int32)`, `Array(String)`, …). It * types every bound parameter (`{p0:UInt64}`) and decides coercion, LIKE casts and `isEmpty`. * - `expr` — the SQL expression (developer-written, never client input). Defaults to the quoted * field name, i.e. the column of that name. * - `measure` — an aggregate expression (`sum(count)`, `uniqMerge(users)`). A table with measures * is an **aggregated** table: rows are grouped by the requested dimensions (`select`, or the * table's `groupBy`), measures are projected per group, and a filter on a measure goes to HAVING. * - `searchable` — included in `search` when the filter class declares no `static search` list * (dynamic mode searches every searchable field). Defaults to true for String types. */ export interface ClickHouseFieldDefinition { type: string; expr?: string; measure?: boolean; searchable?: boolean; } export interface ClickHouseTableDefinition { /** * The FROM target — a table name, `db.table`, or any trusted table expression * (`events FINAL`, a subquery in parentheses). Emitted verbatim. */ table: string; /** Display name (errors, the `alias` computed sources receive). Defaults to `table`. */ name?: string; /** * The fields a client may filter, sort, search, group and project by — the allowlist. A bare * string is the type of the column of that name. */ fields: Record<string, string | ClickHouseFieldDefinition>; /** Unique row key — the cursor-pagination tiebreaker, and what `select` keeps. */ primaryKey?: string; /** Aggregated tables: the dimensions rows are grouped by when the request selects none. */ groupBy?: string[]; /** * A condition always applied (trusted SQL), e.g. a time bound on a raw events table: * `at >= now64(3) - toIntervalDay(30)`. */ where?: string; } /** The type family a ClickHouse type belongs to, for coercion and operator shapes. */ export type ClickHouseTypeKind = 'string' | 'int' | 'float' | 'bool' | 'date' | 'datetime' | 'array' | 'other'; export interface ResolvedClickHouseField { name: string; /** The declared type. */ type: string; /** The type with `Nullable(…)` / `LowCardinality(…)` unwrapped — what parameters are typed as. */ baseType: string; kind: ClickHouseTypeKind; /** For `Array(T)`: the resolved element type. */ element?: { baseType: string; kind: ClickHouseTypeKind; }; nullable: boolean; expr: string; measure: boolean; searchable: boolean; } declare const TABLE: unique symbol; /** `Nullable(LowCardinality(String))` → `{ base: 'String', nullable: true }`. */ export declare function unwrapType(type: string): { base: string; nullable: boolean; }; export declare function typeKind(base: string): ClickHouseTypeKind; /** * A declared ClickHouse table — the adapter's "entity", used wherever a Drizzle table or an entity * class goes: `@Filterable({ entity: events })`, `runner.findAndCount(events, input)`. */ export declare class ClickHouseTable<T = Record<string, unknown>> implements SchemaEntity<T> { /** Type-only: the row type. */ readonly $inferSelect: T; readonly [TABLE] = true; readonly table: string; readonly name: string; readonly primaryKey: string | undefined; readonly groupBy: string[]; readonly where: string | undefined; private readonly fieldMap; constructor(definition: ClickHouseTableDefinition); field(name: string): ResolvedClickHouseField | undefined; fields(): ResolvedClickHouseField[]; /** Whether the table has measures (rows are groups, measures aggregate per group). */ get aggregated(): boolean; } /** * Declares a ClickHouse table. * * ```ts * export const events = defineClickHouseTable({ * table: 'events', * primaryKey: 'id', * fields: { * id: 'UUID', * at: "DateTime64(3, 'UTC')", * event: { type: 'LowCardinality(String)', expr: 'name' }, * day: { type: 'Date', expr: 'toDate(at)' }, * durationMs: 'UInt64', * }, * }); * * export const errorsDaily = defineClickHouseTable({ * table: 'errors_daily', * groupBy: ['event', 'provider'], * fields: { * day: 'Date', * event: { type: 'String', expr: 'name' }, * provider: 'String', * count: { type: 'UInt64', expr: 'sum(count)', measure: true }, * }, * }); * ``` */ export declare function defineClickHouseTable<T = Record<string, unknown>>(definition: ClickHouseTableDefinition): ClickHouseTable<T>; export declare function isClickHouseTable(value: unknown): value is ClickHouseTable<unknown>; export {}; //# sourceMappingURL=table.d.ts.map