@loopback/context 1.25.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -0
- package/dist/binding-filter.d.ts +20 -2
- package/dist/binding-filter.js +58 -9
- package/dist/binding-filter.js.map +1 -1
- package/dist/binding.d.ts +50 -2
- package/dist/binding.js +33 -1
- package/dist/binding.js.map +1 -1
- package/dist/context-event.d.ts +23 -0
- package/dist/context-event.js +7 -0
- package/dist/context-event.js.map +1 -0
- package/dist/context-observer.d.ts +1 -36
- package/dist/context-subscription.d.ts +147 -0
- package/dist/context-subscription.js +336 -0
- package/dist/context-subscription.js.map +1 -0
- package/dist/context-tag-indexer.d.ts +42 -0
- package/dist/context-tag-indexer.js +134 -0
- package/dist/context-tag-indexer.js.map +1 -0
- package/dist/context-view.d.ts +2 -1
- package/dist/context-view.js.map +1 -1
- package/dist/context.d.ts +44 -68
- package/dist/context.js +69 -249
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/inject.d.ts +9 -2
- package/dist/inject.js +60 -0
- package/dist/inject.js.map +1 -1
- package/dist/interceptor.js +4 -4
- package/dist/interceptor.js.map +1 -1
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +1 -5
- package/dist/invocation.js.map +1 -1
- package/dist/json-types.d.ts +28 -0
- package/dist/json-types.js +7 -0
- package/dist/json-types.js.map +1 -0
- package/dist/resolution-session.d.ts +2 -6
- package/dist/resolution-session.js +0 -4
- package/dist/resolution-session.js.map +1 -1
- package/dist/value-promise.d.ts +1 -3
- package/package.json +9 -9
- package/src/binding-filter.ts +83 -11
- package/src/binding.ts +79 -3
- package/src/context-event.ts +30 -0
- package/src/context-observer.ts +1 -38
- package/src/context-subscription.ts +403 -0
- package/src/context-tag-indexer.ts +149 -0
- package/src/context-view.ts +2 -5
- package/src/context.ts +104 -290
- package/src/index.ts +3 -0
- package/src/inject.ts +65 -0
- package/src/interceptor.ts +7 -6
- package/src/invocation.ts +1 -3
- package/src/json-types.ts +35 -0
- package/src/resolution-session.ts +4 -7
- package/src/value-promise.ts +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/context
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {Binding, BindingEventListener, BindingTag} from './binding';
|
|
7
|
+
import {BindingFilter, filterByTag} from './binding-filter';
|
|
8
|
+
import {Context} from './context';
|
|
9
|
+
import {ContextEventListener} from './context-event';
|
|
10
|
+
import {BoundValue} from './value-promise';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Indexer for context bindings by tag
|
|
14
|
+
*/
|
|
15
|
+
export class ContextTagIndexer {
|
|
16
|
+
/**
|
|
17
|
+
* Index for bindings by tag names
|
|
18
|
+
*/
|
|
19
|
+
readonly bindingsIndexedByTag: Map<
|
|
20
|
+
string,
|
|
21
|
+
Set<Readonly<Binding<unknown>>>
|
|
22
|
+
> = new Map();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A listener for binding events
|
|
26
|
+
*/
|
|
27
|
+
private bindingEventListener: BindingEventListener;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A listener to maintain tag index for bindings
|
|
31
|
+
*/
|
|
32
|
+
private tagIndexListener: ContextEventListener;
|
|
33
|
+
|
|
34
|
+
constructor(protected readonly context: Context) {
|
|
35
|
+
this.setupTagIndexForBindings();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Set up context/binding listeners and refresh index for bindings by tag
|
|
40
|
+
*/
|
|
41
|
+
private setupTagIndexForBindings() {
|
|
42
|
+
this.bindingEventListener = ({binding, operation}) => {
|
|
43
|
+
if (operation === 'tag') {
|
|
44
|
+
this.updateTagIndexForBinding(binding);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
this.tagIndexListener = event => {
|
|
48
|
+
const {binding, type} = event;
|
|
49
|
+
if (event.context !== this.context) return;
|
|
50
|
+
if (type === 'bind') {
|
|
51
|
+
this.updateTagIndexForBinding(binding);
|
|
52
|
+
binding.on('changed', this.bindingEventListener);
|
|
53
|
+
} else if (type === 'unbind') {
|
|
54
|
+
this.removeTagIndexForBinding(binding);
|
|
55
|
+
binding.removeListener('changed', this.bindingEventListener);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
this.context.on('bind', this.tagIndexListener);
|
|
59
|
+
this.context.on('unbind', this.tagIndexListener);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Remove tag index for the given binding
|
|
64
|
+
* @param binding - Binding object
|
|
65
|
+
*/
|
|
66
|
+
private removeTagIndexForBinding(binding: Readonly<Binding<unknown>>) {
|
|
67
|
+
for (const [, bindings] of this.bindingsIndexedByTag) {
|
|
68
|
+
bindings.delete(binding);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Update tag index for the given binding
|
|
74
|
+
* @param binding - Binding object
|
|
75
|
+
*/
|
|
76
|
+
private updateTagIndexForBinding(binding: Readonly<Binding<unknown>>) {
|
|
77
|
+
this.removeTagIndexForBinding(binding);
|
|
78
|
+
for (const tag of binding.tagNames) {
|
|
79
|
+
let bindings = this.bindingsIndexedByTag.get(tag);
|
|
80
|
+
if (bindings == null) {
|
|
81
|
+
bindings = new Set();
|
|
82
|
+
this.bindingsIndexedByTag.set(tag, bindings);
|
|
83
|
+
}
|
|
84
|
+
bindings.add(binding);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Find bindings by tag leveraging indexes
|
|
90
|
+
* @param tag - Tag name pattern or name/value pairs
|
|
91
|
+
*/
|
|
92
|
+
findByTagIndex<ValueType = BoundValue>(
|
|
93
|
+
tag: BindingTag | RegExp,
|
|
94
|
+
): Readonly<Binding<ValueType>>[] {
|
|
95
|
+
let tagNames: string[];
|
|
96
|
+
// A flag to control if a union of matched bindings should be created
|
|
97
|
+
let union = false;
|
|
98
|
+
if (tag instanceof RegExp) {
|
|
99
|
+
// For wildcard/regexp, a union of matched bindings is desired
|
|
100
|
+
union = true;
|
|
101
|
+
// Find all matching tag names
|
|
102
|
+
tagNames = [];
|
|
103
|
+
for (const t of this.bindingsIndexedByTag.keys()) {
|
|
104
|
+
if (tag.test(t)) {
|
|
105
|
+
tagNames.push(t);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} else if (typeof tag === 'string') {
|
|
109
|
+
tagNames = [tag];
|
|
110
|
+
} else {
|
|
111
|
+
tagNames = Object.keys(tag);
|
|
112
|
+
}
|
|
113
|
+
let filter: BindingFilter | undefined;
|
|
114
|
+
let bindings: Set<Readonly<Binding<ValueType>>> | undefined;
|
|
115
|
+
for (const t of tagNames) {
|
|
116
|
+
const bindingsByTag = this.bindingsIndexedByTag.get(t);
|
|
117
|
+
if (bindingsByTag == null) break; // One of the tags is not found
|
|
118
|
+
filter = filter ?? filterByTag(tag);
|
|
119
|
+
const matched = new Set(Array.from(bindingsByTag).filter(filter)) as Set<
|
|
120
|
+
Readonly<Binding<ValueType>>
|
|
121
|
+
>;
|
|
122
|
+
if (!union && matched.size === 0) break; // One of the tag name/value is not found
|
|
123
|
+
if (bindings == null) {
|
|
124
|
+
// First set of bindings matching the tag
|
|
125
|
+
bindings = matched;
|
|
126
|
+
} else {
|
|
127
|
+
if (union) {
|
|
128
|
+
matched.forEach(b => bindings?.add(b));
|
|
129
|
+
} else {
|
|
130
|
+
// Now need to find intersected bindings against visited tags
|
|
131
|
+
const intersection = new Set<Readonly<Binding<ValueType>>>();
|
|
132
|
+
bindings.forEach(b => {
|
|
133
|
+
if (matched.has(b)) {
|
|
134
|
+
intersection.add(b);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
bindings = intersection;
|
|
138
|
+
}
|
|
139
|
+
if (!union && bindings.size === 0) break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return bindings == null ? [] : Array.from(bindings);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
close() {
|
|
146
|
+
this.context.removeListener('bind', this.tagIndexListener);
|
|
147
|
+
this.context.removeListener('unbind', this.tagIndexListener);
|
|
148
|
+
}
|
|
149
|
+
}
|
package/src/context-view.ts
CHANGED
|
@@ -10,11 +10,8 @@ import {Binding} from './binding';
|
|
|
10
10
|
import {BindingFilter} from './binding-filter';
|
|
11
11
|
import {BindingComparator} from './binding-sorter';
|
|
12
12
|
import {Context} from './context';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
ContextObserver,
|
|
16
|
-
Subscription,
|
|
17
|
-
} from './context-observer';
|
|
13
|
+
import {ContextEventType, ContextObserver} from './context-observer';
|
|
14
|
+
import {Subscription} from './context-subscription';
|
|
18
15
|
import {Getter} from './inject';
|
|
19
16
|
import {ResolutionSession} from './resolution-session';
|
|
20
17
|
import {isPromiseLike, resolveList, ValueOrPromise} from './value-promise';
|