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
JavaScript
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