cmpstr
Version:
CmpStr is a lightweight, fast and well performing package for calculating string similarity
143 lines (141 loc) • 4.95 kB
JavaScript
// CmpStr v3.0.1 dev-052fa0c-250614 by Paul Köhler @komed3 / MIT License
/**
* Registry Utility
* src/utils/Registry.ts
*
* This module provides a Registry function that allows for registering,
* removing, checking, getting, and listing class constructors.
*
* It is designed to manage class extensions, ensuring that all registered
* classes extend a specified base constructor.
*
* @module Utils/Registry
* @author Paul Köhler (komed3)
* @license MIT
*/
/**
* Global registry object to hold multiple registries.
* Each registry is keyed by a string identifier.
*
* @type {Record<string, RegistryService<any>>}
*/
const registry = Object.create(null);
/**
* Factory object to hold factory functions for creating instances.
* This is used to create instances of registered classes.
*
* @type {Record<string, ( cls: string, ...args: any[] ) => InstanceType<any>>}
*/
const factory = Object.create(null);
/**
* Registry function to create a service for managing class constructors.
*
* @param {string} reg - The name of the registry
* @param {RegistryConstructor<T>} ctor - The base constructor that all registered classes must extend
* @returns {RegistryService<T>} - An object with methods to register, remove, check, get, and list classes
* @throws {Error} If the registry already exists (overwriting is forbidden)
*/
function Registry(reg, ctor) {
// Throws an error if the registry already exists
if (reg in registry || reg in factory)
throw new Error(
`registry <${reg}> already exists / overwriting is forbidden`
);
// Create a registry object to hold class constructors
const classes = Object.create(null);
const service = {
/**
* Register a new extension of the base class.
*
* @param {string} name - The name of the class to register
* @param {RegistryConstructor<T>} cls - The class constructor
* @param {boolean} [update=false] - Whether to allow overwriting an existing entry
* @throws {TypeError} If the class does not extend the base constructor
* @throws {Error} If the class name already exists and update is false
*/
add(name, cls, update = false) {
if (!(cls.prototype instanceof ctor))
throw new TypeError(`class must extend <${reg}>`);
if (!update && name in classes)
throw new Error(
`entry <${name}> already exists / use <update=true> to overwrite`
);
classes[name] = cls;
},
/**
* Remove a class from the registry.
*
* @param {string} name - The name of the class to remove
*/
remove(name) {
delete classes[name];
},
/**
* Check if a class is registered.
*
* @param {string} name - The name of the class to check
* @returns {boolean} - True if the class is registered, false otherwise
*/
has(name) {
return name in classes;
},
/**
* List all registered class names.
*
* @returns {string[]} - An array of registered class names
*/
list() {
return Object.keys(classes);
},
/**
* Get a registered class by name.
*
* @param {string} name - The name of the class to retrieve
* @returns {RegistryConstructor<T>} - The class constructor
* @throws {Error} If the class is not registered
*/
get(name) {
if (!(name in classes))
throw new Error(`class <${name}> not registered for <${reg}>`);
return classes[name];
}
};
// Register the service in the global registry
registry[reg] = service;
// Create a factory function for creating instances from the registry
factory[reg] = (cls, ...args) => createFromRegistry(reg, cls, ...args);
// Return the service object
return service;
}
/**
* Resolve a class constructor from a specific registry.
*
* @param {string} reg - The name of the registry
* @param {T|string} cls - The class itself or name of the class to resolve
* @returns {T|undefined} - The class constructor if found, otherwise undefined
* @throws {ReferenceError} If the registry does not exist
*/
function resolveCls(reg, cls) {
if (!(reg in registry))
throw new ReferenceError(`registry <${reg}> does not exist`);
return typeof cls === 'string' ? registry[reg]?.get(cls) : cls;
}
/**
* Create an instance of a class from a specific registry.
*
* @param {string} reg - The name of the registry
* @param {T|string} cls - The class itself or name of the class to instantiate
* @param {...any} args - Arguments to pass to the class constructor
* @returns {T} - An instance of the class
* @throws {Error} If the class cannot be instantiated
*/
function createFromRegistry(reg, cls, ...args) {
cls = resolveCls(reg, cls);
try {
return new cls(...args);
} catch (err) {
throw new Error(`cannot instantiate class <${cls}>`);
}
}
export { Registry, createFromRegistry, factory, registry, resolveCls };
//# sourceMappingURL=Registry.js.map