API reference

Every exported function, type and class in the Filtron packages. This page is generated from the source and its JSDoc comments when the site is built.

A plain-text version for tools and LLMs is available at llms/api.txt.

@filtron/core

Filtron parses human-friendly filter strings into structured queries you can use anywhere — SQL databases, in-memory arrays, or your own custom backend.

parsefunction

function parse(query: string, options?: ParseOptions): ParseResult;

Parses a Filtron query string into an Abstract Syntax Tree (AST).

ParameterDescription
queryThe Filtron query string to parse
optionsOptional parse limits, see ParseOptions

Returns A ParseResult containing either the AST or an error

const result = parse('age > 18 AND status = "active"');
if (result.success) {
  console.log(result.ast);
} else {
  console.error(result.message);
}

parseOrThrowfunction

function parseOrThrow(query: string, options?: ParseOptions): ASTNode;

Parses a Filtron query string and throws an error if parsing fails. Use this when you want to handle errors with try/catch instead of checking the result.

ParameterDescription
queryThe Filtron query string to parse
optionsOptional parse limits, see ParseOptions

Returns The parsed AST

Throws FiltronParseError if parsing fails, with position information

try {
  const ast = parseOrThrow('age > 18');
  console.log(ast);
} catch (error) {
  if (error instanceof FiltronParseError) {
    console.error('Parse failed at position', error.position, ':', error.message);
  }
}

FiltronParseErrorclass

class FiltronParseError extends Error {
  constructor(message: string, position?: number);
  position: number | undefined;
}

Error thrown when parsing a Filtron query fails. Includes the position in the query where the error occurred.

ParseOptionsinterface

interface ParseOptions {
  maxLength?: number;
  maxDepth?: number;
}

Limits applied while parsing a query. Both values are upper bounds; pass larger numbers to raise them.

ParseResulttype

type ParseResult = ParseSuccess | ParseFailure;

The generic parse result

ParseSuccessinterface

interface ParseSuccess {
  success: true;
  ast: ASTNode;
}

Result of a successful parse operation

ParseFailureinterface

interface ParseFailure {
  success: false;
  message: string;
  position?: number;
}

Result of a failed parse operation

walkfunction

function walk(node: ASTNode, visitor: (node: ASTNode) => boolean | undefined): void;

Walks an AST in pre-order depth-first order, calling the visitor on each node

The visitor is called on a node before its children. Returning false from the visitor skips that node's children; any other return value (including undefined) descends. Children of "or" and "and" nodes are visited in order; "not" nodes descend through their expression. All other nodes are leaves.

ParameterDescription
nodeThe AST node to walk
visitorCalled once per visited node; return false to skip children
import { parseOrThrow, walk } from "@filtron/core";

const ast = parseOrThrow('age > 18 AND status = "active"');
const fields: string[] = [];
walk(ast, (node) => {
  if ("field" in node) {
    fields.push(node.field);
  }
});
// fields: ["age", "status"]

printfunction

function print(node: ASTNode): string;

Prints an AST as canonical Filtron query text

Parsing the output reproduces the AST: parseOrThrow(print(ast)) is deeply equal to ast for any parser-produced tree. Parentheses appear only where a child binds looser than its parent, strings are double-quoted with escapes, and temporal values print behind @. Useful for canonicalizing queries (cache keys, logs) and roundtrip testing.

ParameterDescription
nodeThe AST node to print

Returns The canonical query text

import { parseOrThrow, print } from "@filtron/core";

print(parseOrThrow("(a AND (b OR c))"));
// "a AND (b OR c)"

validateFieldsfunction

function validateFields(node: ASTNode, allowedFields: readonly string[]): void;

Validates that every field referenced in an AST is in the allowlist

Walks the AST in pre-order and throws on the first field that is not in allowedFields. Useful for guarding hand-built ASTs and untrusted queries before generating filters or SQL.

