helene
Version:
Real-time Web Apps for Node.js
150 lines • 5.12 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientChannel = void 0;
const utils_1 = require("../utils");
const eventemitter2_1 = require("eventemitter2");
const castArray_1 = __importDefault(require("lodash/castArray"));
const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
const isString_1 = __importDefault(require("lodash/isString"));
class ClientChannel extends eventemitter2_1.EventEmitter2 {
client;
name;
events = new Set();
// Built-in from EventEmitter2
_events;
constructor(name) {
super({
maxListeners: 128,
});
if (!(0, isString_1.default)(name) || !name)
throw new Error('the channel name needs to be a string');
this.name = name;
}
setClient(client) {
this.client = client;
}
pendingSubscriptions = new Set();
subscribeDebounceTimeout;
async commitPendingSubscriptions() {
const channel = this.name;
const allEvents = Array.from(this.pendingSubscriptions);
this.pendingSubscriptions.clear();
if (!(0, isEmpty_1.default)(allEvents)) {
let result = null;
try {
result = await this.client.call(utils_1.Methods.RPC_ON, {
events: allEvents,
channel,
});
}
catch {
result = null;
}
this.emit(utils_1.HeleneEvents.COMMIT_PENDING_SUBSCRIPTIONS, result);
}
}
async subscribe(event) {
const events = (0, castArray_1.default)(event);
if ((0, isEmpty_1.default)(events))
return {};
for (const event of events) {
this.events.add(event);
this.pendingSubscriptions.add(event);
}
if (this.subscribeDebounceTimeout) {
clearTimeout(this.subscribeDebounceTimeout);
}
this.subscribeDebounceTimeout = setTimeout(this.commitPendingSubscriptions.bind(this), 100);
try {
const [result] = await this.waitFor(utils_1.HeleneEvents.COMMIT_PENDING_SUBSCRIPTIONS, 5000);
return result;
}
catch (error) {
console.error('[Helene] Failed to commit subscriptions', error);
return {};
}
}
pendingUnsubscriptions = new Set();
unsubscribeDebounceTimeout;
async commitPendingUnsubscriptions() {
const channel = this.name;
const allEvents = Array.from(this.pendingUnsubscriptions);
this.pendingUnsubscriptions.clear();
if (!(0, isEmpty_1.default)(allEvents)) {
let result = null;
try {
result = await this.client.call(utils_1.Methods.RPC_OFF, {
events: allEvents,
channel,
});
}
catch {
result = {};
}
this.emit(utils_1.HeleneEvents.COMMIT_PENDING_UNSUBSCRIPTIONS, result);
}
}
async unsubscribe(event) {
const events = (0, castArray_1.default)(event);
if ((0, isEmpty_1.default)(events))
return {};
for (const event of events) {
this.events.delete(event);
this.pendingUnsubscriptions.add(event);
}
if (this.unsubscribeDebounceTimeout) {
clearTimeout(this.unsubscribeDebounceTimeout);
}
this.unsubscribeDebounceTimeout = setTimeout(this.commitPendingUnsubscriptions.bind(this), 100);
try {
const [result] = await this.waitFor(utils_1.HeleneEvents.COMMIT_PENDING_UNSUBSCRIPTIONS, 5000);
return result;
}
catch (error) {
console.error('[Helene] Failed to commit unsubscriptions', error);
return {};
}
}
async resubscribe() {
return this.subscribe(Array.from(this.events));
}
/**
* Wait for an event to fire asynchronously.
*
* Returns true if no params are sent.
*/
wait(event, callback) {
return new Promise(resolve => {
this.once(event, function (data = true) {
if (callback) {
resolve(callback(data));
}
else {
resolve(data);
}
});
});
}
/**
* Returns true if the event was not fired within a given timeout.
*/
timeout(event, timeoutMs = 1000) {
return new Promise(resolve => {
const timeout = setTimeout(() => resolve(true), timeoutMs);
this.wait(event).then(res => {
if (timeout) {
clearTimeout(timeout);
}
resolve(false);
});
});
}
iterator(event) {
return (0, utils_1.createIterator)(this, event);
}
}
exports.ClientChannel = ClientChannel;
//# sourceMappingURL=client-channel.js.map