sveltelean Query
Version v0.2.0

Import

import
import { live, rule } from '@svelte-lean/query/live';

Usage

src/lib/api/live.ts
// src/lib/api/live.ts
import { patch, tag, type } from '@svelte-lean/query';
import { live, rule, type LiveSource } from '@svelte-lean/query/live';
import { getMember } from '$api/members';
import type { Member } from '$api/types';

// An adapter: one EventSource per channel.
const source: LiveSource = {
	subscribe({ channel, event }, deliver, ready) {
		const events = new EventSource(`/events/${channel}`);
		events.addEventListener('open', ready, { once: true });
		events.addEventListener(event, (e) => deliver(JSON.parse((e as MessageEvent).data)));
		return () => events.close();
	}
};

export const realtime = live(source, [
	// Poke, then pull: the observed member lists refetch, coalesced.
	rule('Members', { channel: 'members', event: 'MemberCreated' }),
	// The event carries the row: every cached copy of it is patched, nothing is refetched.
	rule('Members', {
		channel: 'members',
		event: 'MemberUpdated',
		message: type<{ member: Member }>(),
		patch: (m) => patch(tag('Member', m.member.id), () => m.member)
	}),
	// Patch the one detail entry the message names.
	rule(getMember, {
		channel: 'members',
		event: 'MemberPinned',
		message: type<{ id: number; pinned: boolean }>(),
		patch: (m) => patch([getMember, { id: m.id }], (member) => ({ ...member, pinned: m.pinned }))
	})
]);

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)
live (marginal)query2777 B2565 B3100 B

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

Functions

The module and its rules.

Exports

Runtime exports of the entry.

NameTypeDefaultDescription
# live (source: LiveSource, rules: LiveRule[], options?: LiveOptions) => Module–The realtime module; channels are reference-counted and reseeded on reconnect. Inert on the server.
# rule (target: TagTarget, init: LiveRuleInit) => LiveRule–A rule on a tag: every event invalidates it (poke, then pull), or patches the entity it carries.
# rule (endpoint) (target: QueryEndpoint | [QueryEndpoint, Partial<P>], init: LiveRuleInit & { match? }) => LiveRule–A rule on an endpoint: match narrows its default invalidation to the entries a message concerns.

Options

The module options and the rule options.

LiveOptions

The third argument of live().

NameTypeDefaultDescription
# window Duration'100ms'Coalescing window per burst.
# maxWindow Duration'2s'Adaptive ceiling of the window under sustained bursts.
# linger Duration'1.5s'Keep a channel after its last observer left.

LiveRuleInit

The second argument of rule(). match applies to endpoint targets only.

NameTypeDefaultDescription
# channel requiredstring | ((params) => string)–A channel name, or one per entry from its params.
# event requiredstring–The event name.
# message StandardSchemaV1<unknown, M>–Validates each payload; type<M>() for no validation. A failure drops the event.
# access Access<P>–The rule's own access; endpoint targets also need the endpoint's verdict.
# when boolean | (() => boolean)–Reactive gate (session, settings).
# invalidate InvalidateTarget[] | ((message) => InvalidateTarget[])–What an event invalidates; default the rule's target (narrowed by match) without patch, nothing with it.
# patch (message: M, at: { channel, event }) => void–Applies the event to cached values: call patch() here (the entity it carries, or the entry it concerns). Local writes, also applied when another tab forwards the event.
# reseed booleantrueInvalidate on a confirmed subscription and on reconnect.
# reason Reason–Reason carried by the refetches this rule starts.
# name string'channel:event'Source label of those refetches.
# match (message: M) => Partial<P> | undefined–The params of the entries a message concerns; the default invalidation reaches only those.

Source

Where events come from: a Pusher or Reverb client, an EventSource, a test double (fakeSource() in ./testing).

LiveSource

The contract an adapter implements.

NameTypeDefaultDescription
# subscribe required(at: { channel, event }, deliver, ready) => () => void–Start delivering an event; call ready once the server confirmed; return the stop function.
# watch (listener: (connected: boolean) => void) => () => void–Optional connection state; true after false after true is a reconnect.

Guide

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