UNPKG

contexify

Version:

A TypeScript library providing a powerful dependency injection container with context-based IoC capabilities, inspired by LoopBack's Context system.

129 lines 3.72 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import { filterByTag } from "../binding/binding-filter.js"; class ContextTagIndexer { static { __name(this, "ContextTagIndexer"); } context; /** * Index for bindings by tag names */ bindingsIndexedByTag = /* @__PURE__ */ new Map(); /** * A listener for binding events */ bindingEventListener; /** * A listener to maintain tag index for bindings */ tagIndexListener; constructor(context) { this.context = context; this.setupTagIndexForBindings(); } /** * Set up context/binding listeners and refresh index for bindings by tag */ setupTagIndexForBindings() { this.bindingEventListener = ({ binding, operation }) => { if (operation === "tag") { this.updateTagIndexForBinding(binding); } }; this.tagIndexListener = (event) => { const { binding, type } = event; if (event.context !== this.context) return; if (type === "bind") { this.updateTagIndexForBinding(binding); binding.on("changed", this.bindingEventListener); } else if (type === "unbind") { this.removeTagIndexForBinding(binding); binding.removeListener("changed", this.bindingEventListener); } }; this.context.on("bind", this.tagIndexListener); this.context.on("unbind", this.tagIndexListener); } /** * Remove tag index for the given binding * @param binding - Binding object */ removeTagIndexForBinding(binding) { for (const [, bindings] of this.bindingsIndexedByTag) { bindings.delete(binding); } } /** * Update tag index for the given binding * @param binding - Binding object */ updateTagIndexForBinding(binding) { this.removeTagIndexForBinding(binding); for (const tag of binding.tagNames) { let bindings = this.bindingsIndexedByTag.get(tag); if (bindings == null) { bindings = /* @__PURE__ */ new Set(); this.bindingsIndexedByTag.set(tag, bindings); } bindings.add(binding); } } /** * Find bindings by tag leveraging indexes * @param tag - Tag name pattern or name/value pairs */ findByTagIndex(tag) { let tagNames; let union = false; if (tag instanceof RegExp) { union = true; tagNames = []; for (const t of this.bindingsIndexedByTag.keys()) { if (tag.test(t)) { tagNames.push(t); } } } else if (typeof tag === "string") { tagNames = [ tag ]; } else { tagNames = Object.keys(tag); } let filter; let bindings; for (const t of tagNames) { const bindingsByTag = this.bindingsIndexedByTag.get(t); if (bindingsByTag == null) break; filter = filter ?? filterByTag(tag); const matched = new Set(Array.from(bindingsByTag).filter(filter)); if (!union && matched.size === 0) break; if (bindings == null) { bindings = matched; } else { if (union) { matched.forEach((b) => bindings?.add(b)); } else { const intersection = /* @__PURE__ */ new Set(); bindings.forEach((b) => { if (matched.has(b)) { intersection.add(b); } }); bindings = intersection; } if (!union && bindings.size === 0) break; } } return bindings == null ? [] : Array.from(bindings); } close() { this.context.removeListener("bind", this.tagIndexListener); this.context.removeListener("unbind", this.tagIndexListener); } } export { ContextTagIndexer }; //# sourceMappingURL=context-tag-indexer.js.map