UNPKG

4.91 kBJavaScriptView Raw
1"use strict";
2// Copyright IBM Corp. and LoopBack contributors 2020. All Rights Reserved.
3// Node module: @loopback/context
4// This file is licensed under the MIT License.
5// License text available at https://opensource.org/licenses/MIT
6Object.defineProperty(exports, "__esModule", { value: true });
7exports.ContextTagIndexer = void 0;
8const binding_filter_1 = require("./binding-filter");
9/**
10 * Indexer for context bindings by tag
11 */
12class ContextTagIndexer {
13 constructor(context) {
14 this.context = context;
15 /**
16 * Index for bindings by tag names
17 */
18 this.bindingsIndexedByTag = new Map();
19 this.setupTagIndexForBindings();
20 }
21 /**
22 * Set up context/binding listeners and refresh index for bindings by tag
23 */
24 setupTagIndexForBindings() {
25 this.bindingEventListener = ({ binding, operation }) => {
26 if (operation === 'tag') {
27 this.updateTagIndexForBinding(binding);
28 }
29 };
30 this.tagIndexListener = event => {
31 const { binding, type } = event;
32 if (event.context !== this.context)
33 return;
34 if (type === 'bind') {
35 this.updateTagIndexForBinding(binding);
36 binding.on('changed', this.bindingEventListener);
37 }
38 else if (type === 'unbind') {
39 this.removeTagIndexForBinding(binding);
40 binding.removeListener('changed', this.bindingEventListener);
41 }
42 };
43 this.context.on('bind', this.tagIndexListener);
44 this.context.on('unbind', this.tagIndexListener);
45 }
46 /**
47 * Remove tag index for the given binding
48 * @param binding - Binding object
49 */
50 removeTagIndexForBinding(binding) {
51 for (const [, bindings] of this.bindingsIndexedByTag) {
52 bindings.delete(binding);
53 }
54 }
55 /**
56 * Update tag index for the given binding
57 * @param binding - Binding object
58 */
59 updateTagIndexForBinding(binding) {
60 this.removeTagIndexForBinding(binding);
61 for (const tag of binding.tagNames) {
62 let bindings = this.bindingsIndexedByTag.get(tag);
63 if (bindings == null) {
64 bindings = new Set();
65 this.bindingsIndexedByTag.set(tag, bindings);
66 }
67 bindings.add(binding);
68 }
69 }
70 /**
71 * Find bindings by tag leveraging indexes
72 * @param tag - Tag name pattern or name/value pairs
73 */
74 findByTagIndex(tag) {
75 let tagNames;
76 // A flag to control if a union of matched bindings should be created
77 let union = false;
78 if (tag instanceof RegExp) {
79 // For wildcard/regexp, a union of matched bindings is desired
80 union = true;
81 // Find all matching tag names
82 tagNames = [];
83 for (const t of this.bindingsIndexedByTag.keys()) {
84 if (tag.test(t)) {
85 tagNames.push(t);
86 }
87 }
88 }
89 else if (typeof tag === 'string') {
90 tagNames = [tag];
91 }
92 else {
93 tagNames = Object.keys(tag);
94 }
95 let filter;
96 let bindings;
97 for (const t of tagNames) {
98 const bindingsByTag = this.bindingsIndexedByTag.get(t);
99 if (bindingsByTag == null)
100 break; // One of the tags is not found
101 filter = filter !== null && filter !== void 0 ? filter : (0, binding_filter_1.filterByTag)(tag);
102 const matched = new Set(Array.from(bindingsByTag).filter(filter));
103 if (!union && matched.size === 0)
104 break; // One of the tag name/value is not found
105 if (bindings == null) {
106 // First set of bindings matching the tag
107 bindings = matched;
108 }
109 else {
110 if (union) {
111 matched.forEach(b => bindings === null || bindings === void 0 ? void 0 : bindings.add(b));
112 }
113 else {
114 // Now need to find intersected bindings against visited tags
115 const intersection = new Set();
116 bindings.forEach(b => {
117 if (matched.has(b)) {
118 intersection.add(b);
119 }
120 });
121 bindings = intersection;
122 }
123 if (!union && bindings.size === 0)
124 break;
125 }
126 }
127 return bindings == null ? [] : Array.from(bindings);
128 }
129 close() {
130 this.context.removeListener('bind', this.tagIndexListener);
131 this.context.removeListener('unbind', this.tagIndexListener);
132 }
133}
134exports.ContextTagIndexer = ContextTagIndexer;
135//# sourceMappingURL=context-tag-indexer.js.map
\No newline at end of file