ParameterDescription
nodeThe AST node to validate
allowedFieldsField names that are allowed to appear in the AST

Throws Error if a field is not in the allowlist

import { parseOrThrow, validateFields } from "@filtron/core";

const ast = parseOrThrow("password = \"hunter2\"");
validateFields(ast, ["name", "age"]);
// Error: Field "password" is not allowed. Allowed fields: name, age

Lexerclass

class Lexer {
  constructor(input: string);
  next(): Token;
}

Lexer for tokenizing Filtron query strings

Tokentype

type Token = StringToken | NumberToken | BooleanToken | TemporalToken | SymbolToken;

Discriminated union of all token types for proper type narrowing

TokenTypetype

type TokenType = "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "COMMA" | "QUESTION" | "DOT" | "DOTDOT" | "MINUS" | "AND" | "OR" | "NOT" | "TRUE" | "FALSE" | "EQ" | "NEQ" | "GT" | "GTE" | "LT" | "LTE" | "LIKE" | "COLON" | "NOT_COLON" | "STRING" | "NUMBER" | "IDENT" | "TEMPORAL" | "EOF";

Token types produced by the lexer

StringTokeninterface

interface StringToken extends TokenBase {
  type: "STRING" | "IDENT";
  value: string;
}

Tokens with string values (string literals and identifiers)

NumberTokeninterface

interface NumberToken extends TokenBase {
  type: "NUMBER";
  value: number;
}

Tokens with number values

BooleanTokeninterface

interface BooleanToken extends TokenBase {
  type: "TRUE" | "FALSE";
  value: boolean;
}

Tokens with boolean values

SymbolTokeninterface

interface SymbolToken extends TokenBase {
  type: "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "COMMA" | "QUESTION" | "DOT" | "DOTDOT" | "MINUS" | "AND" | "OR" | "NOT" | "EQ" | "NEQ" | "GT" | "GTE" | "LT" | "LTE" | "LIKE" | "COLON" | "NOT_COLON" | "EOF";
}

Tokens without values (operators, punctuation, keywords, EOF)

ASTNodetype

type ASTNode = OrExpression | AndExpression | NotExpression | ComparisonExpression | OneOfExpression | ExistsExpression | BooleanFieldExpression;

Root AST node type - represents any valid Filtron expression

Valuetype

type Value = StringValue | NumberValue | BooleanValue | IdentifierValue | RangeValue | DateValue | NowValue;

Value type - represents literal values in expressions

ComparisonOperatortype

type ComparisonOperator = "=" | "!=" | "~" | ">" | ">=" | "<" | "<=" | ":";

Comparison operators supported

OrExpressioninterface

interface OrExpression {
  type: "or";
  children: ASTNode[];
}

Logical OR expression - combines two or more expressions with OR

Chains are flat: children always has at least two entries and never contains another OrExpression. The parser splices nested OR chains (including parenthesized ones) into a single node.

AndExpressioninterface

interface AndExpression {
  type: "and";
  children: ASTNode[];
}

Logical AND expression - combines two or more expressions with AND

Chains are flat: children always has at least two entries and never contains another AndExpression. The parser splices nested AND chains (including parenthesized ones) into a single node.

NotExpressioninterface

interface NotExpression {
  type: "not";
  expression: ASTNode;
}

Logical NOT expression - negates an expression

ComparisonExpressioninterface

interface ComparisonExpression {
  type: "comparison";
  field: string;
  operator: ComparisonOperator;
  value: Value;
}

Comparison expression - compares a field to a value using an operator Example: age > 18, status = "active"

OneOfExpressioninterface

interface OneOfExpression {
  type: "oneOf";
  field: string;
  values: Value[];
  negated: boolean;
}

Membership expression - checks whether a field matches any value in a list Example: status : ["pending", "approved"], status !: ["deleted"] (negated)

ExistsExpressioninterface

