sveltelean Query
Version v0.2.0

Import

import
import { defineQuery, defineMutation, createQuery, createMutation, createClient, tag, type, page } from '@svelte-lean/query';

Size

Production Vite builds of a small consumer entry, Svelte external. A marginal row is the bytes the entry adds over the row it names.

BuildOvergzipbrotliBudget (gzip)
query–11787 B10839 B11800 B
query+mutation–15409 B14167 B15500 B
root (every export)–16134 B14844 B16200 B

Read from packages/query/artifacts/size.json. Every entry and its method: Performance.

Definitions

Endpoints are values made once in a feature module. Builders are free of side effects, so an endpoint nobody imports is removed from the bundle.

Functions

Builders of endpoints, schemas, tags and access rules.

NameTypeDefaultDescription
# defineQuery (init: QueryInit) => QueryEndpoint<P, R>–A read endpoint: method and path, params, result, tags and policies. Path params are inferred from `{name}` segments.
# defineMutation (init: MutationInit) => MutationEndpoint<I, R, B>–A write endpoint: method and path, body, result, the tags it invalidates and its access rule.
# type <T>() => StandardSchemaV1<T, T>–A type-only schema: the value is typed as T and not validated.
# page <T>(row?: StandardSchemaV1<unknown, T>) => StandardSchemaV1<unknown, Page<T>>–A paged result read through the profile's paginator; with a row schema, each row is validated.
# file () => StandardSchemaV1<FileResult, FileResult>–A file result: the body is read as a Blob with its file name (downloads).
# tag <K extends TagName>(name: K, ...id: TagIdArgs<K>) => Tag–A typed tag value. The id is required, optional or absent as the Tags registry declares it.
# all (...checks: Check<P>[]) => Rule<P>–An access rule that holds when every check holds.
# any (...checks: Check<P>[]) => Rule<P>–An access rule that holds when one of the checks holds.
# not (check: Check<P>) => Rule<P>–The negation of an access check.

defineQuery options

The object passed to defineQuery(). Exactly one of get and post.

NameTypeDefaultDescription
# get string–Path of a GET read, with `{name}` params (`api/members/{id}`); `{+name}` is sent unencoded (an address the server handed over, a full URL).
# post string–Path of a read sent as POST; its params become the JSON body and stay part of the key.
# params StandardSchemaV1<unknown, Q>–Search params (GET) or body (POST reads); path params come from the path.
# result requiredStandardSchemaV1<unknown, R>–The result schema: type<T>(), page<T>(), file() or any Standard Schema.
# id stringMETHOD pathUnique endpoint id; needed when one URL is read two ways.
# map (raw, helpers: { page, params }) => unknown–Reshape the unwrapped server value once per commit (params: the params the entry was asked with); replaces page normalization when given.
true | (keyof P)[]–Params sent in the query string whatever the method: all of them (a POST read with no body) or these keys.
# priority 'high' | 'low'by causeIts automatic fetches as foreground or background work: 'low' queues behind the reads a page waits for and never takes the last slot.
# pageParams (page, perPage) => objectthe profile'sThe page params createPaged and createInfinite add, instead of the profile's: rename them or leave them out.
# entity TagName–Rows (or the value) are entities of this tag: each carries tag(entity, rowId(row)).
# tags TagTarget[] | ((result, params) => TagTarget[])–Tags the entry provides; invalidating one of them refetches or marks the entry.
# fresh Durationclient default (0)How long a value counts as fresh.
# keep Duration'5m'How long an unobserved entry stays cached.
# access Access<P>–Who may read it: a permission, a function, a rule or an array of them (all). false sends nothing and removes cached data; undefined waits.
# scope false–Leave the client scope out of the key (public endpoints only).
# retry number | falseclient default (2); 0 on the serverAttempts after the first for network, timeout, 408, 429 and 5xx failures.
# poll Duration | ((value) => Duration | false) | PollInit<R>–Definition-level polling; PollInit adds until, invalidates, background and reason (jobs).
# persist boolean | { maxAge?: Duration }–Opt in to ./persist for this endpoint.
# share false–Opt out of row identity reuse on refetch.
# rowId (row) => string | numberthe profile's (id)Row identity for reuse, entities and patches.
# orphan 'abort' | 'finish''abort'What happens to a request whose last observer left.
# maxEntries number20 for page() resultsCap on inactive entries of this endpoint.
# transport TransportOverrides–Per-endpoint transport options.

