libflitter/database/model/Setting.model.js

/**
 * @module libflitter/database/model/Setting
 */

const Model = require('flitter-orm/src/model/Model')

/**
 * A model for tracking one-off settings.
 * @extends module:flitter-orm/src/model/Model~Model
 */
class Setting extends Model {
    static get services() {
        return [...super.services, 'output']
    }

    /**
     * Get the schema for this model.
     * @return {object}
     */
    static get schema() {
        return {
            key: String,
            value: String,
            active: {type: Boolean, default: true},
            history: [String],
        }
    }

    /**
     * Guarantee that a setting record exists. If it does, fetch its value.
     * Otherwise, set the default value. Return the value that is set for the key.
     * @param {string} key
     * @param {string} value - default fallback value
     * @returns {Promise<*>} - resolves to the value of the setting (either the default, or the set value)
     */
    static async guarantee(key, value) {
        let setting = await this.findOne({key})
        if ( !setting ) {
            setting = new this({
                key,
                value,
            })

            await setting.save()
        }

        return setting.value
    }

    /**
     * Get the value of the setting with the specified key.
     * @param {string} key
     * @returns {Promise<*>}
     */
    static async get(key) {
        const setting = await this.findOne({key})
        if ( setting ) return setting.value
        this.prototype.output.warn(`Attempted to fetch undefined setting with key: ${key}`)
    }

    /**
     * Set the value of the setting with the specified key.
     * If a setting with the key exists, its value will be updated.
     * Otherwise, a new record will be created.
     * @param {string} key
     * @param {string} value
     * @returns {Promise<void>}
     */
    static async set(key, value) {
        let setting = await this.findOne({key})
        if ( setting ) {
            await setting.change(value)
        } else {
            setting = new this({
                key,
                value,
            })

            await setting.save()
        }
    }

    /**
     * Change the value of this setting, storing the old value in history.
     * @param value
     * @returns {Promise<*>} - returns this for chaining
     */
    async change(value) {
        this.history.push(this.value)
        this.value = value
        await this.save()
        return this
    }
}

module.exports = exports = Setting