@wsocket-io/sdk 0.1.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
+ MIT License
2
+
3
+ Copyright (c) 2026 wSocket
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # wSocket JavaScript SDK
2
+
3
+ Official JavaScript/TypeScript SDK for [wSocket](https://wsocket.io) — Realtime Pub/Sub over WebSockets.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@wsocket-io/sdk)](https://www.npmjs.com/package/@wsocket-io/sdk)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @wsocket-io/sdk
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```typescript
17
+ import { createClient } from '@wsocket-io/sdk';
18
+
19
+ const client = createClient('wss://your-server.com', 'your-api-key');
20
+ client.connect();
21
+
22
+ const chat = client.channel('chat:general');
23
+
24
+ chat.subscribe((data, meta) => {
25
+ console.log(`[${meta.channel}]`, data);
26
+ });
27
+
28
+ chat.publish({ text: 'Hello from JavaScript!' });
29
+ ```
30
+
31
+ ## Features
32
+
33
+ - **Pub/Sub** — Subscribe and publish to channels in real-time
34
+ - **Presence** — Track who is online in a channel
35
+ - **History** — Retrieve past messages
36
+ - **Push Notifications** — Web Push via Service Workers
37
+ - **Connection Recovery** — Automatic reconnection with message replay
38
+ - **TypeScript** — Full type definitions included
39
+
40
+ ## Presence
41
+
42
+ ```typescript
43
+ const chat = client.channel('chat:general');
44
+
45
+ chat.presence.onEnter((member) => {
46
+ console.log(`Joined: ${member.clientId}`);
47
+ });
48
+
49
+ chat.presence.onLeave((member) => {
50
+ console.log(`Left: ${member.clientId}`);
51
+ });
52
+
53
+ chat.presence.enter({ name: 'Alice' });
54
+ const members = chat.presence.get();
55
+ ```
56
+
57
+ ## History
58
+
59
+ ```typescript
60
+ chat.onHistory((result) => {
61
+ result.messages.forEach((msg) => {
62
+ console.log(`[${msg.timestamp}] ${JSON.stringify(msg.data)}`);
63
+ });
64
+ });
65
+
66
+ chat.history({ limit: 50 });
67
+ ```
68
+
69
+ ## Push Notifications
70
+
71
+ ```typescript
72
+ client.configurePush({
73
+ vapidPublicKey: 'your-vapid-public-key',
74
+ serviceWorkerPath: '/sw.js',
75
+ });
76
+
77
+ await client.push?.subscribe('alerts');
78
+ ```
79
+
80
+ ## Requirements
81
+
82
+ - Node.js >= 18 or modern browsers
83
+ - `ws >= 8.0` (Node.js only)
84
+
85
+ ## Development
86
+
87
+ ```bash
88
+ npm install
89
+ npm run build
90
+ npm test
91
+ ```
92
+
93
+ ## License
94
+
95
+ MIT
@@ -0,0 +1,95 @@
1
+ import type { ConnectionState, WSocketOptions, EventCallback } from './types.js';
2
+ import { Channel } from './pubsub/channel.js';
3
+ import { PubSubNamespace } from './pubsub/index.js';
4
+ import { PushClient, type PushClientOptions } from './push/index.js';
5
+ export type { ConnectionState, WSocketOptions, ChannelSubscription, MessageMeta, PresenceMember, HistoryMessage, HistoryResult, HistoryOptions, PublishOptions, EventCallback, ClientMessage, ServerMessage, } from './types.js';
6
+ export { Channel } from './pubsub/channel.js';
7
+ export { Presence } from './pubsub/presence.js';
8
+ export { PubSubNamespace } from './pubsub/index.js';
9
+ export { PushClient, type PushClientOptions, type PushPayload } from './push/index.js';
10
+ export declare class WSocket {
11
+ private ws;
12
+ private url;
13
+ private apiKey;
14
+ private options;
15
+ private state;
16
+ private channels;
17
+ private events;
18
+ private reconnectAttempts;
19
+ private reconnectTimer;
20
+ private pingInterval;
21
+ private lastMessageTimestamp;
22
+ private resumeToken;
23
+ /** Pub/Sub namespace — `client.pubsub.channel('name')` */
24
+ readonly pubsub: PubSubNamespace;
25
+ /** Push notifications namespace — set via `client.configurePush(options)` */
26
+ push: PushClient | null;
27
+ constructor(url: string, apiKey: string, options?: WSocketOptions);
28
+ /**
29
+ * Configure push notification access.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * client.configurePush({
34
+ * baseUrl: 'http://localhost:9001',
35
+ * token: 'your-api-key',
36
+ * appId: 'your-app-id',
37
+ * });
38
+ *
39
+ * await client.push!.sendToMember('user-1', { title: 'Hello' });
40
+ * ```
41
+ */
42
+ configurePush(options: PushClientOptions): PushClient;
43
+ /** Connect to the wSocket server */
44
+ connect(): Promise<void>;
45
+ /** Disconnect from the server */
46
+ disconnect(): void;
47
+ /**
48
+ * Get or create a channel.
49
+ * @deprecated Use `client.pubsub.channel(name)` for new code.
50
+ */
51
+ channel(name: string): Channel;
52
+ /** Listen for client events: 'connected', 'disconnected', 'error', 'state' */
53
+ on(event: string, callback: EventCallback): this;
54
+ /** Remove an event listener */
55
+ off(event: string, callback: EventCallback): this;
56
+ /** Current connection state */
57
+ get connectionState(): ConnectionState;
58
+ private send;
59
+ private handleMessage;
60
+ private setState;
61
+ private emit;
62
+ private resubscribeAll;
63
+ private scheduleReconnect;
64
+ private startPing;
65
+ private stopPing;
66
+ }
67
+ /**
68
+ * Create a new wSocket client.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * import { createClient } from '@wsocket/sdk';
73
+ *
74
+ * const client = createClient('ws://localhost:9001', 'your-api-key');
75
+ * await client.connect();
76
+ *
77
+ * // Pub/Sub (backward compatible)
78
+ * const chat = client.channel('chat');
79
+ * chat.subscribe((data, meta) => console.log('Received:', data));
80
+ * chat.publish({ text: 'Hello!' });
81
+ *
82
+ * // New namespaced API
83
+ * client.pubsub.channel('chat').publish({ text: 'Hello!' });
84
+ *
85
+ * // Push notifications
86
+ * client.configurePush({
87
+ * baseUrl: 'http://localhost:9001',
88
+ * token: 'your-api-key',
89
+ * appId: 'your-app-id',
90
+ * });
91
+ * await client.push!.sendToMember('user-1', { title: 'New message!' });
92
+ * ```
93
+ */
94
+ export declare function createClient(url: string, apiKey: string, options?: WSocketOptions): WSocket;
95
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EAAE,cAAc,EACa,aAAa,EAC1D,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIrE,YAAY,EACV,eAAe,EAAE,cAAc,EAAE,mBAAmB,EACpD,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAC1D,cAAc,EAAE,cAAc,EAAE,aAAa,EAC7C,aAAa,EAAE,aAAa,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAIvF,qBAAa,OAAO;IAClB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA0E;IACzF,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,WAAW,CAAuB;IAE1C,0DAA0D;IAC1D,SAAgB,MAAM,EAAE,eAAe,CAAC;IAExC,6EAA6E;IACtE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAQ;gBAE1B,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB;IAiBrE;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU;IAOrD,oCAAoC;IACpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDxB,iCAAiC;IACjC,UAAU,IAAI,IAAI;IAelB;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAS9B,8EAA8E;IAC9E,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAQhD,+BAA+B;IAC/B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAKjD,+BAA+B;IAC/B,IAAI,eAAe,IAAI,eAAe,CAErC;IAID,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,aAAa;IAiFrB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,IAAI;IAaZ,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,iBAAiB;IAkBzB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,QAAQ;CAMjB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAE3F"}
package/dist/index.js ADDED
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WSocket = exports.PushClient = exports.PubSubNamespace = exports.Presence = exports.Channel = void 0;
7
+ exports.createClient = createClient;
8
+ const ws_1 = __importDefault(require("ws"));
9
+ const channel_js_1 = require("./pubsub/channel.js");
10
+ const index_js_1 = require("./pubsub/index.js");
11
+ const index_js_2 = require("./push/index.js");
12
+ var channel_js_2 = require("./pubsub/channel.js");
13
+ Object.defineProperty(exports, "Channel", { enumerable: true, get: function () { return channel_js_2.Channel; } });
14
+ var presence_js_1 = require("./pubsub/presence.js");
15
+ Object.defineProperty(exports, "Presence", { enumerable: true, get: function () { return presence_js_1.Presence; } });
16
+ var index_js_3 = require("./pubsub/index.js");
17
+ Object.defineProperty(exports, "PubSubNamespace", { enumerable: true, get: function () { return index_js_3.PubSubNamespace; } });
18
+ var index_js_4 = require("./push/index.js");
19
+ Object.defineProperty(exports, "PushClient", { enumerable: true, get: function () { return index_js_4.PushClient; } });
20
+ // ─── wSocket Client ────────────────────────────────────────
21
+ class WSocket {
22
+ ws = null;
23
+ url;
24
+ apiKey;
25
+ options;
26
+ state = 'disconnected';
27
+ channels = new Map();
28
+ events = new Map();
29
+ reconnectAttempts = 0;
30
+ reconnectTimer = null;
31
+ pingInterval = null;
32
+ lastMessageTimestamp = 0;
33
+ resumeToken = null;
34
+ /** Pub/Sub namespace — `client.pubsub.channel('name')` */
35
+ pubsub;
36
+ /** Push notifications namespace — set via `client.configurePush(options)` */
37
+ push = null;
38
+ constructor(url, apiKey, options = {}) {
39
+ this.url = url;
40
+ this.apiKey = apiKey;
41
+ this.options = {
42
+ autoReconnect: options.autoReconnect ?? true,
43
+ maxReconnectAttempts: options.maxReconnectAttempts ?? 10,
44
+ reconnectDelay: options.reconnectDelay ?? 1000,
45
+ token: options.token,
46
+ recover: options.recover ?? true,
47
+ };
48
+ // Pubsub namespace delegates to channel()
49
+ this.pubsub = new index_js_1.PubSubNamespace((name) => this.channel(name));
50
+ }
51
+ // ─── Push Configuration ──────────────────────────────────
52
+ /**
53
+ * Configure push notification access.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * client.configurePush({
58
+ * baseUrl: 'http://localhost:9001',
59
+ * token: 'your-api-key',
60
+ * appId: 'your-app-id',
61
+ * });
62
+ *
63
+ * await client.push!.sendToMember('user-1', { title: 'Hello' });
64
+ * ```
65
+ */
66
+ configurePush(options) {
67
+ this.push = new index_js_2.PushClient(options);
68
+ return this.push;
69
+ }
70
+ // ─── Connection ──────────────────────────────────────────
71
+ /** Connect to the wSocket server */
72
+ connect() {
73
+ return new Promise((resolve, reject) => {
74
+ if (this.state === 'connected') {
75
+ resolve();
76
+ return;
77
+ }
78
+ this.setState('connecting');
79
+ const wsUrl = this.options.token
80
+ ? `${this.url}?token=${encodeURIComponent(this.options.token)}`
81
+ : `${this.url}?key=${encodeURIComponent(this.apiKey)}`;
82
+ try {
83
+ this.ws = new ws_1.default(wsUrl);
84
+ }
85
+ catch (err) {
86
+ this.setState('disconnected');
87
+ reject(err);
88
+ return;
89
+ }
90
+ this.ws.on('open', () => {
91
+ this.setState('connected');
92
+ this.reconnectAttempts = 0;
93
+ this.startPing();
94
+ this.resubscribeAll();
95
+ resolve();
96
+ });
97
+ this.ws.on('message', (raw) => {
98
+ this.handleMessage(raw.toString());
99
+ });
100
+ this.ws.on('close', (code) => {
101
+ this.stopPing();
102
+ this.emit('disconnected', code);
103
+ if (this.state !== 'disconnected' && this.options.autoReconnect) {
104
+ this.scheduleReconnect();
105
+ }
106
+ });
107
+ this.ws.on('error', (err) => {
108
+ this.emit('error', err);
109
+ if (this.state === 'connecting') {
110
+ reject(err);
111
+ }
112
+ });
113
+ });
114
+ }
115
+ /** Disconnect from the server */
116
+ disconnect() {
117
+ this.setState('disconnected');
118
+ this.stopPing();
119
+ if (this.reconnectTimer) {
120
+ clearTimeout(this.reconnectTimer);
121
+ this.reconnectTimer = null;
122
+ }
123
+ if (this.ws) {
124
+ this.ws.close();
125
+ this.ws = null;
126
+ }
127
+ }
128
+ // ─── Channels ────────────────────────────────────────────
129
+ /**
130
+ * Get or create a channel.
131
+ * @deprecated Use `client.pubsub.channel(name)` for new code.
132
+ */
133
+ channel(name) {
134
+ if (!this.channels.has(name)) {
135
+ this.channels.set(name, new channel_js_1.Channel(name, (msg) => this.send(msg)));
136
+ }
137
+ return this.channels.get(name);
138
+ }
139
+ // ─── Events ──────────────────────────────────────────────
140
+ /** Listen for client events: 'connected', 'disconnected', 'error', 'state' */
141
+ on(event, callback) {
142
+ if (!this.events.has(event)) {
143
+ this.events.set(event, new Set());
144
+ }
145
+ this.events.get(event).add(callback);
146
+ return this;
147
+ }
148
+ /** Remove an event listener */
149
+ off(event, callback) {
150
+ this.events.get(event)?.delete(callback);
151
+ return this;
152
+ }
153
+ /** Current connection state */
154
+ get connectionState() {
155
+ return this.state;
156
+ }
157
+ // ─── Internal ────────────────────────────────────────────
158
+ send(msg) {
159
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
160
+ this.ws.send(JSON.stringify(msg));
161
+ }
162
+ }
163
+ handleMessage(raw) {
164
+ let msg;
165
+ try {
166
+ msg = JSON.parse(raw);
167
+ }
168
+ catch {
169
+ return;
170
+ }
171
+ switch (msg.action) {
172
+ case 'message': {
173
+ if (msg.channel) {
174
+ const ch = this.channels.get(msg.channel);
175
+ if (ch) {
176
+ const ts = msg.timestamp || Date.now();
177
+ if (ts > this.lastMessageTimestamp) {
178
+ this.lastMessageTimestamp = ts;
179
+ }
180
+ ch._emit(msg.data, {
181
+ id: msg.id || '',
182
+ channel: msg.channel,
183
+ timestamp: ts,
184
+ });
185
+ }
186
+ }
187
+ break;
188
+ }
189
+ case 'subscribed':
190
+ this.emit('subscribed', msg.channel);
191
+ break;
192
+ case 'unsubscribed':
193
+ this.emit('unsubscribed', msg.channel);
194
+ break;
195
+ case 'ack':
196
+ if (msg.id === 'resume' && msg.data?.resumeToken) {
197
+ this.resumeToken = msg.data.resumeToken;
198
+ }
199
+ this.emit('ack', msg.id, msg.channel);
200
+ break;
201
+ case 'error':
202
+ this.emit('error', new Error(msg.error || 'Unknown error'));
203
+ break;
204
+ case 'pong':
205
+ break;
206
+ case 'presence.enter': {
207
+ if (msg.channel) {
208
+ const ch = this.channels.get(msg.channel);
209
+ if (ch)
210
+ ch.presence._emitEnter(msg.data);
211
+ }
212
+ break;
213
+ }
214
+ case 'presence.leave': {
215
+ if (msg.channel) {
216
+ const ch = this.channels.get(msg.channel);
217
+ if (ch)
218
+ ch.presence._emitLeave(msg.data);
219
+ }
220
+ break;
221
+ }
222
+ case 'presence.update': {
223
+ if (msg.channel) {
224
+ const ch = this.channels.get(msg.channel);
225
+ if (ch)
226
+ ch.presence._emitUpdate(msg.data);
227
+ }
228
+ break;
229
+ }
230
+ case 'presence.members': {
231
+ if (msg.channel) {
232
+ const ch = this.channels.get(msg.channel);
233
+ if (ch)
234
+ ch.presence._emitMembers(msg.data);
235
+ }
236
+ break;
237
+ }
238
+ case 'history': {
239
+ if (msg.channel) {
240
+ const ch = this.channels.get(msg.channel);
241
+ if (ch)
242
+ ch._emitHistory(msg.data);
243
+ }
244
+ break;
245
+ }
246
+ }
247
+ }
248
+ setState(state) {
249
+ const prev = this.state;
250
+ this.state = state;
251
+ if (prev !== state) {
252
+ this.emit('state', state, prev);
253
+ if (state === 'connected')
254
+ this.emit('connected');
255
+ }
256
+ }
257
+ emit(event, ...args) {
258
+ const listeners = this.events.get(event);
259
+ if (listeners) {
260
+ for (const cb of listeners) {
261
+ try {
262
+ cb(...args);
263
+ }
264
+ catch {
265
+ // don't let listener errors propagate
266
+ }
267
+ }
268
+ }
269
+ }
270
+ resubscribeAll() {
271
+ if (this.options.recover && this.lastMessageTimestamp > 0) {
272
+ const channelNames = [];
273
+ for (const [, ch] of this.channels) {
274
+ if (ch._hasListeners) {
275
+ channelNames.push(ch.name);
276
+ ch._markForResubscribe();
277
+ }
278
+ }
279
+ if (channelNames.length > 0) {
280
+ const token = this.resumeToken || btoa(JSON.stringify({
281
+ channels: channelNames,
282
+ lastTs: this.lastMessageTimestamp,
283
+ }));
284
+ this.send({ action: 'resume', resumeToken: token });
285
+ return;
286
+ }
287
+ }
288
+ for (const [, ch] of this.channels) {
289
+ if (ch._hasListeners) {
290
+ ch._markForResubscribe();
291
+ this.send({ action: 'subscribe', channel: ch.name });
292
+ }
293
+ }
294
+ }
295
+ scheduleReconnect() {
296
+ if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
297
+ this.setState('disconnected');
298
+ this.emit('error', new Error('Max reconnect attempts reached'));
299
+ return;
300
+ }
301
+ this.setState('reconnecting');
302
+ const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts);
303
+ this.reconnectAttempts++;
304
+ this.reconnectTimer = setTimeout(() => {
305
+ this.connect().catch(() => {
306
+ // will retry via close handler
307
+ });
308
+ }, delay);
309
+ }
310
+ startPing() {
311
+ this.pingInterval = setInterval(() => {
312
+ this.send({ action: 'ping' });
313
+ }, 30_000);
314
+ }
315
+ stopPing() {
316
+ if (this.pingInterval) {
317
+ clearInterval(this.pingInterval);
318
+ this.pingInterval = null;
319
+ }
320
+ }
321
+ }
322
+ exports.WSocket = WSocket;
323
+ // ─── Factory ────────────────────────────────────────────────
324
+ /**
325
+ * Create a new wSocket client.
326
+ *
327
+ * @example
328
+ * ```ts
329
+ * import { createClient } from '@wsocket/sdk';
330
+ *
331
+ * const client = createClient('ws://localhost:9001', 'your-api-key');
332
+ * await client.connect();
333
+ *
334
+ * // Pub/Sub (backward compatible)
335
+ * const chat = client.channel('chat');
336
+ * chat.subscribe((data, meta) => console.log('Received:', data));
337
+ * chat.publish({ text: 'Hello!' });
338
+ *
339
+ * // New namespaced API
340
+ * client.pubsub.channel('chat').publish({ text: 'Hello!' });
341
+ *
342
+ * // Push notifications
343
+ * client.configurePush({
344
+ * baseUrl: 'http://localhost:9001',
345
+ * token: 'your-api-key',
346
+ * appId: 'your-app-id',
347
+ * });
348
+ * await client.push!.sendToMember('user-1', { title: 'New message!' });
349
+ * ```
350
+ */
351
+ function createClient(url, apiKey, options) {
352
+ return new WSocket(url, apiKey, options);
353
+ }
354
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { ClientMessage, MessageMeta, HistoryResult, HistoryOptions, PublishOptions } from '../types.js';
2
+ import { Presence } from './presence.js';
3
+ export declare class Channel {
4
+ readonly name: string;
5
+ private sendFn;
6
+ private listeners;
7
+ private subscribed;
8
+ readonly presence: Presence;
9
+ constructor(name: string, sendFn: (msg: ClientMessage) => void);
10
+ /** Subscribe to messages on this channel */
11
+ subscribe(callback: (data: unknown, meta: MessageMeta) => void, options?: {
12
+ rewind?: number;
13
+ }): this;
14
+ /** Publish data to this channel */
15
+ publish(data: unknown, options?: PublishOptions): this;
16
+ /** Query message history for this channel */
17
+ history(options?: HistoryOptions): this;
18
+ /** Listen for history query results */
19
+ onHistory(callback: (result: HistoryResult) => void): this;
20
+ /** @internal Emit history result to listeners */
21
+ _emitHistory(result: HistoryResult): void;
22
+ /** Unsubscribe from this channel */
23
+ unsubscribe(): void;
24
+ /** @internal Emit a message to listeners */
25
+ _emit(data: unknown, meta: MessageMeta): void;
26
+ /** @internal Mark as needing re-subscribe (after reconnect) */
27
+ _markForResubscribe(): void;
28
+ /** @internal Whether this channel has active listeners */
29
+ get _hasListeners(): boolean;
30
+ get isSubscribed(): boolean;
31
+ }
32
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/pubsub/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,qBAAa,OAAO;aAMA,IAAI,EAAE,MAAM;IAC5B,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,SAAS,CAAsE;IACvF,OAAO,CAAC,UAAU,CAAS;IAC3B,SAAgB,QAAQ,EAAE,QAAQ,CAAC;gBAGjB,IAAI,EAAE,MAAM,EACpB,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI;IAK9C,4CAA4C;IAC5C,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAgBpG,mCAAmC;IACnC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI;IAYtD,6CAA6C;IAC7C,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI;IAavC,uCAAuC;IACvC,SAAS,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAQ1D,iDAAiD;IACjD,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IASzC,oCAAoC;IACpC,WAAW,IAAI,IAAI;IAMnB,4CAA4C;IAC5C,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI;IAa7C,+DAA+D;IAC/D,mBAAmB,IAAI,IAAI;IAI3B,0DAA0D;IAC1D,IAAI,aAAa,IAAI,OAAO,CAG3B;IAED,IAAI,YAAY,IAAI,OAAO,CAE1B;CACF"}
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Channel = void 0;
4
+ const presence_js_1 = require("./presence.js");
5
+ class Channel {
6
+ name;
7
+ sendFn;
8
+ listeners = new Map();
9
+ subscribed = false;
10
+ presence;
11
+ constructor(name, sendFn) {
12
+ this.name = name;
13
+ this.sendFn = sendFn;
14
+ this.presence = new presence_js_1.Presence(name, sendFn);
15
+ }
16
+ /** Subscribe to messages on this channel */
17
+ subscribe(callback, options) {
18
+ if (!this.listeners.has('message')) {
19
+ this.listeners.set('message', new Set());
20
+ }
21
+ this.listeners.get('message').add(callback);
22
+ if (!this.subscribed) {
23
+ const msg = { action: 'subscribe', channel: this.name };
24
+ if (options?.rewind)
25
+ msg.rewind = options.rewind;
26
+ this.sendFn(msg);
27
+ this.subscribed = true;
28
+ }
29
+ return this;
30
+ }
31
+ /** Publish data to this channel */
32
+ publish(data, options) {
33
+ const msg = {
34
+ action: 'publish',
35
+ channel: this.name,
36
+ data,
37
+ id: crypto.randomUUID?.() || `${Date.now()}-${Math.random().toString(36).slice(2)}`,
38
+ };
39
+ if (options?.persist === false)
40
+ msg.persist = false;
41
+ this.sendFn(msg);
42
+ return this;
43
+ }
44
+ /** Query message history for this channel */
45
+ history(options) {
46
+ const msg = {
47
+ action: 'history',
48
+ channel: this.name,
49
+ };
50
+ if (options?.limit)
51
+ msg.limit = options.limit;
52
+ if (options?.before)
53
+ msg.before = options.before;
54
+ if (options?.after)
55
+ msg.after = options.after;
56
+ if (options?.direction)
57
+ msg.direction = options.direction;
58
+ this.sendFn(msg);
59
+ return this;
60
+ }
61
+ /** Listen for history query results */
62
+ onHistory(callback) {
63
+ if (!this.listeners.has('history')) {
64
+ this.listeners.set('history', new Set());
65
+ }
66
+ this.listeners.get('history').add(callback);
67
+ return this;
68
+ }
69
+ /** @internal Emit history result to listeners */
70
+ _emitHistory(result) {
71
+ const listeners = this.listeners.get('history');
72
+ if (listeners) {
73
+ for (const cb of listeners) {
74
+ try {
75
+ cb(result);
76
+ }
77
+ catch { /* ignore */ }
78
+ }
79
+ }
80
+ }
81
+ /** Unsubscribe from this channel */
82
+ unsubscribe() {
83
+ this.sendFn({ action: 'unsubscribe', channel: this.name });
84
+ this.subscribed = false;
85
+ this.listeners.clear();
86
+ }
87
+ /** @internal Emit a message to listeners */
88
+ _emit(data, meta) {
89
+ const listeners = this.listeners.get('message');
90
+ if (listeners) {
91
+ for (const cb of listeners) {
92
+ try {
93
+ cb(data, meta);
94
+ }
95
+ catch {
96
+ // don't let listener errors break the loop
97
+ }
98
+ }
99
+ }
100
+ }
101
+ /** @internal Mark as needing re-subscribe (after reconnect) */
102
+ _markForResubscribe() {
103
+ this.subscribed = false;
104
+ }
105
+ /** @internal Whether this channel has active listeners */
106
+ get _hasListeners() {
107
+ const listeners = this.listeners.get('message');
108
+ return !!listeners && listeners.size > 0;
109
+ }
110
+ get isSubscribed() {
111
+ return this.subscribed;
112
+ }
113
+ }
114
+ exports.Channel = Channel;
115
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/pubsub/channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PubSub namespace — provides a scoped API surface for pub/sub operations.
3
+ *
4
+ * Usage:
5
+ * client.pubsub.channel('chat').subscribe(cb);
6
+ * client.pubsub.channel('chat').publish({ text: 'Hello!' });
7
+ *
8
+ * This is a lightweight proxy that delegates to the main WSocket instance.
9
+ */
10
+ import type { Channel } from './channel.js';
11
+ export { Channel } from './channel.js';
12
+ export { Presence } from './presence.js';
13
+ export declare class PubSubNamespace {
14
+ private channelFn;
15
+ constructor(channelFn: (name: string) => Channel);
16
+ /** Get or create a channel (same as client.channel()) */
17
+ channel(name: string): Channel;
18
+ }
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pubsub/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,qBAAa,eAAe;IAExB,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO;IAG9C,yDAAyD;IACzD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAG/B"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * PubSub namespace — provides a scoped API surface for pub/sub operations.
4
+ *
5
+ * Usage:
6
+ * client.pubsub.channel('chat').subscribe(cb);
7
+ * client.pubsub.channel('chat').publish({ text: 'Hello!' });
8
+ *
9
+ * This is a lightweight proxy that delegates to the main WSocket instance.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PubSubNamespace = exports.Presence = exports.Channel = void 0;
13
+ var channel_js_1 = require("./channel.js");
14
+ Object.defineProperty(exports, "Channel", { enumerable: true, get: function () { return channel_js_1.Channel; } });
15
+ var presence_js_1 = require("./presence.js");
16
+ Object.defineProperty(exports, "Presence", { enumerable: true, get: function () { return presence_js_1.Presence; } });
17
+ class PubSubNamespace {
18
+ channelFn;
19
+ constructor(channelFn) {
20
+ this.channelFn = channelFn;
21
+ }
22
+ /** Get or create a channel (same as client.channel()) */
23
+ channel(name) {
24
+ return this.channelFn(name);
25
+ }
26
+ }
27
+ exports.PubSubNamespace = PubSubNamespace;
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pubsub/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAIH,2CAAuC;AAA9B,qGAAA,OAAO,OAAA;AAChB,6CAAyC;AAAhC,uGAAA,QAAQ,OAAA;AAEjB,MAAa,eAAe;IAEhB;IADV,YACU,SAAoC;QAApC,cAAS,GAAT,SAAS,CAA2B;IAC3C,CAAC;IAEJ,yDAAyD;IACzD,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;CACF;AATD,0CASC"}
@@ -0,0 +1,36 @@
1
+ import type { ClientMessage, PresenceMember } from '../types.js';
2
+ /** Presence API for a channel */
3
+ export declare class Presence {
4
+ private channelName;
5
+ private sendFn;
6
+ private enterListeners;
7
+ private leaveListeners;
8
+ private updateListeners;
9
+ private membersListeners;
10
+ constructor(channelName: string, sendFn: (msg: ClientMessage) => void);
11
+ /** Enter presence set with optional data */
12
+ enter(data?: Record<string, unknown>): this;
13
+ /** Leave presence set */
14
+ leave(): this;
15
+ /** Update presence data */
16
+ update(data: Record<string, unknown>): this;
17
+ /** Get current members */
18
+ get(): this;
19
+ /** Listen for members entering */
20
+ onEnter(cb: (member: PresenceMember) => void): this;
21
+ /** Listen for members leaving */
22
+ onLeave(cb: (member: PresenceMember) => void): this;
23
+ /** Listen for presence data updates */
24
+ onUpdate(cb: (member: PresenceMember) => void): this;
25
+ /** Listen for member list response */
26
+ onMembers(cb: (members: PresenceMember[]) => void): this;
27
+ /** @internal */
28
+ _emitEnter(member: PresenceMember): void;
29
+ /** @internal */
30
+ _emitLeave(member: PresenceMember): void;
31
+ /** @internal */
32
+ _emitUpdate(member: PresenceMember): void;
33
+ /** @internal */
34
+ _emitMembers(members: PresenceMember[]): void;
35
+ }
36
+ //# sourceMappingURL=presence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../src/pubsub/presence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,iCAAiC;AACjC,qBAAa,QAAQ;IAOjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,gBAAgB,CAAkD;gBAGhE,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI;IAG9C,4CAA4C;IAC5C,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3C,yBAAyB;IACzB,KAAK,IAAI,IAAI;IAKb,2BAA2B;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3C,0BAA0B;IAC1B,GAAG,IAAI,IAAI;IAKX,kCAAkC;IAClC,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAKnD,iCAAiC;IACjC,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAKnD,uCAAuC;IACvC,QAAQ,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAKpD,sCAAsC;IACtC,SAAS,CAAC,EAAE,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,IAAI,GAAG,IAAI;IAKxD,gBAAgB;IAChB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIxC,gBAAgB;IAChB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIxC,gBAAgB;IAChB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIzC,gBAAgB;IAChB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI;CAG9C"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Presence = void 0;
4
+ /** Presence API for a channel */
5
+ class Presence {
6
+ channelName;
7
+ sendFn;
8
+ enterListeners = new Set();
9
+ leaveListeners = new Set();
10
+ updateListeners = new Set();
11
+ membersListeners = new Set();
12
+ constructor(channelName, sendFn) {
13
+ this.channelName = channelName;
14
+ this.sendFn = sendFn;
15
+ }
16
+ /** Enter presence set with optional data */
17
+ enter(data) {
18
+ this.sendFn({ action: 'presence.enter', channel: this.channelName, data });
19
+ return this;
20
+ }
21
+ /** Leave presence set */
22
+ leave() {
23
+ this.sendFn({ action: 'presence.leave', channel: this.channelName });
24
+ return this;
25
+ }
26
+ /** Update presence data */
27
+ update(data) {
28
+ this.sendFn({ action: 'presence.update', channel: this.channelName, data });
29
+ return this;
30
+ }
31
+ /** Get current members */
32
+ get() {
33
+ this.sendFn({ action: 'presence.get', channel: this.channelName });
34
+ return this;
35
+ }
36
+ /** Listen for members entering */
37
+ onEnter(cb) {
38
+ this.enterListeners.add(cb);
39
+ return this;
40
+ }
41
+ /** Listen for members leaving */
42
+ onLeave(cb) {
43
+ this.leaveListeners.add(cb);
44
+ return this;
45
+ }
46
+ /** Listen for presence data updates */
47
+ onUpdate(cb) {
48
+ this.updateListeners.add(cb);
49
+ return this;
50
+ }
51
+ /** Listen for member list response */
52
+ onMembers(cb) {
53
+ this.membersListeners.add(cb);
54
+ return this;
55
+ }
56
+ /** @internal */
57
+ _emitEnter(member) {
58
+ for (const cb of this.enterListeners) {
59
+ try {
60
+ cb(member);
61
+ }
62
+ catch { }
63
+ }
64
+ }
65
+ /** @internal */
66
+ _emitLeave(member) {
67
+ for (const cb of this.leaveListeners) {
68
+ try {
69
+ cb(member);
70
+ }
71
+ catch { }
72
+ }
73
+ }
74
+ /** @internal */
75
+ _emitUpdate(member) {
76
+ for (const cb of this.updateListeners) {
77
+ try {
78
+ cb(member);
79
+ }
80
+ catch { }
81
+ }
82
+ }
83
+ /** @internal */
84
+ _emitMembers(members) {
85
+ for (const cb of this.membersListeners) {
86
+ try {
87
+ cb(members);
88
+ }
89
+ catch { }
90
+ }
91
+ }
92
+ }
93
+ exports.Presence = Presence;
94
+ //# sourceMappingURL=presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/pubsub/presence.ts"],"names":[],"mappings":";;;AAEA,iCAAiC;AACjC,MAAa,QAAQ;IAOT;IACA;IAPF,cAAc,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC7D,cAAc,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC7D,eAAe,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC9D,gBAAgB,GAAG,IAAI,GAAG,EAAuC,CAAC;IAE1E,YACU,WAAmB,EACnB,MAAoC;QADpC,gBAAW,GAAX,WAAW,CAAQ;QACnB,WAAM,GAAN,MAAM,CAA8B;IAC3C,CAAC;IAEJ,4CAA4C;IAC5C,KAAK,CAAC,IAA8B;QAClC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yBAAyB;IACzB,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2BAA2B;IAC3B,MAAM,CAAC,IAA6B;QAClC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0BAA0B;IAC1B,GAAG;QACD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kCAAkC;IAClC,OAAO,CAAC,EAAoC;QAC1C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iCAAiC;IACjC,OAAO,CAAC,EAAoC;QAC1C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,QAAQ,CAAC,EAAoC;QAC3C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sCAAsC;IACtC,SAAS,CAAC,EAAuC;QAC/C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB;IAChB,UAAU,CAAC,MAAsB;QAC/B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QAAC,CAAC;IACxE,CAAC;IAED,gBAAgB;IAChB,UAAU,CAAC,MAAsB;QAC/B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QAAC,CAAC;IACxE,CAAC;IAED,gBAAgB;IAChB,WAAW,CAAC,MAAsB;QAChC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QAAC,CAAC;IACzE,CAAC;IAED,gBAAgB;IAChB,YAAY,CAAC,OAAyB;QACpC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,EAAE,CAAC,OAAO,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QAAC,CAAC;IAC3E,CAAC;CACF;AA9ED,4BA8EC"}
@@ -0,0 +1,55 @@
1
+ export interface PushClientOptions {
2
+ /** API base URL (e.g. http://localhost:9001) */
3
+ baseUrl: string;
4
+ /** API key or JWT token for auth */
5
+ token: string;
6
+ /** App ID to register push for */
7
+ appId: string;
8
+ }
9
+ export interface PushPayload {
10
+ title: string;
11
+ body?: string;
12
+ icon?: string;
13
+ image?: string;
14
+ badge?: string;
15
+ url?: string;
16
+ data?: Record<string, unknown>;
17
+ ttl?: number;
18
+ urgency?: 'very-low' | 'low' | 'normal' | 'high';
19
+ }
20
+ export declare class PushClient {
21
+ private baseUrl;
22
+ private token;
23
+ private appId;
24
+ constructor(options: PushClientOptions);
25
+ /** Get the VAPID public key for Web Push subscription */
26
+ getVapidKey(): Promise<string | null>;
27
+ /** Register a Web Push subscription (browser) */
28
+ registerWebPush(subscription: any, memberId?: string): Promise<string>;
29
+ /** Register an FCM device token (Android) */
30
+ registerFCM(deviceToken: string, memberId?: string): Promise<string>;
31
+ /** Register an APNs device token (iOS) */
32
+ registerAPNs(deviceToken: string, memberId?: string): Promise<string>;
33
+ /** Unregister push notifications */
34
+ unregister(memberId: string, platform?: 'web' | 'fcm' | 'apns'): Promise<number>;
35
+ /** Send a push notification to a specific member */
36
+ sendToMember(memberId: string, payload: PushPayload): Promise<unknown>;
37
+ /** Send a push notification to multiple members */
38
+ sendToMembers(memberIds: string[], payload: PushPayload): Promise<unknown>;
39
+ /** Broadcast a push notification to all subscribers of the app */
40
+ broadcast(payload: PushPayload): Promise<unknown>;
41
+ /** List push subscriptions for the app */
42
+ listSubscriptions(options?: {
43
+ memberId?: string;
44
+ platform?: 'web' | 'fcm' | 'apns';
45
+ limit?: number;
46
+ }): Promise<unknown>;
47
+ /**
48
+ * Request browser permission and subscribe to Web Push.
49
+ * Returns the PushSubscription or null if denied/unsupported.
50
+ * Only works in browser environments.
51
+ */
52
+ subscribeBrowser(serviceWorkerPath?: string): Promise<any | null>;
53
+ private api;
54
+ }
55
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/push/index.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CAClD;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,iBAAiB;IAMtC,yDAAyD;IACnD,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK3C,iDAAiD;IAC3C,eAAe,CAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAa5E,6CAA6C;IACvC,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS1E,0CAA0C;IACpC,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS3E,oCAAoC;IAC9B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQtF,oDAAoD;IAC9C,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAO5E,mDAAmD;IAC7C,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAOhF,kEAAkE;IAC5D,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAMvD,0CAA0C;IACpC,iBAAiB,CAAC,OAAO,CAAC,EAAE;QAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;QAClC,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,OAAO,CAAC;IASpB;;;;OAIG;IACG,gBAAgB,CAAC,iBAAiB,SAAW,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;YAuB3D,GAAG;CAelB"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ // ─── Push Notification Client ───────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.PushClient = void 0;
5
+ class PushClient {
6
+ baseUrl;
7
+ token;
8
+ appId;
9
+ constructor(options) {
10
+ this.baseUrl = options.baseUrl.replace(/\/$/, '');
11
+ this.token = options.token;
12
+ this.appId = options.appId;
13
+ }
14
+ /** Get the VAPID public key for Web Push subscription */
15
+ async getVapidKey() {
16
+ const res = await this.api('GET', `/api/admin/apps/${this.appId}/push/config`);
17
+ return res.vapidPublicKey || null;
18
+ }
19
+ /** Register a Web Push subscription (browser) */
20
+ async registerWebPush(subscription, memberId) {
21
+ const json = typeof subscription.toJSON === 'function' ? subscription.toJSON() : subscription;
22
+ const res = await this.api('POST', `/api/push/register`, {
23
+ provider: 'web',
24
+ memberId: memberId || 'anonymous',
25
+ webPush: {
26
+ endpoint: json.endpoint,
27
+ keys: json.keys,
28
+ },
29
+ });
30
+ return res.subscriptionId;
31
+ }
32
+ /** Register an FCM device token (Android) */
33
+ async registerFCM(deviceToken, memberId) {
34
+ const res = await this.api('POST', `/api/push/register`, {
35
+ provider: 'fcm',
36
+ memberId: memberId || 'anonymous',
37
+ deviceToken,
38
+ });
39
+ return res.subscriptionId;
40
+ }
41
+ /** Register an APNs device token (iOS) */
42
+ async registerAPNs(deviceToken, memberId) {
43
+ const res = await this.api('POST', `/api/push/register`, {
44
+ provider: 'apns',
45
+ memberId: memberId || 'anonymous',
46
+ deviceToken,
47
+ });
48
+ return res.subscriptionId;
49
+ }
50
+ /** Unregister push notifications */
51
+ async unregister(memberId, platform) {
52
+ const res = await this.api('DELETE', `/api/push/unregister`, {
53
+ memberId,
54
+ platform,
55
+ });
56
+ return res.unregistered;
57
+ }
58
+ /** Send a push notification to a specific member */
59
+ async sendToMember(memberId, payload) {
60
+ return this.api('POST', `/api/push/send`, {
61
+ memberId,
62
+ payload,
63
+ });
64
+ }
65
+ /** Send a push notification to multiple members */
66
+ async sendToMembers(memberIds, payload) {
67
+ return this.api('POST', `/api/push/send`, {
68
+ memberIds,
69
+ payload,
70
+ });
71
+ }
72
+ /** Broadcast a push notification to all subscribers of the app */
73
+ async broadcast(payload) {
74
+ return this.api('POST', `/api/push/broadcast`, {
75
+ payload,
76
+ });
77
+ }
78
+ /** List push subscriptions for the app */
79
+ async listSubscriptions(options) {
80
+ const params = new URLSearchParams();
81
+ if (options?.memberId)
82
+ params.set('memberId', options.memberId);
83
+ if (options?.platform)
84
+ params.set('platform', options.platform);
85
+ if (options?.limit)
86
+ params.set('limit', String(options.limit));
87
+ const qs = params.toString();
88
+ return this.api('GET', `/api/push/subscriptions${qs ? '?' + qs : ''}`);
89
+ }
90
+ /**
91
+ * Request browser permission and subscribe to Web Push.
92
+ * Returns the PushSubscription or null if denied/unsupported.
93
+ * Only works in browser environments.
94
+ */
95
+ async subscribeBrowser(serviceWorkerPath = '/sw.js') {
96
+ if (typeof window === 'undefined' || !('serviceWorker' in navigator) || !('PushManager' in window)) {
97
+ return null;
98
+ }
99
+ const permission = await Notification.requestPermission();
100
+ if (permission !== 'granted')
101
+ return null;
102
+ const vapidKey = await this.getVapidKey();
103
+ if (!vapidKey)
104
+ throw new Error('VAPID public key not available');
105
+ const reg = await navigator.serviceWorker.register(serviceWorkerPath);
106
+ await navigator.serviceWorker.ready;
107
+ const sub = await reg.pushManager.subscribe({
108
+ userVisibleOnly: true,
109
+ applicationServerKey: urlBase64ToUint8Array(vapidKey),
110
+ });
111
+ await this.registerWebPush(sub);
112
+ return sub;
113
+ }
114
+ async api(method, path, body) {
115
+ const res = await fetch(`${this.baseUrl}${path}`, {
116
+ method,
117
+ headers: {
118
+ 'Content-Type': 'application/json',
119
+ 'Authorization': `Bearer ${this.token}`,
120
+ },
121
+ body: body ? JSON.stringify(body) : undefined,
122
+ });
123
+ if (!res.ok) {
124
+ const text = await res.text();
125
+ throw new Error(`Push API error ${res.status}: ${text}`);
126
+ }
127
+ return res.json();
128
+ }
129
+ }
130
+ exports.PushClient = PushClient;
131
+ function urlBase64ToUint8Array(base64String) {
132
+ const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
133
+ const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
134
+ const raw = atob(base64);
135
+ const arr = new Uint8Array(raw.length);
136
+ for (let i = 0; i < raw.length; i++)
137
+ arr[i] = raw.charCodeAt(i);
138
+ return arr;
139
+ }
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/push/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
2
+ export interface WSocketOptions {
3
+ /** Auto reconnect on disconnect (default: true) */
4
+ autoReconnect?: boolean;
5
+ /** Max reconnect attempts (default: 10) */
6
+ maxReconnectAttempts?: number;
7
+ /** Base reconnect delay in ms (default: 1000) */
8
+ reconnectDelay?: number;
9
+ /** Use JWT token instead of API key for auth */
10
+ token?: string;
11
+ /** Enable connection state recovery — resend missed messages on reconnect (default: true) */
12
+ recover?: boolean;
13
+ }
14
+ export interface ChannelSubscription {
15
+ channel: string;
16
+ callback: (data: unknown, meta: MessageMeta) => void;
17
+ }
18
+ export interface MessageMeta {
19
+ id: string;
20
+ channel: string;
21
+ timestamp: number;
22
+ }
23
+ export type EventCallback = (...args: unknown[]) => void;
24
+ export interface ClientMessage {
25
+ action: 'subscribe' | 'unsubscribe' | 'publish' | 'ping' | 'presence.enter' | 'presence.leave' | 'presence.update' | 'presence.get' | 'history';
26
+ channel?: string;
27
+ data?: unknown;
28
+ id?: string;
29
+ persist?: boolean;
30
+ rewind?: number;
31
+ limit?: number;
32
+ before?: number;
33
+ after?: number;
34
+ direction?: 'forward' | 'backward';
35
+ }
36
+ export interface ServerMessage {
37
+ action: 'message' | 'subscribed' | 'unsubscribed' | 'error' | 'pong' | 'ack' | 'presence.enter' | 'presence.leave' | 'presence.update' | 'presence.members' | 'history';
38
+ channel?: string;
39
+ data?: unknown;
40
+ id?: string;
41
+ error?: string;
42
+ timestamp?: number;
43
+ }
44
+ export interface PresenceMember {
45
+ clientId: string;
46
+ data?: Record<string, unknown>;
47
+ joinedAt: number;
48
+ }
49
+ export interface HistoryMessage {
50
+ id: string;
51
+ channel: string;
52
+ data: unknown;
53
+ publisherId: string;
54
+ timestamp: number;
55
+ sequence: number;
56
+ }
57
+ export interface HistoryResult {
58
+ channel: string;
59
+ messages: HistoryMessage[];
60
+ hasMore: boolean;
61
+ }
62
+ export interface HistoryOptions {
63
+ limit?: number;
64
+ before?: number;
65
+ after?: number;
66
+ direction?: 'forward' | 'backward';
67
+ }
68
+ export interface PublishOptions {
69
+ /** Set to false to skip persisting to history (ephemeral message) */
70
+ persist?: boolean;
71
+ }
72
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;AAE3F,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2CAA2C;IAC3C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAIzD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,GACpD,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,cAAc,GACxE,SAAS,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GACxE,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,kBAAkB,GAC5E,SAAS,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // ─── Shared Types ───────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,+DAA+D"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@wsocket-io/sdk",
3
+ "version": "0.1.0",
4
+ "description": "wSocket JavaScript SDK — Realtime Pub/Sub client",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": ["dist", "README.md", "LICENSE"],
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/wsocket-io/sdk-js.git"
11
+ },
12
+ "homepage": "https://wsocket.io",
13
+ "bugs": {
14
+ "url": "https://github.com/wsocket-io/sdk-js/issues"
15
+ },
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "prepublishOnly": "npm run build",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest"
21
+ },
22
+ "keywords": ["websocket", "pubsub", "realtime", "wsocket"],
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "ws": "^8.18.0"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.7.3",
29
+ "vitest": "^3.0.5",
30
+ "@types/node": "^22.12.0",
31
+ "@types/ws": "^8.5.14"
32
+ }
33
+ }