@apinator/server 2.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/CHANGELOG.md +64 -0
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/index.d.mts +362 -0
- package/dist/index.d.ts +362 -0
- package/dist/index.js +424 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +387 -0
- package/dist/index.mjs.map +1 -0
- package/docs/api-reference.md +62 -0
- package/docs/quickstart.md +50 -0
- package/package.json +60 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the Realtime client.
|
|
3
|
+
*/
|
|
4
|
+
interface RealtimeOptions {
|
|
5
|
+
/** Application ID */
|
|
6
|
+
appId: string;
|
|
7
|
+
/** API key */
|
|
8
|
+
key: string;
|
|
9
|
+
/** API secret */
|
|
10
|
+
secret: string;
|
|
11
|
+
/** Cluster region identifier (e.g. "eu", "us") */
|
|
12
|
+
cluster: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parameters for triggering an event.
|
|
16
|
+
*/
|
|
17
|
+
interface TriggerParams {
|
|
18
|
+
/** Event name */
|
|
19
|
+
name: string;
|
|
20
|
+
/** Single channel name (mutually exclusive with channels) */
|
|
21
|
+
channel?: string;
|
|
22
|
+
/** Multiple channel names (mutually exclusive with channel) */
|
|
23
|
+
channels?: string[];
|
|
24
|
+
/** Event data as JSON string */
|
|
25
|
+
data: string;
|
|
26
|
+
/** Optional socket ID to exclude from receiving the event */
|
|
27
|
+
socketId?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Response from channel authentication.
|
|
31
|
+
*/
|
|
32
|
+
interface ChannelAuthResponse {
|
|
33
|
+
/** Authentication signature in format "key:signature" */
|
|
34
|
+
auth: string;
|
|
35
|
+
/** Optional channel data for presence channels */
|
|
36
|
+
channel_data?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Information about a channel.
|
|
40
|
+
*/
|
|
41
|
+
interface ChannelInfo {
|
|
42
|
+
/** Channel name */
|
|
43
|
+
name: string;
|
|
44
|
+
/** Number of active subscriptions */
|
|
45
|
+
subscription_count: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Webhook event data.
|
|
49
|
+
*/
|
|
50
|
+
interface WebhookEvent {
|
|
51
|
+
/** HTTP headers from the webhook request */
|
|
52
|
+
headers: Record<string, string | string[] | undefined>;
|
|
53
|
+
/** Raw request body */
|
|
54
|
+
body: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Server-side client for triggering events and managing channels.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { Apinator } from '@apinator/server';
|
|
63
|
+
*
|
|
64
|
+
* const client = new Apinator({
|
|
65
|
+
* appId: 'my-app-id',
|
|
66
|
+
* key: 'my-key',
|
|
67
|
+
* secret: 'my-secret',
|
|
68
|
+
* cluster: 'eu', // or 'us'
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Trigger an event
|
|
72
|
+
* await client.trigger({
|
|
73
|
+
* name: 'order-placed',
|
|
74
|
+
* channel: 'orders',
|
|
75
|
+
* data: JSON.stringify({ orderId: '123' }),
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* // Authenticate a channel subscription
|
|
79
|
+
* const auth = client.authenticateChannel(socketId, 'private-chat');
|
|
80
|
+
*
|
|
81
|
+
* // Get channel info
|
|
82
|
+
* const channel = await client.getChannel('orders');
|
|
83
|
+
* console.log(channel.subscription_count);
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare class Apinator {
|
|
87
|
+
private readonly appId;
|
|
88
|
+
private readonly key;
|
|
89
|
+
private readonly secret;
|
|
90
|
+
private readonly host;
|
|
91
|
+
constructor(options: RealtimeOptions);
|
|
92
|
+
/**
|
|
93
|
+
* Trigger an event on one or more channels.
|
|
94
|
+
*
|
|
95
|
+
* @param params - Event parameters
|
|
96
|
+
* @throws {ValidationError} If the request is invalid (400)
|
|
97
|
+
* @throws {AuthenticationError} If authentication fails (401)
|
|
98
|
+
* @throws {ApiError} For other API errors
|
|
99
|
+
*
|
|
100
|
+
* @example Single channel
|
|
101
|
+
* ```ts
|
|
102
|
+
* await client.trigger({
|
|
103
|
+
* name: 'message',
|
|
104
|
+
* channel: 'chat',
|
|
105
|
+
* data: JSON.stringify({ text: 'Hello!' }),
|
|
106
|
+
* });
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example Multiple channels
|
|
110
|
+
* ```ts
|
|
111
|
+
* await client.trigger({
|
|
112
|
+
* name: 'notification',
|
|
113
|
+
* channels: ['user-1', 'user-2'],
|
|
114
|
+
* data: JSON.stringify({ message: 'New update' }),
|
|
115
|
+
* });
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @example Exclude socket
|
|
119
|
+
* ```ts
|
|
120
|
+
* await client.trigger({
|
|
121
|
+
* name: 'message',
|
|
122
|
+
* channel: 'chat',
|
|
123
|
+
* data: JSON.stringify({ text: 'Hello!' }),
|
|
124
|
+
* socketId: '12345.67890', // Don't send to this connection
|
|
125
|
+
* });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
trigger(params: TriggerParams): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Authenticate a channel subscription request.
|
|
131
|
+
*
|
|
132
|
+
* This generates the authentication signature required for private and presence channels.
|
|
133
|
+
* The returned auth object should be sent back to the client for channel subscription.
|
|
134
|
+
*
|
|
135
|
+
* @param socketId - WebSocket connection socket ID from the client
|
|
136
|
+
* @param channelName - Channel name to authenticate
|
|
137
|
+
* @param channelData - Optional channel data for presence channels (JSON string with user info)
|
|
138
|
+
* @returns Channel authentication response with auth signature
|
|
139
|
+
*
|
|
140
|
+
* @example Private channel
|
|
141
|
+
* ```ts
|
|
142
|
+
* const auth = client.authenticateChannel('12345.67890', 'private-chat');
|
|
143
|
+
* // Send auth back to client
|
|
144
|
+
* res.json(auth);
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @example Presence channel
|
|
148
|
+
* ```ts
|
|
149
|
+
* const channelData = JSON.stringify({
|
|
150
|
+
* user_id: 'user1',
|
|
151
|
+
* user_info: { name: 'Alice' }
|
|
152
|
+
* });
|
|
153
|
+
* const auth = client.authenticateChannel('12345.67890', 'presence-room', channelData);
|
|
154
|
+
* res.json(auth);
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
authenticateChannel(socketId: string, channelName: string, channelData?: string): ChannelAuthResponse;
|
|
158
|
+
/**
|
|
159
|
+
* Get a list of channels, optionally filtered by prefix.
|
|
160
|
+
*
|
|
161
|
+
* @param prefix - Optional prefix to filter channels (e.g., "private-", "presence-")
|
|
162
|
+
* @returns Array of channel information
|
|
163
|
+
* @throws {AuthenticationError} If authentication fails (401)
|
|
164
|
+
* @throws {ApiError} For other API errors
|
|
165
|
+
*
|
|
166
|
+
* @example Get all channels
|
|
167
|
+
* ```ts
|
|
168
|
+
* const channels = await client.getChannels();
|
|
169
|
+
* channels.forEach(ch => console.log(ch.name, ch.subscription_count));
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @example Get presence channels only
|
|
173
|
+
* ```ts
|
|
174
|
+
* const presenceChannels = await client.getChannels('presence-');
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
getChannels(prefix?: string): Promise<ChannelInfo[]>;
|
|
178
|
+
/**
|
|
179
|
+
* Get information about a specific channel.
|
|
180
|
+
*
|
|
181
|
+
* @param channelName - Channel name
|
|
182
|
+
* @returns Channel information
|
|
183
|
+
* @throws {AuthenticationError} If authentication fails (401)
|
|
184
|
+
* @throws {ApiError} For other API errors (including 404 if channel not found)
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* try {
|
|
189
|
+
* const channel = await client.getChannel('chat');
|
|
190
|
+
* console.log(`Channel has ${channel.subscription_count} subscribers`);
|
|
191
|
+
* } catch (err) {
|
|
192
|
+
* if (err instanceof ApiError && err.status === 404) {
|
|
193
|
+
* console.log('Channel not found');
|
|
194
|
+
* }
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
getChannel(channelName: string): Promise<ChannelInfo>;
|
|
199
|
+
/**
|
|
200
|
+
* Verify the authenticity of a webhook request.
|
|
201
|
+
*
|
|
202
|
+
* This function verifies that the webhook was sent by the Realtime service
|
|
203
|
+
* by validating the HMAC signature in the request headers.
|
|
204
|
+
*
|
|
205
|
+
* @param headers - HTTP headers from the webhook request
|
|
206
|
+
* @param body - Raw request body as string
|
|
207
|
+
* @param maxAge - Optional maximum age in seconds for the webhook timestamp
|
|
208
|
+
* @returns true if the webhook is valid, false otherwise
|
|
209
|
+
*
|
|
210
|
+
* @example Express.js webhook handler
|
|
211
|
+
* ```ts
|
|
212
|
+
* app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
213
|
+
* const body = req.body.toString('utf8');
|
|
214
|
+
*
|
|
215
|
+
* if (!client.verifyWebhook(req.headers, body, 300)) {
|
|
216
|
+
* return res.status(401).send('Invalid signature');
|
|
217
|
+
* }
|
|
218
|
+
*
|
|
219
|
+
* const event = JSON.parse(body);
|
|
220
|
+
* // Process webhook...
|
|
221
|
+
* });
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
verifyWebhook(headers: Record<string, string | string[] | undefined>, body: string, maxAge?: number): boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Make an authenticated API request.
|
|
227
|
+
*/
|
|
228
|
+
private request;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Authenticate a channel subscription request.
|
|
233
|
+
*
|
|
234
|
+
* This generates the authentication signature required for private and presence channels.
|
|
235
|
+
* The returned auth string should be sent back to the client for channel subscription.
|
|
236
|
+
*
|
|
237
|
+
* @param secret - API secret
|
|
238
|
+
* @param key - API key
|
|
239
|
+
* @param socketId - WebSocket connection socket ID from the client
|
|
240
|
+
* @param channelName - Channel name to authenticate
|
|
241
|
+
* @param channelData - Optional channel data for presence channels (JSON string with user info)
|
|
242
|
+
* @returns Channel authentication response with auth signature
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* const authResponse = authenticateChannel(
|
|
247
|
+
* "my-secret",
|
|
248
|
+
* "my-key",
|
|
249
|
+
* "12345.67890",
|
|
250
|
+
* "private-chat"
|
|
251
|
+
* );
|
|
252
|
+
* // Returns: { auth: "my-key:abc123..." }
|
|
253
|
+
* ```
|
|
254
|
+
*
|
|
255
|
+
* @example Presence channel with user data
|
|
256
|
+
* ```ts
|
|
257
|
+
* const authResponse = authenticateChannel(
|
|
258
|
+
* "my-secret",
|
|
259
|
+
* "my-key",
|
|
260
|
+
* "12345.67890",
|
|
261
|
+
* "presence-room",
|
|
262
|
+
* JSON.stringify({ user_id: "user1", user_info: { name: "Alice" } })
|
|
263
|
+
* );
|
|
264
|
+
* // Returns: { auth: "my-key:abc123...", channel_data: "..." }
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
declare function authenticateChannel(secret: string, key: string, socketId: string, channelName: string, channelData?: string): ChannelAuthResponse;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Verify the authenticity of a webhook request.
|
|
271
|
+
*
|
|
272
|
+
* This function verifies that the webhook was sent by the Realtime service
|
|
273
|
+
* by validating the HMAC signature in the request headers.
|
|
274
|
+
*
|
|
275
|
+
* @param secret - Webhook secret
|
|
276
|
+
* @param headers - HTTP headers from the webhook request (case-insensitive keys)
|
|
277
|
+
* @param body - Raw request body as string
|
|
278
|
+
* @param maxAge - Optional maximum age in seconds for the webhook timestamp
|
|
279
|
+
* @returns true if the webhook is valid, false otherwise
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* // Express.js webhook handler
|
|
284
|
+
* app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
285
|
+
* const headers = req.headers;
|
|
286
|
+
* const body = req.body.toString('utf8');
|
|
287
|
+
*
|
|
288
|
+
* if (!verifyWebhook('my-webhook-secret', headers, body, 300)) {
|
|
289
|
+
* return res.status(401).send('Invalid signature');
|
|
290
|
+
* }
|
|
291
|
+
*
|
|
292
|
+
* // Process webhook
|
|
293
|
+
* const event = JSON.parse(body);
|
|
294
|
+
* // ...
|
|
295
|
+
* });
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
declare function verifyWebhook(secret: string, headers: Record<string, string | string[] | undefined>, body: string, maxAge?: number): boolean;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Compute MD5 hash of data and return as hex string.
|
|
302
|
+
*/
|
|
303
|
+
declare function md5Hex(data: string): string;
|
|
304
|
+
/**
|
|
305
|
+
* Sign an API request using HMAC-SHA256.
|
|
306
|
+
*
|
|
307
|
+
* @param secret - API secret
|
|
308
|
+
* @param method - HTTP method (e.g., "POST", "GET")
|
|
309
|
+
* @param path - Request path (e.g., "/apps/123/events")
|
|
310
|
+
* @param body - Request body as string
|
|
311
|
+
* @param timestamp - Unix timestamp in seconds
|
|
312
|
+
* @returns HMAC signature as hex string
|
|
313
|
+
*/
|
|
314
|
+
declare function signRequest(secret: string, method: string, path: string, body: string, timestamp: number): string;
|
|
315
|
+
/**
|
|
316
|
+
* Sign a channel authentication request using HMAC-SHA256.
|
|
317
|
+
*
|
|
318
|
+
* @param secret - API secret
|
|
319
|
+
* @param socketId - WebSocket connection socket ID
|
|
320
|
+
* @param channelName - Channel name to authenticate
|
|
321
|
+
* @param channelData - Optional channel data for presence channels (JSON string)
|
|
322
|
+
* @returns HMAC signature as hex string
|
|
323
|
+
*/
|
|
324
|
+
declare function signChannel(secret: string, socketId: string, channelName: string, channelData?: string): string;
|
|
325
|
+
/**
|
|
326
|
+
* Sign a webhook payload using HMAC-SHA256.
|
|
327
|
+
*
|
|
328
|
+
* @param secret - Webhook secret
|
|
329
|
+
* @param timestamp - Timestamp from X-Realtime-Timestamp header
|
|
330
|
+
* @param payload - Raw webhook body
|
|
331
|
+
* @returns HMAC signature as hex string
|
|
332
|
+
*/
|
|
333
|
+
declare function signWebhookPayload(secret: string, timestamp: string, payload: string): string;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Base error class for all Realtime SDK errors.
|
|
337
|
+
*/
|
|
338
|
+
declare class RealtimeError extends Error {
|
|
339
|
+
constructor(message: string);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Error thrown when authentication fails (401 responses).
|
|
343
|
+
*/
|
|
344
|
+
declare class AuthenticationError extends RealtimeError {
|
|
345
|
+
constructor(message: string);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Error thrown when request validation fails (400 responses).
|
|
349
|
+
*/
|
|
350
|
+
declare class ValidationError extends RealtimeError {
|
|
351
|
+
constructor(message: string);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Generic API error with status code and response body.
|
|
355
|
+
*/
|
|
356
|
+
declare class ApiError extends RealtimeError {
|
|
357
|
+
readonly status: number;
|
|
358
|
+
readonly body: string;
|
|
359
|
+
constructor(message: string, status: number, body: string);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export { ApiError, Apinator, AuthenticationError, type ChannelAuthResponse, type ChannelInfo, RealtimeError, type RealtimeOptions, type TriggerParams, ValidationError, type WebhookEvent, authenticateChannel, md5Hex, signChannel, signRequest, signWebhookPayload, verifyWebhook };
|