anephenix/hub

View on GitHub
lib/dataStores/memory.js

Summary

Maintainability
C
7 hrs
Test Coverage
B
81%
class MemoryDataStore {
    constructor() {
        this.clients = {};
        this.channels = {};
        this.banRules = [];
        this.messageQueue = [];
        this.messageQueue.push = function (item) {
            Array.prototype.push.call(this, item);
            this.onPush(item);
        };
    }

    bindOnPublish(func) {
        this.messageQueue.onPush = func;
    }

    async putMessageOnQueue(message) {
        this.messageQueue.push(message);
    }

    async addItemToCollection({ value, hash, key }) {
        if (!hash[key]) {
            hash[key] = [value];
        } else {
            if (hash[key].indexOf(value) === -1) {
                hash[key].push(value);
            }
        }
    }

    async removeItemFromCollection({ value, hash, key }) {
        if (!hash[key]) return;
        const valueIndex = hash[key].indexOf(value);
        if (valueIndex === -1) return;
        hash[key].splice(valueIndex, 1);
    }

    async performActionForClientAndChannel({ action, clientId, channel }) {
        const { channels, clients } = this;
        await Promise.all([
            this[action]({
                hash: channels,
                key: channel,
                value: clientId,
            }),
            this[action]({
                hash: clients,
                key: clientId,
                value: channel,
            }),
        ]);
    }

    async addClientToChannel({ clientId, channel }) {
        await this.performActionForClientAndChannel({
            action: 'addItemToCollection',
            clientId,
            channel,
        });
    }

    async removeClientFromChannel({ clientId, channel }) {
        await this.performActionForClientAndChannel({
            action: 'removeItemFromCollection',
            clientId,
            channel,
        });
    }

    async getClientIdsForChannel(channel) {
        const { channels } = this;
        return channels[channel];
    }

    async getChannelsForClientId(clientId) {
        const { clients } = this;
        return clients[clientId];
    }

    async getBanRules() {
        return this.banRules;
    }

    async clearBanRules() {
        return (this.banRules = []);
    }

    async hasBanRule(item) {
        const banRules = await this.getBanRules();
        const matchFilter = (b) => {
            const keys = Object.keys(b).filter(x => b[x]);
            const matches = keys.map(k => b[k] === item[k]);
            return matches.every(x => x === true);
        };
        return banRules.filter(matchFilter).length > 0;
    }

    async addBanRule({ clientId, host, ipAddress }) {
        const existsAlready = await this.hasBanRule({
            clientId,
            host,
            ipAddress,
        });
        if (existsAlready) return;
        this.banRules.push({ clientId, host, ipAddress });
    }

    async removeBanRule({ clientId, host, ipAddress }) {
        const matchFilter = (b) => {
            return (
                b.clientId === clientId &&
                b.host === host &&
                b.ipAddress === ipAddress
            );
        };
        const banRule = this.banRules.find(matchFilter);

        if (!banRule) return null;
        const index = this.banRules.indexOf(banRule);
        this.banRules.splice(index, 1);
        return banRule;
    }
}

module.exports = MemoryDataStore;