@glowlabs-org/events-sdk 0.1.0 → 1.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/README.md +247 -153
- package/dist/admin.d.ts +7 -6
- package/dist/admin.js +6 -6
- package/dist/base-event.d.ts +32 -0
- package/dist/base-event.js +17 -0
- package/dist/emitter.d.ts +18 -0
- package/dist/emitter.js +59 -0
- package/dist/event-registry.d.ts +2 -0
- package/dist/event-registry.js +19 -0
- package/dist/index.d.ts +2 -5
- package/dist/index.js +2 -5
- package/dist/listener.d.ts +14 -0
- package/dist/listener.js +88 -0
- package/dist/schemas/audit-pfees-paid.v1.d.ts +15 -0
- package/dist/schemas/audit-pfees-paid.v1.js +14 -0
- package/dist/schemas/audit-pushed.v1.d.ts +15 -0
- package/dist/schemas/audit-pushed.v1.js +13 -0
- package/dist/schemas/audit-slashed.v1.d.ts +12 -0
- package/dist/schemas/audit-slashed.v1.js +10 -0
- package/dist/types.d.ts +19 -21
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +45 -0
- package/dist/zones.d.ts +7 -0
- package/dist/zones.js +8 -0
- package/package.json +8 -11
- package/dist/consumer.d.ts +0 -14
- package/dist/consumer.js +0 -84
- package/dist/glow-listener.d.ts +0 -31
- package/dist/glow-listener.js +0 -74
- package/dist/producer.d.ts +0 -8
- package/dist/producer.js +0 -46
- package/dist/schemas/auditPushed.d.ts +0 -69
- package/dist/schemas/auditPushed.js +0 -42
- package/dist/typed-emitter.d.ts +0 -7
- package/dist/typed-emitter.js +0 -17
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Glow Events SDK
|
2
2
|
|
3
|
-
A TypeScript-first SDK for consuming and emitting typed events on the Glow platform, powered by RabbitMQ (
|
3
|
+
A TypeScript-first SDK for consuming and emitting typed events on the Glow platform, powered by RabbitMQ (topic exchange). Provides runtime validation and type inference using Zod schemas.
|
4
4
|
|
5
5
|
---
|
6
6
|
|
@@ -9,193 +9,288 @@ A TypeScript-first SDK for consuming and emitting typed events on the Glow platf
|
|
9
9
|
### 1. Install
|
10
10
|
|
11
11
|
```bash
|
12
|
-
|
12
|
+
pnpm install @glowlabs-org/events-sdk
|
13
13
|
```
|
14
14
|
|
15
|
-
|
15
|
+
---
|
16
|
+
|
17
|
+
## 📚 Zones
|
18
|
+
|
19
|
+
The following zones are currently available:
|
20
|
+
|
21
|
+
| Zone ID | Zone Name |
|
22
|
+
| ------- | ------------------ |
|
23
|
+
| 0 | All Zones |
|
24
|
+
| 1 | Clean Grid Project |
|
25
|
+
| 2 | Coming Soon Zone |
|
26
|
+
|
27
|
+
- Use `zoneId: 0` (with `zoneName: "All Zones"`) to emit to or listen to all zones.
|
28
|
+
- The SDK types and runtime validation now officially support `zoneId: 0` and `zoneName: "All Zones"` everywhere (emitter, listener, event types).
|
29
|
+
|
30
|
+
---
|
31
|
+
|
32
|
+
## 📦 Event Types & Versions
|
33
|
+
|
34
|
+
Currently supported event types and versions:
|
35
|
+
|
36
|
+
| Event Name | Version | Payload Type | Description |
|
37
|
+
| ------------------ | ------- | ------------------------- | ----------------------------------- |
|
38
|
+
| `audit.pushed` | 1 | `AuditPushedV1Payload` | Emitted when an audit is pushed |
|
39
|
+
| `audit.slashed` | 1 | `AuditSlashedV1Payload` | Emitted when a farm is slashed |
|
40
|
+
| `audit.pfees.paid` | 1 | `AuditPfeesPaidV1Payload` | Emitted when protocol fees are paid |
|
41
|
+
|
42
|
+
---
|
43
|
+
|
44
|
+
## 📝 Event Payload Schemas
|
45
|
+
|
46
|
+
### `audit.pushed` v1
|
16
47
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
48
|
+
```ts
|
49
|
+
export interface AuditPushedV1Payload {
|
50
|
+
farmId: string; // bytes32 hex string (0x...)
|
51
|
+
protocolFeeUSDPrice_12Decimals: string; // uint256 (decimal) − 12 implied decimals
|
52
|
+
expectedProduction_12Decimals: string; // uint256 (decimal) − 12 implied decimals
|
53
|
+
}
|
54
|
+
```
|
55
|
+
|
56
|
+
**Validation:**
|
57
|
+
|
58
|
+
- `farmId` must be a 32-byte hex string (e.g., `0x...`).
|
59
|
+
- `protocolFeeUSDPrice_12Decimals` and `expectedProduction_12Decimals` must be decimal strings representing unsigned big integers.
|
60
|
+
|
61
|
+
### `audit.slashed` v1
|
62
|
+
|
63
|
+
```ts
|
64
|
+
export interface AuditSlashedV1Payload {
|
65
|
+
farmId: string; // bytes32 hex string (0x...)
|
66
|
+
slasher: string; // Ethereum address (0x...)
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
**Validation:**
|
21
71
|
|
22
|
-
|
72
|
+
- `farmId` must be a 32-byte hex string (e.g., `0x...`).
|
73
|
+
- `slasher` must be a valid Ethereum address (0x...40 hex chars).
|
74
|
+
|
75
|
+
### `audit.pfees.paid` v1
|
23
76
|
|
24
77
|
```ts
|
25
|
-
|
26
|
-
|
27
|
-
//
|
28
|
-
|
29
|
-
|
30
|
-
// tokenPrices: { token: string; priceWAD_usd12Decimals: string }[];
|
31
|
-
// expectedProduction_12Decimals: string;
|
32
|
-
// glowRewardSplits: { receiver: string; percent: number }[];
|
33
|
-
// cashRewardSplits: { receiver: string; percent: number }[];
|
34
|
-
// }
|
35
|
-
|
36
|
-
// AuditSlashedId
|
37
|
-
// type AuditSlashedId = `0x${string}`;
|
78
|
+
export interface AuditPfeesPaidV1Payload {
|
79
|
+
farmId: string; // bytes32 hex string (0x...)
|
80
|
+
payer: string; // Ethereum address (0x...)
|
81
|
+
amount_12Decimals: string; // uint256 (decimal) − 12 implied decimals
|
82
|
+
}
|
38
83
|
```
|
39
84
|
|
85
|
+
**Validation:**
|
86
|
+
|
87
|
+
- `farmId` must be a 32-byte hex string (e.g., `0x...`).
|
88
|
+
- `payer` must be a valid Ethereum address (0x...40 hex chars).
|
89
|
+
- `amount_12Decimals` must be a decimal string representing an unsigned big integer (12 implied decimals).
|
90
|
+
|
40
91
|
---
|
41
92
|
|
42
93
|
## ✨ Usage Example
|
43
94
|
|
44
|
-
### Listen to
|
95
|
+
### Listen to Specific Event Types/Versions
|
45
96
|
|
46
97
|
```ts
|
47
|
-
import {
|
48
|
-
|
49
|
-
async function main() {
|
50
|
-
const sdk = await createGlowListener({
|
51
|
-
username: "listener", // or "admin"
|
52
|
-
password: "your-password-here",
|
53
|
-
queueName: "my.precreated.queue", // REQUIRED: must be pre-created and bound by an admin
|
54
|
-
// Optionally specify a custom exchange:
|
55
|
-
// exchange: "glow.audit.v2.exchange",
|
56
|
-
});
|
98
|
+
import { createGlowEventListener } from "@glowlabs-org/events-sdk";
|
57
99
|
|
58
|
-
|
59
|
-
|
60
|
-
|
100
|
+
const listener = createGlowEventListener({
|
101
|
+
username: "listener",
|
102
|
+
password: "your-password-here",
|
103
|
+
zoneId: 1,
|
104
|
+
queueName: "my.precreated.queue",
|
105
|
+
});
|
61
106
|
|
62
|
-
|
63
|
-
|
64
|
-
|
107
|
+
listener.onEvent("audit.pushed", 1, (event) => {
|
108
|
+
console.log("Received audit.pushed v1:", event.farmId);
|
109
|
+
});
|
65
110
|
|
66
|
-
|
111
|
+
listener.onEvent("audit.slashed", 1, (event) => {
|
112
|
+
console.log("Received audit.slashed v1:", event.farmId, event.slasher);
|
113
|
+
});
|
67
114
|
|
68
|
-
|
69
|
-
|
70
|
-
|
115
|
+
listener.onEvent("audit.pfees.paid", 1, (event) => {
|
116
|
+
console.log(
|
117
|
+
"Received audit.pfees.paid v1:",
|
118
|
+
event.farmId,
|
119
|
+
event.payer,
|
120
|
+
event.amount_12Decimals
|
121
|
+
);
|
122
|
+
});
|
71
123
|
|
72
|
-
|
124
|
+
await listener.start();
|
125
|
+
// To stop listening:
|
126
|
+
// await listener.stop();
|
73
127
|
```
|
74
128
|
|
75
129
|
### Emit Events (Admin Only)
|
76
130
|
|
77
131
|
```ts
|
78
|
-
import {
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
132
|
+
import { createGlowEventEmitter } from "@glowlabs-org/events-sdk";
|
133
|
+
|
134
|
+
const emitter = createGlowEventEmitter({
|
135
|
+
username: "admin",
|
136
|
+
password: "your-password-here",
|
137
|
+
zoneId: 1,
|
138
|
+
});
|
139
|
+
|
140
|
+
await emitter.emit({
|
141
|
+
eventType: "audit.pushed",
|
142
|
+
schemaVersion: 1,
|
143
|
+
payload: {
|
90
144
|
farmId: "0x...",
|
91
145
|
protocolFeeUSDPrice_12Decimals: "...",
|
92
|
-
tokenPrices: [],
|
93
146
|
expectedProduction_12Decimals: "...",
|
94
|
-
|
95
|
-
|
96
|
-
});
|
147
|
+
},
|
148
|
+
});
|
97
149
|
|
98
|
-
|
99
|
-
|
150
|
+
await emitter.emit({
|
151
|
+
eventType: "audit.slashed",
|
152
|
+
schemaVersion: 1,
|
153
|
+
payload: {
|
154
|
+
farmId: "0x...",
|
155
|
+
slasher: "0x...",
|
156
|
+
},
|
157
|
+
});
|
158
|
+
|
159
|
+
await emitter.emit({
|
160
|
+
eventType: "audit.pfees.paid",
|
161
|
+
schemaVersion: 1,
|
162
|
+
payload: {
|
163
|
+
farmId: "0x...",
|
164
|
+
payer: "0x...",
|
165
|
+
amount_12Decimals: "1000000000000",
|
166
|
+
},
|
167
|
+
});
|
100
168
|
|
101
|
-
|
169
|
+
await emitter.disconnect();
|
102
170
|
```
|
103
171
|
|
104
|
-
|
172
|
+
### 🌐 Emitting or Listening to All Zones
|
105
173
|
|
106
|
-
|
174
|
+
You can emit to or listen to **all zones at once** by passing `zoneId: 0` to the emitter or listener.
|
107
175
|
|
108
|
-
|
176
|
+
#### Emit to All Zones
|
109
177
|
|
110
|
-
|
178
|
+
```ts
|
179
|
+
import { createGlowEventEmitter } from "@glowlabs-org/events-sdk";
|
111
180
|
|
112
|
-
|
113
|
-
|
114
|
-
-
|
115
|
-
|
116
|
-
|
117
|
-
- `.stopListener()` — Stop listening to events
|
181
|
+
const emitter = createGlowEventEmitter({
|
182
|
+
username: "admin",
|
183
|
+
password: "your-password-here",
|
184
|
+
zoneId: 0, // special value for all zones
|
185
|
+
});
|
118
186
|
|
119
|
-
|
187
|
+
await emitter.emit({
|
188
|
+
eventType: "audit.pushed",
|
189
|
+
schemaVersion: 1,
|
190
|
+
payload: {
|
191
|
+
farmId: "0x...",
|
192
|
+
protocolFeeUSDPrice_12Decimals: "...",
|
193
|
+
expectedProduction_12Decimals: "...",
|
194
|
+
},
|
195
|
+
});
|
120
196
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
197
|
+
await emitter.emit({
|
198
|
+
eventType: "audit.slashed",
|
199
|
+
schemaVersion: 1,
|
200
|
+
payload: {
|
201
|
+
farmId: "0x...",
|
202
|
+
slasher: "0x...",
|
203
|
+
},
|
204
|
+
});
|
126
205
|
|
127
|
-
|
206
|
+
await emitter.emit({
|
207
|
+
eventType: "audit.pfees.paid",
|
208
|
+
schemaVersion: 1,
|
209
|
+
payload: {
|
210
|
+
farmId: "0x...",
|
211
|
+
payer: "0x...",
|
212
|
+
amount_12Decimals: "1000000000000",
|
213
|
+
},
|
214
|
+
});
|
128
215
|
|
129
|
-
|
216
|
+
await emitter.disconnect();
|
217
|
+
```
|
130
218
|
|
131
|
-
|
132
|
-
- **Admin credentials:** Can subscribe, emit events, and create/bind new queues and exchanges.
|
219
|
+
#### Listen to All Zones
|
133
220
|
|
134
|
-
|
221
|
+
```ts
|
222
|
+
import { createGlowEventListener } from "@glowlabs-org/events-sdk";
|
135
223
|
|
136
|
-
|
224
|
+
const listener = createGlowEventListener({
|
225
|
+
username: "listener",
|
226
|
+
password: "your-password-here",
|
227
|
+
zoneId: 0, // special value for all zones
|
228
|
+
queueName: "my.precreated.queue",
|
229
|
+
});
|
137
230
|
|
138
|
-
|
231
|
+
listener.onEvent("audit.pushed", 1, (event) => {
|
232
|
+
console.log("Received audit.pushed v1 from any zone:", event.farmId);
|
233
|
+
});
|
139
234
|
|
140
|
-
|
235
|
+
listener.onEvent("audit.slashed", 1, (event) => {
|
236
|
+
console.log(
|
237
|
+
"Received audit.slashed v1 from any zone:",
|
238
|
+
event.farmId,
|
239
|
+
event.slasher
|
240
|
+
);
|
241
|
+
});
|
141
242
|
|
142
|
-
|
243
|
+
listener.onEvent("audit.pfees.paid", 1, (event) => {
|
244
|
+
console.log(
|
245
|
+
"Received audit.pfees.paid v1 from any zone:",
|
246
|
+
event.farmId,
|
247
|
+
event.payer,
|
248
|
+
event.amount_12Decimals
|
249
|
+
);
|
250
|
+
});
|
143
251
|
|
144
|
-
|
252
|
+
await listener.start();
|
253
|
+
// To stop listening:
|
254
|
+
// await listener.stop();
|
255
|
+
```
|
145
256
|
|
146
|
-
|
257
|
+
---
|
147
258
|
|
148
|
-
|
259
|
+
## 🧪 Validation & Error Handling
|
149
260
|
|
150
|
-
|
261
|
+
- All events are validated at runtime using Zod schemas.
|
262
|
+
- If you emit or process an event with a `zoneName` that does not match the `zoneId`, an error is thrown. `zoneId: 0` and `zoneName: "All Zones"` are a valid pairing.
|
263
|
+
- If you emit or process an event with a `schemaVersion` for which no schema exists (e.g., `audit.pushed` v2), an error is thrown.
|
264
|
+
- If the payload does not match the schema, an error is thrown.
|
151
265
|
|
152
266
|
---
|
153
267
|
|
154
|
-
##
|
268
|
+
## 🔐 Permissions & Credentials
|
155
269
|
|
156
|
-
|
270
|
+
- **Listener credentials:** Can only subscribe to events. Cannot emit events or create new queues.
|
271
|
+
- **Admin credentials:** Can subscribe, emit events, and create/bind new queues and exchanges.
|
157
272
|
|
158
|
-
|
159
|
-
import { z } from "zod";
|
160
|
-
|
161
|
-
export const AuditPushedDataZ = z
|
162
|
-
.object({
|
163
|
-
farmId: z.string().regex(/^0x[0-9a-fA-F]{64}$/, "bytes32 hex string"),
|
164
|
-
protocolFeeUSDPrice_12Decimals: z
|
165
|
-
.string()
|
166
|
-
.regex(/^[0-9]+$/, "uint256 (decimal) − 12 implied decimals"),
|
167
|
-
tokenPrices: z.array(
|
168
|
-
z.object({
|
169
|
-
token: z.string().regex(/^0x[0-9a-fA-F]{40}$/, "ERC‑20 address"),
|
170
|
-
priceWAD_usd12Decimals: z.string().regex(/^[0-9]+$/),
|
171
|
-
})
|
172
|
-
),
|
173
|
-
expectedProduction_12Decimals: z.string().regex(/^[0-9]+$/),
|
174
|
-
glowRewardSplits: z.array(
|
175
|
-
z.object({
|
176
|
-
receiver: z.string().regex(/^0x[0-9a-fA-F]{40}$/),
|
177
|
-
percent: z.number().min(0).max(100),
|
178
|
-
})
|
179
|
-
),
|
180
|
-
cashRewardSplits: z.array(
|
181
|
-
z.object({
|
182
|
-
receiver: z.string().regex(/^0x[0-9a-fA-F]{40}$/),
|
183
|
-
percent: z.number().min(0).max(100),
|
184
|
-
})
|
185
|
-
),
|
186
|
-
})
|
187
|
-
.strict();
|
188
|
-
|
189
|
-
export type AuditPushedData = z.infer<typeof AuditPushedDataZ>;
|
190
|
-
```
|
273
|
+
If you try to emit with listener credentials, the SDK will throw an error.
|
191
274
|
|
192
275
|
---
|
193
276
|
|
194
|
-
##
|
277
|
+
## 🛠️ Admin & Queue Management
|
195
278
|
|
196
279
|
The SDK exposes helpers for programmatically creating, binding, and deleting exchanges and queues (admin credentials required). Use these for pre-creating queues for listeners, bootstrapping environments, or advanced queue management.
|
197
280
|
|
198
|
-
###
|
281
|
+
### `createExchange(options)`
|
282
|
+
|
283
|
+
Creates a topic exchange (default: `exchangeType = "topic"`).
|
284
|
+
|
285
|
+
### `bindQueueToExchange(options)`
|
286
|
+
|
287
|
+
Binds a queue to a topic exchange. You can specify a `routingKey` for fine-grained event filtering:
|
288
|
+
|
289
|
+
- `routingKey = "#"` (default): all events
|
290
|
+
- `routingKey = "audit.pushed.v1"`: only audit.pushed v1 events
|
291
|
+
- `routingKey = "audit.pushed.*"`: all versions of audit.pushed
|
292
|
+
|
293
|
+
#### Example
|
199
294
|
|
200
295
|
```ts
|
201
296
|
import {
|
@@ -203,31 +298,20 @@ import {
|
|
203
298
|
bindQueueToExchange,
|
204
299
|
deleteExchange,
|
205
300
|
deleteQueue,
|
206
|
-
} from "@
|
301
|
+
} from "@glowlabs-org/events-sdk";
|
207
302
|
|
208
303
|
await createExchange({
|
209
304
|
username: "admin",
|
210
305
|
password: "your-password-here",
|
211
|
-
exchange: "glow.
|
306
|
+
exchange: "glow.zone-1.events",
|
212
307
|
});
|
213
308
|
|
214
309
|
await bindQueueToExchange({
|
215
310
|
username: "admin",
|
216
311
|
password: "your-password-here",
|
217
|
-
exchange: "glow.
|
218
|
-
queue: "glow-listener-queue",
|
219
|
-
});
|
220
|
-
|
221
|
-
await deleteExchange({
|
222
|
-
username: "admin",
|
223
|
-
password: "your-password-here",
|
224
|
-
exchange: "glow.audit.v1.exchange",
|
225
|
-
});
|
226
|
-
|
227
|
-
await deleteQueue({
|
228
|
-
username: "admin",
|
229
|
-
password: "your-password-here",
|
312
|
+
exchange: "glow.zone-1.events",
|
230
313
|
queue: "glow-listener-queue",
|
314
|
+
routingKey: "audit.pushed.v1", // only audit.pushed v1 events
|
231
315
|
});
|
232
316
|
```
|
233
317
|
|
@@ -240,27 +324,27 @@ If your listener credentials only have `read` permission (no `configure`), you m
|
|
240
324
|
### 1. Admin: Pre-create and bind the queue
|
241
325
|
|
242
326
|
```ts
|
243
|
-
import {
|
327
|
+
import { bindQueueToExchange } from "@glowlabs-org/events-sdk";
|
244
328
|
|
245
|
-
await
|
329
|
+
await bindQueueToExchange({
|
246
330
|
username: "admin",
|
247
331
|
password: "your-admin-password",
|
248
|
-
exchange: "glow.
|
332
|
+
exchange: "glow.zone-1.events",
|
249
333
|
queue: "my.precreated.queue",
|
334
|
+
routingKey: "audit.pushed.v1", // only audit.pushed v1 events
|
250
335
|
});
|
251
336
|
```
|
252
337
|
|
253
338
|
### 2. Listener: Consume from the pre-created queue
|
254
339
|
|
255
340
|
```ts
|
256
|
-
import {
|
341
|
+
import { createGlowEventListener } from "@glowlabs-org/events-sdk";
|
257
342
|
|
258
|
-
const
|
343
|
+
const listener = createGlowEventListener({
|
259
344
|
username: "listener",
|
260
345
|
password: "your-listener-password",
|
346
|
+
zoneId: 1,
|
261
347
|
queueName: "my.precreated.queue",
|
262
|
-
// Optionally specify a custom exchange:
|
263
|
-
// exchange: "glow.audit.v1.exchange",
|
264
348
|
});
|
265
349
|
```
|
266
350
|
|
@@ -269,9 +353,19 @@ const sdk = await createGlowListener({
|
|
269
353
|
|
270
354
|
---
|
271
355
|
|
272
|
-
## 🧩 Advanced: Multiple Listeners/
|
356
|
+
## 🧩 Advanced: Multiple Listeners/Emitters
|
357
|
+
|
358
|
+
You can create multiple listeners or emitters in the same process, each with its own configuration (e.g., for different credentials, exchanges, or RabbitMQ URLs). This is useful for multi-tenant, multi-topic, or advanced scenarios. **Every listener receives every event for the bound routing key(s).**
|
359
|
+
|
360
|
+
---
|
361
|
+
|
362
|
+
## 🧪 Extending Event Types
|
363
|
+
|
364
|
+
To add new event types or versions:
|
273
365
|
|
274
|
-
|
366
|
+
1. Create a new schema in `src/schemas/`.
|
367
|
+
2. Add the event type and version to `eventTypeRegistry` in `src/event-registry.ts`.
|
368
|
+
3. Update the base event type in `src/base-event.ts` if needed.
|
275
369
|
|
276
370
|
---
|
277
371
|
|
@@ -286,7 +380,7 @@ make clean
|
|
286
380
|
```
|
287
381
|
|
288
382
|
- The first time, run `npm login` to authenticate with npm.
|
289
|
-
- For scoped packages (like `@
|
383
|
+
- For scoped packages (like `@glowlabs-org/events-sdk`), the Makefile uses `--access public` for publishing.
|
290
384
|
|
291
385
|
---
|
292
386
|
|
package/dist/admin.d.ts
CHANGED
@@ -7,32 +7,33 @@ export interface CreateAndBindQueueOptions {
|
|
7
7
|
exchangeType?: string;
|
8
8
|
queueOptions?: amqp.Options.AssertQueue;
|
9
9
|
exchangeOptions?: amqp.Options.AssertExchange;
|
10
|
+
routingKey?: string;
|
10
11
|
}
|
11
12
|
/**
|
12
|
-
* Create a RabbitMQ exchange (admin credentials required).
|
13
|
+
* Create a RabbitMQ topic exchange (admin credentials required).
|
13
14
|
*
|
14
15
|
* @param options - Connection and exchange options
|
15
16
|
* @returns Promise<void>
|
16
17
|
*/
|
17
|
-
export declare function createExchange({ username, password, exchange, exchangeType, exchangeOptions, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions">): Promise<void>;
|
18
|
+
export declare function createExchange({ username, password, exchange, exchangeType, exchangeOptions, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "routingKey">): Promise<void>;
|
18
19
|
/**
|
19
|
-
* Create a RabbitMQ queue and bind it to
|
20
|
+
* Create a RabbitMQ queue and bind it to a topic exchange (admin credentials required).
|
20
21
|
*
|
21
22
|
* @param options - Connection, queue, and exchange options
|
22
23
|
* @returns Promise<void>
|
23
24
|
*/
|
24
|
-
export declare function bindQueueToExchange({ username, password, exchange, queue, exchangeType, queueOptions, exchangeOptions, }: CreateAndBindQueueOptions): Promise<void>;
|
25
|
+
export declare function bindQueueToExchange({ username, password, exchange, queue, exchangeType, queueOptions, exchangeOptions, routingKey, }: CreateAndBindQueueOptions): Promise<void>;
|
25
26
|
/**
|
26
27
|
* Delete a RabbitMQ exchange (admin credentials required).
|
27
28
|
*
|
28
29
|
* @param options - Connection and exchange options
|
29
30
|
* @returns Promise<void>
|
30
31
|
*/
|
31
|
-
export declare function deleteExchange({ username, password, exchange, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "exchangeType" | "exchangeOptions">): Promise<void>;
|
32
|
+
export declare function deleteExchange({ username, password, exchange, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "exchangeType" | "exchangeOptions" | "routingKey">): Promise<void>;
|
32
33
|
/**
|
33
34
|
* Delete a RabbitMQ queue (admin credentials required).
|
34
35
|
*
|
35
36
|
* @param options - Connection and queue options
|
36
37
|
* @returns Promise<void>
|
37
38
|
*/
|
38
|
-
export declare function deleteQueue({ username, password, queue, }: Omit<CreateAndBindQueueOptions, "exchange" | "exchangeType" | "exchangeOptions" | "queueOptions">): Promise<void>;
|
39
|
+
export declare function deleteQueue({ username, password, queue, }: Omit<CreateAndBindQueueOptions, "exchange" | "exchangeType" | "exchangeOptions" | "queueOptions" | "routingKey">): Promise<void>;
|
package/dist/admin.js
CHANGED
@@ -12,16 +12,16 @@ function validateName(name, type) {
|
|
12
12
|
// Require at least two segments separated by dots, only alphanumerics, dashes, underscores, and dots
|
13
13
|
const pattern = /^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
|
14
14
|
if (!pattern.test(name)) {
|
15
|
-
throw new Error(`${type} name '${name}' is invalid. Must be dot-separated (e.g., 'glow.
|
15
|
+
throw new Error(`${type} name '${name}' is invalid. Must be dot-separated (e.g., 'glow.zone-1.events').`);
|
16
16
|
}
|
17
17
|
}
|
18
18
|
/**
|
19
|
-
* Create a RabbitMQ exchange (admin credentials required).
|
19
|
+
* Create a RabbitMQ topic exchange (admin credentials required).
|
20
20
|
*
|
21
21
|
* @param options - Connection and exchange options
|
22
22
|
* @returns Promise<void>
|
23
23
|
*/
|
24
|
-
async function createExchange({ username, password, exchange, exchangeType = "
|
24
|
+
async function createExchange({ username, password, exchange, exchangeType = "topic", exchangeOptions = { durable: true }, }) {
|
25
25
|
validateName(exchange, "exchange");
|
26
26
|
const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
|
27
27
|
const conn = await amqplib_1.default.connect(url.toString());
|
@@ -31,12 +31,12 @@ async function createExchange({ username, password, exchange, exchangeType = "fa
|
|
31
31
|
await conn.close();
|
32
32
|
}
|
33
33
|
/**
|
34
|
-
* Create a RabbitMQ queue and bind it to
|
34
|
+
* Create a RabbitMQ queue and bind it to a topic exchange (admin credentials required).
|
35
35
|
*
|
36
36
|
* @param options - Connection, queue, and exchange options
|
37
37
|
* @returns Promise<void>
|
38
38
|
*/
|
39
|
-
async function bindQueueToExchange({ username, password, exchange, queue, exchangeType = "
|
39
|
+
async function bindQueueToExchange({ username, password, exchange, queue, exchangeType = "topic", queueOptions = { durable: false }, exchangeOptions = { durable: true }, routingKey = "#", }) {
|
40
40
|
validateName(exchange, "exchange");
|
41
41
|
validateName(queue, "queue");
|
42
42
|
const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
|
@@ -44,7 +44,7 @@ async function bindQueueToExchange({ username, password, exchange, queue, exchan
|
|
44
44
|
const channel = await conn.createChannel();
|
45
45
|
await channel.assertExchange(exchange, exchangeType, exchangeOptions);
|
46
46
|
await channel.assertQueue(queue, queueOptions);
|
47
|
-
await channel.bindQueue(queue, exchange,
|
47
|
+
await channel.bindQueue(queue, exchange, routingKey);
|
48
48
|
await channel.close();
|
49
49
|
await conn.close();
|
50
50
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { z } from "zod";
|
2
|
+
import { ZoneName } from "./zones";
|
3
|
+
export declare const baseEventZ: z.ZodObject<{
|
4
|
+
id: z.ZodString;
|
5
|
+
zoneId: z.ZodEffects<z.ZodNumber, number, number>;
|
6
|
+
zoneName: z.ZodEnum<[string, ...string[]]>;
|
7
|
+
schemaVersion: z.ZodLiteral<1>;
|
8
|
+
eventType: z.ZodEnum<["audit.pushed", "audit.slashed", "audit.pfees.paid"]>;
|
9
|
+
timeStamp: z.ZodNumber;
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
11
|
+
id: string;
|
12
|
+
zoneId: number;
|
13
|
+
zoneName: string;
|
14
|
+
schemaVersion: 1;
|
15
|
+
eventType: "audit.pushed" | "audit.slashed" | "audit.pfees.paid";
|
16
|
+
timeStamp: number;
|
17
|
+
}, {
|
18
|
+
id: string;
|
19
|
+
zoneId: number;
|
20
|
+
zoneName: string;
|
21
|
+
schemaVersion: 1;
|
22
|
+
eventType: "audit.pushed" | "audit.slashed" | "audit.pfees.paid";
|
23
|
+
timeStamp: number;
|
24
|
+
}>;
|
25
|
+
export interface BaseEvent {
|
26
|
+
id: string;
|
27
|
+
zoneId: number;
|
28
|
+
zoneName: ZoneName;
|
29
|
+
schemaVersion: 1;
|
30
|
+
eventType: "audit.pushed" | "audit.slashed" | "audit.pfees.paid";
|
31
|
+
timeStamp: number;
|
32
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.baseEventZ = void 0;
|
4
|
+
const zod_1 = require("zod");
|
5
|
+
const zones_1 = require("./zones");
|
6
|
+
const zoneIdNumbers = Object.keys(zones_1.zoneMap).map(Number);
|
7
|
+
const zoneNames = Object.values(zones_1.zoneMap);
|
8
|
+
exports.baseEventZ = zod_1.z.object({
|
9
|
+
id: zod_1.z.string().uuid(),
|
10
|
+
zoneId: zod_1.z.number().refine((id) => zoneIdNumbers.includes(id), {
|
11
|
+
message: "Invalid zoneId",
|
12
|
+
}),
|
13
|
+
zoneName: zod_1.z.enum(zoneNames),
|
14
|
+
schemaVersion: zod_1.z.literal(1),
|
15
|
+
eventType: zod_1.z.enum(["audit.pushed", "audit.slashed", "audit.pfees.paid"]),
|
16
|
+
timeStamp: zod_1.z.number().int(),
|
17
|
+
});
|