@fimbul-works/observable
Version:
A lightweight, strongly-typed TypeScript library for reactive programming patterns, providing observable collections, values, and event handling.
140 lines (139 loc) • 5.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObservableRegistry = void 0;
const map_js_1 = require("./map.js");
/**
* A strict key-value registry that enforces unique registration and required existence.
* Extends ObservableMap to provide change notifications while adding stricter guarantees.
*
* @template K The type of keys in the registry
* @template V The type of values in the registry
* @extends {ObservableMap<K, V>}
*/
class ObservableRegistry extends map_js_1.ObservableMap {
/**
* Registers a new key-value pair in the registry.
* Throws an error if the key is already registered.
*
* @param key - The key to register
* @param value - The value to associate with the key
* @returns {this} The registry instance for method chaining
* @throws {Error} If the key is already registered
*/
register(key, value) {
if (this.has(key)) {
throw new Error(`Already registered: ${String(key)}`);
}
return this.set(key, value);
}
/**
* Registers a new key-value pair and waits for all change handlers to complete.
* @param key - The key to register
* @param value - The value to associate with the key
* @returns {Promise<this>} Promise resolving to the registry instance for method chaining
* @throws {Error} If the key is already registered
*/
async registerAsync(key, value) {
if (this.has(key)) {
throw new Error(`Already registered: ${String(key)}`);
}
return this.setAsync(key, value);
}
/**
* Removes a registered key-value pair from the registry.
*
* @param key - The key to unregister
* @returns {boolean} True if the key was unregistered, false if it wasn't registered
*/
unregister(key) {
return this.delete(key);
}
/**
* Removes a registered key-value pair and waits for all change handlers to complete.
* @param key - The key to unregister
* @returns {Promise<boolean>} Promise resolving to true if the key was unregistered, false otherwise
*/
async unregisterAsync(key) {
return this.deleteAsync(key);
}
/**
* Retrieves a value from the registry by its key.
* Unlike the parent ObservableMap, this method throws if the key doesn't exist.
* @param key - The key to look up
* @param throwErrorOnMissing - Throws error when a key is registered if true
* @returns {V} The value associated with the key
* @throws {Error} If the key is not registered
* @override
*/
get(key, throwErrorOnMissing = true) {
const value = super.get(key);
if (value === undefined && throwErrorOnMissing) {
throw new Error(`Not registered: ${String(key)}`);
}
return value;
}
/**
* Updates a registered value if it exists.
* Unlike set(), this method throws if the key doesn't exist.
* @param key - The key to update
* @param value - The new value to associate with the key
* @returns {this} The registry instance for method chaining
* @throws {Error} If the key is not registered
*/
update(key, value) {
if (!this.has(key)) {
throw new Error(`Cannot update: ${String(key)} is not registered`);
}
return this.set(key, value);
}
/**
* Updates a registered value and waits for all change handlers to complete.
* @param key - The key to update
* @param value - The new value to associate with the key
* @returns {Promise<this>} Promise resolving to the registry instance for method chaining
* @throws {Error} If the key is not registered
*/
async updateAsync(key, value) {
if (!this.has(key)) {
throw new Error(`Cannot update: ${String(key)} is not registered`);
}
return this.setAsync(key, value);
}
/**
* Updates a registered value using a transformation function.
* Throws if the key doesn't exist.
* @param key - The key to update
* @param updateFn - Function that receives the current value and returns the new value
* @returns {this} The registry instance for method chaining
* @throws {Error} If the key is not registered
*/
updateWith(key, updateFn) {
const currentValue = this.get(key);
return this.set(key, updateFn(currentValue));
}
/**
* Updates a registered value using a transformation function and waits for all change handlers to complete.
* @param key - The key to update
* @param updateFn - Function that receives the current value and returns the new value
* @returns {Promise<this>} Promise resolving to the registry instance for method chaining
* @throws {Error} If the key is not registered
*/
async updateWithAsync(key, updateFn) {
const currentValue = this.get(key);
return this.setAsync(key, updateFn(currentValue));
}
/**
* Checks if all provided keys are registered.
* @param keys - The keys to check
* @returns {boolean} True if all keys are registered, false otherwise
*/
hasAll(keys) {
for (const key of keys) {
if (!this.has(key)) {
return false;
}
}
return true;
}
}
exports.ObservableRegistry = ObservableRegistry;