npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@hardingjam/svelte-socket

v0.0.9

Published

WebSocket wrapper for Svelte 5 using runes.

Readme

svelte-socket

WebSocket wrapper for Svelte 5 using runes.

Overview

This library provides:

  • SvelteSocket - WebSocket wrapper class with reactive state properties (connectionStatus, sentMessages, receivedMessages)
  • SocketProvider - Context provider component that instantiates SvelteSocket and makes it available to child components
  • Debugger - UI panel component showing connection status, sent messages, and received messages
  • useSocket() - Hook to access socket instance from context

Features

  • Constructor accepts configuration object with URL and optional callbacks (onMessage, onOpen, onClose, onError)
  • Optional debug logging via debug flag
  • Auto-reconnection with configurable delay and max attempts
  • Reactive message history (sent and received)
  • All state properties use Svelte 5 $state runes
  • TypeScript support

Installation

npm install svelte-socket

Usage

In parent components including +page.svelte or +layout.svelte...

<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>

In any child component...

<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}

API

SvelteSocket

Constructor

new 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')
});

Properties

| 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}

Methods

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) => void

Throws 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();

SocketProvider

Context 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>

Debugger

Debug 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:

  • Connection state (CONNECTING/OPEN/CLOSING/CLOSED)
  • Message counts (sent/received)
  • Sent message history with timestamps
  • Received message history with data

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
};

Context Functions

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.

Examples

Basic

<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>

Auto-reconnect

<script>
	import { SvelteSocket } from 'svelte-socket';

	const socket = new SvelteSocket({
		url: 'ws://localhost:8080',
		debug: true,
		reconnectOptions: {
			enabled: true,
			delay: 1000,
			maxAttempts: 5
		}
	});
</script>

JSON Messages

<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>

Message History

<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>

With Provider

<!-- +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>

TouchDesigner Integration

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")

Requirements

  • Svelte 5.0+
  • WebSocket support

License

MIT