@ghuts/disocket
v1.0.1
Published
Zero-dependency native C++ realtime chat engine for Node.js
Maintainers
Readme
@ghuts/disocket
Native C++ realtime chat engine for Node.js with zero runtime dependencies.
@ghuts/disocket is a Socket.io-like chat/live-data package bundled as one npm package. The core engine is a native C++ N-API addon. The JavaScript layer is a thin ergonomic wrapper and the browser client uses the built-in WebSocket API.
Features v1.0.0
- Native C++ core via direct C N-API, no
node-addon-apiwrapper. - zero runtime dependencies in
package.json. - Rooms: join, leave, history, visible/hidden presence.
- Messaging: canonical IDs, room sequence, tempId dedupe, threadId, edit, soft delete/tombstone.
- Ack-ready packet model through canonical message return values.
- Moderation: mute, ban enforcement, kick helper, moderator-role checks, audit log, shadow-mute action contract.
- Reliability primitives: idempotency through tempId, append-only file log, delivery policy option surface.
- Security: signed HMAC auth tokens via Node built-in
crypto, room/user validation, membership enforcement option, role-protected moderation, path-safe file storage names. - Abuse controls: max message size, per-socket token bucket rate limit, slow-mode enforcement, max sockets, max rooms per socket.
- Memory/resource controls: resource stats, max history limit, max messages per room, prune, compact, wipeRoom, close/clear.
- Room controls: read-only, locked, slow-mode/retention config surface.
- Reactions and presence.
- Metrics, health snapshots, and resource snapshots.
- Bundled browser client under
@ghuts/disocket/clientwith strict packet validation. - Manual TypeScript types.
- Makefile, tests, review script, and npm pack validation.
Install
npm install @ghuts/disocketFrom source:
npm install
npm run build
npm testQuickstart
const { NativeChatServer } = require('@ghuts/disocket');
const secret = process.env.DISOCKET_SECRET || 'dev-secret';
const token = NativeChatServer.issueAuthToken(
{ id: 'u1', name: 'Alice', roles: ['member'] },
secret,
{ expiresInMs: 60_000 }
);
const chat = new NativeChatServer({
auth: { mode: 'signed', secret },
validation: {
roomPattern: '^[A-Za-z0-9._:-]{1,64}$',
allowControlChars: false
},
permissions: {
requireJoinBeforeSend: true,
moderatorRoles: ['mod', 'admin']
},
resourceLimits: {
maxSockets: 10_000,
maxRoomsPerSocket: 32,
maxMessagesPerRoom: 10_000,
maxHistoryLimit: 500,
messageOverflow: 'prune-oldest'
},
storage: { type: 'file', dir: './chat-data' },
rateLimit: { messagesPerMinute: 120 }
});
const alice = chat.connect({ token });
chat.join(alice.socketId, 'general');
const msg = chat.sendMessage(alice.socketId, 'general', 'halo dunia', {
tempId: 'tmp-1',
delivery: 'effectively-once'
});
console.log(msg.id, msg.seq);
console.log(chat.history('general', { limit: 20 }));
console.log(chat.resourceStats({ rooms: true }));Memory and security operations
// enforce slow mode and lock/read-only controls at runtime
chat.setRoomConfig('general', { slowModeMs: 3000, readOnly: false });
// moderator-only if bySocketId is supplied
chat.moderate({
action: 'ban',
userId: 'spammer',
room: 'general',
durationMs: 60_000,
bySocketId: 'sock_mod'
});
// remove tombstones from memory, then rewrite append-only log
chat.prune({ room: 'general', tombstonesOnly: true, compact: true });
chat.compact({ room: 'general', storage: true });
// wipe sensitive room data and remove its log
chat.wipeRoom('secure-room', { removeLog: true, bestEffortSecure: true });Browser client
const { DisocketClient } = require('@ghuts/disocket/client');
const client = new DisocketClient('ws://localhost:3000/chat').connect();
client.on('message:new', console.log);
client.sendMessage('general', 'halo');The v1 package ships the protocol/client shape in the bundle. A full native WebSocket listener can be layered on this core without changing the public event contract.
Event contract
Core event names supported by the public API:
connection,disconnectroom:joined,room:left,room:config:updatemessage:new,message:update,message:deletereaction:add,reaction:removemoderation:mute,moderation:ban,moderation:shadow_muteserver:announce
Recommended wire packet:
{
"v": 1,
"id": "pkt_1",
"type": "event",
"event": "message:create",
"room": "general",
"data": { "text": "halo", "tempId": "tmp_1" },
"ts": 1781090000000
}Storage
Default storage is memory. File storage writes an append-only NDJSON log per room. Room names are encoded into path-safe filenames to block path traversal:
const chat = new NativeChatServer({ storage: { type: 'file', dir: './data' } });
console.log(chat.roomLogName('general')); // hex_67656e6572616c.logLogs are stored at:
data/rooms/<encoded-room>.logMetrics
console.log(chat.metrics());
console.log(chat.health());Metric fields include active sockets/rooms, total connections/disconnections, received/sent/failed messages.
Development
make all # install, build, test, review
make test
make packDesign notes
This package intentionally bundles the native core, JS wrapper, client SDK, types, tests, and docs into a single package instead of splitting Redis/Postgres/client packages. External adapters can be added later behind optional configuration, but v1 keeps the install small and dependency-free.
