From 7cdff6c1723d47e2c374350c1f1f1bca513508a9 Mon Sep 17 00:00:00 2001 From: ikopeykin Date: Mon, 17 Jun 2019 01:04:01 +0300 Subject: [PATCH] refactor(esdoc): OptionsDefaulter --- lib/OptionsDefaulter.js | 66 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/lib/OptionsDefaulter.js b/lib/OptionsDefaulter.js index cad07ea06c2..59b3b089598 100644 --- a/lib/OptionsDefaulter.js +++ b/lib/OptionsDefaulter.js @@ -4,8 +4,14 @@ */ "use strict"; -const getProperty = (obj, name) => { - name = name.split("."); +/** + * Gets the value at path of object + * @param {object} obj - object to query + * @param {string} path - query path + * @returns {any} - if {@param path} requests element from array, then `undefined` will be returned + */ +const getProperty = (obj, path) => { + let name = path.split("."); for (let i = 0; i < name.length - 1; i++) { obj = obj[name[i]]; if (typeof obj !== "object" || !obj || Array.isArray(obj)) return; @@ -13,8 +19,15 @@ const getProperty = (obj, name) => { return obj[name.pop()]; }; -const setProperty = (obj, name, value) => { - name = name.split("."); +/** + * Sets the value at path of object. Stops execution, if {@param path} requests element from array to be set + * @param {object} obj - object to query + * @param {string} path - query path + * @param {any} value - value to be set + * @returns {void} + */ +const setProperty = (obj, path, value) => { + let name = path.split("."); for (let i = 0; i < name.length - 1; i++) { if (typeof obj[name[i]] !== "object" && obj[name[i]] !== undefined) return; if (Array.isArray(obj[name[i]])) return; @@ -24,21 +37,53 @@ const setProperty = (obj, name, value) => { obj[name.pop()] = value; }; +/** + * @typedef {'call' | 'make' | 'append'} ConfigType + */ +/** + * @typedef {(options: object) => any} MakeConfigHandler + */ +/** + * @typedef {(value: any, options: object) => any} CallConfigHandler + */ +/** + * @typedef {any[]} AppendConfigValues + */ + class OptionsDefaulter { constructor() { + /** + * Stores default options settings or functions for computing them + */ this.defaults = {}; + /** + * Stores configuration for options + * @type {{[key: string]: ConfigType}} + */ this.config = {}; } + /** + * Enhancing {@param options} with default values + * @param {object} options - provided options + * @returns {object} - enhanced options + * @throws {Error} - will throw error, if configuration value is other then `undefined` or {@link ConfigType} + */ process(options) { options = Object.assign({}, options); for (let name in this.defaults) { switch (this.config[name]) { + /** + * If {@link ConfigType} doesn't specified and current value is `undefined`, then default value will be assigned + */ case undefined: if (getProperty(options, name) === undefined) { setProperty(options, name, this.defaults[name]); } break; + /** + * Assign result of {@link CallConfigHandler} + */ case "call": setProperty( options, @@ -46,11 +91,17 @@ class OptionsDefaulter { this.defaults[name].call(this, getProperty(options, name), options) ); break; + /** + * Assign result of {@link MakeConfigHandler}, if current value is `undefined` + */ case "make": if (getProperty(options, name) === undefined) { setProperty(options, name, this.defaults[name].call(this, options)); } break; + /** + * Adding {@link AppendConfigValues} at the end of the current array + */ case "append": { let oldValue = getProperty(options, name); if (!Array.isArray(oldValue)) { @@ -69,6 +120,13 @@ class OptionsDefaulter { return options; } + /** + * Builds up default values + * @param {string} name - option path + * @param {ConfigType | any} config - if {@param def} is provided, then only {@link ConfigType} is allowed + * @param {MakeConfigHandler | CallConfigHandler | AppendConfigValues} [def] - defaults + * @returns {void} + */ set(name, config, def) { if (def !== undefined) { this.defaults[name] = def;