interface ExistsExpression {
  type: "exists";
  field: string;
  negated: boolean;
}

Exists expression - checks whether a field exists (is not null/undefined) Example: email?, -email (negated)

BooleanFieldExpressioninterface

interface BooleanFieldExpression {
  type: "booleanField";
  field: string;
}

Boolean field expression - shorthand for checking if a boolean field is true Example: verified, premium

StringValueinterface

interface StringValue {
  type: "string";
  value: string;
}

String value - a quoted string literal

NumberValueinterface

interface NumberValue {
  type: "number";
  value: number;
}

Number value - an integer or floating-point number

BooleanValueinterface

interface BooleanValue {
  type: "boolean";
  value: boolean;
}

Boolean value - true or false

IdentifierValueinterface

interface IdentifierValue {
  type: "identifier";
  value: string;
}

Identifier value - an unquoted identifier used as a value

RangeValuetype

type RangeValue = NumberRangeValue | TemporalRangeValue;

Range value - an inclusive interval over numbers or points in time

NumberRangeValueinterface

interface NumberRangeValue {
  type: "range";
  kind: "number";
  min: number;
  max: number;
}

Range value over numbers - an inclusive interval Valid with the =, : and != operators only Example: age = 18..65, price != 0..100

TemporalRangeValueinterface

interface TemporalRangeValue {
  type: "range";
  kind: "temporal";
  min: TemporalPoint;
  max: TemporalPoint;
}

Range value over points in time - an inclusive interval Valid with the =, : and != operators only Example: deployed = @2024-06-01..2024-06-30, created =

DateValueinterface

interface DateValue {
  type: "date";
  value: string;
}

Date value - an absolute point in time, written as @<ISO 8601> Example: @2024-06-01, @2024-06-30T14:00:00Z

NowValueinterface

interface NowValue {
  type: "now";
  offset: {
    amount: number;
    unit: DurationUnit;
  } | null;
}

Now value - a point in time relative to evaluation, written as

TemporalPointtype

type TemporalPoint = DateValue | NowValue;

A temporal range bound: an absolute date or a now-relative point

DurationUnittype

type DurationUnit = "s" | "m" | "h" | "d" | "w" | "M" | "y";

Units for now-relative offsets Case-sensitive: m is minutes, M is months

@filtron/js

Filtron helper: transform filter expressions into JavaScript predicates for Array.filter()

toFilterfunction

function toFilter<T extends Record<string, unknown> = Record<string, unknown>>(ast: ASTNode, options?: FilterOptions): FilterPredicate<T>;

Converts a Filtron AST to a predicate function for filtering arrays

ParameterDescription
astThe Filtron AST node to convert
optionsFilter generation options

Returns A predicate function that can be used with Array.filter()

import { parse } from '@filtron/core';
import { toFilter } from '@filtron/js';

const result = parse('age > 18 AND status = "active"');
if (result.success) {
  const filter = toFilter(result.ast);

  const users = [
    { name: 'Alice', age: 25, status: 'active' },
    { name: 'Bob', age: 16, status: 'active' },
    { name: 'Charlie', age: 30, status: 'inactive' },
  ];

  const filtered = users.filter(filter);
  // [{ name: 'Alice', age: 25, status: 'active' }]
}

nestedAccessorfunction

function nestedAccessor(separator?: string): (obj: Record<string, unknown>, field: string) => unknown;

Creates a field accessor for nested properties using dot notation

ParameterDescription
separatorThe separator used in field names (default: ".")

Returns A field accessor function

const filter = toFilter(ast, {
  fieldAccessor: nestedAccessor()
});

// Now you can query nested fields like "user.address.city"
const items = data.filter(filter);

FilterPredicatetype

type FilterPredicate<T = Record<string, unknown>> = (item: T) => boolean;

Predicate function type that filters objects

FilterOptionsinterface

