🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@elementaio/koine

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@elementaio/koine

Zero-dependency TypeScript client for Koine embedded chat: one WebSocket, typed events, idempotent sends, automatic reconnect, exact cursor catch-up.

latest
Source
npmnpm
Version
0.1.1
Version published
Maintainers
1
Created
Source

@elementaio/koine

Zero-dependency TypeScript client for Koine embedded chat.

One WebSocket per device. Your backend mints a short-TTL JWT; you hand it to the client and it speaks the Koine wire protocol for you — idempotent sends with ack tracking, typed events, automatic reconnect with backoff, and exact cursor-based catch-up (it remembers the highest seq it has seen per conversation and re-syncs the gap on reconnect, once).

Runs in the browser and in Node 22+ — both expose a global WebSocket.

Install

npm install @elementaio/koine

Use

import { KoineClient } from "@elementaio/koine";

const koine = new KoineClient({
  url: "wss://chat.example.com/ws",
  token: jwtFromYourBackend,   // HS256, signed with the secret you share with Koine
  device: "web-1",             // stable per device → resumes cursors on reconnect
});

koine.on("message", (m) => render(m.conv, m.from, m.payload, m.seq));
koine.on("receipt", (r) => markRead(r.conv, r.from, r.seq));
koine.on("typing",  (t) => showTyping(t.conv, t.from));
koine.on("error",   (e) => console.warn("koine:", e.reason));

koine.connect();

// Idempotent send — the returned promise resolves with the durable seq.
const ack = await koine.send("general", "hello");
console.log("stored as seq", ack.seq);

// Live signals and read state:
koine.typing("general");
koine.read("general", ack.seq);
koine.presence("alice");

Reconnect & catch-up

By default the client reconnects on an unexpected drop (exponential backoff with jitter) and, once reconnected, re-syncs every conversation it has seen from its cursor — so you get exactly the messages you missed, once. After a full page reload, seed the cursors from your own persisted state first:

koine.setCursor("general", lastSeqYouRendered);
koine.connect();

API

MethodPurpose
connect() / close()open the socket (reconnects are automatic) / close for good
send(conv, payload, { id?, kind? })send; resolves with the ack (kind: "ephemeral" = live-only)
read(conv, seq)advance your read watermark
typing(conv)ephemeral typing signal
readState(conv, seq)ask group read state (seen-by count)
presence(user)ask if a user is online / last-seen
sync(conv, after?)explicit catch-up (defaults to the tracked cursor)
cursor(conv) / setCursor(conv, seq)read / seed catch-up state
on(event, handler) / off(...)subscribe / unsubscribe
connectedis the socket open right now

Events: open, close, reconnecting, message, ack, receipt, sync_page, read_state, presence, system, typing, error — all typed.

Options

OptionDefaultMeaning
url / token(required)gateway URL and the client JWT
devicerandomstable device id; resumes this device's cursors
WebSocketglobalThis.WebSocketinject an implementation if none is global
autoReconnecttruereconnect on unexpected close
autoResynctruere-sync tracked conversations on reconnect
reconnectBackoffMsexp + jitter(attempt) => ms schedule
ackTimeoutMs10000how long send() waits for its ack before rejecting

The full wire protocol is documented in docs/PROTOCOL.md.

Develop

npm install
npm test        # builds, then runs the node:test suite against a mock socket

License

MIT © Emad Jumaah

Keywords

chat

FAQs

Package last updated on 04 Jul 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts