@loopback/context 4.0.0-alpha.7 → 4.0.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.
Files changed (137) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +116 -0
  3. package/dist/binding-config.d.ts +40 -0
  4. package/dist/binding-config.js +33 -0
  5. package/dist/binding-config.js.map +1 -0
  6. package/dist/binding-decorator.d.ts +45 -0
  7. package/dist/binding-decorator.js +118 -0
  8. package/dist/binding-decorator.js.map +1 -0
  9. package/dist/binding-filter.d.ts +108 -0
  10. package/dist/binding-filter.js +162 -0
  11. package/dist/binding-filter.js.map +1 -0
  12. package/dist/binding-inspector.d.ts +150 -0
  13. package/dist/binding-inspector.js +249 -0
  14. package/dist/binding-inspector.js.map +1 -0
  15. package/dist/binding-key.d.ts +66 -0
  16. package/dist/binding-key.js +121 -0
  17. package/dist/binding-key.js.map +1 -0
  18. package/dist/binding-sorter.d.ts +71 -0
  19. package/dist/binding-sorter.js +89 -0
  20. package/dist/binding-sorter.js.map +1 -0
  21. package/dist/binding.d.ts +577 -0
  22. package/dist/binding.js +788 -0
  23. package/dist/binding.js.map +1 -0
  24. package/dist/context-event.d.ts +23 -0
  25. package/dist/context-event.js +7 -0
  26. package/dist/context-event.js.map +1 -0
  27. package/dist/context-observer.d.ts +36 -0
  28. package/dist/context-observer.js +7 -0
  29. package/dist/context-observer.js.map +1 -0
  30. package/dist/context-subscription.d.ts +147 -0
  31. package/dist/context-subscription.js +317 -0
  32. package/dist/context-subscription.js.map +1 -0
  33. package/dist/context-tag-indexer.d.ts +42 -0
  34. package/dist/context-tag-indexer.js +135 -0
  35. package/dist/context-tag-indexer.js.map +1 -0
  36. package/dist/context-view.d.ts +209 -0
  37. package/dist/context-view.js +240 -0
  38. package/dist/context-view.js.map +1 -0
  39. package/dist/context.d.ts +513 -0
  40. package/dist/context.js +717 -0
  41. package/dist/context.js.map +1 -0
  42. package/dist/index.d.ts +52 -0
  43. package/dist/index.js +60 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/inject-config.d.ts +67 -0
  46. package/dist/inject-config.js +181 -0
  47. package/dist/inject-config.js.map +1 -0
  48. package/dist/inject.d.ts +250 -0
  49. package/dist/inject.js +535 -0
  50. package/dist/inject.js.map +1 -0
  51. package/dist/interception-proxy.d.ts +76 -0
  52. package/dist/interception-proxy.js +67 -0
  53. package/dist/interception-proxy.js.map +1 -0
  54. package/dist/interceptor-chain.d.ts +121 -0
  55. package/dist/interceptor-chain.js +148 -0
  56. package/dist/interceptor-chain.js.map +1 -0
  57. package/dist/interceptor.d.ts +138 -0
  58. package/dist/interceptor.js +299 -0
  59. package/dist/interceptor.js.map +1 -0
  60. package/dist/invocation.d.ts +101 -0
  61. package/dist/invocation.js +163 -0
  62. package/dist/invocation.js.map +1 -0
  63. package/dist/json-types.d.ts +28 -0
  64. package/dist/json-types.js +7 -0
  65. package/dist/json-types.js.map +1 -0
  66. package/dist/keys.d.ts +65 -0
  67. package/dist/keys.js +74 -0
  68. package/dist/keys.js.map +1 -0
  69. package/dist/provider.d.ts +31 -0
  70. package/dist/provider.js +7 -0
  71. package/dist/provider.js.map +1 -0
  72. package/dist/resolution-session.d.ts +180 -0
  73. package/dist/resolution-session.js +274 -0
  74. package/dist/resolution-session.js.map +1 -0
  75. package/dist/resolver.d.ts +46 -0
  76. package/dist/resolver.js +203 -0
  77. package/dist/resolver.js.map +1 -0
  78. package/dist/unique-id.d.ts +14 -0
  79. package/dist/unique-id.js +26 -0
  80. package/dist/unique-id.js.map +1 -0
  81. package/dist/value-promise.d.ts +134 -0
  82. package/dist/value-promise.js +277 -0
  83. package/dist/value-promise.js.map +1 -0
  84. package/package.json +49 -35
  85. package/src/binding-config.ts +73 -0
  86. package/src/binding-decorator.ts +136 -0
  87. package/src/binding-filter.ts +250 -0
  88. package/src/binding-inspector.ts +371 -0
  89. package/src/binding-key.ts +136 -0
  90. package/src/binding-sorter.ts +124 -0
  91. package/src/binding.ts +1107 -0
  92. package/src/context-event.ts +30 -0
  93. package/src/context-observer.ts +50 -0
  94. package/src/context-subscription.ts +402 -0
  95. package/src/context-tag-indexer.ts +147 -0
  96. package/src/context-view.ts +440 -0
  97. package/src/context.ts +1079 -0
  98. package/src/index.ts +58 -0
  99. package/src/inject-config.ts +239 -0
  100. package/src/inject.ts +796 -0
  101. package/src/interception-proxy.ts +127 -0
  102. package/src/interceptor-chain.ts +268 -0
  103. package/src/interceptor.ts +430 -0
  104. package/src/invocation.ts +269 -0
  105. package/src/json-types.ts +35 -0
  106. package/src/keys.ts +85 -0
  107. package/src/provider.ts +37 -0
  108. package/src/resolution-session.ts +414 -0
  109. package/src/resolver.ts +282 -0
  110. package/src/unique-id.ts +24 -0
  111. package/src/value-promise.ts +318 -0
  112. package/index.d.ts +0 -6
  113. package/index.js +0 -9
  114. package/lib/binding.d.ts +0 -75
  115. package/lib/binding.js +0 -102
  116. package/lib/context.d.ts +0 -14
  117. package/lib/context.js +0 -96
  118. package/lib/index.d.ts +0 -5
  119. package/lib/index.js +0 -13
  120. package/lib/inject.d.ts +0 -47
  121. package/lib/inject.js +0 -73
  122. package/lib/isPromise.d.ts +0 -1
  123. package/lib/isPromise.js +0 -14
  124. package/lib/resolver.d.ts +0 -30
  125. package/lib/resolver.js +0 -128
  126. package/lib6/binding.d.ts +0 -75
  127. package/lib6/binding.js +0 -102
  128. package/lib6/context.d.ts +0 -14
  129. package/lib6/context.js +0 -96
  130. package/lib6/index.d.ts +0 -5
  131. package/lib6/index.js +0 -13
  132. package/lib6/inject.d.ts +0 -47
  133. package/lib6/inject.js +0 -73
  134. package/lib6/isPromise.d.ts +0 -1
  135. package/lib6/isPromise.js +0 -14
  136. package/lib6/resolver.d.ts +0 -30
  137. package/lib6/resolver.js +0 -128
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 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
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ContextTagIndexer = void 0;
8
+ const binding_filter_1 = require("./binding-filter");
9
+ /**
10
+ * Indexer for context bindings by tag
11
+ */
12
+ class 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
+ }
134
+ exports.ContextTagIndexer = ContextTagIndexer;
135
+ //# sourceMappingURL=context-tag-indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-tag-indexer.js","sourceRoot":"","sources":["../src/context-tag-indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { Binding } from './binding';
4
+ import { BindingFilter } from './binding-filter';
5
+ import { BindingComparator } from './binding-sorter';
6
+ import { Context } from './context';
7
+ import { ContextEvent } from './context-event';
8
+ import { ContextEventType, ContextObserver } from './context-observer';
9
+ import { Subscription } from './context-subscription';
10
+ import { Getter } from './inject';
11
+ import { ResolutionOptions, ResolutionOptionsOrSession, ResolutionSession } from './resolution-session';
12
+ import { ValueOrPromise } from './value-promise';
13
+ /**
14
+ * An event emitted by a `ContextView`
15
+ */
16
+ export interface ContextViewEvent<T> extends ContextEvent {
17
+ /**
18
+ * Optional cached value for an `unbind` event
19
+ */
20
+ cachedValue?: T;
21
+ }
22
+ /**
23
+ * `ContextView` provides a view for a given context chain to maintain a live
24
+ * list of matching bindings and their resolved values within the context
25
+ * hierarchy.
26
+ *
27
+ * This class is the key utility to implement dynamic extensions for extension
28
+ * points. For example, the RestServer can react to `controller` bindings even
29
+ * they are added/removed/updated after the application starts.
30
+ *
31
+ * `ContextView` is an event emitter that emits the following events:
32
+ * - 'bind': when a binding is added to the view
33
+ * - 'unbind': when a binding is removed from the view
34
+ * - 'close': when the view is closed (stopped observing context events)
35
+ * - 'refresh': when the view is refreshed as bindings are added/removed
36
+ * - 'resolve': when the cached values are resolved and updated
37
+ */
38
+ export declare class ContextView<T = unknown> extends EventEmitter implements ContextObserver {
39
+ readonly context: Context;
40
+ readonly filter: BindingFilter;
41
+ readonly comparator?: BindingComparator | undefined;
42
+ private resolutionOptions?;
43
+ /**
44
+ * An array of cached bindings that matches the binding filter
45
+ */
46
+ protected _cachedBindings: Readonly<Binding<T>>[] | undefined;
47
+ /**
48
+ * A map of cached values by binding
49
+ */
50
+ protected _cachedValues: Map<Readonly<Binding<T>>, T> | undefined;
51
+ private _subscription;
52
+ /**
53
+ * Create a context view
54
+ * @param context - Context object to watch
55
+ * @param filter - Binding filter to match bindings of interest
56
+ * @param comparator - Comparator to sort the matched bindings
57
+ */
58
+ constructor(context: Context, filter: BindingFilter, comparator?: BindingComparator | undefined, resolutionOptions?: Omit<ResolutionOptions, "session"> | undefined);
59
+ /**
60
+ * Update the cached values keyed by binding
61
+ * @param values - An array of resolved values
62
+ */
63
+ private updateCachedValues;
64
+ /**
65
+ * Get an array of cached values
66
+ */
67
+ private getCachedValues;
68
+ /**
69
+ * Start listening events from the context
70
+ */
71
+ open(): Subscription | undefined;
72
+ /**
73
+ * Stop listening events from the context
74
+ */
75
+ close(): void;
76
+ /**
77
+ * Get the list of matched bindings. If they are not cached, it tries to find
78
+ * them from the context.
79
+ */
80
+ get bindings(): Readonly<Binding<T>>[];
81
+ /**
82
+ * Find matching bindings and refresh the cache
83
+ */
84
+ protected findBindings(): Readonly<Binding<T>>[];
85
+ /**
86
+ * Listen on `bind` or `unbind` and invalidate the cache
87
+ */
88
+ observe(event: ContextEventType, binding: Readonly<Binding<unknown>>, context: Context): void;
89
+ /**
90
+ * Refresh the view by invalidating its cache
91
+ */
92
+ refresh(): void;
93
+ /**
94
+ * Resolve values for the matching bindings
95
+ * @param session - Resolution session
96
+ */
97
+ resolve(session?: ResolutionOptionsOrSession): ValueOrPromise<T[]>;
98
+ /**
99
+ * Get the list of resolved values. If they are not cached, it tries to find
100
+ * and resolve them.
101
+ */
102
+ values(session?: ResolutionOptionsOrSession): Promise<T[]>;
103
+ /**
104
+ * As a `Getter` function
105
+ */
106
+ asGetter(session?: ResolutionOptionsOrSession): Getter<T[]>;
107
+ /**
108
+ * Get the single value
109
+ */
110
+ singleValue(session?: ResolutionOptionsOrSession): Promise<T | undefined>;
111
+ /**
112
+ * The "bind" event is emitted when a new binding is added to the view.
113
+ *
114
+ * @param eventName The name of the event - always `bind`.
115
+ * @param listener The listener function to call when the event is emitted.
116
+ */
117
+ on(eventName: 'bind', listener: <V>(event: ContextViewEvent<V>) => void): this;
118
+ /**
119
+ * The "unbind" event is emitted a new binding is removed from the view.
120
+ *
121
+ * @param eventName The name of the event - always `unbind`.
122
+ * @param listener The listener function to call when the event is emitted.
123
+ */
124
+ on(eventName: 'unbind', listener: <V>(event: ContextViewEvent<V> & {
125
+ cachedValue?: V;
126
+ }) => void): this;
127
+ /**
128
+ * The "refresh" event is emitted when the view is refreshed as bindings are
129
+ * added/removed.
130
+ *
131
+ * @param eventName The name of the event - always `refresh`.
132
+ * @param listener The listener function to call when the event is emitted.
133
+ */
134
+ on(eventName: 'refresh', listener: () => void): this;
135
+ /**
136
+ * The "resolve" event is emitted when the cached values are resolved and
137
+ * updated.
138
+ *
139
+ * @param eventName The name of the event - always `refresh`.
140
+ * @param listener The listener function to call when the event is emitted.
141
+ */
142
+ on(eventName: 'refresh', listener: <V>(result: V[]) => void): this;
143
+ /**
144
+ * The "close" event is emitted when the view is closed (stopped observing
145
+ * context events)
146
+ *
147
+ * @param eventName The name of the event - always `close`.
148
+ * @param listener The listener function to call when the event is emitted.
149
+ */
150
+ on(eventName: 'close', listener: () => void): this;
151
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
152
+ /**
153
+ * The "bind" event is emitted when a new binding is added to the view.
154
+ *
155
+ * @param eventName The name of the event - always `bind`.
156
+ * @param listener The listener function to call when the event is emitted.
157
+ */
158
+ once(eventName: 'bind', listener: <V>(event: ContextViewEvent<V>) => void): this;
159
+ /**
160
+ * The "unbind" event is emitted a new binding is removed from the view.
161
+ *
162
+ * @param eventName The name of the event - always `unbind`.
163
+ * @param listener The listener function to call when the event is emitted.
164
+ */
165
+ once(eventName: 'unbind', listener: <V>(event: ContextViewEvent<V> & {
166
+ cachedValue?: V;
167
+ }) => void): this;
168
+ /**
169
+ * The "refresh" event is emitted when the view is refreshed as bindings are
170
+ * added/removed.
171
+ *
172
+ * @param eventName The name of the event - always `refresh`.
173
+ * @param listener The listener function to call when the event is emitted.
174
+ */
175
+ once(eventName: 'refresh', listener: () => void): this;
176
+ /**
177
+ * The "resolve" event is emitted when the cached values are resolved and
178
+ * updated.
179
+ *
180
+ * @param eventName The name of the event - always `refresh`.
181
+ * @param listener The listener function to call when the event is emitted.
182
+ */
183
+ once(eventName: 'refresh', listener: <V>(result: V[]) => void): this;
184
+ /**
185
+ * The "close" event is emitted when the view is closed (stopped observing
186
+ * context events)
187
+ *
188
+ * @param eventName The name of the event - always `close`.
189
+ * @param listener The listener function to call when the event is emitted.
190
+ */
191
+ once(eventName: 'close', listener: () => void): this;
192
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
193
+ }
194
+ /**
195
+ * Create a context view as a getter with the given filter
196
+ * @param ctx - Context object
197
+ * @param bindingFilter - A function to match bindings
198
+ * @param session - Resolution session
199
+ */
200
+ export declare function createViewGetter<T = unknown>(ctx: Context, bindingFilter: BindingFilter, session?: ResolutionSession): Getter<T[]>;
201
+ /**
202
+ * Create a context view as a getter with the given filter and sort matched
203
+ * bindings by the comparator.
204
+ * @param ctx - Context object
205
+ * @param bindingFilter - A function to match bindings
206
+ * @param bindingComparator - A function to compare two bindings
207
+ * @param session - Resolution session
208
+ */
209
+ export declare function createViewGetter<T = unknown>(ctx: Context, bindingFilter: BindingFilter, bindingComparator?: BindingComparator, session?: ResolutionOptionsOrSession): Getter<T[]>;
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2019,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
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createViewGetter = exports.ContextView = void 0;
8
+ const tslib_1 = require("tslib");
9
+ const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
10
+ const events_1 = require("events");
11
+ const util_1 = require("util");
12
+ const resolution_session_1 = require("./resolution-session");
13
+ const value_promise_1 = require("./value-promise");
14
+ const debug = (0, debug_1.default)('loopback:context:view');
15
+ const nextTick = (0, util_1.promisify)(process.nextTick);
16
+ /**
17
+ * `ContextView` provides a view for a given context chain to maintain a live
18
+ * list of matching bindings and their resolved values within the context
19
+ * hierarchy.
20
+ *
21
+ * This class is the key utility to implement dynamic extensions for extension
22
+ * points. For example, the RestServer can react to `controller` bindings even
23
+ * they are added/removed/updated after the application starts.
24
+ *
25
+ * `ContextView` is an event emitter that emits the following events:
26
+ * - 'bind': when a binding is added to the view
27
+ * - 'unbind': when a binding is removed from the view
28
+ * - 'close': when the view is closed (stopped observing context events)
29
+ * - 'refresh': when the view is refreshed as bindings are added/removed
30
+ * - 'resolve': when the cached values are resolved and updated
31
+ */
32
+ class ContextView extends events_1.EventEmitter {
33
+ /**
34
+ * Create a context view
35
+ * @param context - Context object to watch
36
+ * @param filter - Binding filter to match bindings of interest
37
+ * @param comparator - Comparator to sort the matched bindings
38
+ */
39
+ constructor(context, filter, comparator, resolutionOptions) {
40
+ super();
41
+ this.context = context;
42
+ this.filter = filter;
43
+ this.comparator = comparator;
44
+ this.resolutionOptions = resolutionOptions;
45
+ }
46
+ /**
47
+ * Update the cached values keyed by binding
48
+ * @param values - An array of resolved values
49
+ */
50
+ updateCachedValues(values) {
51
+ var _a;
52
+ if (this._cachedBindings == null)
53
+ return undefined;
54
+ this._cachedValues = new Map();
55
+ for (let i = 0; i < ((_a = this._cachedBindings) === null || _a === void 0 ? void 0 : _a.length); i++) {
56
+ this._cachedValues.set(this._cachedBindings[i], values[i]);
57
+ }
58
+ return this._cachedValues;
59
+ }
60
+ /**
61
+ * Get an array of cached values
62
+ */
63
+ getCachedValues() {
64
+ var _a, _b;
65
+ return Array.from((_b = (_a = this._cachedValues) === null || _a === void 0 ? void 0 : _a.values()) !== null && _b !== void 0 ? _b : []);
66
+ }
67
+ /**
68
+ * Start listening events from the context
69
+ */
70
+ open() {
71
+ debug('Start listening on changes of context %s', this.context.name);
72
+ if (this.context.isSubscribed(this)) {
73
+ return this._subscription;
74
+ }
75
+ this._subscription = this.context.subscribe(this);
76
+ return this._subscription;
77
+ }
78
+ /**
79
+ * Stop listening events from the context
80
+ */
81
+ close() {
82
+ debug('Stop listening on changes of context %s', this.context.name);
83
+ if (!this._subscription || this._subscription.closed)
84
+ return;
85
+ this._subscription.unsubscribe();
86
+ this._subscription = undefined;
87
+ this.emit('close');
88
+ }
89
+ /**
90
+ * Get the list of matched bindings. If they are not cached, it tries to find
91
+ * them from the context.
92
+ */
93
+ get bindings() {
94
+ debug('Reading bindings');
95
+ if (this._cachedBindings == null) {
96
+ this._cachedBindings = this.findBindings();
97
+ }
98
+ return this._cachedBindings;
99
+ }
100
+ /**
101
+ * Find matching bindings and refresh the cache
102
+ */
103
+ findBindings() {
104
+ debug('Finding matching bindings');
105
+ const found = this.context.find(this.filter);
106
+ if (typeof this.comparator === 'function') {
107
+ found.sort(this.comparator);
108
+ }
109
+ /* istanbul ignore if */
110
+ if (debug.enabled) {
111
+ debug('Bindings found', found.map(b => b.key));
112
+ }
113
+ return found;
114
+ }
115
+ /**
116
+ * Listen on `bind` or `unbind` and invalidate the cache
117
+ */
118
+ observe(event, binding, context) {
119
+ var _a;
120
+ const ctxEvent = {
121
+ context,
122
+ binding,
123
+ type: event,
124
+ };
125
+ debug('Observed event %s %s %s', event, binding.key, context.name);
126
+ if (event === 'unbind') {
127
+ const cachedValue = (_a = this._cachedValues) === null || _a === void 0 ? void 0 : _a.get(binding);
128
+ this.emit(event, { ...ctxEvent, cachedValue });
129
+ }
130
+ else {
131
+ this.emit(event, ctxEvent);
132
+ }
133
+ this.refresh();
134
+ }
135
+ /**
136
+ * Refresh the view by invalidating its cache
137
+ */
138
+ refresh() {
139
+ debug('Refreshing the view by invalidating cache');
140
+ this._cachedBindings = undefined;
141
+ this._cachedValues = undefined;
142
+ this.emit('refresh');
143
+ }
144
+ /**
145
+ * Resolve values for the matching bindings
146
+ * @param session - Resolution session
147
+ */
148
+ resolve(session) {
149
+ debug('Resolving values');
150
+ if (this._cachedValues != null) {
151
+ return this.getCachedValues();
152
+ }
153
+ const bindings = this.bindings;
154
+ let result = (0, value_promise_1.resolveList)(bindings, b => {
155
+ const options = {
156
+ ...this.resolutionOptions,
157
+ ...(0, resolution_session_1.asResolutionOptions)(session),
158
+ };
159
+ options.session = resolution_session_1.ResolutionSession.fork(options.session);
160
+ return b.getValue(this.context, options);
161
+ });
162
+ if ((0, value_promise_1.isPromiseLike)(result)) {
163
+ result = result.then(values => {
164
+ const list = values.filter(v => v != null);
165
+ this.updateCachedValues(list);
166
+ this.emit('resolve', list);
167
+ return list;
168
+ });
169
+ }
170
+ else {
171
+ // Clone the array so that the cached values won't be mutated
172
+ const list = (result = result.filter(v => v != null));
173
+ this.updateCachedValues(list);
174
+ this.emit('resolve', list);
175
+ }
176
+ return result;
177
+ }
178
+ /**
179
+ * Get the list of resolved values. If they are not cached, it tries to find
180
+ * and resolve them.
181
+ */
182
+ async values(session) {
183
+ debug('Reading values');
184
+ // Wait for the next tick so that context event notification can be emitted
185
+ await nextTick();
186
+ if (this._cachedValues == null) {
187
+ return this.resolve(session);
188
+ }
189
+ return this.getCachedValues();
190
+ }
191
+ /**
192
+ * As a `Getter` function
193
+ */
194
+ asGetter(session) {
195
+ return () => this.values(session);
196
+ }
197
+ /**
198
+ * Get the single value
199
+ */
200
+ async singleValue(session) {
201
+ const values = await this.values(session);
202
+ if (values.length === 0)
203
+ return undefined;
204
+ if (values.length === 1)
205
+ return values[0];
206
+ throw new Error('The ContextView has more than one value. Use values() to access them.');
207
+ }
208
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
209
+ on(event, listener) {
210
+ return super.on(event, listener);
211
+ }
212
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
213
+ once(event, listener) {
214
+ return super.once(event, listener);
215
+ }
216
+ }
217
+ exports.ContextView = ContextView;
218
+ /**
219
+ * Create a context view as a getter
220
+ * @param ctx - Context object
221
+ * @param bindingFilter - A function to match bindings
222
+ * @param bindingComparatorOrSession - A function to sort matched bindings or
223
+ * resolution session if the comparator is not needed
224
+ * @param session - Resolution session if the comparator is provided
225
+ */
226
+ function createViewGetter(ctx, bindingFilter, bindingComparatorOrSession, session) {
227
+ let bindingComparator = undefined;
228
+ if (typeof bindingComparatorOrSession === 'function') {
229
+ bindingComparator = bindingComparatorOrSession;
230
+ }
231
+ else if (bindingComparatorOrSession instanceof resolution_session_1.ResolutionSession) {
232
+ session = bindingComparatorOrSession;
233
+ }
234
+ const options = (0, resolution_session_1.asResolutionOptions)(session);
235
+ const view = new ContextView(ctx, bindingFilter, bindingComparator, options);
236
+ view.open();
237
+ return view.asGetter(options);
238
+ }
239
+ exports.createViewGetter = createViewGetter;
240
+ //# sourceMappingURL=context-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-view.js","sourceRoot":"","sources":["../src/context-view.ts"],"names":[],"mappings":"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"}