defineMutation options

The object passed to defineMutation(). Exactly one method key.

NameTypeDefaultDescription
# post string–Path of a POST write, with `{name}` params.
# put string–Path of a PUT write.
# patch string–Path of a PATCH write.
# delete string–Path of a DELETE write.
# get string–Path of a GET that changes server state (rare).
# id stringMETHOD pathUnique endpoint id.
# body StandardSchemaV1<unknown, B>–The body schema; the input is body plus path params.
# result StandardSchemaV1<unknown, R>voidThe result schema.
# map (raw, helpers: { input }) => unknown–Reshape the unwrapped server value; input is the run's input.
true | (keyof B)[]–Input fields sent in the query string: all of them (no body) or these keys; path params stay in the path.
# invalidates TagTarget[] | ((result, input) => TagTarget[])–Tags invalidated after success: observed entries refetch once, the others are marked stale.
# access Access<I>–Who may run it; a run without access sends nothing.
# queue (input) => string–Serialize runs that share a key (one write per entity at a time, in order).
# encode 'json' | 'multipart' | 'auto' | ((input) => 'json' | 'multipart')'auto'Body encoding; auto sends multipart when the body holds a File or Blob and no body when only path params remain; json and multipart always send one ({} or an empty form). A FormData input is sent as it is.
# retry number | falsefalseRetries for this write.
# transport TransportOverrides–Per-endpoint transport options.

Query endpoint

The value defineQuery() returns. Its methods act on the active client unless options.client is given.

NameTypeDefaultDescription
# kind 'query'–Discriminant.
# id string–The endpoint id; a segment of every cache key.
# fetch (params, options?: FetchOptions) => Promise<R>–A fresh cached value, else one request (cause user); rejects with QueryError.
# prefetch (params, options?: { client? }) => void–A low-priority fetch; errors are stored on the entry, never thrown.
# get (params) => R | undefined–Synchronous read of the cached value, optimistic layers applied.
# set (params, data: R | ((previous) => R)) => void–A permanent local write; replayed over an older response in flight.
# invalidate (params?: Partial<P>, call?: FetchCall) => void–Mark matching entries stale; observed ones refetch.
# allowed (params?) => Verdict–The access verdict for these params, without fetching.

Mutation endpoint

The value defineMutation() returns.

NameTypeDefaultDescription
# kind 'mutation'–Discriminant.
# id string–The endpoint id.
# run (input, options?: RunOptions) => Promise<R>–An imperative run on the active client: the createMutation pipeline without reactive state.

Client

One client per application in the browser, one per request on the server. It owns the cache, the scheduler, the modules and the engine parts.

Functions

Creating the client and reaching it.

NameTypeDefaultDescription
# createClient (init: ClientInit) => Client–Creates a client. In the browser the first client becomes the realm client.
# setClient (client: Client) => void–Sets the client for this component subtree (context) and, in the browser, as the realm client, which code after an await reaches. Outside a component (a test's beforeEach) it only sets the realm client; disposing it hands the realm back.
# getClient () => Client–The active client: the context client during component initialisation, else the realm client.
# invalidate (targets: InvalidateTarget | InvalidateTarget[], call?: FetchCall) => void–Refetch: tags, endpoints or [endpoint, partial params]; observed entries refetch, the others are marked stale.
# patch (target: Tag | QueryEndpoint | [QueryEndpoint, params] | TagName, update, options?: PatchOptions) => void–Change cached values now. On an entity tag, every cached row or detail carrying it; update returns the new value, undefined (no change) or null (removed). Inside optimistic, a layer undone if the run fails.
# send <R>(request: SendRequest, client?: Client) => Promise<R>–Escape hatch: one request through the transport, no cache, no tags.
# defineModule <M extends Module>(module: M) => M–Makes a module for createClient({ modules }); it brings the hook set, so a client without modules carries none of it.

createClient options

ClientInit, the object passed to createClient().

