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

@mosnpm/litesocket

v0.2.3

Published

Lightweight WebSocket client and server with RPC support

Readme

LiteSocket

English | 简体中文

One codebase, two builds: a complete Node.js library and a browser client that uses the native WebSocket API.

Runtime requirements

  • Node.js: 20 or later.
  • Browsers: support for ES2021, native WebSocket, and the Web APIs used by the client.
  • The JavaScript compilation target is ES2021. Some browser integration tests require Node.js 22 or later; this is separate from the library's minimum runtime version.

Inspiration

The low-level transport layer, LiteServer / LiteClient, is inspired by Socket.IO, providing connection lifecycle events, messages, heartbeats, and room broadcasts. Built on that layer, IOServer / IOClient simplify application APIs and add message dispatch, RPC, error codes, and diagnostics. The main use case is communication between game clients and Node.js servers.

LiteSocket uses its own JSON message protocol and is not compatible with the Socket.IO or Engine.IO protocols. Both ends must use LiteSocket or implement its protocol. Socket.IO clients and servers cannot be mixed directly with LiteSocket endpoints.

Two API layers

| Layer | Server / client | Responsibilities | | --- | --- | --- | | Transport layer | LiteServer / LiteClient | WebSocket / WSS connections, string-named messages, lifecycle events, heartbeats, reconnection, size limits, and server-side room broadcasts | | Application layer (recommended) | IOServer / IOClient | Message-ID dispatch and simpler registration/send APIs on top of the transport, plus session-based RPC, error codes, and timeout handling |

Use IOServer / IOClient for application development: onMessage() and send() handle ordinary messages, onCallback() registers RPC handlers, asend() returns an error code and results, and asende() returns only the error code. Use LiteServer / LiteClient directly when you want to organize string-named events and your own application protocol.

Connections and heartbeats belong to the transport layer and are reused by the IO layer. RPC sessions, results, and timeouts belong to the IO layer. The Socket.IO comparison below concerns the transport layer; the code examples use the recommended IO layer.

Why build another library?

For applications that have already chosen WebSocket, this project provides a focused communication layer that is straightforward to maintain and adapt:

  • Explicit connection readiness: await connectPromise() returns a connection result. A connection is ready only after the client receives the server's system message and completes protocol initialization.
  • Separate lifecycle events from application messages: onEvent() handles client lifecycle events, while on() handles messages. The server uses onClient() for client connection events.
  • Different registration semantics for events and messages: LiteClient.onEvent(), LiteServer.onClient(), and the server broadcast-exception onEvent('exception') support multiple listeners. Message handlers (on() / onMessage()) keep one handler per event name; registering again replaces it and logs a warning.
  • RPC shaped around application needs: IOServer and IOClient use message IDs, session IDs, and error codes. asend() returns a result tuple; asende() returns only the error code.
  • Built-in diagnostics: injectable logging, per-connection message observation, profiling, message size limits, and exception notifications.
  • A focused maintenance scope: the browser uses native WebSocket and the server uses ws, concentrating the implementation on connections, heartbeats, reconnection, and message dispatch.

Readability, application integration, and maintenance scope are the main design goals. Socket.IO also provides Promise-based APIs and timeouts, and covers a broader range of transport and connection-management scenarios.

Comparison with Socket.IO

This compares Socket.IO with LiteServer / LiteClient. Both provide bidirectional communication, connection notifications, heartbeat detection, and server-side room broadcasts. The application-level RPC extensions in IOServer / IOClient are described in the next section.

| Area | Socket.IO | LiteServer / LiteClient | | --- | --- | --- | | Transport | Engine.IO, with HTTP long-polling, WebSocket, and transport upgrades | WebSocket / WSS only; no long-polling fallback | | Message protocol | Socket.IO / Engine.IO protocols | JSON { e, d } packets, dispatched by string event names | | Event and message registration | Multiple listeners per event | Events support multiple listeners; each message name has one handler, and re-registration replaces it with a warning | | Connection handling | Connection events and connection management | connectPromise() waits for the system message before marking the protocol ready | | Automatic reconnection | Available in the client | Disabled by default; enable exponential backoff with autoReconnect | | Rooms and scaling | Rooms, namespaces, and multi-instance adapters | In-process rooms and broadcasts; no namespaces or cross-instance adapters | | Connection recovery | Optional connection state recovery | Client message handlers survive reconnection; server application state and requests are not automatically restored or replayed |

The transport comparison refers to the official Socket.IO feature overview and client API. Connection retries in LiteSocket do not imply message replay: persistence, application retries, and idempotency are application responsibilities.

What IOServer / IOClient add

IOServer / IOClient provide application-facing APIs on top of LiteServer / LiteClient:

  • Message-ID dispatch: register numeric message IDs with onMessage() and send ordinary messages with send([messageId, ...args]).
  • RPC: register server handlers with onCallback(). Return an error code or [errorCode, ...results], and await the matching result with asend(). The framework matches session IDs.
  • Consistent error handling: ErrorEnum covers disconnected clients, missing handlers, invalid results, timeouts, disconnects, and send failures. Use asende() when only the error code matters.
  • Less application wiring: IOServer manages message handlers and IOServerSocket instances. IOClient.connectServer() establishes the connection and binds dispatch, reusing transport logging, observation, and connection management.

