@glowlabs-org/events-sdk 1.0.3 → 1.0.5

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 CHANGED
@@ -26,6 +26,27 @@ The following zones are currently available:
26
26
 
27
27
  - Use `zoneId: 0` (with `zoneName: "All Zones"`) to listen to all zones. **Emitters must be constructed with a specific zoneId (not 0).**
28
28
  - The SDK types and runtime validation now officially support `zoneId: 0` and `zoneName: "All Zones"` everywhere for listeners, but not for emitters.
29
+ - **Use the `getZoneId` utility to get the correct zoneId for a given zone name:**
30
+
31
+ ```ts
32
+ import { getZoneId } from "@glowlabs-org/events-sdk";
33
+ const zoneId = getZoneId("CleanGridProject");
34
+ ```
35
+
36
+ ---
37
+
38
+ ## 🛠️ Options for Listeners & Emitters
39
+
40
+ Both `createGlowEventListener` and `createGlowEventEmitter` accept the following options:
41
+
42
+ | Option | Type | Required | Description |
43
+ | ---------------- | ------ | -------- | ------------------------------------------------------------------ |
44
+ | `username` | string | Yes | RabbitMQ username |
45
+ | `password` | string | Yes | RabbitMQ password |
46
+ | `zoneId` | number | Yes | Zone ID (use `getZoneId("ZoneName")`) |
47
+ | `queueName` | string | No | (Listener only) Pre-created queue name |
48
+ | `exchangePrefix` | string | No | Exchange prefix (default: `glow.zone-`) |
49
+ | `host` | string | No | **RabbitMQ host/port** (default: `turntable.proxy.rlwy.net:50784`) |
29
50
 
30
51
  ---
31
52
 
@@ -35,11 +56,29 @@ Currently supported event types and versions:
35
56
 
36
57
  | Event Name | Version | Payload Type | Description |
37
58
  | --------------------- | ------- | ----------------------------- | -------------------------------------- |
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` | Paid (by applicationId) |
41
- | `audit.pfees.paid` | 2 | `AuditPfeesPaidV2Payload` | Paid (by farmId) |
42
- | `application.created` | 1 | `ApplicationCreatedV1Payload` | Emitted when an application is created |
59
+ | `audit.pushed` | "v1" | `AuditPushedV1Payload` | Emitted when an audit is pushed |
60
+ | `audit.slashed` | "v1" | `AuditSlashedV1Payload` | Emitted when a farm is slashed |
61
+ | `audit.pfees.paid` | "v1" | `AuditPfeesPaidV1Payload` | Paid (by applicationId) |
62
+ | `audit.pfees.paid` | "v2" | `AuditPfeesPaidV2Payload` | Paid (by farmId) |
63
+ | `application.created` | "v1" | `ApplicationCreatedV1Payload` | Emitted when an application is created |
64
+
65
+ ---
66
+
67
+ ### Event Types Enum
68
+
69
+ The SDK provides a TypeScript constant for all supported event types to ensure type safety and avoid typos:
70
+
71
+ ```ts
72
+ import { eventTypes, EventType } from "./src/event-types";
73
+
74
+ // Usage example:
75
+ const myEventType: EventType = eventTypes.auditPushed;
76
+ ```
77
+
78
+ - `eventTypes` is a readonly object containing all event type strings.
79
+ - `EventType` is a TypeScript type representing any valid event type string.
80
+
81
+ Use these in your code to avoid hardcoding event names and to benefit from autocompletion and type checking.
43
82
 
44
83
  ---
45
84
 
@@ -141,50 +180,65 @@ export interface ApplicationCreatedV1Payload {
141
180
  ### Listen to Specific Event Types/Versions
142
181
 
143
182
  ```ts
144
- import { createGlowEventListener } from "@glowlabs-org/events-sdk";
183
+ import { createGlowEventListener, getZoneId } from "@glowlabs-org/events-sdk";
145
184
 
146
185
  const listener = createGlowEventListener({
147
186
  username: "listener",
148
187
  password: "your-password-here",
149
- zoneId: 1,
188
+ zoneId: getZoneId("CleanGridProject"),
150
189
  queueName: "my.precreated.queue",
190
+ host: "my.rabbitmq.host:5672", // Optional: override the default host
151
191
  });
152
192
 
