/**
* @copyright Copyright 2021 Kevin Locke <kevin@kevinlocke.name>
* @license MIT
*/
import { isDeepStrictEqual } from 'node:util';
/** Manages named additions to defined components.
*/
export default class ComponentManager {
constructor(component) {
if (component === null
|| typeof component !== 'object'
|| Array.isArray(component)) {
throw new TypeError('component must be a non-Array, non-null object');
}
this.component = component;
}
/** Adds a given value, optionally with a given (base) name.
*
* @param {*} value Value to add to the component being managed.
* @param {string=} basename Preferred name for value in component.
* ({@link getNames}).
* @returns {string} Name of added value.
*/
add(value, basename) {
for (const name of this.getNames(basename)) {
if (this.component[name] === undefined) {
this.component[name] = value;
return name;
}
if (this.isMatch(this.component[name], value)) {
return name;
}
}
throw new Error('No suitable name matched value to add');
}
/** Gets property names to check for a given base name.
*
* @param {string=} basename Base name to use for property.
* @yields {string} Property names to check for #add().
*/
// eslint-disable-next-line class-methods-use-this
* getNames(basename) {
yield `${basename}`;
for (let i = 2; ; i += 1) {
yield `${basename}${i}`;
}
}
}
/** Determines if given values match such that an existing value can be used in
* place of an added value.
*/
ComponentManager.prototype.isMatch = isDeepStrictEqual;