Typed Channels
Define message schemas per topic so event names and data shapes are validated at publish time. Catches typos and shape mismatches before they reach the wire - instead of silently sending garbage that the client ignores.
Setup
// src/lib/server/channels.js
import { createChannel } from 'svelte-adapter-uws/plugins/channels';
export const todos = createChannel('todos', {
created: (d) => ({ id: d.id, text: d.text, done: d.done }),
updated: (d) => ({ id: d.id, text: d.text, done: d.done }),
deleted: (d) => ({ id: d.id })
}); Each event maps to a validator function. The function receives the raw data and returns the validated (and optionally transformed) output. Throw to reject.
With Zod (or any library that exposes .parse()):
import { z } from 'zod';
import { createChannel } from 'svelte-adapter-uws/plugins/channels';
const Todo = z.object({ id: z.string(), text: z.string(), done: z.boolean() });
export const todos = createChannel('todos', {
created: Todo,
updated: Todo,
deleted: z.object({ id: z.string() })
}); Server API
| Method | Description |
|---|---|
channel.publish(platform, event, data) | Validate and broadcast to all subscribers |
channel.send(platform, ws, event, data) | Validate and send to a single connection |
channel.topic | The topic string |
channel.events | Array of valid event names |
Validators can strip private fields before publishing. If your validator returns { id, text } but the input had { id, text, secret }, only id and text reach clients.
Server example
import { todos } from '$lib/server/channels';
// In a form action or API route:
export async function POST({ request, platform }) {
const data = await request.json();
const todo = await db.save(data);
todos.publish(platform, 'created', todo); // validates, then publishes
todos.publish(platform, 'typo', todo); // throws: unknown event "typo"
todos.publish(platform, 'created', {}); // throws: validation failed (if validator rejects)
} Client API
The client wrapper is optional - it catches event name typos on the receiving side too.
<script>
import { channel } from 'svelte-adapter-uws/plugins/channels/client';
const todos = channel('todos', ['created', 'updated', 'deleted']);
const all = todos.on(); // all events (same as on('todos'))
const created = todos.on('created'); // filtered (same as on('todos', 'created'))
const typo = todos.on('craeted'); // throws Error immediately
</script> The events array is optional. Without it, .on() works exactly like the regular on() with the topic pre-filled - no validation, just convenience.
You can still use crud(), lookup(), latest(), etc. directly with the topic string. The client channel is purely additive.
Limitations
- Runtime only. The validation happens at publish/send time, not at compile time. TypeScript generics give you autocomplete for event names, but data shape checking is runtime.
- No dependency on Zod. The plugin accepts any validator function or any object with a
.parse()method. You bring your own validation library (or use plain functions).
Was this page helpful?