UNPKG

indexable-map

Version:

Built-in JavaScript Map with secondary indexes

96 lines (95 loc) 3.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IndexableMap = void 0; const objKeys = Object.keys.bind(Object); class IndexableMap extends Map { _indexes = {}; _indexFields = {}; _indexFilters = {}; _indexesEnabled = true; constructor(entries = [], { indexes = [], indexesEnabled = true, } = { indexes: [], indexesEnabled: true }) { super(entries); for (const { field, filter, name } of indexes) { this._indexes[name] = new Map(); this._indexFields[name] = field; this._indexFilters[name] = filter; } if (indexesEnabled === false) { this._indexesEnabled = false; } if (this._indexesEnabled) { this.refreshIndexes(); } } getByIndex(name, value) { const resp = []; for (const key of this._indexes[name]?.get(value) ?? new Set()) { resp.push(this.get(key)); } return resp; } refreshIndexes() { for (const indexedField of objKeys(this._indexes)) { this._indexes[indexedField].clear(); } for (const [key, value] of this.entries()) { for (const indexName of objKeys(this._indexes)) { if (this._indexFilters[indexName](value)) { this._indexes[indexName].set(value[this._indexFields[indexName]], (this._indexes[indexName].get(value[this._indexFields[indexName]]) ?? new Set()).add(key)); } } } return this; } enableIndexes() { this._indexesEnabled = true; return this; } disableIndexes() { this._indexesEnabled = false; return this; } vacuum() { for (const indexedField of objKeys(this._indexes)) { for (const [fieldValue, set] of this._indexes[indexedField].entries()) { if (!set.size) { this._indexes[indexedField].delete(fieldValue); } } } } set(key, value) { if (this._indexesEnabled) { const oldVal = this.get(key); for (const indexName of objKeys(this._indexes)) { if (oldVal != null) { this._indexes[indexName].get(oldVal[this._indexFields[indexName]])?.delete(key); } if (this._indexFilters[indexName](value)) { this._indexes[indexName].set(value[this._indexFields[indexName]], (this._indexes[indexName].get(value[this._indexFields[indexName]]) ?? new Set()).add(key)); } } } return super.set(key, value); } delete(key) { if (this._indexesEnabled) { const oldVal = this.get(key); if (oldVal != null) { for (const indexName of objKeys(this._indexes)) { this._indexes[indexName].get(oldVal[this._indexFields[indexName]])?.delete(key); } } } return super.delete(key); } clear() { if (this._indexesEnabled) { for (const indexedField of objKeys(this._indexes)) { this._indexes[indexedField].clear(); } } return super.clear(); } } exports.IndexableMap = IndexableMap;