@pushflodev/sdk 1.0.1
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 +21 -0
- package/README.md +500 -0
- package/dist/PushFloClient-JPowShqE.d.cts +102 -0
- package/dist/PushFloClient-ny0iyTYJ.d.ts +102 -0
- package/dist/api-DYrG_5uC.d.cts +149 -0
- package/dist/api-DYrG_5uC.d.ts +149 -0
- package/dist/index.cjs +1210 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +1204 -0
- package/dist/index.js.map +1 -0
- package/dist/message-CVgilLwz.d.cts +130 -0
- package/dist/message-CVgilLwz.d.ts +130 -0
- package/dist/react.cjs +1300 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +116 -0
- package/dist/react.d.ts +116 -0
- package/dist/react.js +1295 -0
- package/dist/react.js.map +1 -0
- package/dist/server.cjs +558 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +47 -0
- package/dist/server.d.ts +47 -0
- package/dist/server.js +553 -0
- package/dist/server.js.map +1 -0
- package/package.json +103 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 PushFlo
|
|
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,500 @@
|
|
|
1
|
+
# @pushflodev/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for [PushFlo](https://pushflo.dev) real-time messaging service.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Zero runtime dependencies** - Built entirely on native Web APIs
|
|
8
|
+
- **Full TypeScript support** - Complete type definitions included
|
|
9
|
+
- **Three entry points** - Browser client, server client, and React hooks
|
|
10
|
+
- **Auto-reconnection** - Automatic reconnection with exponential backoff
|
|
11
|
+
- **Lightweight** - Minimal bundle size
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm
|
|
17
|
+
npm install @pushflodev/sdk
|
|
18
|
+
|
|
19
|
+
# yarn
|
|
20
|
+
yarn add @pushflodev/sdk
|
|
21
|
+
|
|
22
|
+
# pnpm
|
|
23
|
+
pnpm add @pushflodev/sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start - Browser (60 seconds)
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { PushFloClient } from '@pushflodev/sdk';
|
|
30
|
+
|
|
31
|
+
// 1. Create client
|
|
32
|
+
const client = new PushFloClient({
|
|
33
|
+
publishKey: 'pub_xxxxxxxxxxxxx', // Get from console.pushflo.dev
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// 2. Connect
|
|
37
|
+
await client.connect();
|
|
38
|
+
|
|
39
|
+
// 3. Subscribe to channel
|
|
40
|
+
const subscription = client.subscribe('notifications', {
|
|
41
|
+
onMessage: (message) => {
|
|
42
|
+
console.log('Received:', message.content);
|
|
43
|
+
console.log('Event type:', message.eventType);
|
|
44
|
+
console.log('Timestamp:', new Date(message.timestamp));
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// 4. Cleanup when done
|
|
49
|
+
subscription.unsubscribe();
|
|
50
|
+
client.disconnect();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start - Server (60 seconds)
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { PushFloServer } from '@pushflodev/sdk/server';
|
|
57
|
+
|
|
58
|
+
// 1. Create server client
|
|
59
|
+
const pushflo = new PushFloServer({
|
|
60
|
+
secretKey: 'sec_xxxxxxxxxxxxx', // Get from console.pushflo.dev
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// 2. Publish a message
|
|
64
|
+
const result = await pushflo.publish('notifications', {
|
|
65
|
+
title: 'New Order',
|
|
66
|
+
orderId: '12345',
|
|
67
|
+
amount: 99.99,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
console.log('Message ID:', result.id);
|
|
71
|
+
console.log('Delivered to:', result.delivered, 'subscribers');
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Quick Start - React (60 seconds)
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
// App.tsx - Wrap your app with provider
|
|
78
|
+
import { PushFloProvider } from '@pushflodev/sdk/react';
|
|
79
|
+
|
|
80
|
+
function App() {
|
|
81
|
+
return (
|
|
82
|
+
<PushFloProvider publishKey="pub_xxxxxxxxxxxxx">
|
|
83
|
+
<NotificationList />
|
|
84
|
+
</PushFloProvider>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// NotificationList.tsx - Subscribe to channel
|
|
89
|
+
import { useChannel } from '@pushflodev/sdk/react';
|
|
90
|
+
|
|
91
|
+
function NotificationList() {
|
|
92
|
+
const { messages, connectionState } = useChannel('notifications');
|
|
93
|
+
|
|
94
|
+
if (connectionState === 'connecting') {
|
|
95
|
+
return <div>Connecting...</div>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<ul>
|
|
100
|
+
{messages.map((msg) => (
|
|
101
|
+
<li key={msg.id}>
|
|
102
|
+
<strong>{msg.content.title}</strong>
|
|
103
|
+
<span>{new Date(msg.timestamp).toLocaleString()}</span>
|
|
104
|
+
</li>
|
|
105
|
+
))}
|
|
106
|
+
</ul>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Browser Client
|
|
112
|
+
|
|
113
|
+
### Connection State Handling
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { PushFloClient, ConnectionState } from '@pushflodev/sdk';
|
|
117
|
+
|
|
118
|
+
const client = new PushFloClient({ publishKey: 'pub_xxx' });
|
|
119
|
+
|
|
120
|
+
// Listen to connection changes
|
|
121
|
+
client.onConnectionChange((state: ConnectionState) => {
|
|
122
|
+
switch (state) {
|
|
123
|
+
case 'disconnected':
|
|
124
|
+
console.log('Disconnected from PushFlo');
|
|
125
|
+
break;
|
|
126
|
+
case 'connecting':
|
|
127
|
+
console.log('Connecting to PushFlo...');
|
|
128
|
+
break;
|
|
129
|
+
case 'connected':
|
|
130
|
+
console.log('Connected to PushFlo!');
|
|
131
|
+
break;
|
|
132
|
+
case 'error':
|
|
133
|
+
console.log('Connection error');
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await client.connect();
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Client Options
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const client = new PushFloClient({
|
|
145
|
+
// Required
|
|
146
|
+
publishKey: 'pub_xxxxxxxxxxxxx',
|
|
147
|
+
|
|
148
|
+
// Optional
|
|
149
|
+
baseUrl: 'https://api.pushflo.dev', // Custom API URL
|
|
150
|
+
autoConnect: false, // Auto-connect on creation
|
|
151
|
+
debug: false, // Enable debug logging
|
|
152
|
+
connectionTimeout: 30000, // Connection timeout (ms)
|
|
153
|
+
heartbeatInterval: 25000, // Heartbeat interval (ms)
|
|
154
|
+
autoReconnect: true, // Auto-reconnect on disconnect
|
|
155
|
+
maxReconnectAttempts: 0, // Max reconnect attempts (0 = infinite)
|
|
156
|
+
reconnectDelay: 1000, // Initial reconnect delay (ms)
|
|
157
|
+
maxReconnectDelay: 30000, // Max reconnect delay (ms)
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Subscription Options
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const subscription = client.subscribe('notifications', {
|
|
165
|
+
onMessage: (message) => {
|
|
166
|
+
console.log('Received:', message);
|
|
167
|
+
},
|
|
168
|
+
onError: (error) => {
|
|
169
|
+
console.error('Subscription error:', error);
|
|
170
|
+
},
|
|
171
|
+
onSubscribed: () => {
|
|
172
|
+
console.log('Successfully subscribed');
|
|
173
|
+
},
|
|
174
|
+
onUnsubscribed: () => {
|
|
175
|
+
console.log('Unsubscribed');
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Later: unsubscribe
|
|
180
|
+
subscription.unsubscribe();
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Event Listeners
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Listen for all messages
|
|
187
|
+
client.on('message', (message) => {
|
|
188
|
+
console.log('Message on', message.channel, ':', message.content);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Listen for errors
|
|
192
|
+
client.on('error', (error) => {
|
|
193
|
+
console.error('Error:', error);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Listen for connection events
|
|
197
|
+
client.on('connected', (info) => {
|
|
198
|
+
console.log('Connected with client ID:', info.clientId);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
client.on('disconnected', (reason) => {
|
|
202
|
+
console.log('Disconnected:', reason);
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Server Client
|
|
207
|
+
|
|
208
|
+
### Channel Management
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { PushFloServer } from '@pushflodev/sdk/server';
|
|
212
|
+
|
|
213
|
+
const pushflo = new PushFloServer({ secretKey: 'sec_xxx' });
|
|
214
|
+
|
|
215
|
+
// List all channels
|
|
216
|
+
const { channels, pagination } = await pushflo.listChannels({
|
|
217
|
+
page: 1,
|
|
218
|
+
pageSize: 25,
|
|
219
|
+
});
|
|
220
|
+
console.log('Channels:', channels);
|
|
221
|
+
console.log('Total:', pagination.total);
|
|
222
|
+
|
|
223
|
+
// Get a specific channel
|
|
224
|
+
const channel = await pushflo.getChannel('notifications');
|
|
225
|
+
console.log('Channel:', channel.name, '- Messages:', channel.messageCount);
|
|
226
|
+
|
|
227
|
+
// Create a new channel
|
|
228
|
+
const newChannel = await pushflo.createChannel({
|
|
229
|
+
name: 'Order Updates',
|
|
230
|
+
slug: 'order-updates',
|
|
231
|
+
description: 'Real-time order status updates',
|
|
232
|
+
isPrivate: false,
|
|
233
|
+
});
|
|
234
|
+
console.log('Created:', newChannel.slug);
|
|
235
|
+
|
|
236
|
+
// Update a channel
|
|
237
|
+
const updated = await pushflo.updateChannel('order-updates', {
|
|
238
|
+
description: 'Updated description',
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Delete a channel
|
|
242
|
+
await pushflo.deleteChannel('order-updates');
|
|
243
|
+
console.log('Channel deleted');
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Message History
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { PushFloServer } from '@pushflodev/sdk/server';
|
|
250
|
+
|
|
251
|
+
const pushflo = new PushFloServer({ secretKey: 'sec_xxx' });
|
|
252
|
+
|
|
253
|
+
// Get message history
|
|
254
|
+
const { messages, pagination } = await pushflo.getMessageHistory('notifications', {
|
|
255
|
+
page: 1,
|
|
256
|
+
pageSize: 50,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
messages.forEach((msg) => {
|
|
260
|
+
console.log(`[${msg.eventType}] ${JSON.stringify(msg.content)}`);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
console.log(`Page ${pagination.page} of ${pagination.totalPages}`);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Publishing with Event Types
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { PushFloServer } from '@pushflodev/sdk/server';
|
|
270
|
+
|
|
271
|
+
const pushflo = new PushFloServer({ secretKey: 'sec_xxx' });
|
|
272
|
+
|
|
273
|
+
// Publish with custom event type
|
|
274
|
+
await pushflo.publish('orders',
|
|
275
|
+
{ orderId: '123', status: 'shipped' },
|
|
276
|
+
{ eventType: 'order.shipped' }
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
// Subscribe and filter by event type (browser client)
|
|
280
|
+
client.subscribe('orders', {
|
|
281
|
+
onMessage: (message) => {
|
|
282
|
+
if (message.eventType === 'order.shipped') {
|
|
283
|
+
showShippingNotification(message.content);
|
|
284
|
+
} else if (message.eventType === 'order.delivered') {
|
|
285
|
+
showDeliveryNotification(message.content);
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Server Options
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
const pushflo = new PushFloServer({
|
|
295
|
+
// Required
|
|
296
|
+
secretKey: 'sec_xxxxxxxxxxxxx',
|
|
297
|
+
|
|
298
|
+
// Optional
|
|
299
|
+
baseUrl: 'https://api.pushflo.dev', // Custom API URL
|
|
300
|
+
timeout: 30000, // Request timeout (ms)
|
|
301
|
+
debug: false, // Enable debug logging
|
|
302
|
+
retryAttempts: 3, // Retry failed requests
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## React Integration
|
|
307
|
+
|
|
308
|
+
### Provider Options
|
|
309
|
+
|
|
310
|
+
```tsx
|
|
311
|
+
import { PushFloProvider } from '@pushflodev/sdk/react';
|
|
312
|
+
|
|
313
|
+
function App() {
|
|
314
|
+
return (
|
|
315
|
+
<PushFloProvider
|
|
316
|
+
publishKey={process.env.NEXT_PUBLIC_PUSHFLO_PUBLISH_KEY!}
|
|
317
|
+
baseUrl={process.env.NEXT_PUBLIC_PUSHFLO_BASE_URL}
|
|
318
|
+
autoConnect={true}
|
|
319
|
+
debug={process.env.NODE_ENV === 'development'}
|
|
320
|
+
>
|
|
321
|
+
<Dashboard />
|
|
322
|
+
</PushFloProvider>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### usePushFlo Hook
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
import { usePushFlo } from '@pushflodev/sdk/react';
|
|
331
|
+
|
|
332
|
+
function Dashboard() {
|
|
333
|
+
const { connectionState, isConnected, connect, disconnect } = usePushFlo();
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<div>
|
|
337
|
+
<p>Status: {connectionState}</p>
|
|
338
|
+
<button onClick={connect} disabled={isConnected}>Connect</button>
|
|
339
|
+
<button onClick={disconnect} disabled={!isConnected}>Disconnect</button>
|
|
340
|
+
</div>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### useChannel Hook
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
import { useChannel } from '@pushflodev/sdk/react';
|
|
349
|
+
|
|
350
|
+
function NotificationBell() {
|
|
351
|
+
const { messages, lastMessage, clearMessages, isSubscribed } = useChannel('notifications', {
|
|
352
|
+
onMessage: (msg) => {
|
|
353
|
+
// Play sound, show toast, etc.
|
|
354
|
+
playNotificationSound();
|
|
355
|
+
},
|
|
356
|
+
maxMessages: 100, // Limit stored messages
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
return (
|
|
360
|
+
<div>
|
|
361
|
+
<span>({messages.length} new)</span>
|
|
362
|
+
{lastMessage && <p>Latest: {lastMessage.content.title}</p>}
|
|
363
|
+
<button onClick={clearMessages}>Clear</button>
|
|
364
|
+
</div>
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Error Handling
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import {
|
|
373
|
+
PushFloClient,
|
|
374
|
+
PushFloError,
|
|
375
|
+
ConnectionError,
|
|
376
|
+
AuthenticationError
|
|
377
|
+
} from '@pushflodev/sdk';
|
|
378
|
+
|
|
379
|
+
const client = new PushFloClient({ publishKey: 'pub_xxx' });
|
|
380
|
+
|
|
381
|
+
try {
|
|
382
|
+
await client.connect();
|
|
383
|
+
} catch (error) {
|
|
384
|
+
if (error instanceof AuthenticationError) {
|
|
385
|
+
console.error('Invalid API key:', error.message);
|
|
386
|
+
} else if (error instanceof ConnectionError) {
|
|
387
|
+
console.error('Connection failed:', error.message);
|
|
388
|
+
if (error.retryable) {
|
|
389
|
+
console.log('Will auto-retry...');
|
|
390
|
+
}
|
|
391
|
+
} else if (error instanceof PushFloError) {
|
|
392
|
+
console.error('PushFlo error:', error.code, error.message);
|
|
393
|
+
} else {
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Listen for runtime errors
|
|
399
|
+
client.on('error', (error) => {
|
|
400
|
+
console.error('Runtime error:', error);
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Error Types
|
|
405
|
+
|
|
406
|
+
| Error Class | Description | Retryable |
|
|
407
|
+
|-------------|-------------|-----------|
|
|
408
|
+
| `PushFloError` | Base error class | Varies |
|
|
409
|
+
| `ConnectionError` | WebSocket connection issues | Yes |
|
|
410
|
+
| `AuthenticationError` | Invalid/missing API key | No |
|
|
411
|
+
| `NetworkError` | HTTP request failures | Varies |
|
|
412
|
+
|
|
413
|
+
## Environment Variables
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
# .env.local (Next.js)
|
|
417
|
+
NEXT_PUBLIC_PUSHFLO_PUBLISH_KEY=pub_xxxxxxxxxxxxx
|
|
418
|
+
NEXT_PUBLIC_PUSHFLO_BASE_URL=https://api.pushflo.dev
|
|
419
|
+
PUSHFLO_SECRET_KEY=sec_xxxxxxxxxxxxx
|
|
420
|
+
|
|
421
|
+
# .env (Vite)
|
|
422
|
+
VITE_PUSHFLO_PUBLISH_KEY=pub_xxxxxxxxxxxxx
|
|
423
|
+
VITE_PUSHFLO_BASE_URL=https://api.pushflo.dev
|
|
424
|
+
|
|
425
|
+
# .env (Node.js server)
|
|
426
|
+
PUSHFLO_SECRET_KEY=sec_xxxxxxxxxxxxx
|
|
427
|
+
PUSHFLO_BASE_URL=https://api.pushflo.dev
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## TypeScript Types
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
import type {
|
|
434
|
+
// Connection
|
|
435
|
+
ConnectionState,
|
|
436
|
+
ClientOptions,
|
|
437
|
+
ServerOptions,
|
|
438
|
+
|
|
439
|
+
// Channels
|
|
440
|
+
Channel,
|
|
441
|
+
ChannelInput,
|
|
442
|
+
|
|
443
|
+
// Messages
|
|
444
|
+
Message,
|
|
445
|
+
PublishOptions,
|
|
446
|
+
PublishResult,
|
|
447
|
+
|
|
448
|
+
// API
|
|
449
|
+
Pagination,
|
|
450
|
+
|
|
451
|
+
// Subscriptions
|
|
452
|
+
Subscription,
|
|
453
|
+
SubscriptionOptions,
|
|
454
|
+
} from '@pushflodev/sdk';
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
## API Keys
|
|
458
|
+
|
|
459
|
+
| Key Prefix | Permissions | Use Case |
|
|
460
|
+
|------------|-------------|----------|
|
|
461
|
+
| `pub_xxx` | Read/Subscribe | Browser clients |
|
|
462
|
+
| `sec_xxx` | Read/Write/Publish | Server-side code |
|
|
463
|
+
| `mgmt_xxx` | Full access | Channel management |
|
|
464
|
+
|
|
465
|
+
## Troubleshooting
|
|
466
|
+
|
|
467
|
+
### Connection Issues
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
// Enable debug logging
|
|
471
|
+
const client = new PushFloClient({
|
|
472
|
+
publishKey: 'pub_xxx',
|
|
473
|
+
debug: true, // Logs all WebSocket activity
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### CORS Errors
|
|
478
|
+
|
|
479
|
+
CORS is configured on the PushFlo servers. If you see CORS errors, ensure:
|
|
480
|
+
- You're using the correct API endpoint
|
|
481
|
+
- Your domain is registered in the PushFlo console
|
|
482
|
+
|
|
483
|
+
### React Strict Mode
|
|
484
|
+
|
|
485
|
+
The SDK handles React Strict Mode correctly. The client is cleaned up and recreated as needed during development.
|
|
486
|
+
|
|
487
|
+
### Server-Side Rendering (SSR)
|
|
488
|
+
|
|
489
|
+
The browser client requires `WebSocket` which is not available on the server. Use the SDK only in client components or with dynamic imports:
|
|
490
|
+
|
|
491
|
+
```tsx
|
|
492
|
+
// Next.js App Router
|
|
493
|
+
'use client';
|
|
494
|
+
|
|
495
|
+
import { PushFloProvider } from '@pushflodev/sdk/react';
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## License
|
|
499
|
+
|
|
500
|
+
MIT
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { a as ConnectionInfo, M as Message, C as ClientOptions, b as ConnectionState, e as SubscriptionOptions, S as Subscription } from './message-CVgilLwz.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type-safe event emitter with zero dependencies
|
|
5
|
+
*/
|
|
6
|
+
type EventMap = {
|
|
7
|
+
[key: string]: unknown[];
|
|
8
|
+
};
|
|
9
|
+
type EventHandler<T extends unknown[]> = (...args: T) => void;
|
|
10
|
+
declare class TypedEventEmitter<Events extends EventMap> {
|
|
11
|
+
private listeners;
|
|
12
|
+
/**
|
|
13
|
+
* Register an event listener
|
|
14
|
+
*/
|
|
15
|
+
on<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): this;
|
|
16
|
+
/**
|
|
17
|
+
* Register a one-time event listener
|
|
18
|
+
*/
|
|
19
|
+
once<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): this;
|
|
20
|
+
/**
|
|
21
|
+
* Remove an event listener
|
|
22
|
+
*/
|
|
23
|
+
off<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): this;
|
|
24
|
+
/**
|
|
25
|
+
* Emit an event to all registered listeners
|
|
26
|
+
*/
|
|
27
|
+
protected emit<K extends keyof Events>(event: K, ...args: Events[K]): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Remove all listeners for an event, or all listeners if no event specified
|
|
30
|
+
*/
|
|
31
|
+
removeAllListeners<K extends keyof Events>(event?: K): this;
|
|
32
|
+
/**
|
|
33
|
+
* Get the number of listeners for an event
|
|
34
|
+
*/
|
|
35
|
+
listenerCount<K extends keyof Events>(event: K): number;
|
|
36
|
+
/**
|
|
37
|
+
* Get all event names with registered listeners
|
|
38
|
+
*/
|
|
39
|
+
eventNames(): (keyof Events)[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface PushFloClientEvents {
|
|
43
|
+
[key: string]: unknown[];
|
|
44
|
+
connected: [ConnectionInfo];
|
|
45
|
+
disconnected: [reason?: string];
|
|
46
|
+
message: [Message];
|
|
47
|
+
error: [Error];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Browser client for PushFlo real-time messaging
|
|
51
|
+
*/
|
|
52
|
+
declare class PushFloClient extends TypedEventEmitter<PushFloClientEvents> {
|
|
53
|
+
private readonly wsManager;
|
|
54
|
+
private readonly subscriptions;
|
|
55
|
+
private readonly logger;
|
|
56
|
+
private connectionChangeListeners;
|
|
57
|
+
constructor(options: ClientOptions);
|
|
58
|
+
/**
|
|
59
|
+
* Get current connection state
|
|
60
|
+
*/
|
|
61
|
+
get connectionState(): ConnectionState;
|
|
62
|
+
/**
|
|
63
|
+
* Get client ID (available after connected)
|
|
64
|
+
*/
|
|
65
|
+
get clientId(): string | null;
|
|
66
|
+
/**
|
|
67
|
+
* Connect to PushFlo
|
|
68
|
+
*/
|
|
69
|
+
connect(): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Disconnect from PushFlo
|
|
72
|
+
*/
|
|
73
|
+
disconnect(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Clean up all resources
|
|
76
|
+
*/
|
|
77
|
+
destroy(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Subscribe to a channel
|
|
80
|
+
*/
|
|
81
|
+
subscribe(channel: string, options?: SubscriptionOptions): Subscription;
|
|
82
|
+
/**
|
|
83
|
+
* Unsubscribe from a channel
|
|
84
|
+
*/
|
|
85
|
+
unsubscribe(channel: string): void;
|
|
86
|
+
/**
|
|
87
|
+
* Register a connection state change listener
|
|
88
|
+
*/
|
|
89
|
+
onConnectionChange(listener: (state: ConnectionState) => void): () => void;
|
|
90
|
+
/**
|
|
91
|
+
* Get list of subscribed channels
|
|
92
|
+
*/
|
|
93
|
+
getSubscribedChannels(): string[];
|
|
94
|
+
/**
|
|
95
|
+
* Check if subscribed to a channel
|
|
96
|
+
*/
|
|
97
|
+
isSubscribed(channel: string): boolean;
|
|
98
|
+
private setupEventHandlers;
|
|
99
|
+
private handleServerMessage;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { PushFloClient as P };
|