Getting started
Guides
Evaluating queries in JavaScript
Compile a query into a predicate and filter rows in the browser or on the server.
compile turns a query into a plain function once; call it on as many rows as you like.
import { compile } from '@qnot/core';
const matches = compile(fields, query);
const result = users.filter(matches);The row type defaults to RowOf<typeof fields>. Struct fields read nested objects
(address.city reads row.address.city), and array groups iterate the row's array. To read rows of
another shape, pass get:
const matches = compile<typeof fields, User>(fields, query, {
get: (user, field) => (field === 'plan' ? user.subscription.plan : user[field as keyof User]),
});matches(fields, query, row) compiles and tests a single row in one call.
Semantics
- Incomplete rules are skipped by default, as the export codecs do, so a half-built query still
filters;
incompleteRules: falsemakes them fail closed instead. - Invalid rules match nothing by default (a present value of the wrong type, out of range, or on
an unknown field), so an untrusted query can never widen;
invalidRules: 'skip'leaves them out. An empty query matches everything. - Text compares case-insensitively unless the field sets
caseSensitive: true. - Dates and date-times compare as instants; times compare as
HH:mm[:ss]strings. - Null and undefined fail every comparison except
isNullandisEmpty;notInandnotBetweendon't match missing values. isEmptymatchesnull,undefined,''and empty arrays;isNullonlynull/undefined.- Multi-value fields:
hasAny,hasAll,hasNone,setEq,setNeqcompare the row's array against the rule's list. - Array groups quantify over the array:
some,all(true for an empty array),none, or a count ({ count: 'gte', value: 3 }, orbetween). - Functions run their
evaluate; custom operators run theirs.
Switch cases
compileCases compiles an ordered list of conditions with results; the first match wins.
import { compileCases } from '@qnot/core';
const route = compileCases(fields, {
cases: [
{ when: vipQuery, then: 'concierge' },
{ when: emeaQuery, then: 'emea-team' },
],
otherwise: 'self-serve',
});
route(user); // { value: 'emea-team', index: 1 }On this page