itty-sockets

0.5.4 • Public • Published

itty-sockets

Version Bundle Size Coverage Status Issues Discord


WebSockets : simplified and minified.

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?')

Or simply use connect as a tiny WebSocket client that brings the following:

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

Getting Started

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

2. Connect to a Channel (or external server)

To start, simply connect to a channel based on a unique name (this can be anything).

NOTE: Pass a valid ws:// or wss:// 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')

Connection Options

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

3. Use the channel.

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)

Example

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

Events

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.')

EventTypes

All event types other than message are identified with a type attribute. For the sake of smaller payloads, type is omitted on normal messages.

MessageEvent

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
}

JoinEvent

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
}

LeaveEvent

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
}

ErrorEvent

type MessageEvent = {
  type: 'error'   // error event identifier
  date: Date      // JavaScript Date object
  message: any    // the message payload
}

Privacy

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:

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

  2. I ask that you please use the channels responsibly. We're all sharing this space!

Package Sidebar

Install

npm i itty-sockets

Weekly Downloads

198

Version

0.5.4

License

MIT

Unpacked Size

15.3 kB

Total Files

6

Last publish

Collaborators

  • krwhitley