diff --git a/src/util/Postie.js b/src/util/Postie.js new file mode 100644 index 0000000..c3bf806 --- /dev/null +++ b/src/util/Postie.js @@ -0,0 +1,91 @@ +class Postie { + constructor() { + this._topics = new Map(); + } + + _getSubscribers(topic) { + const subscribers = this._topics.get(topic); + if (typeof subscribers === 'undefined') { + throw new Error(`Topic:"${topic}" doesn't exist.`); + } + return subscribers; + } + + _getSubscriber(topic, address) { + const subscribers = this._getSubscribers(topic); + const subscriber = subscribers.get(address); + if (typeof subscriber === 'undefined') { + throw new Error(`Subscriber on topic:"${topic}" at address:"${address}" doesn't exist.`); + } + return subscriber; + } + + hasTopic(topic) { + return typeof this._topics.get(topic) !== 'undefined'; + } + + hasSubscriber(topic, address) { + const subscribers = this._getSubscribers(topic); + return typeof subscribers.get(address) !== 'undefined'; + } + + hasTopicAndSubscriber(topic, address) { + return (this.isTopicExist(topic)) + ? this.isSubscriberExist(topic, address) + : 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 (typeof this._topics.get(topic) === 'undefined') { + this._topics.set(topic, new Map()); + } + const subscribers = this._topics.get(topic); + if (subscribers.get(address)) { + throw new Error(`Subscription on topic:"${topic}" at address:"${address}" already exist.`); + } + subscribers.set(address, inbox); + } + + unsubscribe(topic, address) { + const subscribers = this._getSubscribers(topic); + if (subscribers.has(address)) { + subscribers.delete(address); + } else throw new Error(`Unable to unsubscribe. Subscriber on topic:"${topic}" at address:"${address}" doesn't exist`); + if (subscribers.size === 0) { + this._topics.delete(topic); + } + } + + /** + * @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 = (subscriber, addr) => { + if (typeof subscriber === 'undefined') { + throw new Error(`Unable to post on topic:"${topic}" at address:"${addr}". Subscriber doesn't exist.`); + } + subscriber(data); + }; + if (Array.isArray(address)) { + const subscribers = this._getSubscribers(topic); + address.forEach((addr) => { + sendPost(subscribers.get(addr), addr); + }); + return; + } + sendPost(this._getSubscriber(topic, address), address); + } +} + +export default Postie;