cinny/src/util/Postie.js

98 lines
2.8 KiB
JavaScript
Raw Normal View History

2021-08-30 17:33:59 +02:00
class Postie {
constructor() {
this._topics = new Map();
}
_getSubscribers(topic) {
const subscribers = this._topics.get(topic);
if (subscribers === undefined) {
2021-08-30 17:33:59 +02:00
throw new Error(`Topic:"${topic}" doesn't exist.`);
}
return subscribers;
}
_getInboxes(topic, address) {
2021-08-30 17:33:59 +02:00
const subscribers = this._getSubscribers(topic);
const inboxes = subscribers.get(address);
if (inboxes === undefined) {
throw new Error(`Inbox on topic:"${topic}" at address:"${address}" doesn't exist.`);
2021-08-30 17:33:59 +02:00
}
return inboxes;
2021-08-30 17:33:59 +02:00
}
hasTopic(topic) {
return this._topics.get(topic) !== undefined;
2021-08-30 17:33:59 +02:00
}
hasSubscriber(topic, address) {
const subscribers = this._getSubscribers(topic);
return subscribers.get(address) !== undefined;
2021-08-30 17:33:59 +02:00
}
hasTopicAndSubscriber(topic, address) {
2021-09-12 05:42:59 +02:00
return (this.hasTopic(topic))
? this.hasSubscriber(topic, address)
2021-08-30 17:33:59 +02:00
: false;
}
/**
* @param {string} topic - Subscription topic
* @param {string} address - Address of subscriber
* @param {function} inbox - The inbox function to receive post data
*/
subscribe(topic, address, inbox) {
if (typeof inbox !== 'function') {
throw new TypeError('Inbox must be a function.');
}
if (this._topics.has(topic) === false) {
2021-08-30 17:33:59 +02:00
this._topics.set(topic, new Map());
}
const subscribers = this._topics.get(topic);
const inboxes = subscribers.get(address) ?? new Set();
inboxes.add(inbox);
subscribers.set(address, inboxes);
return () => this.unsubscribe(topic, address, inbox);
2021-08-30 17:33:59 +02:00
}
unsubscribe(topic, address, inbox) {
2021-08-30 17:33:59 +02:00
const subscribers = this._getSubscribers(topic);
if (!subscribers) throw new Error(`Unable to unsubscribe. Topic: "${topic}" doesn't exist.`);
const inboxes = subscribers.get(address);
if (!inboxes) throw new Error(`Unable to unsubscribe. Subscriber on topic:"${topic}" at address:"${address}" doesn't exist`);
if (!inboxes.delete(inbox)) throw new Error('Unable to unsubscribe. Inbox doesn\'t exist');
if (inboxes.size === 0) subscribers.delete(address);
if (subscribers.size === 0) this._topics.delete(topic);
2021-08-30 17:33:59 +02:00
}
/**
* @param {string} topic - Subscription topic
* @param {string|string[]} address - Address of subscriber
* @param {*} data - Data to deliver to subscriber
*/
post(topic, address, data) {
const sendPost = (inboxes, addr) => {
if (inboxes === undefined) {
2021-08-30 17:33:59 +02:00
throw new Error(`Unable to post on topic:"${topic}" at address:"${addr}". Subscriber doesn't exist.`);
}
inboxes.forEach((inbox) => inbox(data));
2021-08-30 17:33:59 +02:00
};
if (typeof address === 'string') {
sendPost(this._getInboxes(topic, address), address);
2021-08-30 17:33:59 +02:00
return;
}
const subscribers = this._getSubscribers(topic);
address.forEach((addr) => {
sendPost(subscribers.get(addr), addr);
});
2021-08-30 17:33:59 +02:00
}
}
export default Postie;