RocketChat/Rocket.Chat

View on GitHub
apps/meteor/app/settings/lib/settings.ts

Summary

Maintainability
B
5 hrs
Test Coverage
import type { SettingValue } from '@rocket.chat/core-typings';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';

import { sdk } from '../../utils/client/lib/SDKClient';

type SettingComposedValue<T extends SettingValue = SettingValue> = { key: string; value: T };
type SettingCallback = (key: string, value: SettingValue, initialLoad?: boolean) => void;

interface ISettingRegexCallbacks {
    regex: RegExp;
    callbacks: SettingCallback[];
}

export class SettingsBase {
    private callbacks = new Map<string, SettingCallback[]>();

    private regexCallbacks = new Map<string, ISettingRegexCallbacks>();

    // private ts = new Date()

    public get(_id: RegExp, callback: SettingCallback): void;

    public get(_id: string, callback: SettingCallback): void;

    public get<T extends SettingValue = SettingValue>(_id: RegExp): SettingComposedValue<T>[];

    public get<T extends SettingValue = SettingValue>(_id: string): T | undefined;

    public get<T extends SettingValue = SettingValue>(
        _id: string | RegExp,
        callback?: SettingCallback,
    ): T | undefined | SettingComposedValue<T>[] | void {
        if (callback != null) {
            this.onload(_id, callback);
            if (!Meteor.settings) {
                return;
            }
            if (_id === '*') {
                return Object.keys(Meteor.settings).forEach((key) => {
                    const value = Meteor.settings[key];
                    callback(key, value);
                });
            }
            if (_.isRegExp(_id) && Meteor.settings) {
                return Object.keys(Meteor.settings).forEach((key) => {
                    if (!_id.test(key)) {
                        return;
                    }
                    const value = Meteor.settings[key];
                    callback(key, value);
                });
            }

            if (typeof _id === 'string') {
                const value = Meteor.settings[_id];
                if (value != null) {
                    callback(_id, Meteor.settings[_id]);
                }
                return;
            }
        }

        if (!Meteor.settings) {
            return;
        }

        if (_.isRegExp(_id)) {
            return Object.keys(Meteor.settings).reduce((items: SettingComposedValue<T>[], key) => {
                const value = Meteor.settings[key];
                if (_id.test(key)) {
                    items.push({
                        key,
                        value,
                    });
                }
                return items;
            }, []);
        }

        return Meteor.settings?.[_id];
    }

    set(_id: string, value: SettingValue, callback: (err?: unknown, result?: any) => void): void {
        sdk
            .call('saveSetting', _id, value)
            .then((result) => callback(undefined, result))
            .catch(callback);
    }

    batchSet(settings: Array<{ _id: string; value: SettingValue }>, callback: (err?: unknown, result?: any) => void): void {
        sdk
            .call('saveSettings', settings)
            .then((result) => callback(undefined, result))
            .catch(callback);
    }

    load(key: string, value: SettingValue, initialLoad: boolean): void {
        ['*', key].forEach((item) => {
            const callbacks = this.callbacks.get(item);
            if (callbacks) {
                callbacks.forEach((callback) => callback(key, value, initialLoad));
            }
        });
        this.regexCallbacks.forEach((cbValue) => {
            if (!cbValue?.regex.test(key)) {
                return;
            }
            cbValue.callbacks.forEach((callback) => callback(key, value, initialLoad));
        });
    }

    onload(key: string | string[] | RegExp | RegExp[], callback: SettingCallback): void {
        // if key is '*'
        //     for key, value in Meteor.settings
        //         callback key, value, false
        // else if Meteor.settings?[_id]?
        //     callback key, Meteor.settings[_id], false
        const keys: Array<string | RegExp> = Array.isArray(key) ? key : [key];
        keys.forEach((k) => {
            if (_.isRegExp(k)) {
                if (!this.regexCallbacks.has(k.source)) {
                    this.regexCallbacks.set(k.source, {
                        regex: k,
                        callbacks: [],
                    });
                }
                this.regexCallbacks.get(k.source)?.callbacks.push(callback);
            } else {
                if (!this.callbacks.has(k)) {
                    this.callbacks.set(k, []);
                }
                this.callbacks.get(k)?.push(callback);
            }
        });
    }
}