NameTypeDefaultDescription
# transport requiredTransport–The function that performs requests, usually http().
# scope () => Scope–Reactive. Its canonical string prefixes every key (operator, tenant, region).
# onScopeChange 'drop' | 'keep' | ((from, to) => 'drop' | 'keep')'drop'What happens to entries of the previous scope.
# can (permission: Permission) => Verdict–Resolves permission strings in access rules; undefined means not known yet.
# access (endpoint, input) => Verdict–A rule for every endpoint, combined with each endpoint's access.
# defaults { fresh?, keep?, retry?, slowAfter?, loadingDelay?, focus? }fresh 0, keep '5m', retry 2, slowAfter '8s', loadingDelay 0, focus trueClient-wide defaults.
# presets { [name in PresetName]?: Duration }–Named durations (the Presets registry) usable wherever a Duration is.
# limits { concurrency?: number | 'auto', inactiveBytes?, inactiveEntries? }6, 32 MiB, 2000Requests per origin (auto: 24 once an answer reports HTTP/2 or HTTP/3, which a cross-origin API shows only with Timing-Allow-Origin) and the memory budget of unobserved entries.
# modules Module[]–Optional behavior set up with the client (live, persist, devtools), made with defineModule().
# parts EnginePart[]none: each loads on first useEngine parts from ./parts included up front (allParts for a large app); parts not listed load on first use.
# clock Clock–Time source and timers; the test client passes a virtual one.
# environment Environment–Visibility and lifecycle events; the browser one by default.

Client

Properties and methods of the value createClient() returns.

NameTypeDefaultDescription
# scopeKey string–The current canonical scope string.
# online boolean–Reactive; false while requests fail with network.
# invalidate (targets, call?: FetchCall) => void–Invalidate tags, endpoints or [endpoint, params], coalesced per microtask.
# cancel (filter?: { cause? }) => void–Abort requests in flight, all or those of one cause.
# clear () => void–Abort everything and drop every entry and optimistic layer (sign-out).
# dispose () => void–Stop timers and listeners and abort everything (end of a server request, tests).
# stats () => ClientStats–Counters of the cache, the queue and the totals.
# recheck () => void–Re-evaluate access rules, for a can() that reads non-reactive state.

ClientStats

What client.stats() returns.

NameTypeDefaultDescription
# entries number–Cached entries.
# observed number–Entries read by a binding.
# inactiveBytes number–Approximate size of unobserved entries.
# fetching number–Requests in flight.
# queued number–Requests waiting for a connection.
# mutating number–Mutation runs not settled.
# optimistic number–Active optimistic layers.
# timers number–Items in the scheduler (one platform timer serves them).
# totals { requests, joins, aborts, retries, invalidations, evictions }–Counters since the client was created.

Bindings

Reactive results for components and classes. Call them during initialisation; every field is its own signal, written only when its value changes.

Functions

createQuery and createMutation.

NameTypeDefaultDescription
# createQuery (endpoint, params?: () => P | undefined | null, options?: QueryOptions) => QueryResult<R, P>–A query read where it is used: nothing is requested until a field is read in a reactive context. undefined (or null) from params means not ready: no key, no request.
# createQuery (without params) (endpoint, options: QueryOptions) => QueryResult<R, P>–For an endpoint without params, or with when: false and load(params) for a binding started by hand.
# createMutation (endpoint, options?: MutationOptions) => MutationResult<I, R, B>–A write with run(), busy, data and typed field errors.

createQuery options

QueryOptions, the last argument of createQuery().

NameTypeDefaultDescription
# when boolean | (() => boolean)trueA state condition at the call site (dialog open, tab active); false pauses automatic fetching and keeps data. load() still starts it.
# keepPrevious booleanfalseShow the previous key's data while a new key loads.
# placeholder R | (() => R | undefined)–Shown while pending, never cached.
# poll PollOption | (() => PollOption)–Runtime polling control; the shortest active interval wins.
# fresh Duration–Per-use freshness; the shortest of the active uses wins.
# priority 'high' | 'low'the endpoint'sThis use's automatic fetches as foreground or background work.

QueryState

The everyday fields of every query-shaped result (createQuery, createPaged). Each is its own signal.