interface FilterOptions {
  allowedFields?: string[];
  fieldAccessor?: (obj: Record<string, unknown>, field: string) => unknown;
  caseInsensitive?: boolean;
  fieldMapping?: Record<string, string>;
}

Filter generation options

@filtron/sql

Filtron helper: generate safe, parameterized SQL WHERE clauses from filter expressions

toSQLfunction

function toSQL(ast: ASTNode, options?: SQLOptions): SQLResult;

Converts a Filtron AST to a parameterized SQL WHERE clause

ParameterDescription
astThe Filtron AST node to convert
optionsSQL generation options

Returns SQL result with WHERE clause and parameters

import { parse } from '@filtron/core';
import { toSQL } from '@filtron/sql';

const ast = parse('age > 18 AND status = "active"');
if (ast.success) {
  const { sql, params } = toSQL(ast.ast);
  console.log(sql);    // "age > $1 AND status = $2"
  console.log(params); // [18, "active"]
}

escapeLikefunction

function escapeLike(value: string): string;

Escapes special LIKE characters (%, _, \) in a string value Use this to prevent LIKE injection when user input is used in LIKE patterns

ParameterDescription
valueThe value to escape

Returns Escaped string safe for use in LIKE patterns

escapeLike("admin%") // "admin\\%"
escapeLike("test_user") // "test\\_user"

containsfunction

function contains(value: string | number | boolean): string;

Wraps a value with wildcards for "contains" matching Automatically escapes special LIKE characters This is the default ~ value transform (likeMode 'contains')

ParameterDescription
valueThe value to wrap

Returns Value wrapped with % wildcards

contains("foo") // "%foo%"

prefixfunction

function prefix(value: string | number | boolean): string;

Adds trailing wildcard for "starts with" matching Automatically escapes special LIKE characters

ParameterDescription
valueThe value to wrap

Returns Value with % wildcard at the end

toSQL(ast, { valueMapper: prefix })
// "admin" becomes "admin%"

suffixfunction

function suffix(value: string | number | boolean): string;

Adds leading wildcard for "ends with" matching Automatically escapes special LIKE characters

ParameterDescription
valueThe value to wrap

Returns Value with % wildcard at the beginning

toSQL(ast, { valueMapper: suffix })
// ".pdf" becomes "%.pdf"

SQLResultinterface

interface SQLResult {
  sql: string;
  params: unknown[];
}

SQL generation result

SQLOptionsinterface

interface SQLOptions {
  dialect?: "postgres" | "mysql" | "sqlite";
  parameterStyle?: "numbered" | "question";
  fieldMapper?: (field: string) => string;
  valueMapper?: (value: string | number | boolean) => string | number | boolean;
  likeMode?: "contains" | "raw";
  startIndex?: number;
  allowedFields?: string[];
}

SQL generation options

@filtron/time-resolver

Filtron helper: resolve now-relative temporal values into absolute dates

resolveTemporalfunction

function resolveTemporal(node: ASTNode, options?: ResolveTemporalOptions): ASTNode;

Resolves every now-relative temporal value in an AST to an absolute date, returning a new AST

Nodes without relative values are returned by reference, so an AST without any @now usage comes back unchanged and identity-equal. Fixed-length units (s, m, h, d, w) offset by exact milliseconds; months and years move the calendar in UTC and clamp to the last day of the target month (Jan 31 minus one month is Feb 28 or 29). Resolved dates are full ISO 8601 UTC instants.

ParameterDescription
nodeThe AST to resolve
optionsResolution options

Returns An AST in which every temporal value is absolute

Throws Error if the reference time is invalid or a resolved range ends up inverted

import { parseOrThrow } from "@filtron/core";
import { resolveTemporal } from "@filtron/time-resolver";

const ast = resolveTemporal(parseOrThrow("created > @now-7d"), {
  now: new Date("2026-07-17T12:00:00Z"),
});
// comparison value: { type: "date", value: "2026-07-10T12:00:00.000Z" }