@glowlabs-org/events-sdk
Version:
Typed event SDK for Glow, powered by RabbitMQ and Zod.
75 lines (74 loc) • 3.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createGlowEventEmitter = createGlowEventEmitter;
const amqplib_1 = __importDefault(require("amqplib"));
const utils_1 = require("./utils");
const uuid_1 = require("uuid");
const zones_1 = require("./zones");
function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "glow.zone-", host = "turntable.proxy.rlwy.net:50784", environment = "production", }) {
let amqpConnection = null;
let amqpChannel = null;
// Exchanges for global and specific zone
const globalExchangeName = `${exchangePrefix}0.events`;
const zoneExchangeName = `${exchangePrefix}${zoneId}.events`;
function buildUrl() {
return (0, utils_1.buildAmqpUrl)({ username, password, host });
}
async function connectIfNeeded() {
if (!amqpConnection) {
amqpConnection = (await amqplib_1.default.connect(buildUrl()));
// create a confirm channel so we can wait for broker acknowledgements
amqpChannel = (await amqpConnection.createConfirmChannel());
// if a message is unroutable this handler will fire
amqpChannel.on("return", (msg) => {
console.error("❌ UNROUTABLE:", msg.fields.routingKey);
});
}
if (amqpChannel) {
await amqpChannel.assertExchange(globalExchangeName, "topic", {
durable: true,
});
await amqpChannel.assertExchange(zoneExchangeName, "topic", {
durable: true,
});
}
}
async function emit(args) {
const { eventType, schemaVersion, payload } = args;
const zoneName = zones_1.zoneMap[zoneId];
if (!zoneName)
throw new Error(`Invalid zoneId: ${zoneId}`);
const event = {
id: (0, uuid_1.v4)(),
eventType,
schemaVersion,
zoneId,
zoneName,
timeStamp: Date.now(),
environment,
payload,
};
(0, utils_1.validateZoneNameAndId)(event.zoneId, event.zoneName);
(0, utils_1.validateEventPayload)(event.eventType, schemaVersion, event);
const routingKey = `${event.eventType}.${event.schemaVersion.toString()}`;
await connectIfNeeded();
// Emit to both the global and the specific zone exchange
const globalPublish = amqpChannel.publish(globalExchangeName, routingKey, Buffer.from(JSON.stringify(event)), { persistent: true, mandatory: true });
const zonePublish = amqpChannel.publish(zoneExchangeName, routingKey, Buffer.from(JSON.stringify(event)), { persistent: true, mandatory: true });
console.log("globalPublish", globalPublish);
console.log("zonePublish", zonePublish);
// Wait for broker to acknowledge publishes; rejects on nack
await amqpChannel.waitForConfirms();
}
async function disconnect() {
if (amqpConnection) {
await amqpConnection.close();
amqpConnection = null;
amqpChannel = null;
}
}
return { emit, disconnect };
}