153
- listener.onEvent("audit.pushed", 1, (event) => {
154
- console.log("Received audit.pushed v1:", event.farmId);
193
+ listener.onEvent("audit.pushed", "v1", (event) => {
194
+ // event: GlowEvent<AuditPushedV1Payload>
195
+ console.log(
196
+ "Received audit.pushed v1:",
197
+ event.payload.farmId,
198
+ event.zoneId,
199
+ event.zoneName
200
+ );
155
201
  });
156
202
 
157
- listener.onEvent("audit.slashed", 1, (event) => {
158
- console.log("Received audit.slashed v1:", event.farmId, event.slasher);
203
+ listener.onEvent("audit.slashed", "v1", (event) => {
204
+ // event: GlowEvent<AuditSlashedV1Payload>
205
+ console.log(
206
+ "Received audit.slashed v1:",
207
+ event.payload.farmId,
208
+ event.payload.slasher
209
+ );
159
210
  });
160
211
 
161
- listener.onEvent("audit.pfees.paid", 1, (event) => {
212
+ listener.onEvent("audit.pfees.paid", "v1", (event) => {
213
+ // event: GlowEvent<AuditPfeesPaidV1Payload>
162
214
  console.log(
163
215
  "Received audit.pfees.paid v1:",
164
- event.applicationId,
165
- event.payer,
166
- event.amount_12Decimals
216
+ event.payload.applicationId,
217
+ event.payload.payer,
218
+ event.payload.amount_12Decimals
167
219
  );
168
220
  });
169
221
 
170
- listener.onEvent("audit.pfees.paid", 2, (event) => {
222
+ listener.onEvent("audit.pfees.paid", "v2", (event) => {
223
+ // event: GlowEvent<AuditPfeesPaidV2Payload>
171
224
  console.log(
172
225
  "Received audit.pfees.paid v2:",
173
- event.farmId,
174
- event.payer,
175
- event.amount_12Decimals
226
+ event.payload.farmId,
227
+ event.payload.payer,
228
+ event.payload.amount_12Decimals
176
229
  );
177
230
  });
178
231
 
179
- listener.onEvent("application.created", 1, (event) => {
232
+ listener.onEvent("application.created", "v1", (event) => {
233
+ // event: GlowEvent<ApplicationCreatedV1Payload>
180
234
  console.log(
181
235
  "Received application.created v1:",
182
- event.gcaAddress,
183
- event.lat,
184
- event.lng,
185
- event.estimatedCostOfPowerPerKWh,
186
- event.estimatedKWhGeneratedPerYear,
187
- event.installerCompanyName
236
+ event.payload.gcaAddress,
237
+ event.payload.lat,
238
+ event.payload.lng,
239
+ event.payload.estimatedCostOfPowerPerKWh,
240
+ event.payload.estimatedKWhGeneratedPerYear,
241
+ event.payload.installerCompanyName
188
242
  );
189
243
  });
190
244
 
@@ -196,57 +250,62 @@ await listener.start();
196
250
  ### Emit Events (Admin Only)
197
251
 
198
252
  ```ts
199
- import { createGlowEventEmitter } from "@glowlabs-org/events-sdk";
253
+ import { createGlowEventEmitter, getZoneId } from "@glowlabs-org/events-sdk";
200
254
 
201
255
  // You must construct the emitter with a specific zoneId (not 0)
202
256
  const emitter = createGlowEventEmitter({
203
257
  username: "admin",
204
258
  password: "your-password-here",
205
- zoneId: 1, // must be a specific zone
259
+ zoneId: getZoneId("CleanGridProject"), // must be a specific zone
260
+ host: "my.rabbitmq.host:5672", // Optional: override the default host
206
261
  });
207
262
 
208
263
  await emitter.emit({
209
264
  eventType: "audit.pushed",
210
- schemaVersion: 1,
265
+ schemaVersion: "v1",
211
266
  payload: {
212
267
  farmId: "0x...",
213
268
  protocolFeeUSDPrice_12Decimals: "...",
214
269
  expectedProduction_12Decimals: "...",
270
+ txHash: "0x...",
215
271
  },
216
272
  });
217
273
 
218
274
  await emitter.emit({
219
275
  eventType: "audit.slashed",
220
- schemaVersion: 1,
276
+ schemaVersion: "v1",
221
277
  payload: {
222
278
  farmId: "0x...",
223
279
  slasher: "0x...",
280
+ txHash: "0x...",
224
281
  },
225
282
  });
226
283
 
227
284
  await emitter.emit({
228
285
  eventType: "audit.pfees.paid",
229
- schemaVersion: 1,
286
+ schemaVersion: "v1",
230
287
  payload: {
231
288
  applicationId: "0x...",
232
289
  payer: "0x...",
233
290
  amount_12Decimals: "1000000000000",
291
+ txHash: "0x...",
234
292
  },
235
293
  });
236
294
 
237
295
  await emitter.emit({
238
296
  eventType: "audit.pfees.paid",
239
- schemaVersion: 2,
297
+ schemaVersion: "v2",
240
298
  payload: {
241
299
  farmId: "0x...",
242
300
  payer: "0x...",
243
301
  amount_12Decimals: "1000000000000",
302
+ txHash: "0x...",
244
303
  },
245
304
  });
246
305
 
247
306
  await emitter.emit({
248
307
  eventType: "application.created",
249
- schemaVersion: 1,
308
+ schemaVersion: "v1",
250
309
  payload: {
251
310
  gcaAddress: "0x...",
252
311
  lat: 45.5017,
@@ -264,10 +323,12 @@ await emitter.disconnect();
264
323
  >
265
324
  > - The emitter will automatically publish each event to both the global (zone 0) and the specific zone exchange.
266
325
  > - You cannot construct an emitter for zoneId: 0, and you cannot specify zoneId per emit call.
326
+ > - `schemaVersion` is always a string (e.g., "v1", "v2").
327
+ > - **You can override the RabbitMQ host using the `host` option. Default is `turntable.proxy.rlwy.net:50784`.**
267
328
 
268
329
  ### 🌐 Listening to All Zones
269
330
 
270
- You can listen to **all zones at once** by passing `zoneId: 0` to the listener. **Emitters must always use a specific zone.**
331
+ You can listen to **all zones at once** by passing `zoneId: 0` and `zoneName: "All Zones"` to the listener. **Emitters must always use a specific zone.**
271
332
 
272
333
  #### Listen to All Zones
273
334
 
@@ -281,47 +342,16 @@ const listener = createGlowEventListener({
281
342
  queueName: "my.precreated.queue",
282
343
  });
283
344
 
284
- listener.onEvent("audit.pushed", 1, (event) => {
285
- console.log("Received audit.pushed v1 from any zone:", event.farmId);
286
- });
287
-
288
- listener.onEvent("audit.slashed", 1, (event) => {
345
+ listener.onEvent("audit.pushed", "v1", (event) => {
289
346
  console.log(
290
- "Received audit.slashed v1 from any zone:",
291
- event.farmId,
292
- event.slasher
347
+ "Received audit.pushed v1 from any zone:",
348
+ event.payload.farmId,
349
+ event.zoneId,
350
+ event.zoneName
293
351
  );
294
352
  });
295
353
 
296
- listener.onEvent("audit.pfees.paid", 1, (event) => {
297
- console.log(
298
- "Received audit.pfees.paid v1 from any zone:",
299
- event.applicationId,
300
- event.payer,
301
- event.amount_12Decimals
302
- );
303
- });
304
-
305
- listener.onEvent("audit.pfees.paid", 2, (event) => {
306
- console.log(
307
- "Received audit.pfees.paid v2 from any zone:",
308
- event.farmId,
309
- event.payer,
310
- event.amount_12Decimals
311
- );
312
- });
313
-
314
- listener.onEvent("application.created", 1, (event) => {
315
- console.log(
316
- "Received application.created v1 from any zone:",
317
- event.gcaAddress,
318
- event.lat,
319
- event.lng,
320
- event.estimatedCostOfPowerPerKWh,
321
- event.estimatedKWhGeneratedPerYear,
322
- event.installerCompanyName
323
- );
324
- });
354
+ // ... other event handlers ...
325
355
 
326
356
  await listener.start();
327
357
  // To stop listening:
package/dist/admin.d.ts CHANGED
@@ -8,6 +8,7 @@ export interface CreateAndBindQueueOptions {
8
8
  queueOptions?: amqp.Options.AssertQueue;
9
9
  exchangeOptions?: amqp.Options.AssertExchange;
10
10
  routingKey?: string;
11
+ host?: string;
11
12
  }
12
13
  /**
13
14
  * Create a RabbitMQ topic exchange (admin credentials required).
@@ -15,25 +16,31 @@ export interface CreateAndBindQueueOptions {
15
16
  * @param options - Connection and exchange options
16
17
  * @returns Promise<void>
17
18
  */
18
- export declare function createExchange({ username, password, exchange, exchangeType, exchangeOptions, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "routingKey">): Promise<void>;
19
+ export declare function createExchange({ username, password, exchange, exchangeType, exchangeOptions, host, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "routingKey"> & {
20
+ host?: string;
21
+ }): Promise<void>;
19
22
  /**
20
23
  * Create a RabbitMQ queue and bind it to a topic exchange (admin credentials required).
21
24
  *
22
25
  * @param options - Connection, queue, and exchange options
23
26
  * @returns Promise<void>
24
27
  */
25
- export declare function bindQueueToExchange({ username, password, exchange, queue, exchangeType, queueOptions, exchangeOptions, routingKey, }: CreateAndBindQueueOptions): Promise<void>;
28
+ export declare function bindQueueToExchange({ username, password, exchange, queue, exchangeType, queueOptions, exchangeOptions, routingKey, host, }: CreateAndBindQueueOptions): Promise<void>;
26
29
  /**
27
30
  * Delete a RabbitMQ exchange (admin credentials required).
28
31
  *
29
32
  * @param options - Connection and exchange options
30
33
  * @returns Promise<void>
31
34
  */
32
- export declare function deleteExchange({ username, password, exchange, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "exchangeType" | "exchangeOptions" | "routingKey">): Promise<void>;
35
+ export declare function deleteExchange({ username, password, exchange, host, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "exchangeType" | "exchangeOptions" | "routingKey"> & {
36
+ host?: string;
37
+ }): Promise<void>;
33
38
  /**
34
39
  * Delete a RabbitMQ queue (admin credentials required).
35
40
  *
36
41
  * @param options - Connection and queue options
37
42
  * @returns Promise<void>
38
43
  */
39
- export declare function deleteQueue({ username, password, queue, }: Omit<CreateAndBindQueueOptions, "exchange" | "exchangeType" | "exchangeOptions" | "queueOptions" | "routingKey">): Promise<void>;
44
+ export declare function deleteQueue({ username, password, queue, host, }: Omit<CreateAndBindQueueOptions, "exchange" | "exchangeType" | "exchangeOptions" | "queueOptions" | "routingKey"> & {
45
+ host?: string;
46
+ }): Promise<void>;
package/dist/admin.js CHANGED
@@ -8,23 +8,17 @@ exports.bindQueueToExchange = bindQueueToExchange;
8
8
  exports.deleteExchange = deleteExchange;
9
9
  exports.deleteQueue = deleteQueue;
10
10
  const amqplib_1 = __importDefault(require("amqplib"));
11
- function validateName(name, type) {
12
- // Require at least two segments separated by dots, only alphanumerics, dashes, underscores, and dots
13
- const pattern = /^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
14
- if (!pattern.test(name)) {
15
- throw new Error(`${type} name '${name}' is invalid. Must be dot-separated (e.g., 'glow.zone-1.events').`);
16
- }
17
- }
11
+ const utils_1 = require("./utils");
18
12
  /**
19
13
  * Create a RabbitMQ topic exchange (admin credentials required).
20
14
  *
21
15
  * @param options - Connection and exchange options
22
16
  * @returns Promise<void>
23
17
  */
24
- async function createExchange({ username, password, exchange, exchangeType = "topic", exchangeOptions = { durable: true }, }) {
25
- validateName(exchange, "exchange");
26
- const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
27
- const conn = await amqplib_1.default.connect(url.toString());
18
+ async function createExchange({ username, password, exchange, exchangeType = "topic", exchangeOptions = { durable: true }, host = "turntable.proxy.rlwy.net:50784", }) {
19
+ (0, utils_1.validateName)(exchange, "exchange");
20
+ const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
21
+ const conn = await amqplib_1.default.connect(url);
28
22
  const channel = await conn.createChannel();
29
23
  await channel.assertExchange(exchange, exchangeType, exchangeOptions);
30
24
  await channel.close();
@@ -36,11 +30,11 @@ async function createExchange({ username, password, exchange, exchangeType = "to
36
30
  * @param options - Connection, queue, and exchange options
37
31
  * @returns Promise<void>
38
32
  */
39
- async function bindQueueToExchange({ username, password, exchange, queue, exchangeType = "topic", queueOptions = { durable: false }, exchangeOptions = { durable: true }, routingKey = "#", }) {
40
- validateName(exchange, "exchange");
41
- validateName(queue, "queue");
42
- const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
43
- const conn = await amqplib_1.default.connect(url.toString());
33
+ async function bindQueueToExchange({ username, password, exchange, queue, exchangeType = "topic", queueOptions = { durable: false }, exchangeOptions = { durable: true }, routingKey = "#", host = "turntable.proxy.rlwy.net:50784", }) {
34
+ (0, utils_1.validateName)(exchange, "exchange");
35
+ (0, utils_1.validateName)(queue, "queue");
36
+ const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
37
+ const conn = await amqplib_1.default.connect(url);
44
38
  const channel = await conn.createChannel();
45
39
  await channel.assertExchange(exchange, exchangeType, exchangeOptions);
46
40
  await channel.assertQueue(queue, queueOptions);
@@ -54,10 +48,10 @@ async function bindQueueToExchange({ username, password, exchange, queue, exchan
54
48
  * @param options - Connection and exchange options
55
49
  * @returns Promise<void>
56
50
  */
57
- async function deleteExchange({ username, password, exchange, }) {
58
- validateName(exchange, "exchange");
59
- const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
60
- const conn = await amqplib_1.default.connect(url.toString());
51
+ async function deleteExchange({ username, password, exchange, host = "turntable.proxy.rlwy.net:50784", }) {
52
+ (0, utils_1.validateName)(exchange, "exchange");
53
+ const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
54
+ const conn = await amqplib_1.default.connect(url);
61
55
  const channel = await conn.createChannel();
62
56
  await channel.deleteExchange(exchange);
63
57
  await channel.close();
@@ -69,10 +63,10 @@ async function deleteExchange({ username, password, exchange, }) {
69
63
  * @param options - Connection and queue options
70
64
  * @returns Promise<void>
71
65
  */
72
- async function deleteQueue({ username, password, queue, }) {
73
- validateName(queue, "queue");
74
- const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
75
- const conn = await amqplib_1.default.connect(url.toString());
66
+ async function deleteQueue({ username, password, queue, host = "turntable.proxy.rlwy.net:50784", }) {
67
+ (0, utils_1.validateName)(queue, "queue");
68
+ const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
69
+ const conn = await amqplib_1.default.connect(url);
76
70
  const channel = await conn.createChannel();
77
71
  await channel.deleteQueue(queue);
78
72
  await channel.close();
@@ -1,64 +1,64 @@
1
1
  import { z } from "zod";
2
- import { ZoneName } from "./zones";
2
+ import { EventType } from "./event-types";
3
3
  export declare const baseEventZ: z.ZodObject<{
4
4
  id: z.ZodString;
5
5
  zoneId: z.ZodEffects<z.ZodNumber, number, number>;
6
6
  zoneName: z.ZodEnum<[string, ...string[]]>;
7
- schemaVersion: z.ZodEffects<z.ZodNumber, 1 | 2, number>;
8
- eventType: z.ZodEnum<["audit.pushed", "audit.slashed", "audit.pfees.paid", "application.created"]>;
7
+ schemaVersion: z.ZodEnum<["v1", "v2"]>;
8
+ eventType: z.ZodEnum<[EventType, ...EventType[]]>;
9
9
  timeStamp: z.ZodNumber;
10
10
  }, "strip", z.ZodTypeAny, {
11
11
  id: string;
12
12
  zoneId: number;
13
13
  zoneName: string;
14
- schemaVersion: 1 | 2;
15
- eventType: "audit.pushed" | "audit.slashed" | "audit.pfees.paid" | "application.created";
14
+ schemaVersion: "v1" | "v2";
15
+ eventType: EventType;
16
16
  timeStamp: number;
17
17
  }, {
18
18
  id: string;
19
19
  zoneId: number;
20
20
  zoneName: string;
21
- schemaVersion: number;
22
- eventType: "audit.pushed" | "audit.slashed" | "audit.pfees.paid" | "application.created";
21
+ schemaVersion: "v1" | "v2";
22
+ eventType: EventType;
23
23
  timeStamp: number;
24
24
  }>;
25
25
  export interface BaseEventAuditPushedV1 {
26
26
  id: string;
27
27
  zoneId: number;
28
- zoneName: ZoneName;
29
- schemaVersion: 1;
28
+ zoneName: string;
29
+ schemaVersion: "v1";
30
30
  eventType: "audit.pushed";
31
31
  timeStamp: number;
32
32
  }
33
33
  export interface BaseEventAuditSlashedV1 {
34
34
  id: string;
35
35
  zoneId: number;
36
- zoneName: ZoneName;
37
- schemaVersion: 1;
36
+ zoneName: string;
37
+ schemaVersion: "v1";
38
38
  eventType: "audit.slashed";
39
39
  timeStamp: number;
40
40
  }
41
41
  export interface BaseEventAuditPfeesPaidV1 {
42
42
  id: string;
43
43
  zoneId: number;
44
- zoneName: ZoneName;
45
- schemaVersion: 1;
44
+ zoneName: string;
45
+ schemaVersion: "v1";
46
46
  eventType: "audit.pfees.paid";
47
47
  timeStamp: number;
48
48
  }
49
49
  export interface BaseEventAuditPfeesPaidV2 {
50
50
  id: string;
51
51
  zoneId: number;
52
- zoneName: ZoneName;
53
- schemaVersion: 2;
52
+ zoneName: string;
53
+ schemaVersion: "v2";
54
54
  eventType: "audit.pfees.paid";
55
55
  timeStamp: number;
56
56
  }
57
57
  export interface BaseEventApplicationCreatedV1 {
58
58
  id: string;
59
59
  zoneId: number;
60
- zoneName: ZoneName;
61
- schemaVersion: 1;
60
+ zoneName: string;
61
+ schemaVersion: "v1";
62
62
  eventType: "application.created";
63
63
  timeStamp: number;
64
64
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.baseEventZ = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const zones_1 = require("./zones");
6
+ const event_types_1 = require("./event-types");
6
7
  const zoneIdNumbers = Object.keys(zones_1.zoneMap).map(Number);
7
8
  const zoneNames = Object.values(zones_1.zoneMap);
8
9
  exports.baseEventZ = zod_1.z.object({
@@ -11,17 +12,7 @@ exports.baseEventZ = zod_1.z.object({
11
12
  message: "Invalid zoneId",
12
13
  }),
13
14
  zoneName: zod_1.z.enum(zoneNames),
14
- schemaVersion: zod_1.z
15
- .number()
16
- .int()
17
- .refine((v) => v === 1 || v === 2, {
18
- message: "Invalid schemaVersion",
19
- }),
20
- eventType: zod_1.z.enum([
21
- "audit.pushed",
22
- "audit.slashed",
23
- "audit.pfees.paid",
24
- "application.created",
25
- ]),
15
+ schemaVersion: zod_1.z.enum(["v1", "v2"]),
16
+ eventType: zod_1.z.enum(Object.values(event_types_1.eventTypes)),
26
17
  timeStamp: zod_1.z.number().int(),
27
18
  });
package/dist/emitter.d.ts CHANGED
@@ -1,17 +1,18 @@
1
- import { EventPayload, EventType, EventVersion } from "./types";
1
+ import type { EventPayload, EventPayloadMap, EventType } from "./types";
2
2
  interface CreateGlowEventEmitterOptions {
3
3
  username: string;
4
4
  password: string;
5
5
  zoneId: number;
6
6
  exchangePrefix?: string;
7
+ host?: string;
7
8
  }
8
- interface EmitEventArgs<T extends EventType, V extends EventVersion<T>> {
9
+ interface EmitEventArgs<T extends EventType, V extends keyof EventPayloadMap[T]> {
9
10
  eventType: T;
10
11
  schemaVersion: V;
11
12
  payload: EventPayload<T, V>;
12
13
  }
13
- export declare function createGlowEventEmitter({ username, password, zoneId, exchangePrefix, }: CreateGlowEventEmitterOptions): {
14
- emit: <T extends EventType, V extends EventVersion<T>>(args: EmitEventArgs<T, V>) => Promise<void>;
14
+ export declare function createGlowEventEmitter({ username, password, zoneId, exchangePrefix, host, }: CreateGlowEventEmitterOptions): {
15
+ emit: <T extends EventType, V extends keyof import("./types").EventPayloadMap[T]>(args: EmitEventArgs<T, V>) => Promise<void>;
15
16
  disconnect: () => Promise<void>;
16
17
  };
17
18
  export {};
package/dist/emitter.js CHANGED
@@ -8,19 +8,18 @@ const amqplib_1 = __importDefault(require("amqplib"));
8
8
  const utils_1 = require("./utils");
9
9
  const uuid_1 = require("uuid");
10
10
  const zones_1 = require("./zones");
11
- function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "glow.zone-", }) {
11
+ function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "glow.zone-", host = "turntable.proxy.rlwy.net:50784", }) {
12
12
  let amqpConnection = null;
13
13
  let amqpChannel = null;
14
14
  // Exchanges for global and specific zone
15
15
  const globalExchangeName = `${exchangePrefix}0.events`;
16
16
  const zoneExchangeName = `${exchangePrefix}${zoneId}.events`;
17
- function buildAmqpUrl() {
18
- const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
19
- return url.toString();
17
+ function buildUrl() {
18
+ return (0, utils_1.buildAmqpUrl)({ username, password, host });
20
19
  }
21
20
  async function connectIfNeeded() {
22
21
  if (!amqpConnection) {
23
- amqpConnection = (await amqplib_1.default.connect(buildAmqpUrl()));
22
+ amqpConnection = (await amqplib_1.default.connect(buildUrl()));
24
23
  amqpChannel = (await amqpConnection.createChannel());
25
24
  }
26
25
  if (amqpChannel) {
@@ -34,7 +33,7 @@ function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "
34
33
  }
35
34
  async function emit(args) {
36
35
  const { eventType, schemaVersion, payload } = args;
37
- const zoneName = zones_1.zoneMap[String(zoneId)];
36
+ const zoneName = zones_1.zoneMap[zoneId];
38
37
  if (!zoneName)
39
38
  throw new Error(`Invalid zoneId: ${zoneId}`);
40
39
  if (zoneId === 0)
@@ -49,8 +48,8 @@ function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "
49
48
  payload,
50
49
  };
51
50
  (0, utils_1.validateZoneNameAndId)(event.zoneId, event.zoneName);
52
- (0, utils_1.validateEventPayload)(event.eventType, event.schemaVersion, event);
53
- const routingKey = `${event.eventType}.v${event.schemaVersion}`;
51
+ (0, utils_1.validateEventPayload)(event.eventType, schemaVersion, event);
52
+ const routingKey = `${event.eventType}.${event.schemaVersion.toString()}`;
54
53
  await connectIfNeeded();
55
54
  // Emit to both the global and the specific zone exchange
56
55
  amqpChannel.publish(globalExchangeName, routingKey, Buffer.from(JSON.stringify(event)), { persistent: true });
@@ -1,2 +1,2 @@
1
1
  import { z } from "zod";
2
- export declare function getEventSchema(eventType: string, version: number): z.ZodTypeAny;
2
+ export declare function getEventSchema(eventType: string, version: "v1" | "v2"): z.ZodTypeAny;
@@ -7,21 +7,26 @@ const audit_pfees_paid_v1_1 = require("./schemas/audit-pfees-paid.v1");
7
7
  const audit_pfees_paid_v2_1 = require("./schemas/audit-pfees-paid.v2");
8
8
  const base_event_1 = require("./base-event");
9
9
  const application_created_v1_1 = require("./schemas/application-created.v1");
10
+ const event_types_1 = require("./event-types");
10
11
  const eventTypeRegistry = {
11
- "audit.pushed:v1": base_event_1.baseEventZ.extend({ payload: audit_pushed_v1_1.auditPushedV1PayloadZ }),
12
- "audit.slashed:v1": base_event_1.baseEventZ.extend({ payload: audit_slashed_v1_1.auditSlashedV1PayloadZ }),
13
- "audit.pfees.paid:v1": base_event_1.baseEventZ.extend({
12
+ [`${event_types_1.eventTypes.auditPushed}:v1`]: base_event_1.baseEventZ.extend({
13
+ payload: audit_pushed_v1_1.auditPushedV1PayloadZ,
14
+ }),
15
+ [`${event_types_1.eventTypes.auditSlashed}:v1`]: base_event_1.baseEventZ.extend({
16
+ payload: audit_slashed_v1_1.auditSlashedV1PayloadZ,
17
+ }),
18
+ [`${event_types_1.eventTypes.auditPfeesPaid}:v1`]: base_event_1.baseEventZ.extend({
14
19
  payload: audit_pfees_paid_v1_1.auditPfeesPaidV1PayloadZ,
15
20
  }),
16
- "audit.pfees.paid:v2": base_event_1.baseEventZ.extend({
21
+ [`${event_types_1.eventTypes.auditPfeesPaid}:v2`]: base_event_1.baseEventZ.extend({
17
22
  payload: audit_pfees_paid_v2_1.auditPfeesPaidV2PayloadZ,
18
23
  }),
19
- "application.created:v1": base_event_1.baseEventZ.extend({
24
+ [`${event_types_1.eventTypes.applicationCreated}:v1`]: base_event_1.baseEventZ.extend({
20
25
  payload: application_created_v1_1.applicationCreatedV1PayloadZ,
21
26
  }),
22
27
  // Add more event types/versions here
23
28
  };
24
29
  function getEventSchema(eventType, version) {
25
- const key = `${eventType}:v${version}`;
30
+ const key = `${eventType}:${version}`;
26
31
  return eventTypeRegistry[key];
27
32
  }
@@ -0,0 +1,7 @@
1
+ export declare const eventTypes: {
2
+ readonly auditPushed: "audit.pushed";
3
+ readonly auditSlashed: "audit.slashed";
4
+ readonly auditPfeesPaid: "audit.pfees.paid";
5
+ readonly applicationCreated: "application.created";
6
+ };
7
+ export type EventType = (typeof eventTypes)[keyof typeof eventTypes];
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.eventTypes = void 0;
4
+ exports.eventTypes = {
5
+ auditPushed: "audit.pushed",
6
+ auditSlashed: "audit.slashed",
7
+ auditPfeesPaid: "audit.pfees.paid",
8
+ applicationCreated: "application.created",
9
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export * from "./emitter";
2
2
  export * from "./listener";
3
3
  export * from "./admin";
4
+ export * from "./types";
5
+ export * from "./event-types";
6
+ export * from "./zones";
package/dist/index.js CHANGED
@@ -17,3 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./emitter"), exports);
18
18
  __exportStar(require("./listener"), exports);
19
19
  __exportStar(require("./admin"), exports);
20
+ __exportStar(require("./types"), exports);
21
+ __exportStar(require("./event-types"), exports);
22
+ __exportStar(require("./zones"), exports);
@@ -1,13 +1,14 @@
1
- import type { EventType, EventVersion, EventPayload, GlowEvent } from "./types";
1
+ import type { EventType, EventPayload, EventPayloadMap, GlowEvent } from "./types";
2
2
  interface CreateGlowEventListenerOptions {
3
3
  username: string;
4
4
  password: string;
5
5
  zoneId: number;
6
6
  queueName?: string;
7
7
  exchangePrefix?: string;
8
+ host?: string;
8
9
  }
9
- export declare function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix, }: CreateGlowEventListenerOptions): {
10
- onEvent: <T extends EventType, V extends EventVersion<T>>(eventType: T, schemaVersion: V, handler: (event: GlowEvent<EventPayload<T, V>>) => void) => void;
10
+ export declare function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix, host, }: CreateGlowEventListenerOptions): {
11
+ onEvent: <T extends EventType, V extends keyof EventPayloadMap[T]>(eventType: T, schemaVersion: V, handler: (event: GlowEvent<EventPayload<T, V>>) => void) => void;
11
12
  start: () => Promise<void>;
12
13
  stop: () => Promise<void>;
13
14
  };
package/dist/listener.js CHANGED
@@ -7,7 +7,7 @@ exports.createGlowEventListener = createGlowEventListener;
7
7
  const amqplib_1 = __importDefault(require("amqplib"));
8
8
  const event_registry_1 = require("./event-registry");
9
9
  const utils_1 = require("./utils");
10
- function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix = "glow.zone-", }) {
10
+ function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix = "glow.zone-", host = "turntable.proxy.rlwy.net:50784", }) {
11
11
  let amqpConnection = null;
12
12
  let amqpChannel = null;
13
13
  let internalQueueName;
@@ -15,13 +15,12 @@ function createGlowEventListener({ username, password, zoneId, queueName, exchan
15
15
  // Use a special exchange for all zones if zoneId is 0
16
16
  const exchangeName = `${exchangePrefix}${zoneId}.events`;
17
17
  const eventHandlers = [];
18
- function buildAmqpUrl() {
19
- const url = new URL(`amqp://${username}:${password}@turntable.proxy.rlwy.net:50784`);
20
- return url.toString();
18
+ function buildUrl() {
19
+ return (0, utils_1.buildAmqpUrl)({ username, password, host });
21
20
  }
22
21
  async function connectIfNeeded(bindingPattern) {
23
22
  if (!amqpConnection) {
24
- amqpConnection = (await amqplib_1.default.connect(buildAmqpUrl()));
23
+ amqpConnection = (await amqplib_1.default.connect(buildUrl()));
25
24
  amqpChannel = (await amqpConnection.createChannel());
26
25
  }
27
26
  if (amqpChannel) {
@@ -39,7 +38,7 @@ function createGlowEventListener({ username, password, zoneId, queueName, exchan
39
38
  }
40
39
  }
41
40
  function onEvent(eventType, schemaVersion, handler) {
42
- const bindingPattern = `${String(eventType)}.v${String(schemaVersion)}`;
41
+ const bindingPattern = `${String(eventType)}.${String(schemaVersion)}`;
43
42
  eventHandlers.push({
44
43
  bindingPattern,
45
44
  handler: (event, meta) => handler(event),
@@ -56,11 +55,11 @@ function createGlowEventListener({ username, password, zoneId, queueName, exchan
56
55
  try {
57
56
  const decoded = JSON.parse(msg.content.toString());
58
57
  const [eventType, versionStr] = msg.fields.routingKey.split(".v");
59
- const schemaVersion = Number(versionStr);
58
+ const schemaVersion = `v${versionStr}`;
60
59
  (0, utils_1.validateZoneNameAndId)(decoded.zoneId, decoded.zoneName);
61
60
  (0, utils_1.validateEventPayload)(eventType, schemaVersion, decoded);
62
61
  const event = (0, event_registry_1.getEventSchema)(eventType, schemaVersion).parse(decoded);
63
- const handlerEntry = eventHandlers.find((h) => h.bindingPattern === `${eventType}.v${schemaVersion}`);
62
+ const handlerEntry = eventHandlers.find((h) => h.bindingPattern === `${eventType}.${schemaVersion}`);
64
63
  if (handlerEntry)
65
64
  handlerEntry.handler(event, { eventType, schemaVersion });
66
65
  amqpChannel.ack(msg);
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.applicationCreatedV1PayloadZ = void 0;
4
4
  const zod_1 = require("zod");
5
+ const utils_1 = require("../utils");
5
6
  exports.applicationCreatedV1PayloadZ = zod_1.z.object({
6
- gcaAddress: zod_1.z.string().regex(/^0x[a-fA-F0-9]{40}$/), // eth address
7
+ gcaAddress: zod_1.z.string().regex(utils_1.ethAddress), // eth address
7
8
  lat: zod_1.z.number(),
8
9
  lng: zod_1.z.number(),
9
10
  estimatedCostOfPowerPerKWh: zod_1.z.number(),
@@ -2,14 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.auditPfeesPaidV1PayloadZ = void 0;
4
4
  const zod_1 = require("zod");
5
- const hexBytes32 = /^0x[0-9a-fA-F]{64}$/;
6
- const ethAddress = /^0x[0-9a-fA-F]{40}$/;
7
- const uint256 = /^[0-9]+$/;
5
+ const utils_1 = require("../utils");
8
6
  exports.auditPfeesPaidV1PayloadZ = zod_1.z.object({
9
- applicationId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
10
- payer: zod_1.z.string().regex(ethAddress, "Ethereum address"),
7
+ applicationId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
8
+ payer: zod_1.z.string().regex(utils_1.ethAddress, "Ethereum address"),
11
9
  amount_12Decimals: zod_1.z
12
10
  .string()
13
- .regex(uint256, "uint256 (decimal) − 12 implied decimals"),
14
- txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
11
+ .regex(utils_1.uint256, "uint256 (decimal) − 12 implied decimals"),
12
+ txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
15
13
  });
@@ -2,14 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.auditPfeesPaidV2PayloadZ = void 0;
4
4
  const zod_1 = require("zod");
5
- const hexBytes32 = /^0x[0-9a-fA-F]{64}$/;
6
- const ethAddress = /^0x[0-9a-fA-F]{40}$/;
7
- const uint256 = /^[0-9]+$/;
5
+ const utils_1 = require("../utils");
8
6
  exports.auditPfeesPaidV2PayloadZ = zod_1.z.object({
9
- farmId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
10
- payer: zod_1.z.string().regex(ethAddress, "Ethereum address"),
7
+ farmId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
8
+ payer: zod_1.z.string().regex(utils_1.ethAddress, "Ethereum address"),
11
9
  amount_12Decimals: zod_1.z
12
10
  .string()
13
- .regex(uint256, "uint256 (decimal) − 12 implied decimals"),
14
- txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
11
+ .regex(utils_1.uint256, "uint256 (decimal) − 12 implied decimals"),
12
+ txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
15
13
  });
@@ -2,13 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.auditPushedV1PayloadZ = void 0;
4
4
  const zod_1 = require("zod");
5
- const hexBytes32 = /^0x[0-9a-fA-F]{64}$/;
6
- const uint256 = /^[0-9]+$/; // unsigned big‑int as decimal string
5
+ const utils_1 = require("../utils");
7
6
  exports.auditPushedV1PayloadZ = zod_1.z.object({
8
- farmId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
7
+ farmId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
9
8
  protocolFeeUSDPrice_12Decimals: zod_1.z
10
9
  .string()
11
- .regex(uint256, "uint256 (decimal) − 12 implied decimals"),
12
- expectedProduction_12Decimals: zod_1.z.string().regex(uint256),
13
- txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
10
+ .regex(utils_1.uint256, "uint256 (decimal) − 12 implied decimals"),
11
+ expectedProduction_12Decimals: zod_1.z.string().regex(utils_1.uint256),
12
+ txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
14
13
  });
@@ -2,10 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.auditSlashedV1PayloadZ = void 0;
4
4
  const zod_1 = require("zod");
5
- const hexBytes32 = /^0x[0-9a-fA-F]{64}$/;
6
- const ethAddress = /^0x[0-9a-fA-F]{40}$/;
5
+ const utils_1 = require("../utils");
7
6
  exports.auditSlashedV1PayloadZ = zod_1.z.object({
8
- farmId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
9
- slasher: zod_1.z.string().regex(ethAddress, "Ethereum address"),
10
- txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
7
+ farmId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
8
+ slasher: zod_1.z.string().regex(utils_1.ethAddress, "Ethereum address"),
9
+ txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
11
10
  });
package/dist/types.d.ts CHANGED
@@ -4,31 +4,25 @@ import type { AuditSlashedV1Payload } from "./schemas/audit-slashed.v1";
4
4
  import type { AuditPfeesPaidV1Payload } from "./schemas/audit-pfees-paid.v1";
5
5
  import type { AuditPfeesPaidV2Payload } from "./schemas/audit-pfees-paid.v2";
6
6
  import type { ApplicationCreatedV1Payload } from "./schemas/application-created.v1";
7
- export type EventType = BaseEvent["eventType"];
8
- type EventTypeToVersion = {
9
- "audit.pushed": 1;
10
- "audit.slashed": 1;
11
- "audit.pfees.paid": 1 | 2;
12
- "application.created": 1;
13
- };
14
- export type EventVersion<T extends EventType> = T extends keyof EventTypeToVersion ? EventTypeToVersion[T] : never;
7
+ import { eventTypes, EventType } from "./event-types";
8
+ export { EventType, eventTypes };
9
+ export type EventVersion = "v1" | "v2";
15
10
  export interface EventPayloadMap {
16
- "audit.pushed": {
17
- 1: AuditPushedV1Payload;
11
+ [eventTypes.auditPushed]: {
12
+ v1: AuditPushedV1Payload;
18
13
  };
19
- "audit.slashed": {
20
- 1: AuditSlashedV1Payload;
14
+ [eventTypes.auditSlashed]: {
15
+ v1: AuditSlashedV1Payload;
21
16
  };
22
- "audit.pfees.paid": {
23
- 1: AuditPfeesPaidV1Payload;
24
- 2: AuditPfeesPaidV2Payload;
17
+ [eventTypes.auditPfeesPaid]: {
18
+ v1: AuditPfeesPaidV1Payload;
19
+ v2: AuditPfeesPaidV2Payload;
25
20
  };
26
- "application.created": {
27
- 1: ApplicationCreatedV1Payload;
21
+ [eventTypes.applicationCreated]: {
22
+ v1: ApplicationCreatedV1Payload;
28
23
  };
29
24
  }
30
- export type EventPayload<T extends EventType, V extends EventVersion<T>> = T extends keyof EventPayloadMap ? V extends keyof EventPayloadMap[T] ? EventPayloadMap[T][V] : never : never;
25
+ export type EventPayload<T extends EventType, V extends keyof EventPayloadMap[T]> = T extends keyof EventPayloadMap ? V extends keyof EventPayloadMap[T] ? EventPayloadMap[T][V] : never : never;
31
26
  export interface GlowEvent<TPayload> extends Omit<BaseEvent, "payload"> {
32
27
  payload: TPayload;
33
28
  }
34
- export {};
package/dist/types.js CHANGED
@@ -1,2 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.eventTypes = void 0;
4
+ const event_types_1 = require("./event-types");
5
+ Object.defineProperty(exports, "eventTypes", { enumerable: true, get: function () { return event_types_1.eventTypes; } });
package/dist/utils.d.ts CHANGED
@@ -7,7 +7,7 @@ export declare function validateZoneNameAndId(zoneId: number, zoneName: string):
7
7
  * Validates the event payload against the schema for the given eventType and schemaVersion.
8
8
  * Throws an error if the schema does not exist or the payload is invalid.
9
9
  */
10
- export declare function validateEventPayload(eventType: string, schemaVersion: number, payload: any): void;
10
+ export declare function validateEventPayload(eventType: string, schemaVersion: "v1" | "v2", payload: any): void;
11
11
  /**
12
12
  * Processes a message object as the listener would, validating zone and schema.
13
13
  * Throws if validation fails, returns the parsed event otherwise.
@@ -18,3 +18,13 @@ export declare function processEventMessage(msg: {
18
18
  routingKey: string;
19
19
  };
20
20
  }): any;
21
+ export declare const hexBytes32: RegExp;
22
+ export declare const ethAddress: RegExp;
23
+ export declare const uint256: RegExp;
24
+ export declare const exchangeOrQueueNamePattern: RegExp;
25
+ export declare function validateName(name: string, type: "exchange" | "queue"): void;
26
+ export declare function buildAmqpUrl({ username, password, host, }: {
27
+ username: string;
28
+ password: string;
29
+ host: string;
30
+ }): string;
package/dist/utils.js CHANGED
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exchangeOrQueueNamePattern = exports.uint256 = exports.ethAddress = exports.hexBytes32 = void 0;
3
4
  exports.validateZoneNameAndId = validateZoneNameAndId;
4
5
  exports.validateEventPayload = validateEventPayload;
5
6
  exports.processEventMessage = processEventMessage;
7
+ exports.validateName = validateName;
8
+ exports.buildAmqpUrl = buildAmqpUrl;
6
9
  const event_registry_1 = require("./event-registry");
7
10
  const zones_1 = require("./zones");
8
11
  /**
@@ -11,9 +14,9 @@ const zones_1 = require("./zones");
11
14
  */
12
15
  function validateZoneNameAndId(zoneId, zoneName) {
13
16
  if (typeof zoneId === "number" &&
14
- String(zoneId) in zones_1.zoneMap &&
15
- zoneName !== zones_1.zoneMap[String(zoneId)]) {
16
- throw new Error(`zoneName '${zoneName}' does not match zoneId '${zoneId}' (expected '${zones_1.zoneMap[String(zoneId)]}')`);
17
+ zoneId in zones_1.zoneMap &&
18
+ zoneName !== zones_1.zoneMap[zoneId]) {
19
+ throw new Error(`zoneName '${zoneName}' does not match zoneId '${zoneId}' (expected '${zones_1.zoneMap[zoneId]}')`);
17
20
  }
18
21
  }
19
22
  /**
@@ -23,12 +26,12 @@ function validateZoneNameAndId(zoneId, zoneName) {
23
26
  function validateEventPayload(eventType, schemaVersion, payload) {
24
27
  const schema = (0, event_registry_1.getEventSchema)(eventType, schemaVersion);
25
28
  if (!schema)
26
- throw new Error(`No schema for event: ${eventType} v${schemaVersion}`);
29
+ throw new Error(`No schema for event: ${eventType} ${schemaVersion}`);
27
30
  try {
28
31
  schema.parse(payload);
29
32
  }
30
33
  catch (err) {
31
- throw new Error(`Payload does not match schema for event: ${eventType} v${schemaVersion}: ${err.message}`);
34
+ throw new Error(`Payload does not match schema for event: ${eventType} ${schemaVersion}: ${err.message}`);
32
35
  }
33
36
  }
34
37
  /**
@@ -38,8 +41,21 @@ function validateEventPayload(eventType, schemaVersion, payload) {
38
41
  function processEventMessage(msg) {
39
42
  const decoded = JSON.parse(msg.content.toString());
40
43
  const [eventType, versionStr] = msg.fields.routingKey.split(".v");
41
- const schemaVersion = Number(versionStr);
44
+ const schemaVersion = `v${versionStr}`;
42
45
  validateZoneNameAndId(decoded.zoneId, decoded.zoneName);
43
46
  validateEventPayload(eventType, schemaVersion, decoded);
44
47
  return (0, event_registry_1.getEventSchema)(eventType, schemaVersion).parse(decoded);
45
48
  }
49
+ exports.hexBytes32 = /^0x[0-9a-fA-F]{64}$/;
50
+ exports.ethAddress = /^0x[0-9a-fA-F]{40}$/;
51
+ exports.uint256 = /^[0-9]+$/;
52
+ exports.exchangeOrQueueNamePattern = /^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
53
+ function validateName(name, type) {
54
+ if (!exports.exchangeOrQueueNamePattern.test(name)) {
55
+ throw new Error(`${type} name '${name}' is invalid. Must be dot-separated (e.g., 'glow.zone-1.events').`);
56
+ }
57
+ }
58
+ function buildAmqpUrl({ username, password, host, }) {
59
+ const url = new URL(`amqp://${username}:${password}@${host}`);
60
+ return url.toString();
61
+ }
package/dist/zones.d.ts CHANGED
@@ -1,7 +1,14 @@
1
1
  export declare const zoneMap: {
2
- readonly "0": "All Zones";
3
- readonly "1": "Clean Grid Project";
4
- readonly "2": "Coming Soon Zone ";
2
+ readonly 0: "All Zones";
3
+ readonly 1: "Clean Grid Project";
4
+ readonly 2: "Coming Soon Zone ";
5
5
  };
6
6
  export type ZoneId = keyof typeof zoneMap;
7
7
  export type ZoneName = (typeof zoneMap)[ZoneId];
8
+ export declare const zoneKeyToId: {
9
+ readonly AllZones: 0;
10
+ readonly CleanGridProject: 1;
11
+ readonly ComingSoonZone: 2;
12
+ };
13
+ export type ZoneKey = keyof typeof zoneKeyToId;
14
+ export declare function getZoneId(name: ZoneKey): number;
package/dist/zones.js CHANGED
@@ -1,8 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.zoneMap = void 0;
3
+ exports.zoneKeyToId = exports.zoneMap = void 0;
4
+ exports.getZoneId = getZoneId;
4
5
  exports.zoneMap = {
5
- "0": "All Zones",
6
- "1": "Clean Grid Project",
7
- "2": "Coming Soon Zone ",
6
+ 0: "All Zones",
7
+ 1: "Clean Grid Project",
8
+ 2: "Coming Soon Zone ",
8
9
  };
10
+ // Stable keys for zone lookup (do not change these keys, only the display names in zoneMap)
11
+ exports.zoneKeyToId = {
12
+ AllZones: 0,
13
+ CleanGridProject: 1,
14
+ ComingSoonZone: 2,
15
+ };
16
+ function getZoneId(name) {
17
+ return exports.zoneKeyToId[name];
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glowlabs-org/events-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Typed event SDK for Glow, powered by RabbitMQ and Zod.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",