Skip to content

Filter DSL

namespace

Imported as a namespace, and re-exported member by member from a second entry point.

type CNode = FieldNode | ConditionNode | ValueNode | ValuesNode | OperationNode | ComponentNode;
interface ComponentNode

Component node. Wraps another condition. Think of it like a named term.

type: "Component"

id: string | null – Id of the component

condition: CNode | null – Actual condition, or null for a component that currently filters nothing. An empty component keeps its place in a composition; only the SQL transformation drops it.

type ComputedValue = {
name: string;
args: RawValue[];
};
type Condition = ConditionNode & { [K in keyof typeof CONDITION_METHODS]: CondFn<(typeof CONDITION_METHODS)[K]>; };
interface ConditionNode

Named condition Node.

type: "Condition"

name: string – Name of the condition (e.g. “greater”)

operands: CNode[] – Operands of the condition

type FieldConditionName = keyof typeof FIELD_CONDITIONS;

Name of a condition a field has as a method, eq, containsIgnoreCase, between and so on.

type FieldExpression = string | CNode;
interface FieldNode

Field reference.

type: "FieldReference"

name: string – Name of the field

type FieldReference = FieldNode & FieldConditions & FieldOperations;
type FilterExpression = ConditionNode | ComponentNode;

A composed filter: a condition, or a component marker wrapping one. This is what a filter is - it never includes falsy members.

type LogicalOperand = FilterExpression | null | undefined | false;

What or() / and() accept. Falsy operands are dropped, which is the point of the logical composers: callers compose from helpers that may contribute nothing and let the final logical shape fall out of whatever survived.

Note that flag && cond only lands in this type when flag is a boolean. For a truthy-narrowable value use !!flag && cond, or the equivalent flag ? cond : null - "" | undefined | Condition is not an operand.

interface OperationNode

Operation node. Addition, subtraction etc.

type: "Operation"

name: string – Name of the operation

operands: CNode[] – Operands of the operation

type RawValue = null | string | number | boolean | RawValue[] | {
[key: string]: RawValue;
};

JSON value equivalent

type SortDirection = "asc" | "desc";
interface SortMatch

Where a sort key appears in a sort order.

direction: SortDirection – Direction the key is sorted in.

index: number – Index of the key in the sort order, 0 for the most significant.

type Typed = {
type: string;
};
type Value = ValueNode & FieldConditions & FieldOperations;
interface ValueNode

Value node. Represents a single runtime-typed value.

type: "Value"

scalarType: string – Scalar type of the value

value: RawValue – Raw/json value

interface ValuesNode

Values node. Represents an array of values.

type: "Values"

scalarType: string – Scalar type of the elements in the value array

values: RawValue[] – Array of raw values.

declare const and: (...args: LogicalOperand[]) => (FilterExpression | null);

Logical and condition. Will ignore falsy operands. An empty and collapses to null.

Parameters

{... CNode} operands

Returns {CNode} ANDed condition

declare function component(id: string | null, condition: CNode | null): ComponentNode;

Component condition node. These nodes are just marker for which part of the condition originated from which component Logically they are evaluated as the condition they wrap.

Parameters

{String} id component id
{CNode} condition actual condition for the component, null for an empty one

Returns {CNode}

declare function computedValue(name: string, args?: RawValue[]): ValueNode;
declare function condition(name: string, operands?: CNode[]): CNode;

Generic condition node. Useful for programmatically instantiating conditions. Not needed for fluent style conditions.

Parameters

{String} name condition name
{Array<CNode>} operands operands

Returns {CNode}

declare function conditionsEqual(a: CNode | null | undefined, b: CNode | null | undefined): boolean;

Returns true if the two conditions are structurally equal: the same nodes in the same order, with equal names, ids and values. Values compare by their JSON form, which is how they travel, so a Temporal value and the string the server echoes for it are equal. null and undefined both mean “no condition” and equal each other.

A condition that comes back unchanged from an update() is a different object with the same structure; this is how to tell.

Parameters

a condition or null
b condition or null
declare function field(name: string): FieldReference;

Field / column reference.

Parameters

{String} name field name (e.g. “name”, “owner.name”)

Returns {FieldReference}

declare function fieldConditionArity(name: string): number | undefined;

Number of operands a field condition takes besides the field, 1 for eq, 2 for between, undefined for a name that isn’t one.

Parameters

name condition name
declare function findComponentNode(conditionNode: CNode | null, id: string): CNode | null;

Finds a component node with the given id.

Parameters

{Object} conditionNode condition structure root
{String} id component id

Returns {Object|null} component node or null

declare function getConditionArgCount(name: Function | string): number;

Returns the number of expected arguments for the condition with the given name.

Parameters

{String} name condition name

Returns {number} number of value arguments expected

