querypipe
API reference

createQuery & field constructors

Declaring the schema — fields, stableBy, guards, and the six field constructors.

createQuery

import {
  booleanField,
  createQuery,
  customField,
  dateField,
  enumField,
  numberField,
  stringField,
} from "querypipe";

const q = createQuery({
  fields: {
    id: numberField(),
    name: stringField(),
  },
  stableBy: "id",
  guards: { maxSortColumns: 3, maxFilters: 10, maxValueLength: 256, maxInItems: 100 },
});
OptionMeaning
fieldsThe whitelist. Keys must match [A-Za-z_][A-Za-z0-9_]*; . is reserved for future nested paths.
stableByA unique, sortable field injected as the final sort column during apply / adapter output — never into the spec.
guardsLimits applied at parse/validate time. See Guards & safety for defaults.

Structural misuse of the definition — bad identifiers, duplicate wire names (aliases), an unknown or unsortable stableBy — throws TypeError at createQuery time. Data-path errors never throw.

Field constructors

All six share the base options { sortable?, filterable?, alias? }. Passing { sortable: false } narrows the type (the field disappears from sort()'s allowed names) and the runtime check together.

const catalog = createQuery({
  fields: {
    id: numberField(),
    title: stringField({ alias: "t" }),               // wire name "t" in canonical strings
    name: stringField({ locale: "de", sensitivity: "base" }), // opt-in collator ordering
    price: numberField(),
    inStock: booleanField(),
    createdAt: dateField(),
    tier: enumField(["bronze", "silver", "gold"]),    // value type: "bronze" | "silver" | "gold"
    version: customField<{ major: number; minor: number }>({
      comparator: (a, b) => a.major - b.major || a.minor - b.minor,
    }),
  },
  stableBy: "id",
});
ConstructorValue typeNotes
numberField()numberStrict tokens on the wire: no exponent, no NaN/Infinity.
stringField()stringDefault order is UTF-16 code units; locale/sensitivity opt into Intl.Collator.
dateField()Date | string | number in, ISO string in the specYYYY-MM-DD or ISO datetime with mandatory Z/offset.
booleanField()booleanWire tokens: lowercase true / false only.
enumField(values)union of valuesComparison order = declaration order. Case-sensitive on the wire.
customField<T>({ comparator })TSort basis you define; null-checks-only for filtering in v0.1 (values aren't wire-portable).

Aliases

alias renames a field in the canonical string format only — JSON wire specs always carry internal names. Duplicate wire names throw TypeError at schema construction.

Standard Schema hook

Every constructor (except the comparator requirement on customField) accepts an optional schema implementing the dependency-free Standard Schema interface — Zod, Valibot and ArkType plug in with no coupling and no added runtime dependency:

import { z } from "zod";
import { createQuery, stringField } from "querypipe";

const users = createQuery({
  fields: { id: numberField(), email: stringField({ schema: z.string().email() }) },
  stableBy: "id",
});

Failing hook results surface as INVALID_VALUE on the data path (sync validators only in v0.1; async is on the roadmap). Fragment operators (contains/startsWith/endsWith) bypass value-domain hooks by design — fragments aren't domain values.

On this page