@trap_stevo/iotide
Version:
Provides the ultimate solution for real-time event management. Designed to make your applications dynamic and responsive, IoTide offers unparalleled flexibility in handling events on-the-fly. Effortlessly create interactive web applications, live data das
383 lines (283 loc) β’ 13.5 kB
Markdown
# π IoTide
**A powerful, real-time communication layer for secure and modular socket-based networking.**
Provides the ultimate solution for real-time event management. Designed to make your applications dynamic and responsive, IoTide offers unparalleled flexibility in handling events on-the-fly. Effortlessly create interactive web applications, live data dashboards, chat applications, and collaborative tools with seamless communication between your server and connected clients.
## π Features
- π‘ **Event-Driven Socket Server** β Built with rich customization hooks
- π **Flexible HTTPS/HTTP Support** β Easily configure secure or standard transports
- π§© **RoomIO Support** β Enable join, leave, broadcast, and message semantics per room
- π§ **Tide Identity System** β Enforces socket identity using custom or generated IDs
- π§° **Custom Hooks** β Inject your own logic at connection, disconnection, and room events
- π·οΈ **Dynamic Event Registration** β Easily bind handlers to any incoming socket event
- π§Ό **Cleanup Utilities** β Manage socket lifecycle, disconnects, and teardown gracefully
## π§ Use Cases
IoTide powers secure and scalable systems like:
- Multiplayer game lobbies
- Real-time dashboards
- OTA deployment systems
- Mesh sync engines
- Collaborative tools
- Message relays
- Device/agent coordination
- Just about any application requiring real-time communication
## βοΈ System Requirements
| Requirement | Version |
|----------------|--------------------|
| **Node.js** | β₯ 18.x |
| **npm** | β₯ 9.x (recommended)|
| **OS** | Windows, macOS, Linux |
## π οΈ Constructor
```js
const IoTide = require("@trap_stevo/iotide");
const server = new IoTide(
3000,
{ useCors : true },
true,
(socket) => { console.log("Client connected:", socket.id); },
(_, socket) => { console.log("Client disconnected:", socket.id); },
() => { console.log("Server launched"); }
);
```
### Parameters
| Name | Type | Description |
|-------------------------------|------------|-------------|
| `port` | `number` | Port to bind server |
| `options` | `object` | Configuration object (see below) |
| `roomIO` | `boolean` | Enable room/channel functionality |
| `onConnect(socket)` | `function` | Callback on connection |
| `onDisconnect(ctx, socket)` | `function` | Callback on disconnect |
| `onLaunch()` | `function` | Callback when server launches |
| `joinRoomAction(socket, data)`| `function` | Custom hook on room join |
| `leaveRoomAction(socket, data)`| `function`| Custom hook on room leave |
| `messageRoomAction(...)` | `function` | Custom hook when messaging a room |
| `removeAllFromRoomAction(...)`| `function` | Custom logic for kicking all from room |
## βοΈ Options
| Option | Type | Description |
|-------------------------------|-----------|-------------|
| `useHTTPS` | `boolean` | Use HTTPS server |
| `sslCertPath` | `string` | Path to SSL cert |
| `sslKeyPath` | `string` | Path to SSL key |
| `sslCaPath` | `string` | Path to CA chain file |
| `useCors` | `boolean` | Enable CORS middleware |
| `corsOptions` | `object` | Custom CORS config |
| `tidalCoreOptions` | `object` | TidalCore ID config |
| `socketOptions` | `object` | Options passed to `socket.io()` |
| `joinChannelEventID` | `string` | Event name override |
| `joinedChannelEventID` | `string` | Event after successful join |
| `userJoinedChannelEventID` | `string` | Broadcast when user joins |
| `allUsersChannelEventID` | `string` | Event that lists users in room |
| `messageChannelEventID` | `string` | Event to send room message |
| `incomingMessageChannelEventID` | `string` | Incoming message response |
| `leaveChannelEventID` | `string` | Leave event name override |
| `userLeftChannelEventID` | `string` | Broadcast on leave |
| `onDidNotLaunch` | `function`| Callback if launch fails |
| `allowLaunchRetry` | `boolean` | Retry port binding if true |
## π RoomIO Events
| Event | Payload | Description |
|------------------|-------------------------------------|-------------|
| `join room` | `{ roomName, userID }` | Join a room |
| `leave room` | `{ roomName, userID }` | Leave a room |
| `message room` | `{ roomName, message, userID }` | Broadcast message |
| `room joined` | `{ roomName, userID }` | Ack of join |
| `user joined` | `{ userID }` | Others notified |
| `user left` | `{ userID }` | Others notified |
| `all users` | `{ roomName, users : [userID] }` | Room user list |
| `incoming message`| `{ userID, message }` | Room message received |
## π Specifications
| Method | Description | Async |
|----------------------------------|-----------------------------------------------------------------------------|--------|
| `emit(event, ...args)` | Broadcasts an event to all connected sockets | β |
| `emitToTide(tideID, event, ...args)` | Emits an event to a specific client by tideID | β |
| `emitOnChannel(channel, event, message, userID)` | Broadcasts a message to a specific channel | β |
| `emitToChannel(tideID, channel, event, message, userID, includeSender?)` | Emits to room, optionally including sender | β |
| `emitTideWithResponse(event, args, eventID, timeout?)` | Emits an event and waits for a response | β
|
| `emitTide(event, ...args)` | Emits an event internally for server-side chaining | β |
| `on(event, handler, tideGuardian?)` | Registers a handler for any custom event | β |
| `onChannel(event, handler, tideGuardian?)` | Registers a handler for a specific channel-scope event | β |
| `joinChannel(tideID, roomData)` | Joins a socket to a room | β |
| `leaveChannel(tideID, roomData)`| Removes a socket from a room | β |
| `messageChannel(tideID, roomData)`| Sends a message from a socket to a room | β |
| `removeAllFromChannel(roomData, options?)` | Removes all sockets from a room | β |
| `disconnectTide(tideID, reason?)` | Forcefully disconnects a specific client | β |
| `close()` | Shuts down the IoTide server and disconnects all clients | β |
## π Method Overview
### `emit(event, ...args)`
Broadcast an event globally to all connected sockets.
Useful for system-wide alerts, status updates, or global sync events.
```js
iotide.emit("system:announcement", {
message : "Server will restart in 5 minutes"
});
```
### `emitToTide(tideID, event, ...args)`
Send a targeted message to a specific socket using its `tideID`.
Ideal for private messages, acknowledgments, or scoped commands.
```js
iotide.emitToTide("tide-user-123", "notification", {
title : "New message",
body : "You have 1 unread message"
});
```
### `emitOnChannel(channel, event, message, userID)`
Emit a message to all sockets in a specific room or channel.
Inject `userID` to track the emitter for logging or replay.
```js
iotide.emitOnChannel("support", "chat:message", "Hello, how can I help?", "agent42");
```
### `emitToChannel(tideID, channel, event, message, userID, includeSender = false)`
Send a message to everyone in a room.
Set `includeSender = true` to include the emitting client in the broadcast.
```js
iotide.emitToChannel("tide-user-123", "general", "chat:message", "Hey everyone!", "user123", true);
```
### `emitTide(event, ...args)`
Trigger internal server-side event logic.
Use this to chain actions as if they were client-driven β ideal for orchestration or flow triggers.
```js
iotide.emitTide("internal:sync:data", { resource : "users" });
```
### `emitTideWithResponse(event, args, eventID, timeout = 15000)`
Emit an event and wait for a response tied to a separate event ID.
Times out if no response returns within the given window.
Useful for requestβresponse flows, handshake validation, or async control pipelines.
```js
const result = await iotide.emitTideWithResponse("get:status", {}, "status:response");
console.log("Received response:", result);
```
### `on(event, handler, tideGuardian = null)`
Attach a handler to a specific event.
Pass a `tideGuardian` to guard access β see **TideGuardians** below.
```js
iotide.on("upload:file", (socket, fileData) => {
console.log("Received upload:", fileData);
}, (socket) => socket.userRole === "editor");
```
### `onChannel(event, handler, tideGuardian = null)`
Same as `on()`, but scoped to channel-based logic.
Applies to any room-interaction-based events.
```js
iotide.onChannel("room:edit", (socket, data) => {
console.log(`Room ${data.roomName} modified`);
});
```
### `joinChannel(tideID, roomData)`
Manually join a socket to a room.
Useful when bypassing the default `"join room"` event, or initiating on behalf of a socket.
```js
iotide.joinChannel("tide-user-456", { roomName : "admin", userID : "admin456" });
```
### `leaveChannel(tideID, roomData)`
Force a socket to leave a specific room.
Typically paired with permission logic or cleanup routines.
```js
iotide.leaveChannel("tide-user-456", { roomName : "admin", userID : "admin456" });
```
### `messageChannel(tideID, roomData)`
Push a message into a room from a specific user.
IoTide handles rebroadcasting to all members.
```js
iotide.messageChannel("tide-user-789", {
roomName : "support",
message : "Customer left the chat",
userID : "support-bot"
});
```
### `removeAllFromChannel(roomData, options = {})`
Remove every socket from a specified room.
Inject optional logic for permission checks or state cleanup via `options`.
```js
iotide.removeAllFromChannel({ roomName : "beta-testers" });
```
### `disconnectTide(tideID, reason = "manual disconnect")`
Disconnect a specific socket.
Specify a `reason` for auditing or in-client diagnostics.
```js
iotide.disconnectTide("tide-user-321", "Idle too long");
```
### `close()`
Gracefully shut down the server and disconnect all clients.
Use this during process exits, restarts, or maintenance flows.
```js
process.on("SIGINT", () => {
iotide.close();
process.exit();
});
```
## π§± TideGuardians
**TideGuardians** enforce access control for event handlers.
Use them to validate context, roles, or message content before proceeding.
### Example
```js
iotide.on("admin:delete", (socket, data) => {
console.log("Deleting entry:", data.id);
}, (socket) => socket.userRole === "admin");
```
If the guardian returns `false`, IoTide skips the handler and denies the action.
Use TideGuardians to:
- Protect privileged events
- Enforce custom permissions
- Apply rule-based logic without bloating handlers
## π TidalCore Integration
Each **IoTide server instance** holds a unique `tideID` generated by **TidalCore**.
This identifier supports:
- Authenticating across multiple IoTide nodes
- Synchronizing trusted events between server instances
- Logging session fingerprints tied to the server
- Validating signed identity payloads
Access the serverβs identity:
```js
const myTideID = iotide.ioTideID;
```
All connected sockets receive scoped identifiers for targeted communication and tracking.
Custom identity flows or authorization layers can further enhance validation.
## π¦ Installation
```bash
npm install @trap_stevo/iotide
```
## π‘ Example Usage
```js
const IoTide = require("@trap_stevo/iotide");
const iotide = new IoTide(443, {
useHTTPS : true,
sslCertPath : "./cert.pem",
sslKeyPath : "./key.pem",
useCors : true,
corsOptions : { origin : "*" }
}, true, (socket) => {
console.log("Connected:", socket.tideID);
}, null, () => {
console.log("IoTide server launched");
});
```
## π License
[SCL-1.0-Universal](./SCL-1.0-Universal.md)
## π IoTide: Real-time Networking Made Legendary
Use IoTide to bridge everything β users, apps, devices, or microservices β with clean event architecture, ID-aware logic, and cross-room control.
> **Built for performance. Designed for flexibility. Yours to shape.**