declare function isComposedComponentExpression(node: CNode): boolean;

Returns true if the given condition node is a logical condition with all operands being of type Component

Parameters

node
declare function isComputedValue(raw: unknown): raw is ComputedValue;
declare function isCondition(value: Typed): value is CNode;

Returns true if the given value is a condition node.

Parameters

value
declare function isConditionObject(value: any): boolean;
declare function isLogicalCondition(node: CNode): node is ConditionNode;

Returns true if the given condition node is either a logical and or a logical or condition.

Parameters

{Object} node node

Returns {boolean} true if the node is either an “and” or an “or”

declare function matchSort(sortFields: readonly FieldExpression[], key: FieldExpression): SortMatch | null;

Finds a column’s sort key in a sort order. The key is what the column sorts by – a field path, or an expression node for a computed column – and never carries a direction itself. It matches a sort field sorting by the same field or a structurally equal expression, in either direction, in any of the forms simplifySortField() accepts.

Parameters

sortFields sort order, as in a query config
key field path or expression the column sorts by

Returns direction and position of the key, or null if the sort order doesn’t contain it

declare function matchSortPart(sortFields: readonly FieldExpression[], key: FieldExpression): SortMatch | null;

Finds a sort key inside an expression the sort order sorts by, e.g. num in num % 10: the order doesn’t sort by the key itself, but the key takes part in it. A sort field that is the key, which matchSort() finds, doesn’t count.

Parameters

sortFields sort order, as in a query config
key field path or expression the column sorts by

Returns direction of the expression and its position, the first one containing the key, or null if none does

declare function not(operand: CNode): CNode;

Logical not condition.

Parameters

{CNode} operand

Returns {CNode} negated condition

declare function now(): ValueNode;
declare function operation(name: string, operands?: CNode[]): CNode;

Generic operation node. Useful for programmatically instantiating conditions. Not needed for fluent style conditions.

Parameters

name
operands
declare const or: (...args: LogicalOperand[]) => (FilterExpression | null);

Logical or condition. Will ignore falsy operands. An empty or collapses to null.

Parameters

{... CNode} operands

Returns {CNode} ORed condition

declare function ownedPart(condition: FilterExpression | null, id: string): FilterExpression | null;

The part of a condition that belongs to the holder of the given component id:

  • in a composition of components, the term of its component, or null if there is none;
  • in a lone component, its term if the component is its own, null if it belongs to someone else;
  • any other condition is owned whole.

Components exist on one level only: inside its component, an owner recognizes its terms by content, not by further markers.

Parameters

condition condition or null
id component id of the owner reading

Returns the owned part, null for “nothing”

declare function simplifySortField(sortField: FieldExpression): FieldExpression;

The simple string form of a sort field, where it has one: a field sorts as its name, descending with a ! prefix, whether it came as a string, a field node or a field in asc or desc. An expression has no string form and comes back as it is, unwrapped from an asc, which is the default direction anyway.

Parameters

sortField sort field, as in a query config
declare function toJSON(condition: CNode | null): RawValue;

Converts the given condition graph into simple js objects.

The Filter DSL produces Filter nodes that are in fact instances of the Filter DSL types used to implement to conditions/operations. This works fine in many cases, but sometimes it doesn’t.

One example is that mobx will ignore the instances and not create observables for them. Making the FilterDSL in general observable would be possible, but would mean a huge overhead for a very exotic use-case.

Parameters

condition Input condition, potentially consisting of DSL instances

Returns condition as graph of objects / arrays

declare function today(): ValueNode;
declare function toggleSort(sortFields: readonly FieldExpression[], key: FieldExpression): FieldExpression[];

The sort order a click on a column asks for: the key descending if it already is the whole sort order and ascending, the key ascending in every other case. The result replaces the whole sort order.

A field path comes out in its string form, "name" or "!name"; an expression as itself or wrapped in desc.

Parameters

sortFields current sort order
key field path or expression the column sorts by
declare function updateComponent(condition: FilterExpression | null, id: string, term: FilterExpression | null): FilterExpression | null;

Replaces the part of a condition that belongs to the holder of the given component id – the write side of ownedPart(), by the same rules.

This is how several owners share one condition – a grid’s filter row, a search form, a picker – each writing only its own component and leaving the others as they are:

  • The component with the id gets the new term. A null term keeps the component as component(id, null), so the owner finds its place again later; only the SQL transformation drops an empty component.
  • A missing component is added as another operand of an and composition, or joined with and() to a lone component, so the result stays one flat level. Owners narrow what is shown, so adding means and.
  • An or composition without the component is refused: joining it would widen the result, and wrapping the or would produce a second level. Put component(id, null) into the or where the owner’s term belongs.
  • No condition at all becomes the lone component, so the next owner to write joins it. A null term leaves it at no condition.
  • Any other condition is owned whole and replaced by the plain term, without a marker.

