npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sejatordev/ws-client

v1.0.0

Published

WebSocket client ringan dengan konsep **channel-based** (mirip Pusher), mendukung **auto reconnect**, **manual reconnect**, **heartbeat**, dan **pong timeout**.

Readme

@sejator/ws-client

WebSocket client ringan dengan konsep channel-based (mirip Pusher), mendukung auto reconnect, manual reconnect, heartbeat, dan pong timeout.

Cocok untuk:

  • Real-time order & notifikasi
  • Dashboard admin
  • Public / private channel
  • Browser & bundler modern (ESM / UMD)

✨ Fitur

  • 🔌 Auto connect & auto reconnect
  • 🔁 Manual reconnect API
  • ❤️ Heartbeat + pong timeout protection
  • 📡 Channel & event system
  • 🔄 Auto re-subscribe saat reconnect
  • 🔐 Private channel authentication
  • 🛡️ CSRF token support (cookie-based)
  • 🧠 Fully typed event (TypeScript)
  • 🌐 URL auto normalize (http → ws, /ws)

🔗 Implementasi (SDK untuk @sejator/ws-server)

@sejator/ws-client dirancang khusus sebagai SDK resmi untuk berkomunikasi dengan WebSocket Server @sejator/ws-server.

Client ini mengikuti penuh protokol, event, dan format payload yang digunakan oleh @sejator/ws-server, sehingga:

  • ✅ Plug & Play (tanpa konfigurasi rumit)
  • ✅ Auto kompatibel dengan:
    • Channel system
    • Private channel authentication
    • Heartbeat & pong
    • Reconnect strategy
  • ❌ Tidak ditujukan untuk WebSocket server lain yang tidak mengikuti spesifikasi @sejator/ws-server

⚠️ PENTING
Pastikan backend WebSocket kamu menggunakan @sejator/ws-server, karena:

  • Event seperti connect_success, auth_failed, pong, dll
  • Struktur auth (APP_KEY:signature)
  • Endpoint default (/ws)
    Semuanya bergantung pada implementasi server tersebut.

🔄 Arsitektur Client ↔ Server

Browser / Frontend
        │
        │  @sejator/ws-client
        ▼
WebSocket Protocol (Channel-based)
        │
        │  @sejator/ws-server
        ▼
Application Backend

⚙️ Cara Kerja

  1. Client melakukan koneksi ke endpoint WebSocket server (/ws)
  2. Server membalas dengan:
    • socket_id
    • activity_timeout
  3. Client:
    • Menjaga koneksi dengan heartbeat
    • Auto reconnect jika terputus
  4. Saat subscribe private-* channel:
    • Client meminta auth ke backend
    • Server memverifikasi signature
  5. Event dari server langsung dipetakan ke channel client

📦 Instalasi

✅ Opsi 1 — Clone dari GitHub (Recommended)

git clone https://github.com/sejator/ws-client.git
cd ws-client
npm install
npm run build

Hasil build tersedia di folder:

dist/
├─ ws-client.es.js
├─ ws-client.umd.js
├─ index.d.ts

✅ Opsi 2 — Import manual ke project (ESM)

Copy file hasil build ke project kamu:

dist/ws-client.es.js

Lalu import:

import { WSClient } from '@sejator/ws-client';

✅ Opsi 3 — Browser (UMD tanpa bundler)

Gunakan file UMD hasil build (ws-client.umd.js):

<script src="dist/ws-client.umd.js"></script>
<script>
  const { WSClient } = window.WSClient;
</script>

🚀 Penggunaan

1️⃣ ESM (Vite / Next.js / Node modern)

import { WSClient } from '@sejator/ws-client';

const client = new WSClient('http://localhost:3000', {
  key: 'YOUR_APP_KEY',
  logger: true,
});

client.on('connect_success', (data) => {
  console.log('Connected with socket id:', data.socket_id);
});

client.on('state_change', ({ previous, current }) => {
  console.log('State:', previous, '→', current);
});

client.on('reconnecting', ({ manual }) => {
  console.log('Reconnecting...', manual ? '(manual)' : '(auto)');
});

client.on('auth_failed', (err) => {
  console.error('Auth failed:', err);
});

client.on('error', (err) => {
  console.error('WebSocket error', err);
});

const channel = client.subscribe('public-orders');

channel.bind('order.created', (payload) => {
  console.log('Order created:', payload);
});

channel.bindAll((event, data) => {
  console.log('Event All:', event, data);
});

// unsubscribe dari channel
channel.unsubscribe();

// remove event dari channel
channel.unbind('order.created');

2️⃣ UMD (Browser tanpa bundler)

<script src="/dist/ws-client.umd.js"></script>
<script>
  const { WSClient } = window.WSClient;

  const client = new WSClient('http://localhost:3000', {
    key: 'YOUR_APP_KEY',
    logger: true,
  });

  client.on('connect_success', () => {
    console.log('Connected...');
  });

  const channel = client.subscribe('public-orders');

  channel.bind('order.created', (data) => {
    console.log('Order created:', data);
  });
</script>