Enable checktimeout on IOClient to check RPC deadlines. checkIntervalMs controls the polling interval; the client examples below enable it.

Installation

pnpm add @mosnpm/litesocket

Use the package root, @mosnpm/litesocket, in Node.js. Use @mosnpm/litesocket/client in the browser. Both entry points include TypeScript declarations.

Building from source

pnpm install
pnpm build

You can also run pnpm build:full or pnpm build:client separately. Each build cleans only its own output directory.

lib/
├── full/                     # Complete Node.js library: CommonJS and .d.ts
│   ├── index.js
│   ├── index.d.ts
│   ├── net/
│   └── public/
└── client/                   # Browser client: no Node.js runtime dependencies
    ├── index.js              # ES module
    ├── index.d.ts            # Browser DOM types only
    ├── litesocket.global.js  # Classic script; global name: LiteSocket
    └── package.json

The full library includes LiteServer, IOServer, room management, and all client APIs. Its runtime dependencies are ws and tslib. The browser client includes LiteClient, IOClient, RPC, message types, error codes, logging, and profiling APIs, without server implementations.

Complete Node.js library

TypeScript, using the recommended application layer:

import { IOServer, ErrorEnum } from '@mosnpm/litesocket';
import type { IOServerSocket } from '@mosnpm/litesocket';

enum Message {
    Hello = 960001,
    HelloReply,
    Add,
}

async function main(): Promise<void> {
    const server = new IOServer('server', console);
    server.onMessage(Message.Hello, (socket: IOServerSocket, name: string) => {
        socket.sendMsg(Message.HelloReply, `Hello, ${name}!`);
    });
    server.onCallback(Message.Add, (_socket: IOServerSocket, a: number, b: number) => {
        return [ErrorEnum.ErrorOk, a + b];
    });
    const [ok, error] = await server.listen(8080);
    if (!ok) throw error;
}

void main().catch(console.error);

The package root, @mosnpm/litesocket, exports IOServer and IOClient, as well as the low-level LiteServer / LiteClient. Node.js TypeScript projects can use Node16 for both module and moduleResolution.

Browser client

In a TypeScript browser project, import IOClient from the client entry point and let your bundler resolve it. The message IDs match the IOServer example above:

import { IOClient, ErrorEnum } from '@mosnpm/litesocket/client';

enum Message {
    Hello = 960001,
    HelloReply,
    Add,
}

const client = new IOClient('browser', console, {
    checktimeout: true,
    checkIntervalMs: 50,
});
client.onMessage(Message.HelloReply, (message: string) => {
    console.log(message);
});

async function main(): Promise<void> {
    const [connected, reason] = await client.connectServer('ws://localhost:8080', reason => {
        console.warn('Disconnected:', reason);
    });
    if (!connected) throw new Error(`Connection failed: ${reason}`);
    client.sendMsg(Message.Hello, 'browser');
    const [code, sum] = await client.asendMsg(Message.Add, 3, 5);
    if (code !== ErrorEnum.ErrorOk) throw new Error(`RPC failed: ${code}`);
    console.log('3 + 5 =', sum);
}

void main().catch(console.error);

setMsgNameFunc() can map numeric IDs to names in diagnostic logs. Register it separately in each runtime (browser and server); it does not change the wire protocol.

Include DOM types in your browser TypeScript configuration; moduleResolution: "bundler" can resolve the /client entry point. Node.js clients use the same IOClient API, imported from @mosnpm/litesocket.

Without a bundler, serve the built ES module files from a static server:

<script type="module">
  import { IOClient, ErrorEnum } from './lib/client/index.js';
  ...
</script>

A classic script build is also available:

<script src="./lib/client/litesocket.global.js"></script>
<script>
  const { IOClient, ErrorEnum } = LiteSocket;
  ...
</script>

The browser build uses native WebSocket by default; you do not need to provide createSocket. The IO layer reuses transport connection and reconnection handling. Call client.destroy("leaving page") to close the connection and clear timers. For WSS, use a wss:// URL; certificate validation is handled by the browser.

Verification

Examples for both builds are available in example/lib/. Run pnpm example:lib to start the full-library server and try the client library in a browser.

pnpm test       # Source tests: connections, protocol, RPC, events, TLS, etc.
pnpm test:lib   # Build outputs, browser declarations, and client runtime tests

test:lib requires the native WebSocket implementation in Node.js 22+. Tests run in an isolated environment without require, process, or Buffer, using browser-style numeric timers and native WebSocket against a real server. They cover messages, binary JSON, RPC, timeouts, and reconnection. This verification does not launch a browser UI.

License

LiteSocket is licensed under the MIT License.