@siftql/core

A Lucene-style query language for plain JavaScript objects. Real chronological dates, linear-time regular expressions, zero runtime dependencies.

npm install @siftql/core

Query and results

Results
Rows matching the current query

What those options do

The controls live in the card above, beside the query they affect. This is the explanation, and the resolved shape the engine is actually running with.

dateFormat
A non-ISO layout, declared rather than guessed. 01-06-2020 is 1 June under DD-MM-YYYY and 6 January under MM-DD-YYYY; siftql will never pick for you. Tokens are YYYY MM DD HH mm ss SSS and everything else in the layout is matched literally. Engine-level only.
tolerant
For search-as-you-type, where the query is malformed on almost every keystroke. Holes are repaired and marked instead of thrown. Structural limits still throw — this forgives half-typed syntax, not unbounded input. Engine-level only: passing it per call does nothing at all.
matchKeys
A bare term may match a field NAME as well as its contents. Off by default.
regexGuard
On, a pattern that cannot be matched in guaranteed linear time is refused — backreferences, lookaround, a quantifier whose body can match empty, the u/v flags. Off, those run on RegExp instead, and you get three things: the pattern works, you lose highlight positions for it, and unbounded backtracking is back.
onValueError
What a bad VALUE in the data does — not a bad query, which always throws. skip drops the row; throw raises a SiftQLValueError naming the path and the value.
maxPatternLength
Longest accepted regex source, default 1000.

Resolved options


        

Note temporal.dateFormat: it is flat going in and nested coming out, which is the kind of thing a demo gets wrong quietly.

Date inspector

Two public functions, run live. detectTemporalFormat asks does this match one of the built-in ISO shapes; resolveTemporal asks does it resolve to a real instant — and it also applies any dateFormat you declare, which detect never sees. So the two disagree in both directions, and each disagreement means something different:

AST

The AST is a documented public contract and pure JSON — no RegExp, no Date, no functions — so it survives structuredClone, a cache key, or a worker boundary.

serialize(parse(query))


        

JSON round trip


        

Tree (locations stripped)


      

Regex race

^(a+)+$ against "a".repeat(n) + "!" — the classic catastrophic pattern. siftql matches it on a linear-time automaton. The native RegExp runs in a Web Worker with a hard timeout, because otherwise it would freeze this tab and you would never see the result.

Data

Editable. One caveat worth stating plainly: the seed is built in JavaScript so that created can hold an ISO string, epoch milliseconds and a real Date across different rows. JSON cannot express the third, so anything you paste here loses Date objects — the ISO strings and epoch numbers still behave identically.