Query.live
Stream remote query values with Effect Streams.
Use Query.live when server data should stay connected while the UI is using it. It returns a live query resource on the client and accepts Effect Streams on the server.
When to use this
Use Query.live for changing values such as clocks, presence, notification counts, job progress, or event feeds. Use a normal Query when the user can refresh explicitly.
Minimal working example
import { Query } from "svelte-effect-runtime/server";
import { Schema, Stream } from "effect";
export const get_clock = Query.live(Schema.String, (_clock_id) =>
Stream.tick(1000).pipe(
Stream.map(() => new Date().toISOString()),
),
);<script lang="ts" effect>
import { get_clock } from "./clock.remote";
const clock = get_clock("main");
</script>
{#await yield* clock}
<p>Connecting...</p>
{:then time}
<p>{time}</p>
{/await}
<p>{clock.connected ? "Connected" : "Disconnected"}</p>
<button onclick={() => yield* clock.reconnect()}>Reconnect</button>Stream sources
Effect Streams are the idiomatic source:
import { Query } from "svelte-effect-runtime/server";
import { Stream } from "effect";
export const watch_jobs = Query.live(() =>
Stream.tick(1000).pipe(
Stream.map(() => ({ checked_at: Date.now() })),
),
);Native async iterables also work, which keeps SvelteKit examples easy to migrate:
import { Query } from "svelte-effect-runtime/server";
export const watch_counter = Query.live(async function* () {
let count = 0;
while (count < 3) {
yield count;
count += 1;
}
});Client shape
Query.live returns an Effect-backed live resource. yield* live_query waits for the current or first value. The same object also exposes live state:
const clock = get_clock("main");
clock.current;
clock.connected;
clock.done;
clock.loading;
clock.ready;
clock.error;Use clock.reconnect() from Effect-aware handlers. For lower-level consumers, the resource is async iterable:
for await (const value of clock) {
console.log(value);
}Common mistakes
- Using live queries for data that only changes after a user action.
- Forgetting that every active live query keeps server work alive.
- Returning a plain
PromisefromQuery.live. Return an Effect Stream, iterable, or async iterable. - Calling
reconnect()without yielding or running the returned Effect.