UNPKG

dictionaryjs

Version:

A simple dictionary wrapper for JavaScript providing hashmap functionality with the added benefit of accessing keys using box and dot operators!

285 lines 7.79 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.Dictionary = void 0; /** * Author: Henry Price * Website: Phanxgames.com * --------------------------------- * Dictionary */ class Dictionary { constructor(initial = null, options = null) { /** * @internal */ this[_a] = function* () { let keys = this.getKeys(); //Object.keys(this); for (let key of keys) { yield this[key]; } }; if (initial != null) { this._copyValues(initial); } options = options || { cacheKeys: false }; //Make the internal data non enumerable. Object.defineProperty(this, "__private__", { value: {}, enumerable: false }); this.__private__.cacheKeys = options.cacheKeys; this.__private__.invalidateKeys = true; this.__private__.keys = null; } /** * Use to loop through key, value pairs. * <pre> * for (let [key,value] of dict.entries()) { * //... * } * </pre> * @returns Iterator */ entries() { let self = this; return { "alert": "exposes Symbol.iterator, use with (for ... of) loop", [Symbol.iterator]: function* () { let keys = self.getKeys(); //Object.keys(this); for (let key of keys) { yield [key, self[key]]; } } }; } /** * Checks if collection has this key. * @param {TKey} key * @returns {boolean} */ has(key) { if (key == null) return false; if (typeof key == "string" && key.indexOf("__private__") >= 0) return false; return this.hasOwnProperty(key); } /** * Checks if the value is within the Dictionary. * @param {TValue} value * @returns {boolean} */ contains(value) { if (value == null) return false; let values = Object.values(this); return values.indexOf(value) >= 0; } /** * Returns number of items in collection. * @returns {number} c */ get size() { return this.getKeys().length; } /** * Returns number of items in collection. * @returns {number} c */ get length() { return this.size; } /** * Invalidates keys to recalculate. */ invalidate() { this.__private__.invalidateKeys = true; } /** * @ignore * @alias getKeys() */ keys() { return this.getKeys(); } /** * Return array of keys * @returns {Array<any>} array of keys */ getKeys() { if (!this.__private__.cacheKeys) return Object.keys(this); if (this.__private__.invalidateKeys || this.__private__.keys == null) { this.__private__.invalidateKeys = false; this.__private__.keys = Object.keys(this); } return this.__private__.keys; } /** * Returns values within collection * @returns {Array<TValue>} */ values() { return Object.values(this); } /** * Remove the key from collection. * @param {TKey} key */ remove(key) { this.invalidate(); delete this[key]; } /** * @alias remove */ delete(key) { this.remove(key); } /** * Store value at the key. The key has been tested with strings, * but may support other types. * Value may be any data type. * @param {TKey} key - key of the key/value pair * @param {TValue} value - value of the key/value pair */ set(key, value) { this.invalidate(); this[key] = value; } /** * Returns the value * @param {TKey} key * @returns {TValue} the value */ get(key) { return this[key]; } /** * Returns the default value if key is not found or is null. * @param {TKey} key - key to lookup * @param defaultValue - the default value * @returns value of key or default value */ getDefault(key, defaultValue) { if (this.has(key)) { return this[key]; } else { return defaultValue; } } /** * Removes all keys from collection. * This is blocking. */ empty() { this.forEach((key, value) => { this.remove(key); }); } /** * @alias empty() */ clear() { this.empty(); } /** * Non-blocking method to remove all keys from collection. * @param {Function} cbComplete - cbComplete() */ async asyncEmpty(cbComplete = null) { await this.asyncForEach((key, value, next) => { this.remove(key); next(); }); if (cbComplete != null) cbComplete(); } /** * @ignore * @alias each */ forEach(cb) { this.each(cb); } /** * Blocking loop helper method. * @param {Function} cbEach - cbEach(key:any,value:any) */ each(cbEach) { for (let key in this) { if (this.has(key)) { if (cbEach(key, this[key]) === false) break; } } } /** * Non-blocking loop helper method. * Must call cbNext within cbIterator to move to the next item in the collection. * Example: * <pre> * await collection.asyncForEach( * (key:any,value:any,cbNext:Function) => { * console.log(key,value); * cbNext(); * }); * </pre> * @param {Function} cbIterator - cbIterator(key:any,value:any,cbNext:Function) * @param {Function} cbComplete - Optional - cbComplete() * @returns {Promise<null>} */ asyncForEach(cbIterator, cbComplete = null) { return new Promise((resolve) => { let keys = this.getKeys(); let counter = 0; let len = keys.length; let next = () => { if (counter < len) { process.nextTick(step); //setTimeout(step,100); } else { if (cbComplete != null) cbComplete(); else resolve(); return; } }; let step = () => { if (counter < len) { let key = keys[counter++]; if (cbIterator(key, this[key], next) == false) { if (cbComplete != null) cbComplete(); else resolve(); return; } } else { if (cbComplete != null) cbComplete(); else resolve(); return; } }; step(); }); } toObject() { } _copyValues(initial) { for (let prop in initial) { if (initial.hasOwnProperty(prop)) this[prop] = initial[prop]; } } } exports.Dictionary = Dictionary; _a = Symbol.iterator; //# sourceMappingURL=Dictionary.js.map