RPC - live()
Wrap a server function with live(). Import it in a component. Call it like a regular async function. It runs on the server over WebSocket.
Basic usage
// src/live/todos.js
import { live } from 'svelte-realtime/server';
export const addTodo = live(async (ctx, text) => {
const todo = await db.todos.insert({ text, userId: ctx.user.id });
ctx.publish('todos', 'created', todo);
return todo;
}); <script>
import { addTodo } from '$live/todos';
async function add() {
const todo = await addTodo('Buy milk');
}
</script> The ctx object
Every live() function receives ctx as its first argument. See The ctx Object for the full reference.
export const greet = live((ctx) => {
return `Hello, ${ctx.user.name}`;
}); Multiple arguments
Arguments after ctx are passed from the client:
export const move = live(async (ctx, x, y) => {
ctx.publish('positions', 'update', { key: ctx.user.id, x, y });
}); <script>
import { move } from '$live/game';
await move(100, 200);
</script> Error handling
Throw LiveError on the server. Catch RpcError on the client.
// Server
import { live, LiveError } from 'svelte-realtime/server';
export const deleteItem = live(async (ctx, id) => {
if (!ctx.user) throw new LiveError('UNAUTHORIZED', 'Login required');
await db.items.delete(id);
}); <!-- Client -->
<script>
import { deleteItem } from '$live/items';
try {
await deleteItem(itemId);
} catch (err) {
console.log(err.code); // 'UNAUTHORIZED'
console.log(err.message); // 'Login required'
}
</script> Schema validation
Use live.validated() with Zod or Valibot schemas:
import { z } from 'zod';
import { live } from 'svelte-realtime/server';
const CreateTodo = z.object({
text: z.string().min(1).max(200),
priority: z.enum(['low', 'medium', 'high']).optional()
});
export const addTodo = live.validated(CreateTodo, async (ctx, input) => {
const todo = await db.todos.insert({ ...input, userId: ctx.user.id });
ctx.publish('todos', 'created', todo);
return todo;
}); Validation errors throw RpcError with code: 'VALIDATION' and an issues array.
Request deduplication
Identical calls in the same microtask are coalesced:
const [a, b] = await Promise.all([
getUser(userId),
getUser(userId) // reuses the first request
]); Force a fresh request with .fresh():
const result = await getUser.fresh(userId); Batching
Group multiple calls into a single WebSocket frame:
<script>
import { batch } from 'svelte-realtime/client';
import { createBoard, addColumn } from '$live/boards';
const [board, column] = await batch(() => [
createBoard('My Board'),
addColumn('To Do')
]);
</script> Pass { sequential: true } when order matters. Each call resolves independently - one failure doesn’t cancel the others. Max 50 calls per batch.
Under the hood, RPC calls are routed over the adapter’s WebSocket connection. See svelte-adapter-uws for the transport layer.
Was this page helpful?