Zero-config. Pick a channel and go.
// CLIENT 1 (listens for messages)
connect('unique-channel-name')
// listen for all messages
.on('message', e => console.log(e.message))
// or just our custom messages
.on('my-chat-message', ({ user, text }) => console.log(user, 'says:', text))
// CLIENT 2 (sends messages)
const channel = connect('unique-channel-name')
.send({ foo: 'bar' })
.send({ type: 'my-chat-message', user: 'Halsey', text: 'Meow!' })
channel.send('what else can this do?')
- JSON parsing/stringifying
- message queing - sending automatically connects and queue is flushed on open
- easy reconnection (listeners keep working)
- custom listeners/filters
- chainable syntax (it's just handy)
const ws = connect('wss://somewhere.else')
.on('message', console.log) // log all messages
.send({ foo: 'bar' }) // send immediately, no waiting
// optional - reconnect every second (no effect if open)
setInterval(ws.open, 1000)
1. Import the tiny client.
import { connect } from 'itty-sockets'
...or simply paste this into your environment/console:
let connect=(e,s={})=>{let t,a=0,n=[],p=[],o={},l=()=>(t||(t=new WebSocket((/^wss?:/.test(e)?e:"wss://ittysockets.io/c/"+e)+"?"+new URLSearchParams(s)),t.onmessage=(e,s=JSON.parse(e.data),t=s?.message,a={...null==t?.[0]&&t,...s,...s.date&&{date:new Date(s.date)}})=>{o[s?.type??t?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),p.map(([e,s])=>e(a)&&s(a))},t.onopen=()=>(n.splice(0).map(e=>t?.send(e)),o.open?.map(e=>e()),a&&t?.close()),t.onclose=()=>(a=0,t=null,o.close?.map(e=>e()))),c),c=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==t?.readyState?t.close():a=1,c),push:(e,s)=>(a=1,c.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?"@@"+s+"@@"+e:e,1==t?.readyState?(t.send(e),c):(n.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):p.push([e,s])),l()),remove:(e,s,t=o[e],a=t?.indexOf(s)??-1)=>(~a&&t?.splice(a,1),l())}[s])});return c};
To start, simply connect to a channel based on a unique name (this can be anything).
NOTE: Pass a valid
ws://
orwss://
URL as the channel identifier to bypass the public ittysockets.io service and use your own.
import { connect } from 'itty-sockets'
// basic connection
const channel = connect('my-super-secret-channel')
// with options
const channel = connect('my-super-secret-channel', {
alias: 'Kevin', // optional non-unique identifier, visible in messages
announce: true, // shares your uid/alias with the channel on joining
echo: true // echos your own messages back to you (for testing)
})
// or any external JSON WebSocket server
const channel = connect('wss://somewhere.else.entirely')
option | default value | description |
---|---|---|
{ alias: 'any-string' } |
undefined |
An optional display name to be included in your messages. |
{ as: 'any-string' } |
undefined |
An optional display name to be included in your message (same as alias). |
{ announce: true } |
false |
Shares your uid/alias when joining/leaving. |
{ echo: true } |
false |
Echos messages back to original sender (good for testing). |
With the channel connected, simply call methods on it. Every method is chainable, returning the connection again (for more chaining).
method | description | example |
---|---|---|
.open() |
Opens/re-opens the connection (manually, usually not needed). | |
.close() |
Closes the connection. | channel.close() |
.send(message: any) |
Sends a message to the channel. This can be anything serializable with JSON.stringify. | channel.send({ type: 'chat', text: 'hello' }) |
.push(message: any) |
Sends a message and immediately closes the connection. | channel.push('Hello World!') |
.on(eventName: string, listener) |
Add an event listener. | channel.on('close', () => console.log('channel closed')) |
.remove(eventName: string, listener) |
Remove an event listener. The 2nd argument must be the same listener function registered in the on method. |
channel.remove('open', myListenerFunction) |
// connect
const channel = connect('my-secret-channel')
// add event listeners or send messages
channel
.on('message', ({ alias, uid, message, date }) =>
console.log(`${alias ?? uid} says: ${message} @ ${date.toLocaleTimeString()}`)
)
.on('join', ({ users }) =>
console.log(`A user has joined. There are now ${users} in the channel.`)
)
.on('leave', ({ users }) =>
console.log(`A user has left. There are now ${users} in the channel.`)
)
.send('Hello World!') // this will queue up and send the message once connected
Each event can have multiple listeners registered on it. These are stable, even if the underlying WebSocket is broken/re-established.
event name | description | payload | example |
---|---|---|---|
message |
Triggered when receiving a message event. | MessageEvent | channel.on<MessageType = any>('message', listener) |
join |
Triggered when a user (including self) joins the channel. This alerts all users that someone has joined, and informs them of the total number of users in the channel. If the joining party connected with { announce: true }, their user details will be shared with the channel. | JoinEvent | channel.on('join', e => console.log('There are now', e.users, 'users in the channel.') |
leave |
Triggered when a user leaves the channel. This alerts all users that someone has left, and informs them of the total number of users in the channel. If the leaving party connected with { announce: true }, their user details will be shared with the channel. | LeaveEvent | channel.on('leave', e => console.log('There are now', e.users, 'users in the channel.') |
error |
Triggered when the server sends an error to the user. This is rare. | ErrorEvent | channel.on('error', e => console.error('IttySockets Error:', e.message) |
open |
Triggered when the connection is established. | none | channel.on('open', () => console.log('connected to channel.') |
close |
Triggered when the connection is closed. | none | channel.on('close', () => console.log('disconnected from channel.') |
All event types other than message
are identified with a type
attribute. For the sake of smaller payloads, type
is omitted on normal messages.
type MessageEvent = {
id: string // unique message ID
uid: string // unique user ID
alias: string? // optional display name
date: Date // JavaScript Date object
message: any // the message payload
}
type JoinEvent = {
type: 'join' // type of event
uid?: string // uid of joiner if { announce: true }
alias: string? // alias of joiner if { announce: true }
date: Date // date of event
users: number // new number of users in the channel
}
type LeaveEvent = {
type: 'leave' // type of event
uid?: string // uid of leaver if { announce: true }
alias: string? // alias of leaver if { announce: true }
date: Date // date of event
users: number // new number of users in the channel
}
type MessageEvent = {
type: 'error' // error event identifier
date: Date // JavaScript Date object
message: any // the message payload
}
ittysockets.io is a free, public-use, but private service.
It was designed by me (a developer), to help myself and other developers achieve cool things. As such:
-
Your messages are never transmitted to anything other than the sockets on the channel you're connected to. No third-party service, no loggers, no storage (local or otherwise), not even a collection in memory. This protects your privacy/data, but keeps my costs to virtually zero, allowing me to share this service with the world... hopefully indefinitely.
-
I ask that you please use the channels responsibly. We're all sharing this space!