Skip to content

Migration from v1

v2 splits the single rapiq package into focused @rapiq/* packages and replaces string-building with a typed query AST. This page is a running log of the intentional changes; it is assembled into a full step-by-step guide as v2 stabilizes.

v1 docs

The v1 documentation lives on the v1 branch.

Package split

v1v2
rapiq (everything)@rapiq/core + the packages for your side of the wire (see Installation)

API mapping

v1v2
buildQuery(input) → stringdefineQuery(input)Query, then createURLCodec().encode(query)
parseQuery(input, options)createURLCodec(registry).decode(input, { schema }) for URL input; SimpleParser for canonical object input
per-call allow-list optionsa named Schema in a SchemaRegistry

Behavior changes

Filters: ~ prefix position (breaking)

In v1, ~text meant starts with (text%): the only LIKE form the dialect had. v2 uses a richer, position-based mapping:

Wire valuev1v2
text~(none)starts with (text%)
~textstarts with (text%)ends with (%text)
~text~(none)contains (%text%)

v1 clients sending ~text change meaning from starts-with to ends-with. Rewrite them to text~, or move to typed condition helpers / the expression dialect, which have no positional magic.

Filters: magic value strings are wire-only

v1 accepted '>=18', '~jo~', '!null' as build input. In v2, the string prefixes remain part of the wire format only; build input uses operator objects ({ $gte: 18 }, { $contains: 'jo' }, { $ne: null }) or condition helpers.

Expression dialect: quoted values are never comma-split

eq(name, 'a,b') now parses to the plain string 'a,b'. Lists are expressed as separate arguments (in(status, 'a', 'b')), not comma strings.

Codecs: loud failures instead of silent lossiness (breaking)

v1's URL build silently emitted whatever it was given. v2's encode throws typed errors (FEATURE_UNSUPPORTED, OPERATOR_UNSUPPORTED) for queries the wire dialect cannot represent. The default expression dialect carries nested compounds, or(...) and same-field conditions natively, so its typed failures are limited to operators without a grammar production (regex/mod/exists/elemMatch) and values that would decode to a different condition. Only the deprecated explicit simple encoding (URL_SIMPLE_CODEC) additionally rejects nested compounds, or(...) and same-field conditions. See What fits on the wire.

URL filters: expression output, legacy input

The v2 URL codec writes stamped expression filters by default. Its decoder still recognizes v1-style bracket filters, so deploy receiving applications before switching callers. Deprecated simple encoding remains available explicitly with URL_SIMPLE_CODEC during the v2 migration.

Filters: string equality is case-insensitive (breaking)

In v1, eq/in on strings delegated case behavior to the database: the same query matched Super Hero for super hero on MySQL (*_ci collation) but not on Postgres. v2 normalizes the whole equality family (eq, ne, in, nin) and the anchored operators (contains, startsWith, endsWith) to case-insensitive string matching on every backend; @rapiq/adapter-sql renders lower(field) = lower(?) on case-sensitive dialects. Opt identifier/token fields out with the schema's caseSensitive list.

Sorts: tuple-group allow-lists replaced by index declarations (breaking)

In v1 (and early v2 betas), sort.allowed accepted a nested list ([['name', 'age']]) matched all-or-nothing against the request. v2 removes the nested form: allowed is a flat list, and combination constraints come from the schema-level indexes declaration with sorts: { indexed: true }. The prefix semantics are strictly more permissive for the combinations you declare: an index ['name', 'age'] permits sorting by name alone or by name, age, where a tuple group demanded the exact pair.

Separately, the input key itself is renamed: v2 uses sorts (defineQuery, defineSchema, parse() input, Query.sorts), and the v1 spelling sort is still accepted but deprecated for removal in 3.0. The URL wire parameter is unaffected, still sort. See Sorts.

Coming from typeorm-extension?

The server-pipeline differences (strict mode, join defaults, applyQuery) have their own page.

Released under the MIT License.