@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.
@@ -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 };