itty-sockets
v0.6.1
Published
WebSockets : simplified and minified.
Readme
Documentation | Discord
The last WebSocket client you'll need : 512 bytes, all-in.
Features ✨
- DX perks - JSON-in/out, queued messages, easy-reconnect, chainable everything.
- Works with any JSON-based WebSocket server
- Powerful Routing
- Listen for all messages
.on('message', data => console.log(data)) - Only specific types
// matches any data with { type: 'chat' } .on('chat', ({ text }) => console.log(text)) - or fully custom filters
// matches only messages where data.value > 20 .on( ({ value }) => value > 20), // filter function ({ value }) => console.log(value), )
- Listen for all messages
- Type-safe message handling
- Tiny footprint - 512 bytes, all-in.
- Optional usage with free/public/zero-config itty.ws service
Basic Example
import { connect } from 'itty-sockets'
// connect to the channel
const channel = connect('wss://example.com')
channel
// log all messages
.on('message', e => console.log(e.message))
// send some messages
.send('hey!')
.send({ foo: 'bar' })Optional use with itty.ws public, privacy-first server
itty-sockets has been designed to work with the public itty.ws service for even easier integrations. With this path, it's possible to add realtime features without hosting a backend server at all. We recommend using this for testing, prototyping, or simple projects. As your needs expand, you can always replace itty.ws with your own server(s) - nothing in the client changes.
Using itty.ws channels provides a few features to the client (fully typed by passing the UseItty generic to connect):
connect<UseItty>('my-channel')- connect to a channel and go- adds
uid,alias, anddateto all messages - adds
joinandleaveevents to announce user changes - allows private messaging (by uid)
Installation
Option 1: Import
npm install itty-socketsimport { connect } from 'itty-sockets'Option 2: Just copy this snippet:
let connect=(e,s={})=>{let p,a=0,n=[],t=[],o={},l=()=>(p||(p=new WebSocket((/^wss?:/.test(e)?e:"wss://itty.ws/c/"+e)+"?"+new URLSearchParams(s)),p.onmessage=(e,s=JSON.parse(e.data),p=s?.message,a={...null==p?.[0]&&p,...s})=>{o[s?.type??p?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),t.map(([e,s])=>e(a)&&s(a))},p.onopen=()=>(n.splice(0).map(e=>p?.send(e)),o.open?.map(e=>e()),a&&p?.close()),p.onclose=()=>(a=0,p=null,o.close?.map(e=>e()))),m),m=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==p?.readyState?p.close():a=1,m),push:(e,s)=>(a=1,m.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?""+s+""+e:e,1==p?.readyState?(p.send(e),m):(n.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):t.push([e,s])),l()),remove:(e,s,p=o[e],a=p?.indexOf(s)??-1)=>(~a&&p?.splice(a,1),l())}[s])});return m};Note: This will lose TypeScript support.
Example 2 - Receiving basic messages
Assume the following simple client
import { connect } from 'itty-sockets'
connect('wss://example.com')
// listen for every message
.on('message', console.log)
// and just { type: 'chat' }
.on('chat',
({ user, text }) => console.log(`${user} says: ${text}`)
)Now let's assume the following 2 messages are sent:
{
"type": "chat",
"user": "Kevin",
"text": "Hey!"
}{
"date": 1754659171196,
"items": [1, 2, 3],
}This will output the following to the console:
{ type: "chat", user: "Kevin", text: "Hey!" }
{ date: 1754659171196, items: [1, 2, 3] }
"Kevin says: Hey!"Example 3 - Reconnection
Using itty-sockets, you can safely fire .open() on the connection at any time, even if already connected. All listeners will continue to work perfectly once reconnected.
const channel = connect('wss://example.com')
.on('message', console.log)
.on('open', () => console.log('connected'))
.on('close', () => console.log('disconnected'))
// we'll just reconnect every second - this is safe!
setInterval(channel.open, 1000)