# Source: registry/base.js

    /**
     * @module
     * @private
     */

    /**
     * Base class for all registries.
     *
     * LocusZoom is plugin-extensible, and layouts are JSON-serializable objects that refer to desired features by name (not by class).
     * This is achieved through the use of a central registry that holds a reference to each possible feature.
     *
     * Each registry has some syntactical sugar to make it easier to, eg, modify layouts or create classes.
     * This class is documented solely so that those helper methods can be referenced.
     */
    class RegistryBase {
        constructor() {
            this._items = new Map();
        }

        /**
         * Return the registry member. If the registry stores classes, this returns the class, not the instance.
         * @param {String} name
         * @returns {Function}
         */
        get(name) {
            if (!this._items.has(name)) {
                throw new Error(`Item not found: ${name}`);
            }
            return this._items.get(name);
        }

        /**
         * Add a new item to the registry
         * @param {String} name The name of the item to add to the registry
         * @param {*} item The item to be added (constructor, value, etc)
         * @param {boolean} [override=false] Allow redefining an existing item?
         * @return {*} The actual object as added to the registry
         */
        add(name, item, override = false) {
            if (!override && this._items.has(name)) {
                throw new Error(`Item ${name} is already defined`);
            }
            this._items.set(name, item);
            return item;
        }

        /**
         * Remove a datasource from the registry (if present)
         * @param {String} name
         * @returns {boolean} True if item removed, false if item was never present
         */
        remove(name) {
            return this._items.delete(name);
        }

        /**
         * Check whether the specified item is registered
         * @param {String} name
         * @returns {boolean}
         */
        has(name) {
            return this._items.has(name);
        }

        /**
         * Names of each allowed
         * @returns {String[]}
         */
        list() {
            return Array.from(this._items.keys());
        }
    }

    /**
     * A specialized registry whose members are class constructors. Contains helper methods for creating instances
     *  and subclasses.
     * @ignore
     */
    class ClassRegistry extends RegistryBase {
        /**
         * Create an instance of the specified class from the registry
         * @param {String} name
         * @param {*} args Any additional arguments to be passed to the constructor
         * @returns {*}
         */
        create(name, ...args) {
            const base = this.get(name);
            return new base(...args);
        }

        /**
         * Create a new child class for an item in the registry.
         *
         * This is (almost, but not quite) a compatibility layer for old sites that used locuszoom
         *
         * This is primarily aimed at low-tooling environments. It is syntactic sugar, roughly equivalent to:
         *   `registry.get(base); registry.add(name, class A extends base {});`
         *
         * Because this bypasses es6 class mechanics, certain things, esp super calls, may not work as well as using the
         *   "real" class expression. This method is provided solely for convenience.
         *
         * This method is a compatibility layer for old versions. Born to be deprecated!
         * @deprecated
         * @param {string} parent_name The name of the desired parent class as represented in the registry
         * @param {string} source_name The desired name of the class to be created, as it will be named in the registry
         * @param {object} overrides An object
         * @return {*}
         */
        extend(parent_name, source_name, overrides) {
            console.warn('Deprecation warning: .extend method will be removed in future versions, in favor of explicit ES6 subclasses');
            if (arguments.length !== 3) {
                throw new Error('Invalid arguments to .extend');
            }

            const base = this.get(parent_name);
            class sub extends base {}
            Object.assign(sub.prototype, overrides, base);
            this.add(source_name, sub);
            return sub;
        }
    }

    export default RegistryBase;
    export {RegistryBase, ClassRegistry};