@smarthivelabs-devs/hive-socket-node 1.0.0 → 1.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/README.md +92 -12
- package/dist/index.cjs +48 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @smarthivelabs-devs/hive-socket-node
|
|
2
2
|
|
|
3
|
-
Node.js SDK for Hive-Socket — push real-time notifications and
|
|
3
|
+
Node.js SDK for Hive-Socket — push real-time notifications and broadcast typed messages to connected clients from any backend service.
|
|
4
|
+
|
|
5
|
+
> **v1.1.0** adds `hive.broadcast.toRoom()` for sending structured typed messages received by `useMessages()` on the client. Use this for full-duplex features (live competitions, collaborative editing, presence) where clients need to act on the payload, not just display a notification.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
@@ -31,10 +33,13 @@ Add to your backend `.env`:
|
|
|
31
33
|
|
|
32
34
|
```env
|
|
33
35
|
HIVE_SOCKET_URL=https://socket.smarthivelabs.dev
|
|
34
|
-
HIVE_SOCKET_API_KEY=
|
|
36
|
+
HIVE_SOCKET_API_KEY=shai_<your-key> # same value as INTERNAL_API_KEY on the Hive-Socket server
|
|
37
|
+
SMARTHIVE_PROJECT_ID=<your-auth-project-id> # project ID from SmartHive Auth dashboard
|
|
35
38
|
```
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
`HIVE_SOCKET_API_KEY` — copy the value of `INTERNAL_API_KEY` set on the Hive-Socket server. This is a shared secret between your backends and Hive-Socket.
|
|
41
|
+
|
|
42
|
+
`SMARTHIVE_PROJECT_ID` — the project ID issued by SmartHive Auth when you registered your product. Pass this as `projectId` in every notify call so Hive-Socket scopes messages and notifications to the correct project.
|
|
38
43
|
|
|
39
44
|
---
|
|
40
45
|
|
|
@@ -50,7 +55,7 @@ const hive = createHiveSocketClient({
|
|
|
50
55
|
|
|
51
56
|
// Push a notification to a user
|
|
52
57
|
await hive.notify.user('user-id-123', {
|
|
53
|
-
projectId:
|
|
58
|
+
projectId: process.env.SMARTHIVE_PROJECT_ID!,
|
|
54
59
|
title: 'New message',
|
|
55
60
|
body: 'Alice sent you a message',
|
|
56
61
|
type: 'message',
|
|
@@ -67,9 +72,9 @@ Creates a client instance. Create once and reuse across your application.
|
|
|
67
72
|
|
|
68
73
|
```typescript
|
|
69
74
|
const hive = createHiveSocketClient({
|
|
70
|
-
baseUrl:
|
|
71
|
-
apiKey:
|
|
72
|
-
timeout: 10_000,
|
|
75
|
+
baseUrl: process.env.HIVE_SOCKET_URL!, // e.g. https://socket.smarthivelabs.dev
|
|
76
|
+
apiKey: process.env.HIVE_SOCKET_API_KEY!, // shai_* internal API key
|
|
77
|
+
timeout: 10_000, // Optional. Request timeout in ms. Default: 10000
|
|
73
78
|
});
|
|
74
79
|
```
|
|
75
80
|
|
|
@@ -81,7 +86,7 @@ Push a notification to a specific user. Delivered instantly to all their connect
|
|
|
81
86
|
|
|
82
87
|
```typescript
|
|
83
88
|
await hive.notify.user(userId, {
|
|
84
|
-
projectId: string, //
|
|
89
|
+
projectId: string, // SmartHive Auth project ID (process.env.SMARTHIVE_PROJECT_ID)
|
|
85
90
|
title: string, // Notification title
|
|
86
91
|
body: string, // Notification body
|
|
87
92
|
type: NotificationType, // 'info' | 'success' | 'warning' | 'error' | 'message'
|
|
@@ -93,7 +98,7 @@ await hive.notify.user(userId, {
|
|
|
93
98
|
**Example — payment confirmed:**
|
|
94
99
|
```typescript
|
|
95
100
|
await hive.notify.user(userId, {
|
|
96
|
-
projectId:
|
|
101
|
+
projectId: process.env.SMARTHIVE_PROJECT_ID!,
|
|
97
102
|
title: 'Payment confirmed',
|
|
98
103
|
body: `₦${amount.toLocaleString()} received`,
|
|
99
104
|
type: 'success',
|
|
@@ -122,7 +127,7 @@ Broadcast a notification to all users currently in a room. Room notifications ar
|
|
|
122
127
|
|
|
123
128
|
```typescript
|
|
124
129
|
await hive.notify.room(roomId, {
|
|
125
|
-
projectId: string,
|
|
130
|
+
projectId: string, // SmartHive Auth project ID (process.env.SMARTHIVE_PROJECT_ID)
|
|
126
131
|
title: string,
|
|
127
132
|
body: string,
|
|
128
133
|
type: NotificationType,
|
|
@@ -134,7 +139,7 @@ await hive.notify.room(roomId, {
|
|
|
134
139
|
**Example — quiz started:**
|
|
135
140
|
```typescript
|
|
136
141
|
await hive.notify.room(`course:${courseId}`, {
|
|
137
|
-
projectId:
|
|
142
|
+
projectId: process.env.SMARTHIVE_PROJECT_ID!,
|
|
138
143
|
title: 'Quiz started',
|
|
139
144
|
body: 'Chapter 3 quiz is now live',
|
|
140
145
|
type: 'info',
|
|
@@ -145,7 +150,7 @@ await hive.notify.room(`course:${courseId}`, {
|
|
|
145
150
|
**Example — live vote update:**
|
|
146
151
|
```typescript
|
|
147
152
|
await hive.notify.room(`event:${eventId}`, {
|
|
148
|
-
projectId:
|
|
153
|
+
projectId: process.env.SMARTHIVE_PROJECT_ID!,
|
|
149
154
|
title: 'Results updated',
|
|
150
155
|
body: 'New votes have been counted',
|
|
151
156
|
type: 'info',
|
|
@@ -156,6 +161,40 @@ await hive.notify.room(`event:${eventId}`, {
|
|
|
156
161
|
|
|
157
162
|
---
|
|
158
163
|
|
|
164
|
+
### `hive.broadcast.toRoom(roomId, payload)` *(v1.1.0)*
|
|
165
|
+
|
|
166
|
+
Broadcast a typed structured message to all sockets in a room. Messages are received by clients via `useMessages(roomId)` — they arrive as `message:new` events, distinct from `notification:new` produced by `notify.*`. Use this for real-time game state, collaborative state changes, or any payload where the client needs to react to the message type programmatically.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
await hive.broadcast.toRoom(roomId, {
|
|
170
|
+
projectId: string, // SmartHive Auth project ID
|
|
171
|
+
type: string, // your event type, e.g. "competition.question-change"
|
|
172
|
+
payload: Record<string, unknown>, // arbitrary JSON
|
|
173
|
+
senderId?: string, // optional — defaults to "system"
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Example — competition state advance:**
|
|
178
|
+
```typescript
|
|
179
|
+
await hive.broadcast.toRoom(`competition:${competitionId}`, {
|
|
180
|
+
projectId: process.env.SMARTHIVE_PROJECT_ID!,
|
|
181
|
+
type: 'competition.question-change',
|
|
182
|
+
payload: { questionIndex: 2, questionEndsAt: '2026-05-24T12:00:30.000Z' },
|
|
183
|
+
senderId: 'hivedemia-api',
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Difference between `notify.room` and `broadcast.toRoom`:**
|
|
188
|
+
|
|
189
|
+
| | `notify.room` | `broadcast.toRoom` |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| Client hook | `useNotifications()` | `useMessages(roomId)` |
|
|
192
|
+
| Wire event | `notification:new` | `message:new` |
|
|
193
|
+
| Persisted | Yes (offline delivery) | No (ephemeral) |
|
|
194
|
+
| Best for | In-app alerts, toasts | Game state, live sync |
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
159
198
|
### `hive.health()`
|
|
160
199
|
|
|
161
200
|
Check server health and current connection count.
|
|
@@ -330,12 +369,46 @@ export async function POST(req: Request) {
|
|
|
330
369
|
|
|
331
370
|
---
|
|
332
371
|
|
|
372
|
+
## Security
|
|
373
|
+
|
|
374
|
+
### How the API key is sent and validated
|
|
375
|
+
|
|
376
|
+
Every request from this SDK includes an `x-internal-api-key` header:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
POST /notify/user
|
|
380
|
+
x-internal-api-key: shai_<your-key>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
The Hive-Socket server compares this header against its `INTERNAL_API_KEY` env var using a constant-time comparison (no timing attacks). If the key doesn't match the request is rejected with HTTP 401.
|
|
384
|
+
|
|
385
|
+
**This key is a shared secret between your backends and Hive-Socket.** It must never be used in browser or mobile code — it gives unrestricted ability to send notifications to any user.
|
|
386
|
+
|
|
387
|
+
### What the server enforces
|
|
388
|
+
|
|
389
|
+
| Guarantee | How |
|
|
390
|
+
|-----------|-----|
|
|
391
|
+
| Only trusted backends can push notifications | `x-internal-api-key` validated on every request |
|
|
392
|
+
| Notifications are scoped to the correct project | `projectId` from your payload scopes DB storage and room routing |
|
|
393
|
+
| `userId` comes from your backend, not the client | Clients never call notify endpoints — only your server-side code does |
|
|
394
|
+
|
|
395
|
+
### What you must do
|
|
396
|
+
|
|
397
|
+
- **Store the key in environment variables only.** Never commit it to source control or embed it in client-side code.
|
|
398
|
+
- **Use the same key value** as `INTERNAL_API_KEY` on the Hive-Socket server. They must match exactly.
|
|
399
|
+
- **Use a different key per environment** — generate a separate key for dev and prod, set them independently.
|
|
400
|
+
- **Rotate by updating both env vars** — update `INTERNAL_API_KEY` on Hive-Socket and `HIVE_SOCKET_API_KEY` on your backends, then redeploy. There is no revocation endpoint; rotation is instant once both sides are updated.
|
|
401
|
+
- **Always pass `projectId` from your own config** (`process.env.SMARTHIVE_PROJECT_ID`) — never accept it from user input. It is the SmartHive Auth project ID for your product.
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
333
405
|
## Types
|
|
334
406
|
|
|
335
407
|
```typescript
|
|
336
408
|
import type {
|
|
337
409
|
HiveSocketConfig,
|
|
338
410
|
HiveNotifyPayload,
|
|
411
|
+
HiveBroadcastPayload,
|
|
339
412
|
HiveHealthResponse,
|
|
340
413
|
NotificationType,
|
|
341
414
|
} from '@smarthivelabs-devs/hive-socket-node';
|
|
@@ -357,6 +430,13 @@ interface HiveNotifyPayload {
|
|
|
357
430
|
sourceService?: string;
|
|
358
431
|
}
|
|
359
432
|
|
|
433
|
+
interface HiveBroadcastPayload {
|
|
434
|
+
projectId: string;
|
|
435
|
+
type: string;
|
|
436
|
+
payload: Record<string, unknown>;
|
|
437
|
+
senderId?: string;
|
|
438
|
+
}
|
|
439
|
+
|
|
360
440
|
interface HiveHealthResponse {
|
|
361
441
|
status: 'ok';
|
|
362
442
|
connections: number;
|
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BroadcastResource: () => BroadcastResource,
|
|
23
24
|
HiveSocketAuthError: () => HiveSocketAuthError,
|
|
24
25
|
HiveSocketClient: () => HiveSocketClient,
|
|
25
26
|
HiveSocketError: () => HiveSocketError,
|
|
@@ -99,9 +100,54 @@ var NotifyResource = class {
|
|
|
99
100
|
}
|
|
100
101
|
};
|
|
101
102
|
|
|
103
|
+
// src/resources/broadcast.ts
|
|
104
|
+
var BroadcastResource = class {
|
|
105
|
+
constructor(baseUrl, apiKey, timeout) {
|
|
106
|
+
this.baseUrl = baseUrl;
|
|
107
|
+
this.apiKey = apiKey;
|
|
108
|
+
this.timeout = timeout;
|
|
109
|
+
}
|
|
110
|
+
baseUrl;
|
|
111
|
+
apiKey;
|
|
112
|
+
timeout;
|
|
113
|
+
/** Broadcast a real-time message to all sockets in a room (received via useMessages). */
|
|
114
|
+
async toRoom(roomId, payload) {
|
|
115
|
+
await this.post(`/internal/broadcast/room/${encodeURIComponent(roomId)}`, payload);
|
|
116
|
+
}
|
|
117
|
+
async post(path, body) {
|
|
118
|
+
const controller = new AbortController();
|
|
119
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
120
|
+
try {
|
|
121
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: {
|
|
124
|
+
"content-type": "application/json",
|
|
125
|
+
"x-internal-api-key": this.apiKey
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify(body),
|
|
128
|
+
signal: controller.signal
|
|
129
|
+
});
|
|
130
|
+
if (res.status === 401) throw new HiveSocketAuthError();
|
|
131
|
+
if (!res.ok) {
|
|
132
|
+
const text = await res.text().catch(() => res.statusText);
|
|
133
|
+
throw new HiveSocketError(`Hive-Socket broadcast failed: ${text}`, res.status);
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err instanceof HiveSocketError) throw err;
|
|
137
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
138
|
+
throw new HiveSocketNetworkError(
|
|
139
|
+
controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg
|
|
140
|
+
);
|
|
141
|
+
} finally {
|
|
142
|
+
clearTimeout(timer);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
102
147
|
// src/client.ts
|
|
103
148
|
var HiveSocketClient = class {
|
|
104
149
|
notify;
|
|
150
|
+
broadcast;
|
|
105
151
|
baseUrl;
|
|
106
152
|
apiKey;
|
|
107
153
|
timeout;
|
|
@@ -110,6 +156,7 @@ var HiveSocketClient = class {
|
|
|
110
156
|
this.apiKey = config.apiKey;
|
|
111
157
|
this.timeout = config.timeout ?? 1e4;
|
|
112
158
|
this.notify = new NotifyResource(this.baseUrl, this.apiKey, this.timeout);
|
|
159
|
+
this.broadcast = new BroadcastResource(this.baseUrl, this.apiKey, this.timeout);
|
|
113
160
|
}
|
|
114
161
|
/** Check the Hive-Socket server health and current connection count. */
|
|
115
162
|
async health() {
|
|
@@ -137,6 +184,7 @@ function createHiveSocketClient(config) {
|
|
|
137
184
|
}
|
|
138
185
|
// Annotate the CommonJS export names for ESM import in node:
|
|
139
186
|
0 && (module.exports = {
|
|
187
|
+
BroadcastResource,
|
|
140
188
|
HiveSocketAuthError,
|
|
141
189
|
HiveSocketClient,
|
|
142
190
|
HiveSocketError,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/notify.ts","../src/client.ts"],"sourcesContent":["export { HiveSocketClient, createHiveSocketClient } from './client.js';\nexport { NotifyResource } from './resources/notify.js';\nexport { HiveSocketError, HiveSocketAuthError, HiveSocketNetworkError } from './errors.js';\nexport type {\n HiveSocketConfig,\n HiveNotifyPayload,\n HiveHealthResponse,\n NotificationType,\n} from './types.js';\n","export class HiveSocketError extends Error {\n readonly statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.name = 'HiveSocketError';\n this.statusCode = statusCode;\n }\n}\n\n/** Thrown when the API key is wrong (HTTP 401) */\nexport class HiveSocketAuthError extends HiveSocketError {\n constructor(message = 'Invalid API key') {\n super(message, 401);\n this.name = 'HiveSocketAuthError';\n }\n}\n\n/** Thrown when the fetch fails entirely (network down, timeout) */\nexport class HiveSocketNetworkError extends HiveSocketError {\n constructor(message: string) {\n super(message, 0);\n this.name = 'HiveSocketNetworkError';\n }\n}\n","import { HiveSocketAuthError, HiveSocketError, HiveSocketNetworkError } from '../errors.js';\nimport type { HiveNotifyPayload } from '../types.js';\n\nexport class NotifyResource {\n constructor(\n private readonly baseUrl: string,\n private readonly apiKey: string,\n private readonly timeout: number,\n ) {}\n\n /** Push a notification to a specific user's connected sockets. */\n async user(userId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/user/${encodeURIComponent(userId)}`, payload);\n }\n\n /** Broadcast a notification to all sockets in a room. */\n async room(roomId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/room/${encodeURIComponent(roomId)}`, payload);\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-internal-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (res.status === 401) throw new HiveSocketAuthError();\n if (!res.ok) {\n const text = await res.text().catch(() => res.statusText);\n throw new HiveSocketError(`Hive-Socket request failed: ${text}`, res.status);\n }\n } catch (err) {\n if (err instanceof HiveSocketError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import { NotifyResource } from './resources/notify.js';\nimport { HiveSocketNetworkError } from './errors.js';\nimport type { HiveSocketConfig, HiveHealthResponse } from './types.js';\n\nexport class HiveSocketClient {\n readonly notify: NotifyResource;\n\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n constructor(config: HiveSocketConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 10_000;\n this.notify = new NotifyResource(this.baseUrl, this.apiKey, this.timeout);\n }\n\n /** Check the Hive-Socket server health and current connection count. */\n async health(): Promise<HiveHealthResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: controller.signal,\n });\n if (!res.ok) throw new HiveSocketNetworkError(`Health check failed: ${res.statusText}`);\n return res.json() as Promise<HiveHealthResponse>;\n } catch (err) {\n if (err instanceof HiveSocketNetworkError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Health check timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Create a Hive-Socket server-side client.\n *\n * @example\n * const hive = createHiveSocketClient({\n * baseUrl: process.env.HIVE_SOCKET_URL!,\n * apiKey: process.env.HIVE_SOCKET_API_KEY!,\n * });\n * await hive.notify.user(userId, { projectId, title: 'Hey', body: 'Msg', type: 'message' });\n */\nexport function createHiveSocketClient(config: HiveSocketConfig): HiveSocketClient {\n return new HiveSocketClient(config);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EAET,YAAY,SAAiB,YAAoB;AAC/C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAGO,IAAM,sBAAN,cAAkC,gBAAgB;AAAA,EACvD,YAAY,UAAU,mBAAmB;AACvC,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,yBAAN,cAAqC,gBAAgB;AAAA,EAC1D,YAAY,SAAiB;AAC3B,UAAM,SAAS,CAAC;AAChB,SAAK,OAAO;AAAA,EACd;AACF;;;ACrBO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YACmB,SACA,QACA,SACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAInB,MAAM,KAAK,QAAgB,SAA2C;AACpE,UAAM,KAAK,KAAK,yBAAyB,mBAAmB,MAAM,CAAC,IAAI,OAAO;AAAA,EAChF;AAAA;AAAA,EAGA,MAAM,KAAK,QAAgB,SAA2C;AACpE,UAAM,KAAK,KAAK,yBAAyB,mBAAmB,MAAM,CAAC,IAAI,OAAO;AAAA,EAChF;AAAA,EAEA,MAAc,KAAK,MAAc,MAA8B;AAC7D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,sBAAsB,KAAK;AAAA,QAC7B;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,IAAI,WAAW,IAAK,OAAM,IAAI,oBAAoB;AACtD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,UAAU;AACxD,cAAM,IAAI,gBAAgB,+BAA+B,IAAI,IAAI,IAAI,MAAM;AAAA,MAC7E;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,gBAAiB,OAAM;AAC1C,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAM,IAAI;AAAA,QACR,WAAW,OAAO,UAAU,2BAA2B,KAAK,OAAO,OAAO;AAAA,MAC5E;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AACF;;;AC9CO,IAAM,mBAAN,MAAuB;AAAA,EACnB;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAA0B;AACpC,SAAK,UAAU,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAC/C,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,SAAS,IAAI,eAAe,KAAK,SAAS,KAAK,QAAQ,KAAK,OAAO;AAAA,EAC1E;AAAA;AAAA,EAGA,MAAM,SAAsC;AAC1C,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW;AAAA,QAChD,QAAQ,WAAW;AAAA,MACrB,CAAC;AACD,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,uBAAuB,wBAAwB,IAAI,UAAU,EAAE;AACtF,aAAO,IAAI,KAAK;AAAA,IAClB,SAAS,KAAK;AACZ,UAAI,eAAe,uBAAwB,OAAM;AACjD,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAM,IAAI;AAAA,QACR,WAAW,OAAO,UAAU,gCAAgC,KAAK,OAAO,OAAO;AAAA,MACjF;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AACF;AAYO,SAAS,uBAAuB,QAA4C;AACjF,SAAO,IAAI,iBAAiB,MAAM;AACpC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/notify.ts","../src/resources/broadcast.ts","../src/client.ts"],"sourcesContent":["export { HiveSocketClient, createHiveSocketClient } from './client.js';\nexport { NotifyResource } from './resources/notify.js';\nexport { BroadcastResource } from './resources/broadcast.js';\nexport { HiveSocketError, HiveSocketAuthError, HiveSocketNetworkError } from './errors.js';\nexport type {\n HiveSocketConfig,\n HiveNotifyPayload,\n HiveBroadcastPayload,\n HiveHealthResponse,\n NotificationType,\n} from './types.js';\n","export class HiveSocketError extends Error {\n readonly statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.name = 'HiveSocketError';\n this.statusCode = statusCode;\n }\n}\n\n/** Thrown when the API key is wrong (HTTP 401) */\nexport class HiveSocketAuthError extends HiveSocketError {\n constructor(message = 'Invalid API key') {\n super(message, 401);\n this.name = 'HiveSocketAuthError';\n }\n}\n\n/** Thrown when the fetch fails entirely (network down, timeout) */\nexport class HiveSocketNetworkError extends HiveSocketError {\n constructor(message: string) {\n super(message, 0);\n this.name = 'HiveSocketNetworkError';\n }\n}\n","import { HiveSocketAuthError, HiveSocketError, HiveSocketNetworkError } from '../errors.js';\nimport type { HiveNotifyPayload } from '../types.js';\n\nexport class NotifyResource {\n constructor(\n private readonly baseUrl: string,\n private readonly apiKey: string,\n private readonly timeout: number,\n ) {}\n\n /** Push a notification to a specific user's connected sockets. */\n async user(userId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/user/${encodeURIComponent(userId)}`, payload);\n }\n\n /** Broadcast a notification to all sockets in a room. */\n async room(roomId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/room/${encodeURIComponent(roomId)}`, payload);\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-internal-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (res.status === 401) throw new HiveSocketAuthError();\n if (!res.ok) {\n const text = await res.text().catch(() => res.statusText);\n throw new HiveSocketError(`Hive-Socket request failed: ${text}`, res.status);\n }\n } catch (err) {\n if (err instanceof HiveSocketError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import { HiveSocketAuthError, HiveSocketError, HiveSocketNetworkError } from '../errors.js';\n\nexport class BroadcastResource {\n constructor(\n private readonly baseUrl: string,\n private readonly apiKey: string,\n private readonly timeout: number,\n ) {}\n\n /** Broadcast a real-time message to all sockets in a room (received via useMessages). */\n async toRoom(\n roomId: string,\n payload: { projectId: string; senderId?: string; type: string; payload: Record<string, unknown> },\n ): Promise<void> {\n await this.post(`/internal/broadcast/room/${encodeURIComponent(roomId)}`, payload);\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-internal-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (res.status === 401) throw new HiveSocketAuthError();\n if (!res.ok) {\n const text = await res.text().catch(() => res.statusText);\n throw new HiveSocketError(`Hive-Socket broadcast failed: ${text}`, res.status);\n }\n } catch (err) {\n if (err instanceof HiveSocketError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import { NotifyResource } from './resources/notify.js';\nimport { BroadcastResource } from './resources/broadcast.js';\nimport { HiveSocketNetworkError } from './errors.js';\nimport type { HiveSocketConfig, HiveHealthResponse } from './types.js';\n\nexport class HiveSocketClient {\n readonly notify: NotifyResource;\n readonly broadcast: BroadcastResource;\n\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n constructor(config: HiveSocketConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 10_000;\n this.notify = new NotifyResource(this.baseUrl, this.apiKey, this.timeout);\n this.broadcast = new BroadcastResource(this.baseUrl, this.apiKey, this.timeout);\n }\n\n /** Check the Hive-Socket server health and current connection count. */\n async health(): Promise<HiveHealthResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: controller.signal,\n });\n if (!res.ok) throw new HiveSocketNetworkError(`Health check failed: ${res.statusText}`);\n return res.json() as Promise<HiveHealthResponse>;\n } catch (err) {\n if (err instanceof HiveSocketNetworkError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Health check timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Create a Hive-Socket server-side client.\n *\n * @example\n * const hive = createHiveSocketClient({\n * baseUrl: process.env.HIVE_SOCKET_URL!,\n * apiKey: process.env.HIVE_SOCKET_API_KEY!,\n * });\n * await hive.notify.user(userId, { projectId, title: 'Hey', body: 'Msg', type: 'message' });\n */\nexport function createHiveSocketClient(config: HiveSocketConfig): HiveSocketClient {\n return new HiveSocketClient(config);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -8,6 +8,13 @@ interface HiveNotifyPayload {
|
|
|
8
8
|
metadata?: Record<string, unknown>;
|
|
9
9
|
sourceService?: string;
|
|
10
10
|
}
|
|
11
|
+
/** Payload sent to POST /internal/broadcast/room/:roomId */
|
|
12
|
+
interface HiveBroadcastPayload {
|
|
13
|
+
projectId: string;
|
|
14
|
+
type: string;
|
|
15
|
+
payload: Record<string, unknown>;
|
|
16
|
+
senderId?: string;
|
|
17
|
+
}
|
|
11
18
|
/** Response from GET /health */
|
|
12
19
|
interface HiveHealthResponse {
|
|
13
20
|
status: 'ok';
|
|
@@ -35,8 +42,24 @@ declare class NotifyResource {
|
|
|
35
42
|
private post;
|
|
36
43
|
}
|
|
37
44
|
|
|
45
|
+
declare class BroadcastResource {
|
|
46
|
+
private readonly baseUrl;
|
|
47
|
+
private readonly apiKey;
|
|
48
|
+
private readonly timeout;
|
|
49
|
+
constructor(baseUrl: string, apiKey: string, timeout: number);
|
|
50
|
+
/** Broadcast a real-time message to all sockets in a room (received via useMessages). */
|
|
51
|
+
toRoom(roomId: string, payload: {
|
|
52
|
+
projectId: string;
|
|
53
|
+
senderId?: string;
|
|
54
|
+
type: string;
|
|
55
|
+
payload: Record<string, unknown>;
|
|
56
|
+
}): Promise<void>;
|
|
57
|
+
private post;
|
|
58
|
+
}
|
|
59
|
+
|
|
38
60
|
declare class HiveSocketClient {
|
|
39
61
|
readonly notify: NotifyResource;
|
|
62
|
+
readonly broadcast: BroadcastResource;
|
|
40
63
|
private readonly baseUrl;
|
|
41
64
|
private readonly apiKey;
|
|
42
65
|
private readonly timeout;
|
|
@@ -69,4 +92,4 @@ declare class HiveSocketNetworkError extends HiveSocketError {
|
|
|
69
92
|
constructor(message: string);
|
|
70
93
|
}
|
|
71
94
|
|
|
72
|
-
export { type HiveHealthResponse, type HiveNotifyPayload, HiveSocketAuthError, HiveSocketClient, type HiveSocketConfig, HiveSocketError, HiveSocketNetworkError, type NotificationType, NotifyResource, createHiveSocketClient };
|
|
95
|
+
export { BroadcastResource, type HiveBroadcastPayload, type HiveHealthResponse, type HiveNotifyPayload, HiveSocketAuthError, HiveSocketClient, type HiveSocketConfig, HiveSocketError, HiveSocketNetworkError, type NotificationType, NotifyResource, createHiveSocketClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,13 @@ interface HiveNotifyPayload {
|
|
|
8
8
|
metadata?: Record<string, unknown>;
|
|
9
9
|
sourceService?: string;
|
|
10
10
|
}
|
|
11
|
+
/** Payload sent to POST /internal/broadcast/room/:roomId */
|
|
12
|
+
interface HiveBroadcastPayload {
|
|
13
|
+
projectId: string;
|
|
14
|
+
type: string;
|
|
15
|
+
payload: Record<string, unknown>;
|
|
16
|
+
senderId?: string;
|
|
17
|
+
}
|
|
11
18
|
/** Response from GET /health */
|
|
12
19
|
interface HiveHealthResponse {
|
|
13
20
|
status: 'ok';
|
|
@@ -35,8 +42,24 @@ declare class NotifyResource {
|
|
|
35
42
|
private post;
|
|
36
43
|
}
|
|
37
44
|
|
|
45
|
+
declare class BroadcastResource {
|
|
46
|
+
private readonly baseUrl;
|
|
47
|
+
private readonly apiKey;
|
|
48
|
+
private readonly timeout;
|
|
49
|
+
constructor(baseUrl: string, apiKey: string, timeout: number);
|
|
50
|
+
/** Broadcast a real-time message to all sockets in a room (received via useMessages). */
|
|
51
|
+
toRoom(roomId: string, payload: {
|
|
52
|
+
projectId: string;
|
|
53
|
+
senderId?: string;
|
|
54
|
+
type: string;
|
|
55
|
+
payload: Record<string, unknown>;
|
|
56
|
+
}): Promise<void>;
|
|
57
|
+
private post;
|
|
58
|
+
}
|
|
59
|
+
|
|
38
60
|
declare class HiveSocketClient {
|
|
39
61
|
readonly notify: NotifyResource;
|
|
62
|
+
readonly broadcast: BroadcastResource;
|
|
40
63
|
private readonly baseUrl;
|
|
41
64
|
private readonly apiKey;
|
|
42
65
|
private readonly timeout;
|
|
@@ -69,4 +92,4 @@ declare class HiveSocketNetworkError extends HiveSocketError {
|
|
|
69
92
|
constructor(message: string);
|
|
70
93
|
}
|
|
71
94
|
|
|
72
|
-
export { type HiveHealthResponse, type HiveNotifyPayload, HiveSocketAuthError, HiveSocketClient, type HiveSocketConfig, HiveSocketError, HiveSocketNetworkError, type NotificationType, NotifyResource, createHiveSocketClient };
|
|
95
|
+
export { BroadcastResource, type HiveBroadcastPayload, type HiveHealthResponse, type HiveNotifyPayload, HiveSocketAuthError, HiveSocketClient, type HiveSocketConfig, HiveSocketError, HiveSocketNetworkError, type NotificationType, NotifyResource, createHiveSocketClient };
|
package/dist/index.js
CHANGED
|
@@ -68,9 +68,54 @@ var NotifyResource = class {
|
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
// src/resources/broadcast.ts
|
|
72
|
+
var BroadcastResource = class {
|
|
73
|
+
constructor(baseUrl, apiKey, timeout) {
|
|
74
|
+
this.baseUrl = baseUrl;
|
|
75
|
+
this.apiKey = apiKey;
|
|
76
|
+
this.timeout = timeout;
|
|
77
|
+
}
|
|
78
|
+
baseUrl;
|
|
79
|
+
apiKey;
|
|
80
|
+
timeout;
|
|
81
|
+
/** Broadcast a real-time message to all sockets in a room (received via useMessages). */
|
|
82
|
+
async toRoom(roomId, payload) {
|
|
83
|
+
await this.post(`/internal/broadcast/room/${encodeURIComponent(roomId)}`, payload);
|
|
84
|
+
}
|
|
85
|
+
async post(path, body) {
|
|
86
|
+
const controller = new AbortController();
|
|
87
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
88
|
+
try {
|
|
89
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: {
|
|
92
|
+
"content-type": "application/json",
|
|
93
|
+
"x-internal-api-key": this.apiKey
|
|
94
|
+
},
|
|
95
|
+
body: JSON.stringify(body),
|
|
96
|
+
signal: controller.signal
|
|
97
|
+
});
|
|
98
|
+
if (res.status === 401) throw new HiveSocketAuthError();
|
|
99
|
+
if (!res.ok) {
|
|
100
|
+
const text = await res.text().catch(() => res.statusText);
|
|
101
|
+
throw new HiveSocketError(`Hive-Socket broadcast failed: ${text}`, res.status);
|
|
102
|
+
}
|
|
103
|
+
} catch (err) {
|
|
104
|
+
if (err instanceof HiveSocketError) throw err;
|
|
105
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
106
|
+
throw new HiveSocketNetworkError(
|
|
107
|
+
controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg
|
|
108
|
+
);
|
|
109
|
+
} finally {
|
|
110
|
+
clearTimeout(timer);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
71
115
|
// src/client.ts
|
|
72
116
|
var HiveSocketClient = class {
|
|
73
117
|
notify;
|
|
118
|
+
broadcast;
|
|
74
119
|
baseUrl;
|
|
75
120
|
apiKey;
|
|
76
121
|
timeout;
|
|
@@ -79,6 +124,7 @@ var HiveSocketClient = class {
|
|
|
79
124
|
this.apiKey = config.apiKey;
|
|
80
125
|
this.timeout = config.timeout ?? 1e4;
|
|
81
126
|
this.notify = new NotifyResource(this.baseUrl, this.apiKey, this.timeout);
|
|
127
|
+
this.broadcast = new BroadcastResource(this.baseUrl, this.apiKey, this.timeout);
|
|
82
128
|
}
|
|
83
129
|
/** Check the Hive-Socket server health and current connection count. */
|
|
84
130
|
async health() {
|
|
@@ -105,6 +151,7 @@ function createHiveSocketClient(config) {
|
|
|
105
151
|
return new HiveSocketClient(config);
|
|
106
152
|
}
|
|
107
153
|
export {
|
|
154
|
+
BroadcastResource,
|
|
108
155
|
HiveSocketAuthError,
|
|
109
156
|
HiveSocketClient,
|
|
110
157
|
HiveSocketError,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/resources/notify.ts","../src/client.ts"],"sourcesContent":["export class HiveSocketError extends Error {\n readonly statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.name = 'HiveSocketError';\n this.statusCode = statusCode;\n }\n}\n\n/** Thrown when the API key is wrong (HTTP 401) */\nexport class HiveSocketAuthError extends HiveSocketError {\n constructor(message = 'Invalid API key') {\n super(message, 401);\n this.name = 'HiveSocketAuthError';\n }\n}\n\n/** Thrown when the fetch fails entirely (network down, timeout) */\nexport class HiveSocketNetworkError extends HiveSocketError {\n constructor(message: string) {\n super(message, 0);\n this.name = 'HiveSocketNetworkError';\n }\n}\n","import { HiveSocketAuthError, HiveSocketError, HiveSocketNetworkError } from '../errors.js';\nimport type { HiveNotifyPayload } from '../types.js';\n\nexport class NotifyResource {\n constructor(\n private readonly baseUrl: string,\n private readonly apiKey: string,\n private readonly timeout: number,\n ) {}\n\n /** Push a notification to a specific user's connected sockets. */\n async user(userId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/user/${encodeURIComponent(userId)}`, payload);\n }\n\n /** Broadcast a notification to all sockets in a room. */\n async room(roomId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/room/${encodeURIComponent(roomId)}`, payload);\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-internal-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (res.status === 401) throw new HiveSocketAuthError();\n if (!res.ok) {\n const text = await res.text().catch(() => res.statusText);\n throw new HiveSocketError(`Hive-Socket request failed: ${text}`, res.status);\n }\n } catch (err) {\n if (err instanceof HiveSocketError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import { NotifyResource } from './resources/notify.js';\nimport { HiveSocketNetworkError } from './errors.js';\nimport type { HiveSocketConfig, HiveHealthResponse } from './types.js';\n\nexport class HiveSocketClient {\n readonly notify: NotifyResource;\n\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n constructor(config: HiveSocketConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 10_000;\n this.notify = new NotifyResource(this.baseUrl, this.apiKey, this.timeout);\n }\n\n /** Check the Hive-Socket server health and current connection count. */\n async health(): Promise<HiveHealthResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: controller.signal,\n });\n if (!res.ok) throw new HiveSocketNetworkError(`Health check failed: ${res.statusText}`);\n return res.json() as Promise<HiveHealthResponse>;\n } catch (err) {\n if (err instanceof HiveSocketNetworkError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Health check timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Create a Hive-Socket server-side client.\n *\n * @example\n * const hive = createHiveSocketClient({\n * baseUrl: process.env.HIVE_SOCKET_URL!,\n * apiKey: process.env.HIVE_SOCKET_API_KEY!,\n * });\n * await hive.notify.user(userId, { projectId, title: 'Hey', body: 'Msg', type: 'message' });\n */\nexport function createHiveSocketClient(config: HiveSocketConfig): HiveSocketClient {\n return new HiveSocketClient(config);\n}\n"],"mappings":";AAAO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EAET,YAAY,SAAiB,YAAoB;AAC/C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAGO,IAAM,sBAAN,cAAkC,gBAAgB;AAAA,EACvD,YAAY,UAAU,mBAAmB;AACvC,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,yBAAN,cAAqC,gBAAgB;AAAA,EAC1D,YAAY,SAAiB;AAC3B,UAAM,SAAS,CAAC;AAChB,SAAK,OAAO;AAAA,EACd;AACF;;;ACrBO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YACmB,SACA,QACA,SACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAInB,MAAM,KAAK,QAAgB,SAA2C;AACpE,UAAM,KAAK,KAAK,yBAAyB,mBAAmB,MAAM,CAAC,IAAI,OAAO;AAAA,EAChF;AAAA;AAAA,EAGA,MAAM,KAAK,QAAgB,SAA2C;AACpE,UAAM,KAAK,KAAK,yBAAyB,mBAAmB,MAAM,CAAC,IAAI,OAAO;AAAA,EAChF;AAAA,EAEA,MAAc,KAAK,MAAc,MAA8B;AAC7D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,sBAAsB,KAAK;AAAA,QAC7B;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,IAAI,WAAW,IAAK,OAAM,IAAI,oBAAoB;AACtD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,UAAU;AACxD,cAAM,IAAI,gBAAgB,+BAA+B,IAAI,IAAI,IAAI,MAAM;AAAA,MAC7E;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,gBAAiB,OAAM;AAC1C,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAM,IAAI;AAAA,QACR,WAAW,OAAO,UAAU,2BAA2B,KAAK,OAAO,OAAO;AAAA,MAC5E;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AACF;;;
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/resources/notify.ts","../src/resources/broadcast.ts","../src/client.ts"],"sourcesContent":["export class HiveSocketError extends Error {\n readonly statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.name = 'HiveSocketError';\n this.statusCode = statusCode;\n }\n}\n\n/** Thrown when the API key is wrong (HTTP 401) */\nexport class HiveSocketAuthError extends HiveSocketError {\n constructor(message = 'Invalid API key') {\n super(message, 401);\n this.name = 'HiveSocketAuthError';\n }\n}\n\n/** Thrown when the fetch fails entirely (network down, timeout) */\nexport class HiveSocketNetworkError extends HiveSocketError {\n constructor(message: string) {\n super(message, 0);\n this.name = 'HiveSocketNetworkError';\n }\n}\n","import { HiveSocketAuthError, HiveSocketError, HiveSocketNetworkError } from '../errors.js';\nimport type { HiveNotifyPayload } from '../types.js';\n\nexport class NotifyResource {\n constructor(\n private readonly baseUrl: string,\n private readonly apiKey: string,\n private readonly timeout: number,\n ) {}\n\n /** Push a notification to a specific user's connected sockets. */\n async user(userId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/user/${encodeURIComponent(userId)}`, payload);\n }\n\n /** Broadcast a notification to all sockets in a room. */\n async room(roomId: string, payload: HiveNotifyPayload): Promise<void> {\n await this.post(`/internal/notify/room/${encodeURIComponent(roomId)}`, payload);\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-internal-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (res.status === 401) throw new HiveSocketAuthError();\n if (!res.ok) {\n const text = await res.text().catch(() => res.statusText);\n throw new HiveSocketError(`Hive-Socket request failed: ${text}`, res.status);\n }\n } catch (err) {\n if (err instanceof HiveSocketError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import { HiveSocketAuthError, HiveSocketError, HiveSocketNetworkError } from '../errors.js';\n\nexport class BroadcastResource {\n constructor(\n private readonly baseUrl: string,\n private readonly apiKey: string,\n private readonly timeout: number,\n ) {}\n\n /** Broadcast a real-time message to all sockets in a room (received via useMessages). */\n async toRoom(\n roomId: string,\n payload: { projectId: string; senderId?: string; type: string; payload: Record<string, unknown> },\n ): Promise<void> {\n await this.post(`/internal/broadcast/room/${encodeURIComponent(roomId)}`, payload);\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-internal-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (res.status === 401) throw new HiveSocketAuthError();\n if (!res.ok) {\n const text = await res.text().catch(() => res.statusText);\n throw new HiveSocketError(`Hive-Socket broadcast failed: ${text}`, res.status);\n }\n } catch (err) {\n if (err instanceof HiveSocketError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Request timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import { NotifyResource } from './resources/notify.js';\nimport { BroadcastResource } from './resources/broadcast.js';\nimport { HiveSocketNetworkError } from './errors.js';\nimport type { HiveSocketConfig, HiveHealthResponse } from './types.js';\n\nexport class HiveSocketClient {\n readonly notify: NotifyResource;\n readonly broadcast: BroadcastResource;\n\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n constructor(config: HiveSocketConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 10_000;\n this.notify = new NotifyResource(this.baseUrl, this.apiKey, this.timeout);\n this.broadcast = new BroadcastResource(this.baseUrl, this.apiKey, this.timeout);\n }\n\n /** Check the Hive-Socket server health and current connection count. */\n async health(): Promise<HiveHealthResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: controller.signal,\n });\n if (!res.ok) throw new HiveSocketNetworkError(`Health check failed: ${res.statusText}`);\n return res.json() as Promise<HiveHealthResponse>;\n } catch (err) {\n if (err instanceof HiveSocketNetworkError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n throw new HiveSocketNetworkError(\n controller.signal.aborted ? `Health check timed out after ${this.timeout}ms` : msg,\n );\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Create a Hive-Socket server-side client.\n *\n * @example\n * const hive = createHiveSocketClient({\n * baseUrl: process.env.HIVE_SOCKET_URL!,\n * apiKey: process.env.HIVE_SOCKET_API_KEY!,\n * });\n * await hive.notify.user(userId, { projectId, title: 'Hey', body: 'Msg', type: 'message' });\n */\nexport function createHiveSocketClient(config: HiveSocketConfig): HiveSocketClient {\n return new HiveSocketClient(config);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smarthivelabs-devs/hive-socket-node",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Node.js SDK for Hive-Socket — push notifications and
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Node.js SDK for Hive-Socket — push notifications, events, and real-time messages to connected clients",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|