NameTypeDefaultDescription
# data R | undefined–The server value with optimistic layers applied.
# error QueryError | undefined–The last error; data is kept (except forbidden).
# loading boolean–A fetch the user waits for: cause user, or nothing of this key is shown yet.
# refreshing boolean–A quiet fetch while data is shown: poll, focus, invalidation, live.
# busy boolean–loading or refreshing.
# blocked Blocked | undefined–Why nothing is fetched: 'access', 'waiting' or 'when' (when is false, or the params are not ready).
# info QueryInfo–The less frequent fields: status, placeholder, stale, slow, updatedAt, fetch.
# refetch (call?: FetchCall) => Promise<void>–Refetch the current key now (cause user); sends nothing while blocked.

QueryResult

What createQuery() returns: QueryState and load().

NameTypeDefaultDescription
# load (params?: P, call?: FetchCall) => Promise<R>–Start the binding by hand (cause user, always a request), also while when is false. With params, the binding shows those from now on.

QueryInfo

result.info: the less frequent fields, each its own signal.

NameTypeDefaultDescription
# status 'idle' | 'pending' | 'success' | 'error'–pending means there is no data yet.
# placeholder boolean–data belongs to the previous key or to placeholder.
# stale boolean–The value is older than fresh.
# slow boolean–The current fetch exceeded slowAfter.
# updatedAt number–Time of the last success; 0 before it.
# fetch FetchInfo | undefined–The running fetch, else the last one: cause, reason, source, start, attempt.

createMutation options

MutationOptions, the second argument of createMutation().

NameTypeDefaultDescription
# optimistic (input) => void–Called when run() starts; every patch() it makes is a layer shown until the server confirms, removed if the run fails.
# settle 'response' | 'refetched''response'When run() resolves: on the answer, or after the invalidated observed entries refetched (busy and onSuccess wait too).
# exclusive booleantrueA second run() while one is busy returns its promise (the double-submit guard), whatever the body; false runs them side by side.
# onSuccess (result, input) => void–A reaction bound to the run that triggered it (close a dialog, show a message); patch() and invalidate() in it act on the mutation's client.

MutationResult

What createMutation() returns.

NameTypeDefaultDescription
# run (input: I, options?: RunOptions) => Promise<R>–Send the write; also writes status, data and error, so markup needs no try/catch.
# status 'idle' | 'queued' | 'running' | 'success' | 'error'–queued means waiting behind a run with the same queue key.
# busy boolean–queued or running: disable the button on this.
# data R | undefined–The result of the last successful run.
# error QueryError<B> | undefined–The last error, with field errors typed by the body.
# slow boolean–The run exceeded slowAfter.
# progress { loaded, total } | undefined–Upload progress of a run with transport.progress.
# allowed (input?: I) => boolean–Access: without input for a button, with input for one row.
# reset () => void–Back to idle; clears data and error.

run options

RunOptions, the second argument of run().

NameTypeDefaultDescription
# optimistic (input) => void–Patches of this run, after the mutation's own optimistic.
# signal AbortSignal–Cancel an upload or a long write.
# progress (loaded, total) => void–Upload progress callback for an imperative endpoint.run().
# reason Reason–Carried by the refetches this run's invalidates start.
# loading boolean–Show those refetches as loading (true) or refreshing (false).
# priority 'high' | 'low'–Run those refetches as foreground or background work.

Errors

Errors are values. The package never shows one; kind, status and code give the application what it needs to word it.

QueryError

The error every failed request and run reports. Custom profiles and transports throw it.

NameTypeDefaultDescription
# QueryError class QueryError<B> extends Error–new QueryError(init: QueryErrorInit); the fields below.

QueryError fields

Only network, timeout and HTTP 408, 429 and 5xx failures are retried.

NameTypeDefaultDescription
# kind ErrorKind–'network', 'timeout', 'http', 'refused', 'validation', 'forbidden' or 'parse'.
# status number–0 for network and timeout; 200 for a refusal inside a 2xx.
# code string | number | undefined–The server code.
# message string–The server's text when present, else an empty string.
# fields FieldErrors<B> | undefined–Field errors of a 422 or a refusal with a field map.
# issues Issue[] | undefined–Schema failures (kind parse).
# details unknown–Anything else the server sent.
# requestId string | undefined–The request id, when the server sends one.
# retryAfter number | undefined–Milliseconds, from Retry-After.
# method string–The request method.
# url string–The request URL.

QueryErrorInit

The constructor argument, for custom transports and profiles.

