WebSocket wrapper for Svelte 5 using runes.
This library provides:
connectionStatus, sentMessages, receivedMessages)SvelteSocket and makes it available to child componentsonMessage, onOpen, onClose, onError)debug flag$state runesnpm install svelte-socket
<script>
import { SvelteSocket } from 'svelte-socket';
// Callbacks can be added on construction...
const socket = new SvelteSocket({
url: 'ws://localhost:8080',
onOpen: () => console.log('Hello, server!')
});
const isConnected = $derived(socket.connectionStatus === WebSocket.OPEN);
// ...or later using addEventListener
socket.addEventListener('message', (event) => {
console.log(event.data);
});
socket.sendMessage('text');
</script>
<SocketProvider {svelteSocket}>
{@render children()}
</SocketProvider>
<script>
import { useSocket } from 'svelte-socket';
let { children } = $props();
const socket = useSocket()
let isConnected = $derived(socket.connectionStatus === WebSocket.OPEN);
let receivedMessages = $derived(socket.receivedMessages)
</script>
<p>{isConnected}</p>
{#each receivedMessages as msg, i}
<p>{msg.origin}<p>
{/each}
SvelteSocketnew SvelteSocket(options: SocketConstructorArgs)
Options:
| Property | Type | Required | Description |
|---|---|---|---|
url |
string |
Yes | WebSocket server URL |
onMessage |
(event: MessageEvent) => void |
No | Called when message received |
onOpen |
(event: Event) => void |
No | Called when connection opens |
onClose |
(event: CloseEvent) => void |
No | Called when connection closes |
onError |
(event: Event) => void |
No | Called on error |
debug |
boolean |
No | Enable console logging (default: false) |
reconnectOptions |
ReconnectOptions |
No | Auto-reconnection config |
maxMessageHistory |
number |
No | Max messages to keep in history (default: 50). Set to 0 for unlimited |
ReconnectOptions:
| Property | Type | Description |
|---|---|---|
enabled |
boolean |
Enable auto-reconnection |
delay |
number |
Milliseconds before reconnect attempt |
maxAttempts |
number |
Maximum reconnection attempts |
Example:
const socket = new SvelteSocket({
url: 'ws://localhost:8080',
debug: true,
maxMessageHistory: 100, // Keep last 100 messages (default: 50)
reconnectOptions: {
enabled: true,
delay: 1000,
maxAttempts: 5
},
onMessage: (event) => console.log(event.data),
onOpen: () => console.log('connected'),
onClose: () => console.log('disconnected')
});
| Property | Type | Description |
|---|---|---|
connectionStatus |
WebSocket['readyState'] |
Connection state: 0 (CONNECTING), 1 (OPEN), 2 (CLOSING), 3 (CLOSED) |
sentMessages |
Array<{message: string | ArrayBuffer | Blob | ArrayBufferView, timestamp: number}> |
Sent message history (newest first, via unshift). Auto-trimmed to maxMessageHistory |
receivedMessages |
Array<{message: MessageEvent}> |
Received message history (newest first, via unshift). Auto-trimmed to maxMessageHistory |
maxMessageHistory |
number |
Maximum number of messages to keep in history (default: 50, readonly) |
Example:
<script>
const socket = new SvelteSocket({ url: 'ws://localhost:8080' });
const connectionStatus = $derived(socket.connectionStatus);
const sentMessages = $derived(socket.sentMessages);
const receivedMessages = $derived(socket.receivedMessages);
</script>
{#if connectionStatus === WebSocket.OPEN}
<p>Open</p>
{:else if connectionStatus === WebSocket.CONNECTING}
<p>Connecting</p>
{:else}
<p>Closed</p>
{/if}
<p>{sentMessages.length} sent</p>
<p>{receivedMessages.length} received</p>
{#each receivedMessages as { message }}
<div>{message.data}</div>
{/each}
addEventListener(event, callback)addEventListener(
event: 'message' | 'close' | 'open' | 'error',
callback: (event: MessageEvent | CloseEvent | Event) => void
): void
Adds event listener to WebSocket. The callback type is automatically inferred based on the event type:
'message' → (event: MessageEvent) => void'close' → (event: CloseEvent) => void'open' → (event: Event) => void'error' → (event: Event) => voidThrows if socket not connected.
socket.addEventListener('message', (event) => {
console.log(event.data); // event is typed as MessageEvent
});
removeEventListener(event, callback)removeEventListener(
event: 'message' | 'close' | 'open' | 'error',
callback: (event: MessageEvent | CloseEvent | Event) => void
): void
Removes event listener. Callback types match addEventListener.
const handler = (event) => console.log(event.data);
socket.addEventListener('message', handler);
socket.removeEventListener('message', handler);
sendMessage(message)sendMessage(message: string | ArrayBuffer | Blob | ArrayBufferView): void
Sends a text or binary message through the WebSocket. Supports strings, ArrayBuffer, Blob, TypedArray, and DataView. Stores in sentMessages array. Throws if not connected or not in OPEN state.
Example:
// Send text
socket.sendMessage('Hello, server!');
socket.sendMessage(JSON.stringify({ type: 'ping' }));
// Send binary data
const buffer = new Uint8Array([1, 2, 3, 4]);
socket.sendMessage(buffer);
clearSentMessages()clearSentMessages(): void
Clears sentMessages array.
socket.clearSentMessages();
clearReceivedMessages()clearReceivedMessages(): void
Clears receivedMessages array.
socket.clearReceivedMessages();
removeSocket()removeSocket(): void
Closes WebSocket connection. Clears message history. Prevents reconnection.
socket.removeSocket();
SocketProviderContext provider component that makes a socket instance available to child components.
Props:
| Property | Type | Required | Description |
|---|---|---|---|
url |
string |
Yes* | WebSocket server URL (automatically creates socket) |
svelteSocket |
SvelteSocket |
Yes* | Pre-configured SvelteSocket instance |
children |
Snippet |
No | Child components |
*At least one of url or svelteSocket must be provided. If both are provided, svelteSocket takes precedence.
Basic Usage:
The simplest way to use the provider is to pass a url, which automatically creates a SvelteSocket for you:
<script>
import { SocketProvider } from 'svelte-socket';
let { children } = $props();
</script>
<SocketProvider url="ws://localhost:8080">
{@render children()}
</SocketProvider>
Custom Socket Configuration:
You can also create your own SvelteSocket with custom callbacks and options, then pass it to the provider:
<script>
import { SocketProvider, SvelteSocket } from 'svelte-socket';
let { children } = $props();
const svelteSocket = new SvelteSocket({
url: 'ws://localhost:8080',
debug: true,
reconnectOptions: {
enabled: true,
delay: 1000,
maxAttempts: 5
},
onMessage: (event) => {
console.log('Received:', event.data);
},
onOpen: () => {
console.log('Connected!');
}
});
</script>
<SocketProvider {svelteSocket}>
{@render children()}
</SocketProvider>
useSocket()useSocket(): SvelteSocket
Returns socket instance from context.
Throws if not used within SocketProvider.
Example:
<script>
import { useSocket } from 'svelte-socket';
const socket = useSocket();
</script>
DebuggerDebug UI component. Shows connection status, sent messages, received messages.
Props:
| Property | Type | Required |
|---|---|---|
socket |
SvelteSocket |
Yes |
Example:
<script>
import { SvelteSocket, Debugger } from 'svelte-socket';
const socket = new SvelteSocket({ url: 'ws://localhost:8080' });
</script>
<Debugger {socket} />
Displays:
Styling Requirements:
This component requires Tailwind CSS. You must configure Tailwind to scan the package files:
Tailwind v4:
/* app.css */
@import 'tailwindcss';
@source '../node_modules/@hardingjam/svelte-socket/dist/**/*.svelte';
Tailwind v3:
// tailwind.config.js
export default {
content: [
'./src/**/*.{html,js,svelte,ts}',
'./node_modules/@hardingjam/svelte-socket/dist/**/*.svelte'
]
// ... rest of config
};
setSocket(socket)setSocket(socket: SvelteSocket): void
Sets socket in Svelte context. Used by SocketProvider.
getSocketContext()getSocketContext(): SvelteSocket
Gets socket from context. Throws if not found.
<script>
import { SvelteSocket } from 'svelte-socket';
const socket = new SvelteSocket({ url: 'ws://localhost:8080' });
socket.addEventListener('message', (event) => {
console.log(event.data);
});
function send() {
socket.sendMessage('test');
}
</script>
<button onclick={send}>Send</button>
<script>
import { SvelteSocket } from 'svelte-socket';
const socket = new SvelteSocket({
url: 'ws://localhost:8080',
debug: true,
reconnectOptions: {
enabled: true,
delay: 1000,
maxAttempts: 5
}
});
</script>
<script>
import { SvelteSocket } from 'svelte-socket';
const socket = new SvelteSocket({ url: 'ws://localhost:8080' });
socket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.type === 'ping') {
socket.sendMessage(JSON.stringify({ type: 'pong' }));
}
});
</script>
<script>
import { SvelteSocket } from 'svelte-socket';
const socket = new SvelteSocket({ url: 'ws://localhost:8080' });
const sentMessages = $derived(socket.sentMessages);
const receivedMessages = $derived(socket.receivedMessages);
let input = $state('');
function send() {
if (input) {
socket.sendMessage(input);
input = '';
}
}
</script>
<input bind:value={input} />
<button onclick={send}>Send</button>
<h3>Sent ({sentMessages.length})</h3>
{#each sentMessages as { message, timestamp }}
<div>
{new Date(timestamp).toLocaleTimeString()}: {message}
</div>
{/each}
<h3>Received ({receivedMessages.length})</h3>
{#each receivedMessages as { message }}
<div>{message.data}</div>
{/each}
<button onclick={() => socket.clearSentMessages()}>Clear</button>
<!-- +layout.svelte -->
<script>
import { SocketProvider } from 'svelte-socket';
let { children } = $props();
</script>
<SocketProvider url="ws://localhost:8080">
{@render children()}
</SocketProvider>
<!-- +page.svelte -->
<script>
import { useSocket } from 'svelte-socket';
const socket = useSocket();
socket.addEventListener('message', (event) => {
console.log(event.data);
});
</script>
Broadcast to all connected clients:
# TouchDesigner Text DAT
def broadcast():
webServer = op('webserver1')
clients = webServer.clients
for client in clients:
webServer.webSocketSendText(client, "message")
print(f"Sent to {len(clients)} clients")
MIT