oddsockets-nodejs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ OddSockets Node.js SDK - End User License Agreement
2
+
3
+ Copyright (c) 2026 Tyga.Cloud Ltd. All rights reserved.
4
+
5
+ Permission is granted to install and use this software via npm for its
6
+ intended purpose (interacting with the OddSockets platform at oddsockets.com).
7
+
8
+ You may NOT:
9
+ - Reverse-engineer, decompile, or disassemble this software
10
+ - Redistribute, sublicense, or resell this software
11
+ - Modify or create derivative works based on this software
12
+ - Remove or alter any copyright notices contained in this software
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
+ TYGA.CLOUD LTD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+
21
+ Full terms of service: https://oddsockets.com/terms
package/README.md ADDED
@@ -0,0 +1,448 @@
1
+ # OddSockets Node.js SDK
2
+
3
+ Official Node.js SDK for the OddSockets real-time messaging platform. This SDK provides a simple, powerful interface for building real-time applications with automatic manager discovery, worker load balancing, and message size validation.
4
+
5
+ ## Features
6
+
7
+ - **Simple API** - Easy-to-use interface for real-time messaging
8
+ - **Auto-reconnection** - Automatic reconnection with exponential backoff
9
+ - **Message Size Validation** - Industry-standard 32KB message size limits
10
+ - **Session Stickiness** - Consistent worker assignment for optimal performance
11
+ - **PubNub Compatibility** - Drop-in replacement for PubNub applications
12
+ - **Bulk Operations** - Publish multiple messages efficiently
13
+ - **TypeScript Support** - Full TypeScript definitions included
14
+ - **Presence Tracking** - Real-time user presence and state management
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @oddsocketsai/nodejs-sdk
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ```javascript
25
+ const OddSockets = require('@oddsocketsai/nodejs-sdk');
26
+
27
+ // Initialize the client
28
+ const client = new OddSockets({
29
+ apiKey: 'your-api-key-here',
30
+ userId: 'user-123'
31
+ });
32
+
33
+ // Listen for connection events
34
+ client.on('connected', () => {
35
+ console.log('Connected to OddSockets');
36
+ });
37
+
38
+ // Get a channel and subscribe
39
+ const channel = client.channel('my-channel');
40
+
41
+ await channel.subscribe((message) => {
42
+ console.log('Received:', message);
43
+ });
44
+
45
+ // Publish a message
46
+ await channel.publish({
47
+ text: 'Hello World!',
48
+ timestamp: new Date().toISOString()
49
+ });
50
+ ```
51
+
52
+ ## Configuration Options
53
+
54
+ ```javascript
55
+ const client = new OddSockets({
56
+ apiKey: 'your-api-key-here', // Required: Your OddSockets API key
57
+ userId: 'user-123', // Optional: User identifier
58
+ autoConnect: true, // Optional: Auto-connect on initialization (default: true)
59
+ options: { // Optional: Additional Socket.IO options
60
+ transports: ['websocket', 'polling'],
61
+ timeout: 10000
62
+ }
63
+ });
64
+ ```
65
+
66
+ ## Channel Operations
67
+
68
+ ### Subscribe to Messages
69
+
70
+ ```javascript
71
+ const channel = client.channel('my-channel');
72
+
73
+ // Basic subscription
74
+ await channel.subscribe((message) => {
75
+ console.log('Message:', message.message);
76
+ console.log('Publisher:', message.publisher);
77
+ console.log('Timestamp:', message.timestamp);
78
+ });
79
+
80
+ // Subscribe with options
81
+ await channel.subscribe((message) => {
82
+ console.log('Received:', message);
83
+ }, {
84
+ enablePresence: true, // Enable presence tracking
85
+ retainHistory: true, // Keep message history in memory
86
+ maxHistory: 100 // Maximum messages to retain
87
+ });
88
+ ```
89
+
90
+ ### Publish Messages
91
+
92
+ ```javascript
93
+ // Simple message
94
+ await channel.publish('Hello World!');
95
+
96
+ // Complex message with metadata
97
+ await channel.publish({
98
+ text: 'Hello World!',
99
+ user: 'john_doe',
100
+ timestamp: new Date().toISOString()
101
+ }, {
102
+ ttl: 3600, // Time to live in seconds
103
+ metadata: { // Additional metadata
104
+ priority: 'high'
105
+ }
106
+ });
107
+ ```
108
+
109
+ ### Bulk Publishing
110
+
111
+ ```javascript
112
+ // Publish multiple messages at once
113
+ const results = await client.publishBulk([
114
+ { channel: 'channel-1', message: 'Message 1' },
115
+ { channel: 'channel-2', message: 'Message 2' },
116
+ { channel: 'channel-1', message: 'Message 3', options: { ttl: 3600 } }
117
+ ]);
118
+
119
+ results.forEach((result, index) => {
120
+ if (result.success) {
121
+ console.log(`Message ${index + 1} published successfully`);
122
+ } else {
123
+ console.error(`Message ${index + 1} failed:`, result.error);
124
+ }
125
+ });
126
+ ```
127
+
128
+ ### Message History
129
+
130
+ ```javascript
131
+ // Get recent messages
132
+ const history = await channel.getHistory({
133
+ count: 50, // Number of messages (default: 50)
134
+ start: '2023-01-01T00:00:00Z', // Start time (ISO string)
135
+ end: '2023-12-31T23:59:59Z' // End time (ISO string)
136
+ });
137
+
138
+ console.log('History:', history);
139
+ ```
140
+
141
+ ### Presence Management
142
+
143
+ ```javascript
144
+ // Get current presence
145
+ const presence = await channel.getPresence();
146
+ console.log('Online users:', presence.occupancy);
147
+ console.log('User list:', presence.occupants);
148
+
149
+ // Update user state
150
+ await channel.updateState({
151
+ status: 'online',
152
+ mood: 'happy',
153
+ location: 'New York'
154
+ });
155
+
156
+ // Listen for presence changes
157
+ channel.on('presence_change', (event) => {
158
+ console.log(`User ${event.user.userId} ${event.action}`);
159
+ console.log('Current occupancy:', event.occupancy);
160
+ });
161
+ ```
162
+
163
+ ## PubNub Compatibility
164
+
165
+ Migrate from PubNub with minimal code changes:
166
+
167
+ ```javascript
168
+ const { PubNubCompat } = require('@oddsocketsai/nodejs-sdk');
169
+
170
+ // Initialize with PubNub-style config
171
+ const pubnub = new PubNubCompat({
172
+ publishKey: 'your-api-key-here',
173
+ subscribeKey: 'your-api-key-here',
174
+ userId: 'user-123'
175
+ });
176
+
177
+ // Add listeners (PubNub style)
178
+ pubnub.addListener({
179
+ message: (messageEvent) => {
180
+ console.log('Message:', messageEvent.message);
181
+ console.log('Channel:', messageEvent.channel);
182
+ console.log('Publisher:', messageEvent.publisher);
183
+ },
184
+ presence: (presenceEvent) => {
185
+ console.log('Presence:', presenceEvent.action);
186
+ console.log('User:', presenceEvent.uuid);
187
+ },
188
+ status: (statusEvent) => {
189
+ console.log('Status:', statusEvent.category);
190
+ }
191
+ });
192
+
193
+ // Subscribe to channels
194
+ pubnub.subscribe({
195
+ channels: ['channel-1', 'channel-2'],
196
+ withPresence: true
197
+ });
198
+
199
+ // Publish messages
200
+ pubnub.publish({
201
+ channel: 'channel-1',
202
+ message: 'Hello from PubNub compatibility!'
203
+ }, (response) => {
204
+ if (response.error) {
205
+ console.error('Error:', response.error);
206
+ } else {
207
+ console.log('Published with timetoken:', response.timetoken);
208
+ }
209
+ });
210
+ ```
211
+
212
+ ## Event Handling
213
+
214
+ ```javascript
215
+ // Connection events
216
+ client.on('connected', () => {
217
+ console.log('Connected to OddSockets');
218
+ });
219
+
220
+ client.on('disconnected', (reason) => {
221
+ console.log('Disconnected:', reason);
222
+ });
223
+
224
+ client.on('reconnecting', (attempt) => {
225
+ console.log(`Reconnecting... attempt ${attempt.attempt}/${attempt.maxAttempts}`);
226
+ });
227
+
228
+ client.on('error', (error) => {
229
+ console.error('Connection error:', error);
230
+ });
231
+
232
+ client.on('worker_assigned', (info) => {
233
+ console.log('Assigned to worker:', info.workerId);
234
+ console.log('Worker URL:', info.workerUrl);
235
+ });
236
+
237
+ // Channel events
238
+ channel.on('subscribed', (data) => {
239
+ console.log('Subscribed to channel:', data.channel);
240
+ });
241
+
242
+ channel.on('unsubscribed', (data) => {
243
+ console.log('Unsubscribed from channel:', data.channel);
244
+ });
245
+
246
+ channel.on('published', (data) => {
247
+ console.log('Message published:', data);
248
+ });
249
+ ```
250
+
251
+ ## Error Handling
252
+
253
+ ```javascript
254
+ try {
255
+ await channel.publish('Hello World!');
256
+ } catch (error) {
257
+ if (error.message.includes('Message size')) {
258
+ console.error('Message too large (max 32KB)');
259
+ } else if (error.message.includes('Not connected')) {
260
+ console.error('Client not connected');
261
+ } else {
262
+ console.error('Publish failed:', error.message);
263
+ }
264
+ }
265
+ ```
266
+
267
+ ## Advanced Usage
268
+
269
+ ### Custom Connection Options
270
+
271
+ ```javascript
272
+ const client = new OddSockets({
273
+ apiKey: 'your-api-key-here',
274
+ userId: 'user-123',
275
+ options: {
276
+ transports: ['websocket'], // Force WebSocket only
277
+ timeout: 15000, // Connection timeout
278
+ forceNew: true, // Force new connection
279
+ reconnection: true, // Enable reconnection
280
+ reconnectionDelay: 1000, // Initial reconnection delay
281
+ reconnectionAttempts: 5, // Max reconnection attempts
282
+ maxReconnectionAttempts: 10 // Max total attempts
283
+ }
284
+ });
285
+ ```
286
+
287
+ ### Manual Connection Management
288
+
289
+ ```javascript
290
+ const client = new OddSockets({
291
+ apiKey: 'your-api-key-here',
292
+ autoConnect: false // Don't auto-connect
293
+ });
294
+
295
+ // Connect manually
296
+ await client.connect();
297
+
298
+ // Check connection state
299
+ console.log('State:', client.getState()); // 'connected', 'connecting', 'disconnected', 'reconnecting'
300
+
301
+ // Get worker info
302
+ const workerInfo = client.getWorkerInfo();
303
+ console.log('Worker ID:', workerInfo.workerId);
304
+ console.log('Worker URL:', workerInfo.workerUrl);
305
+
306
+ // Disconnect
307
+ client.disconnect();
308
+ ```
309
+
310
+ ### Session Information
311
+
312
+ ```javascript
313
+ // Get client identifier (used for session stickiness)
314
+ const clientId = client.getClientIdentifier();
315
+ console.log('Client ID:', clientId);
316
+
317
+ // Get session info
318
+ const session = client.getSessionInfo();
319
+ console.log('Session:', session);
320
+ ```
321
+
322
+ ## Message Size Limits
323
+
324
+ The SDK enforces industry-standard message size limits:
325
+
326
+ - **Maximum message size**: 32KB (32,768 bytes)
327
+ - **Encoding**: UTF-8
328
+ - **Validation**: Automatic before publishing
329
+
330
+ ```javascript
331
+ // This will throw an error if message exceeds 32KB
332
+ try {
333
+ await channel.publish({
334
+ data: 'x'.repeat(40000) // Too large!
335
+ });
336
+ } catch (error) {
337
+ console.error(error.message);
338
+ // "Message size (39KB) exceeds maximum allowed size of 32KB"
339
+ }
340
+ ```
341
+
342
+ ## Examples
343
+
344
+ Run the included examples:
345
+
346
+ ```bash
347
+ # Basic usage example
348
+ node examples/basic-usage.js
349
+
350
+ # PubNub compatibility example
351
+ node examples/basic-usage.js pubnub
352
+ ```
353
+
354
+ ## API Reference
355
+
356
+ ### OddSockets Class
357
+
358
+ #### Constructor
359
+ - `new OddSockets(config)` - Create a new client instance
360
+
361
+ #### Methods
362
+ - `connect()` - Connect to OddSockets platform
363
+ - `disconnect()` - Disconnect from platform
364
+ - `channel(name)` - Get or create a channel
365
+ - `publishBulk(messages)` - Publish multiple messages
366
+ - `getState()` - Get connection state
367
+ - `getWorkerInfo()` - Get assigned worker information
368
+ - `getClientIdentifier()` - Get client identifier
369
+ - `getSessionInfo()` - Get session information
370
+
371
+ #### Events
372
+ - `connected` - Connected to platform
373
+ - `disconnected` - Disconnected from platform
374
+ - `reconnecting` - Attempting to reconnect
375
+ - `error` - Connection error occurred
376
+ - `worker_assigned` - Assigned to a worker
377
+
378
+ ### Channel Class
379
+
380
+ #### Methods
381
+ - `subscribe(callback, options)` - Subscribe to messages
382
+ - `unsubscribe()` - Unsubscribe from channel
383
+ - `publish(message, options)` - Publish a message
384
+ - `getHistory(options)` - Get message history
385
+ - `getPresence()` - Get presence information
386
+ - `updateState(state)` - Update user state
387
+ - `isSubscribed()` - Check subscription status
388
+ - `getName()` - Get channel name
389
+
390
+ #### Events
391
+ - `message` - New message received
392
+ - `subscribed` - Successfully subscribed
393
+ - `unsubscribed` - Successfully unsubscribed
394
+ - `published` - Message published
395
+ - `presence` - Presence information
396
+ - `presence_change` - Presence changed
397
+
398
+ ## Get a Free API Key
399
+
400
+ AI agents can sign up with a verified email in two steps — no dashboard, no human required.
401
+
402
+ **Step 1:** Request a verification code
403
+ ```bash
404
+ curl -X POST https://oddsockets.com/api/agent-signup \
405
+ -H "Content-Type: application/json" \
406
+ -d '{"email": "you@example.com", "agentName": "my-agent", "platform": "claude"}'
407
+ ```
408
+
409
+ **Step 2:** Verify the 6-digit code from your email and get your API key
410
+ ```bash
411
+ curl -X POST https://oddsockets.com/api/agent-signup/verify \
412
+ -H "Content-Type: application/json" \
413
+ -d '{"email": "you@example.com", "code": "123456", "agentName": "my-agent"}'
414
+ ```
415
+
416
+ ## Plans
417
+
418
+ | | Free | Starter | Pro |
419
+ |---|---|---|---|
420
+ | **Price** | $0/mo | $49.99/mo | $299/mo |
421
+ | **MAU** | 100 | 1,000 | 50,000 |
422
+ | **Concurrent connections** | 50 | 1,000 | Unlimited |
423
+ | **Messages/day** | 10,000 | 4,320,000 | Unlimited |
424
+ | **Messages/minute** | 100 | 3,000 | Unlimited |
425
+ | **Channels** | 10 | Unlimited | Unlimited |
426
+ | **Storage** | 100MB (24h) | 50GB (6 months) | Unlimited |
427
+ | **Webhooks** | No | Yes | Yes |
428
+ | **Analytics** | No | Yes | Yes |
429
+ | **Support** | Community | 24/5 email & chat | Dedicated team |
430
+
431
+ All limits are enforced in real time. When a limit is reached, the SDK receives a `RATE_LIMIT_EXCEEDED` error with a `retryAfter` value.
432
+
433
+ See [pricing](https://oddsockets.com/pricing) for full details.
434
+
435
+ ## Requirements
436
+
437
+ - Node.js 14.0.0 or higher
438
+ - Active OddSockets API key ([get one free](#get-a-free-api-key))
439
+
440
+ ## Support
441
+
442
+ - [Documentation](https://docs.oddsockets.com/sdks/nodejs)
443
+ - [Issue Tracker](https://github.com/jyswee/oddsockets-nodejs-sdk/issues)
444
+ - [Email Support](mailto:support@oddsockets.com)
445
+
446
+ ## License
447
+
448
+ MIT License - Copyright (c) 2026 Joe Wee, Tyga.Cloud Ltd. See [LICENSE](LICENSE) for details.