NameTypeDefaultDescription
# kind requiredErrorKind–The error kind.
# status number0HTTP status.
# code string | number–Server code.
# message string–Server text.
# fields { [path]: string | string[] }–Raw field map ('lines.0.sku'); strings are wrapped in arrays.
# issues Issue[]–Schema issues.
# details unknown–Anything else.
# requestId string–Request id.
# retryAfter number–Milliseconds.
# method string–Request method.
# url string–Request URL.
# cause unknown–The underlying error.

FieldErrors

error.fields: field messages typed by the request body.

NameTypeDefaultDescription
# fields { [K in keyof B]?: string[] }–Top-level keys: exactly the body's fields.
# at (k1, index?, k2?) => string[] | undefined–Nested keys ('lines.0.sku'), typed step by step.
# raw { [path]: string[] }–Every server key, also ones the body type does not know.

Registries

Interfaces an application augments with declare module '@svelte-lean/query'. An empty registry accepts any string.

Registry interfaces

Augment them once per feature module.

NameTypeDefaultDescription
# Tags interface Tags { Name: IdType }–Tag name to id type; void for a tag without id. A typo in a tag is a compile error.
# Permissions interface Permissions { 'slug': true }–Permission strings accepted by access rules and can().
# Presets interface Presets { name: true }–Duration preset names; values live in createClient({ presets }).
# Reasons interface Reasons { name: true }–Application fetch reasons.
# TransportOverrides interface TransportOverrides–Per-endpoint transport options; applications may add fields.

TransportOverrides

The transport option of a definition.

NameTypeDefaultDescription
# headers HeadersInit–Extra headers for this endpoint.
# envelope 'unwrap' | 'keep' | 'raw'–How the profile treats the platform's envelope.
# accept (envelope: Envelope) => boolean–Accept a success: false envelope as a success (info codes).
# responseType 'json' | 'text' | 'blob''json'How the body is read.
# progress boolean–Upload progress (sent over XHR).
# multipart FormDataOptions–Multipart encoding options.
# timeout Duration–Timeout per attempt.
# methodSpoof booleanthe profile'strue sends this endpoint's PUT, PATCH and DELETE as POST with _method, JSON bodies too; false never.

Types

The other public types, for annotations and custom transports.

Values and unions

Type names exported by the root entry.

NameTypeDefaultDescription
# Duration number | `${number}${'ms' | 's' | 'm' | 'h'}` | 'never' | PresetName–Milliseconds, a string with a unit, never, or a preset name.
# Cause 'mount' | 'params' | 'user' | 'poll' | 'focus' | 'reconnect' | 'invalidate' | 'live' | 'prefetch' | 'retry'–Why a request ran; decides priority and whether it shows loading.
# Blocked 'access' | 'waiting' | 'when'–Why a binding fetches nothing.
# Verdict boolean | undefined–An access verdict; undefined means not known yet (wait, keep data).
# Access Check<P> | Check<P>[]–A permission, a function, a rule, or an array meaning all of them.
# Scope (string | number | null)[]–The client scope.
# Tag opaque–A tag value made by tag().
# TagTarget Tag | TagName–A tag, or a bare name meaning every id.
# InvalidateTarget TagTarget | QueryEndpoint | [QueryEndpoint, object]–What invalidate() accepts.
# PollOption Duration | false | { on, every, background?, reason? }–The poll option of a binding, or what its function returns.
# EnginePart opaque–An optional engine part from ./parts.
# ErrorKind 'network' | 'timeout' | 'http' | 'refused' | 'validation' | 'forbidden' | 'parse'–The kinds of QueryError.
# QueryPolicy, MutationPolicy interface–The options a separate policy module may set (codegen).

Page

The value of a page() result.

NameTypeDefaultDescription
# rows T[]–The rows of this page.
# total number–Rows on every page.
# page number–Page number, 1-based.
# perPage number–Page size.
# lastPage number–The last page number.
# estimated true–Read from a bare list: lastPage and total are derived.

PatchOptions

The third argument of patch().

NameTypeDefaultDescription
# until (value: T) => boolean–Inside optimistic only: after the run succeeded, the layer stays until the server value satisfies until.

FetchInfo

One request as a binding reports it (info.fetch).