📌 Namespace UMD: window.WSClient


📺 Public Channel

const channel = client.subscribe('public-orders');
atau;
const channel = client.subscribe('orders');

channel.bind('order.created', (data) => {
  console.log(data);
});

channel.unbind('order.created');

🔐 Private Channel

Channel dengan prefix private- memerlukan auth token dari backend.

const channel = client.subscribe('private-orders');

channel.bind('order.updated', (data) => {
  console.log(data);
});

🔌 Client Options

interface WSClientOptions {
  key: string; // required

  logger?: boolean; // default false
  reconnect?: boolean; // default true
  maxReconnectDelay?: number; // default 30000 (ms)

  // 🔐 Auth options
  authEndpoint?: string;
  authHeaders?: () => Record<string, string>;
  auth?: (params: {
    socketId: string;
    channel: string;
    headers?: Readonly<Record<string, string>>;
    query?: Record<string, string>;
  }) => Promise<{ auth: string }>;
}

🔐 Authentication (Auth)

Ada 2 cara untuk melakukan auth private channel.

⚠️ PENTING — Response Backend

Backend WAJIB mengembalikan response JSON dengan minimal field berikut:

{
  "data": {
    "auth": "APP_KEY:signature_hash"
  }
}

Format response yang direkomendasikan:

{
  "success": true,
  "code": 200,
  "data": {
    "auth": "APP_KEY:signature_hash"
  }
}

📌 Catatan:

  • Field data.auth WAJIB ada dan bertipe string
  • Field lain (success, code, dll) opsional
  • Jika data.auth tidak ada / null:
    • ❌ Subscribe private channel akan gagal
    • 🔔 Client memicu event auth_failed

✅ Opsi 1 — authEndpoint (paling mudah)

Client akan otomatis melakukan POST ke endpoint backend.

const client = new WSClient('http://localhost:3000', {
  key: 'YOUR_APP_KEY',
  authEndpoint: '/ws/auth',
});

Yang dikirim ke backend:

{
  "socket_id": "...",
  "channel": "private-orders"
}
  • ✔ Cookie otomatis dikirim
  • ✔ CSRF token otomatis ditambahkan (X-XSRF-TOKEN)

✅ Opsi 2 — auth function (fleksibel)

Gunakan jika kamu ingin custom fetch / axios / logic sendiri.

const client = new WSClient('http://localhost:3000', {
  key: 'YOUR_APP_KEY',
  auth: async ({ socketId, channel, headers }) => {
    const res = await fetch('/ws/auth', {
      method: 'POST',
      credentials: 'include',
      headers,
      body: JSON.stringify({
        socket_id: socketId,
        channel,
      }),
    });

    const json = await res.json();
    return { auth: json.data.auth };
  },
});

🛡️ CSRF Protection

Client secara otomatis:

  • Mengambil token dari cookie XSRF-TOKEN
  • Mengirimkannya sebagai header X-XSRF-TOKEN

Tidak perlu konfigurasi tambahan di client.

📌 Cocok untuk:

  • Laravel
  • Django
  • Express (csurf)

📡 Event Client

| Event | Payload | Deskripsi | | ----------------- | --------------------------------- | --------------------------------------------- | | connect_success | { socket_id, activity_timeout } | Koneksi berhasil | | disconnected | void | Socket terputus | | reconnecting | { manual: boolean } | Reconnect dimulai | | auth_failed | string | App key tidak valid/Tidak punya akses channel | | state_change | { previous, current } | Perubahan state client | | error | unknown | Error WebSocket |


🔁 Reconnect Strategy

  • Exponential backoff
  • Auto retry sampai maxReconnectDelay
  • Manual reconnect tersedia
client.reconnect();

❤️ Heartbeat & Pong Timeout

  • Client mengirim ping
  • Server membalas pong
  • Timeout → force reconnect

🌐 URL Normalization

@sejator/ws-client menerima URL HTTP maupun WebSocket, lalu menormalisasikannya otomatis agar sesuai dengan endpoint WebSocket server.

Apa yang dilakukan client?

Client akan:

1. Mengubah protokol:

  • http://ws://

  • https://wss://

2. Menambahkan path WebSocket default /ws

3. Menghapus trailing slash (/) jika ada

Dengan begitu, client selalu terhubung ke endpoint WebSocket yang benar tanpa konfigurasi tambahan.


Contoh

Input URL dari user:

new WSClient('http://localhost:3000', { key: 'APP_KEY' });

Akan otomatis dinormalisasi menjadi:

ws://localhost:3000/ws

Contoh lain: | Input | URL akhir | | ------------------------- | -------------------------- | | https://api.example.com | wss://api.example.com/ws | | ws://localhost:3000 | ws://localhost:3000/ws | | localhost:3000 | ws://localhost:3000/ws |


📦 Build

npm run build

Output:

dist/
├─ ws-client.es.js
├─ ws-client.umd.js
├─ *.map
├─ index.d.ts

Kontak & Dukungan

Maintainer: @sejator
Email: [email protected]
Donasi: https://saweria.co/sejator