JOIN MY SPONSORS

Advanced Chat

Here, we have a slightly more complex chat, with both chat and emote messages. By using type routing, we can listen for each message type separately. We also track connected users via { list: true } — no custom greeting protocol needed.

In this window, you are .... To chat with yourself, open this page in another tab.

no messages yet...
Connected Users
chat.ts
import { connect } from 'itty-sockets'

type ChatMessage = { type: 'chat', text: string }
type EmoteMessage = { type: 'emote', action: string }

let users = []

const chat = connect('examples:typed-chat', {
  announce: true,
  echo: true,
  list: true,
  as: '...',
})
.on('join', ({ uid, alias, users: list }) => {
  if (list) users = list
  else if (uid) users.push({ uid, alias })
})
.on('leave', ({ uid }) => {
  users = users.filter(u => u.uid !== uid)
})
.on<ChatMessage>('chat', ({ alias, text }) => {
  // "Kevin: hello!"
})
.on<EmoteMessage>('emote', ({ alias, action }) => {
  // "*Kevin waves*"
})

chat.send<ChatMessage>({ type: 'chat', text: 'hello!' })
chat.send<EmoteMessage>({ type: 'emote', action: 'waves' })

Alternatively, you can use an event map to type the connection while keeping your downstream code cleaner:

chat.ts (with event map)
import { connect } from 'itty-sockets'

type ChatMessage = { type: 'chat', text: string }
type EmoteMessage = { type: 'emote', action: string }

type Events = {
  chat: ChatMessage
  emote: EmoteMessage
}

let users = []

const chat = connect<Events>('examples:typed-chat', {
  announce: true,
  echo: true,
  list: true,
  as: '...',
})
.on('join', ({ uid, alias, users: list }) => {
  if (list) users = list
  else if (uid) users.push({ uid, alias })
})
.on('leave', ({ uid }) => {
  users = users.filter(u => u.uid !== uid)
})
.on('chat', ({ alias, text }) => {
  // "Kevin: hello!"
})
.on('emote', ({ alias, action }) => {
  // "*Kevin waves*"
})

chat.send({ type: 'chat', text: 'hello!' })
chat.send({ type: 'emote', action: 'waves' })