NameTypeDefaultDescription
# cause Cause–Engine category.
# reason Reason | undefined–Application label.
# source string | undefined–What triggered it: a mutation id, a live rule, a tag.
# loading boolean | undefined–The call's hint: true shows it as loading, false as refreshing.
# startedAt number–Start time.
# attempt number–1, then retries.

FetchCall

Options of every call that starts fetches: refetch, load, invalidate, ep.fetch, ep.invalidate and run.

NameTypeDefaultDescription
# reason Reason–Application label carried by the fetches (info.fetch.reason).
# loading boolean–Show the fetch as loading (true) or refreshing (false) instead of the cause's default.
# priority 'high' | 'low'–Run the fetches this call starts as foreground or background work.

FetchOptions

Options of endpoint.fetch().

NameTypeDefaultDescription
# from 'cache' | 'network''cache'cache returns fresh cached data or fetches; network always fetches.
# reason Reason–Application label.
# loading boolean–Show the fetch as loading or refreshing.
# priority 'high' | 'low'–Foreground or background work.
# signal AbortSignal–Abort the wait.
# client Client–The client to use (a SvelteKit load on the server).

TransportRequest

What a transport receives. Write one to answer from anything other than HTTP.

NameTypeDefaultDescription
# endpoint QueryEndpoint | MutationEndpoint | undefined–The endpoint; undefined for send().
# method 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'–HTTP method.
# path string–Path with params substituted and URL-encoded ({+name}: unencoded).
object | undefined–Search params.
# body unknown–The body.
# scope Scope–The scope captured with the key.
# signal AbortSignal–Aborted when nobody waits for the answer.
# priority 'high' | 'auto' | 'low'–Fetch priority from the cause.
# cause Cause | 'mutation'–Why it was sent.
# progress (loaded, total) => void–Upload progress callback.
# overrides TransportOverrides–The endpoint's transport options.

TransportResponse

What a transport resolves with.

NameTypeDefaultDescription
# data unknown–The unwrapped value.
# bytes number–Approximate size; 0 when unknown.
# text string–Raw text, when the body was text.
# meta ResponseMeta–Request id, code, invalidation hints, refreshed values.
# protocol string–The answer's protocol (h2, h3, http/1.1) when known.

Profile

A platform's conventions, passed to http({ profile }). laravel() is one.

NameTypeDefaultDescription
(params) => string–Params to a query string.
# body (request) => { body, headers?, method? }–Encode a write body.
# read (response, parsed, request) => unknown–Unwrap the envelope or throw a QueryError.
# meta (response, parsed, request) => ResponseMeta | undefined–Request id, info code, freshness hints.
# page (value) => Page–Read a paginator into a Page.
# pageParams (page, perPage) => object–Page params sent by createPaged and createInfinite.
# rowId (row) => string | number | undefined–Default row identity.
# respond (value, init?) => Response–Inverse of read, for mocks and MSW handlers.

Module

An opt-in entry point attached to the client through modules; made with defineModule().

NameTypeDefaultDescription
# name string–Module name.
# setup (client, hooks: ModuleHooks) => void | (() => void)–Called once with the client; returns its teardown.

ModuleHooks

The hook set a module receives. Every act goes through the core pipeline.

NameTypeDefaultDescription
# onEntry (listener) => off–An entry was created.
# onObserved (listener) => off–An entry gained its first or lost its last observer.
# onRequest (listener) => off–A request was sent, with its cause.
# onCommit (listener) => off–A response's value or a final error was written.
# onRemove (listener) => off–An entry was removed, with the reason.
# onInvalidate (listener) => off–Targets were invalidated, locally or from another tab.
# onMutation (listener) => off–A mutation started or settled.
# onLifecycle (listener) => off–Visibility, network and page lifecycle events.
# entries (target) => Iterable<EntryHandle>–The entries a target matches.
# write (entry, update, source) => void–A local write through the pipeline.
# hydrate (entry, record) => boolean–Commit an outside value only when it is newer.
# invalidate (targets, cause, source?) => void–Invalidate with a cause.
# schedule (at, run) => cancel–The shared scheduler.
# lead (role, run) => release–Run while this tab leads the role.
# provideLead (impl: LeadProvider) => void–Install a browser-wide election (./tabs).
# dev (listener) => off–Development diagnostic events; absent in production.

Guide

How to use it, with examples: Defining endpoints. All entry points: Svelte Lean Query.