Returns the very same condition object when the owned part is structurally equal to the new term, so an unchanged filter need not send an update().

Parameters

condition condition or null
id component id of the owner writing
term new term of that owner, null for “filters nothing”

Throws Error for an or composition that lacks the component

declare function value(value: RawValue, type?: string): ValueNode;

Creates a new value node

Parameters

{Object} value scalar value of appropriate type
{String} [type] scalar type name if not given the type will be selected based on value type

Returns {ValueNode} value node

declare function values(type: string, ...values: RawValue[]): ValuesNode;

Creates a new values node that encapsulates a collection of scalar values (for e.g. the IN operator)

Parameters

{String} type scalar type name
{Object} values var args of scalar value of appropriate type

Returns {ValuesNode} values node

function

declare function decompileFilter(condition: CNode | null, level?: number, match?: CNode | null, invert?: boolean): string;

Converts the given FilterDSL condition graph into a pretty-formatted source form using the FilterDSL API (and DateTime.fromIso() expressions)

Parameters

{Object} condition condition graph
{Number} level starting indentation level
{Object} match Optional object to mark. The given node is assumed to an instance in the graph and the source output of that object is marked is enclosed in />>/ /<</ to mark the object
{boolean} invert inverts condition output (mostly internal usage)

Returns {string} pretty-printed source string. If match was used, the >> << might prevent it from being valid JavaScript

function

declare function conditionPredicate<R extends object = any>(type: string, condition: FilterExpression | null): (row: R) => boolean;

Compiles a condition into a test of rows: whether the server would return a row for a query with that condition.

const matches = conditionPredicate("Foo", doc.config.condition);
const shown = created.filter(matches);

Everything the condition decides by itself is checked here, once: a field the type doesn’t have, an operator that doesn’t exist or gets the wrong number of operands, a value its type can’t read. A row missing a field the condition reads is an error when it is tested – the query doesn’t select that field.

It follows the SQL path: three-valued logic, so a row matches only where the condition is true and a comparison with null never is; a path through a to-many relation asks whether some element matches; values read as the type of what they are compared to. Text orders by the user’s locale rather than the database’s collation, likeRegex is a JavaScript regular expression, and now() and today() are the browser’s clock.

Parameters

type GraphQL type name of the rows
condition FilterDSL condition, null for “all rows”

Returns test of a row, in the live form a query result or a working set draft has

function

declare function sortComparator<R extends object = any>(type: string, sortFields: readonly FieldExpression[]): (a: R, b: R) => number;

Compiles sort fields into a comparison of rows, for Array.prototype.sort().

rows.sort(sortComparator("Foo", ["!num", "name"]))

Sort fields come in every form a query config takes them: a field path, "!" in front for descending, a field or expression node, or one in asc() or desc(). Nulls come last ascending and first descending, as in PostgreSQL. Values order by scalarCompare(). Rows equal under every sort field keep their order, sort() being stable.

Parameters

type GraphQL type name of the rows
sortFields sort fields, most significant first

Returns comparison of two rows

Called on a field or value node, and reachable as condition(name, operands) for building a graph programmatically. Operands are the ones passed besides the node it is called on, so isNull takes none and between takes two.

Operator Operands
between 2
betweenSymmetric 2
contains 1
containsIgnoreCase 1
endsWith 1
eq 1
equal 1
equalIgnoreCase 1
ge 1
greaterOrEqual 1
greaterThan 1
gt 1
in 1
isDistinctFrom 1
isFalse 0
isNotDistinctFrom 1
isNotNull 0
isNull 0
isTrue 0
le 1
lessOrEqual 1
lessThan 1
likeRegex 1
lt 1
ne 1
notBetween 2
notBetweenSymmetric 2
notContains 1
notContainsIgnoreCase 1
notEqual 1
notEqualIgnoreCase 1
notLikeRegex 1
startsWith 1

Called on a condition. The functional forms and(), or() and not() build the same nodes.

Operator Operands
and 1
andNot 1
not 0
or 1
orNot 1

Called on a field, producing an expression rather than a condition, and reachable as operation(name, operands). toString is translated into a cast to string; asc and desc are the sort directions.

Operator Operands
add 1
asc 0
bitAnd 1
bitNand 1
bitNor 1
bitNot 0
bitOr 1
bitXNor 1
bitXor 1
concat 1
desc 0
div 1
divide 1
lower 0
minus 1
mod 1
modulo 1
mul 1
multiply 1
neg 0
plus 1
pow 1
power 1
rem 1
shl 1
shr 1
sub 1
subtract 1
times 1
toString 0
unaryMinus 0
unaryPlus 0
upper 0