_/**
 * Provides hook mechanics.
 * @author Satoshi Soma (amekusa.com)
 * @license Apache-2.0
 * Copyright 2020 Satoshi Soma
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
class Hooks {
	/**
	 * @param {object} [opts]
	 * @param {string|boolean} [opts.only=false]
	 * - `'first'`: Only allows 1 function per hook
	 * - `'last'`: Only invokes the last function added
	 * - `false`: Accepts any number of functions (default)
	 */
	constructor(opts = {}) {
		this.only = opts.only || false;
		this.reg = {};
	}
	/**
	 * Adds hook function(s).
	 * @param {object} hooks - Key = hook name, Value = function
	 */
	add(hooks) {
		for (let k in hooks) {
			if (!(k in this.reg)) this.reg[k] = [];
			this.reg[k].push(hooks[k]);
		}
	}
	/**
	 * Invokes the hook functions associated with the given key.
	 * @param {string} key
	 * @param {...any} [args] - Args to pass to the functions
	 */
	do(key, ...args) {
		if (!this.has(key)) return;
		switch (this.only) {
			case 'first': this.reg[key][0](...args); break;
			case 'last':  this.reg[key][this.reg[key].length - 1](...args); break;
			default:      for (let i = 0; i < this.reg[key].length; i++) this.reg[key][i](...args);
		}
	}
	/**
	 * Modifies the given value with the hook functions associated with the given key.
	 * @param {string} key
	 * @param {any} value - Value to pass to the functions
	 * @param {...any} [args] - Additional args to pass to the functions
	 * @return {any} Modified `value`
	 */
	apply(key, value = undefined, ...args) {
		if (!this.has(key)) return value;
		switch (this.only) {
			case 'first': value = this.reg[key][0](value, ...args); break;
			case 'last':  value = this.reg[key][this.reg[key].length - 1](value, ...args); break;
			default:      for (let i = 0; i < this.reg[key].length; i++) value = this.reg[key][i](value, ...args);
		}
		return value;
	}
	/**
	 * Returns whether any hook function associated with the given key exists.
	 * @param {string} key
	 * @return {boolean}
	 */
	has(key) {
		return this.reg[key] && (this.reg[key].length > 0);
	}
}

module.exports = Hooks;

Licensed under the Apache License 2.0

Documentation generated by JSDoc 4.0.2 using Docolatte theme