@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.
- package/LICENSE +25 -0
- package/README.md +116 -0
- package/dist/binding-config.d.ts +40 -0
- package/dist/binding-config.js +33 -0
- package/dist/binding-config.js.map +1 -0
- package/dist/binding-decorator.d.ts +45 -0
- package/dist/binding-decorator.js +118 -0
- package/dist/binding-decorator.js.map +1 -0
- package/dist/binding-filter.d.ts +108 -0
- package/dist/binding-filter.js +162 -0
- package/dist/binding-filter.js.map +1 -0
- package/dist/binding-inspector.d.ts +150 -0
- package/dist/binding-inspector.js +249 -0
- package/dist/binding-inspector.js.map +1 -0
- package/dist/binding-key.d.ts +66 -0
- package/dist/binding-key.js +121 -0
- package/dist/binding-key.js.map +1 -0
- package/dist/binding-sorter.d.ts +71 -0
- package/dist/binding-sorter.js +89 -0
- package/dist/binding-sorter.js.map +1 -0
- package/dist/binding.d.ts +577 -0
- package/dist/binding.js +788 -0
- package/dist/binding.js.map +1 -0
- 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 +36 -0
- package/dist/context-observer.js +7 -0
- package/dist/context-observer.js.map +1 -0
- package/dist/context-subscription.d.ts +147 -0
- package/dist/context-subscription.js +317 -0
- package/dist/context-subscription.js.map +1 -0
- package/dist/context-tag-indexer.d.ts +42 -0
- package/dist/context-tag-indexer.js +135 -0
- package/dist/context-tag-indexer.js.map +1 -0
- package/dist/context-view.d.ts +209 -0
- package/dist/context-view.js +240 -0
- package/dist/context-view.js.map +1 -0
- package/dist/context.d.ts +513 -0
- package/dist/context.js +717 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/inject-config.d.ts +67 -0
- package/dist/inject-config.js +181 -0
- package/dist/inject-config.js.map +1 -0
- package/dist/inject.d.ts +250 -0
- package/dist/inject.js +535 -0
- package/dist/inject.js.map +1 -0
- package/dist/interception-proxy.d.ts +76 -0
- package/dist/interception-proxy.js +67 -0
- package/dist/interception-proxy.js.map +1 -0
- package/dist/interceptor-chain.d.ts +121 -0
- package/dist/interceptor-chain.js +148 -0
- package/dist/interceptor-chain.js.map +1 -0
- package/dist/interceptor.d.ts +138 -0
- package/dist/interceptor.js +299 -0
- package/dist/interceptor.js.map +1 -0
- package/dist/invocation.d.ts +101 -0
- package/dist/invocation.js +163 -0
- package/dist/invocation.js.map +1 -0
- 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/keys.d.ts +65 -0
- package/dist/keys.js +74 -0
- package/dist/keys.js.map +1 -0
- package/dist/provider.d.ts +31 -0
- package/dist/provider.js +7 -0
- package/dist/provider.js.map +1 -0
- package/dist/resolution-session.d.ts +180 -0
- package/dist/resolution-session.js +274 -0
- package/dist/resolution-session.js.map +1 -0
- package/dist/resolver.d.ts +46 -0
- package/dist/resolver.js +203 -0
- package/dist/resolver.js.map +1 -0
- package/dist/unique-id.d.ts +14 -0
- package/dist/unique-id.js +26 -0
- package/dist/unique-id.js.map +1 -0
- package/dist/value-promise.d.ts +134 -0
- package/dist/value-promise.js +277 -0
- package/dist/value-promise.js.map +1 -0
- package/package.json +49 -35
- package/src/binding-config.ts +73 -0
- package/src/binding-decorator.ts +136 -0
- package/src/binding-filter.ts +250 -0
- package/src/binding-inspector.ts +371 -0
- package/src/binding-key.ts +136 -0
- package/src/binding-sorter.ts +124 -0
- package/src/binding.ts +1107 -0
- package/src/context-event.ts +30 -0
- package/src/context-observer.ts +50 -0
- package/src/context-subscription.ts +402 -0
- package/src/context-tag-indexer.ts +147 -0
- package/src/context-view.ts +440 -0
- package/src/context.ts +1079 -0
- package/src/index.ts +58 -0
- package/src/inject-config.ts +239 -0
- package/src/inject.ts +796 -0
- package/src/interception-proxy.ts +127 -0
- package/src/interceptor-chain.ts +268 -0
- package/src/interceptor.ts +430 -0
- package/src/invocation.ts +269 -0
- package/src/json-types.ts +35 -0
- package/src/keys.ts +85 -0
- package/src/provider.ts +37 -0
- package/src/resolution-session.ts +414 -0
- package/src/resolver.ts +282 -0
- package/src/unique-id.ts +24 -0
- package/src/value-promise.ts +318 -0
- package/index.d.ts +0 -6
- package/index.js +0 -9
- package/lib/binding.d.ts +0 -75
- package/lib/binding.js +0 -102
- package/lib/context.d.ts +0 -14
- package/lib/context.js +0 -96
- package/lib/index.d.ts +0 -5
- package/lib/index.js +0 -13
- package/lib/inject.d.ts +0 -47
- package/lib/inject.js +0 -73
- package/lib/isPromise.d.ts +0 -1
- package/lib/isPromise.js +0 -14
- package/lib/resolver.d.ts +0 -30
- package/lib/resolver.js +0 -128
- package/lib6/binding.d.ts +0 -75
- package/lib6/binding.js +0 -102
- package/lib6/context.d.ts +0 -14
- package/lib6/context.js +0 -96
- package/lib6/index.d.ts +0 -5
- package/lib6/index.js +0 -13
- package/lib6/inject.d.ts +0 -47
- package/lib6/inject.js +0 -73
- package/lib6/isPromise.d.ts +0 -1
- package/lib6/isPromise.js +0 -14
- package/lib6/resolver.d.ts +0 -30
- package/lib6/resolver.js +0 -128
package/src/index.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2017,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
|
+
/**
|
|
7
|
+
* Facilities to manage artifacts and their dependencies using {@link Context}
|
|
8
|
+
* in your Node.js applications. It can be used independent of the LoopBack
|
|
9
|
+
* framework.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* This package exposes TypeScript/JavaScript APIs and decorators to register
|
|
13
|
+
* artifacts, declare dependencies, and resolve artifacts by keys. The
|
|
14
|
+
* {@link Context} also serves as an IoC container to support dependency
|
|
15
|
+
* injection.
|
|
16
|
+
* Context and Binding are the two core concepts. A context is a registry of
|
|
17
|
+
* bindings and each binding represents a resolvable artifact by the key.
|
|
18
|
+
*
|
|
19
|
+
* - Bindings can be fulfilled by a constant, a factory function, a class, or a
|
|
20
|
+
* provider.
|
|
21
|
+
* - Bindings can be grouped by tags and searched by tags.
|
|
22
|
+
* - Binding scopes can be used to control how a resolved binding value is
|
|
23
|
+
* shared.
|
|
24
|
+
* - Bindings can be resolved synchronously or asynchronously.
|
|
25
|
+
* - Provide {@link inject | @inject} and other variants of decorators to
|
|
26
|
+
* express dependencies.
|
|
27
|
+
* - Support Constructor, property, and method injections.
|
|
28
|
+
* - Allow contexts to form a hierarchy to share or override bindings.
|
|
29
|
+
*
|
|
30
|
+
* @pakageDocumentation
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export * from '@loopback/metadata';
|
|
34
|
+
export * from './binding';
|
|
35
|
+
export * from './binding-config';
|
|
36
|
+
export * from './binding-decorator';
|
|
37
|
+
export * from './binding-filter';
|
|
38
|
+
export * from './binding-inspector';
|
|
39
|
+
export * from './binding-key';
|
|
40
|
+
export * from './binding-sorter';
|
|
41
|
+
export * from './context';
|
|
42
|
+
export * from './context-event';
|
|
43
|
+
export * from './context-observer';
|
|
44
|
+
export * from './context-subscription';
|
|
45
|
+
export * from './context-view';
|
|
46
|
+
export * from './inject';
|
|
47
|
+
export * from './inject-config';
|
|
48
|
+
export * from './interception-proxy';
|
|
49
|
+
export * from './interceptor';
|
|
50
|
+
export * from './interceptor-chain';
|
|
51
|
+
export * from './invocation';
|
|
52
|
+
export * from './json-types';
|
|
53
|
+
export * from './keys';
|
|
54
|
+
export * from './provider';
|
|
55
|
+
export * from './resolution-session';
|
|
56
|
+
export * from './resolver';
|
|
57
|
+
export * from './unique-id';
|
|
58
|
+
export * from './value-promise';
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2019. 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 {BindingFilter} from './binding-filter';
|
|
7
|
+
import {BindingAddress, BindingKey} from './binding-key';
|
|
8
|
+
import {Context} from './context';
|
|
9
|
+
import {ContextView} from './context-view';
|
|
10
|
+
import {assertTargetType, inject, Injection, InjectionMetadata} from './inject';
|
|
11
|
+
import {ResolutionSession} from './resolution-session';
|
|
12
|
+
import {getDeepProperty, ValueOrPromise} from './value-promise';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Injection metadata for `@config.*`
|
|
16
|
+
*/
|
|
17
|
+
export interface ConfigInjectionMetadata extends InjectionMetadata {
|
|
18
|
+
/**
|
|
19
|
+
* Property path to retrieve the configuration of the target binding, for
|
|
20
|
+
* example, `rest.host`.
|
|
21
|
+
*/
|
|
22
|
+
propertyPath?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Customize the target binding key from which the configuration is fetched.
|
|
25
|
+
* If not specified, the configuration of the current binding that contains
|
|
26
|
+
* the injection is used.
|
|
27
|
+
*/
|
|
28
|
+
fromBinding?: BindingAddress;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Inject a property from `config` of the current binding. If no corresponding
|
|
33
|
+
* config value is present, `undefined` will be injected as the configuration
|
|
34
|
+
* binding is resolved with `optional: true` by default.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* class Store {
|
|
39
|
+
* constructor(
|
|
40
|
+
* @config('x') public optionX: number,
|
|
41
|
+
* @config('y') public optionY: string,
|
|
42
|
+
* ) { }
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* ctx.configure('store1', { x: 1, y: 'a' });
|
|
46
|
+
* ctx.configure('store2', { x: 2, y: 'b' });
|
|
47
|
+
*
|
|
48
|
+
* ctx.bind('store1').toClass(Store);
|
|
49
|
+
* ctx.bind('store2').toClass(Store);
|
|
50
|
+
*
|
|
51
|
+
* const store1 = ctx.getSync('store1');
|
|
52
|
+
* expect(store1.optionX).to.eql(1);
|
|
53
|
+
* expect(store1.optionY).to.eql('a');
|
|
54
|
+
*
|
|
55
|
+
* const store2 = ctx.getSync('store2');
|
|
56
|
+
* expect(store2.optionX).to.eql(2);
|
|
57
|
+
* expect(store2.optionY).to.eql('b');
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @param propertyPath - Optional property path of the config. If is `''` or not
|
|
61
|
+
* present, the `config` object will be returned.
|
|
62
|
+
* @param metadata - Optional metadata to help the injection
|
|
63
|
+
*/
|
|
64
|
+
export function config(
|
|
65
|
+
propertyPath?: string | ConfigInjectionMetadata,
|
|
66
|
+
metadata?: ConfigInjectionMetadata,
|
|
67
|
+
) {
|
|
68
|
+
propertyPath = propertyPath ?? '';
|
|
69
|
+
if (typeof propertyPath === 'object') {
|
|
70
|
+
metadata = propertyPath;
|
|
71
|
+
propertyPath = '';
|
|
72
|
+
}
|
|
73
|
+
metadata = Object.assign(
|
|
74
|
+
{propertyPath, decorator: '@config', optional: true},
|
|
75
|
+
metadata,
|
|
76
|
+
);
|
|
77
|
+
return inject('', metadata, resolveFromConfig);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export namespace config {
|
|
81
|
+
/**
|
|
82
|
+
* `@inject.getter` decorator to inject a config getter function
|
|
83
|
+
* @param propertyPath - Optional property path of the config object
|
|
84
|
+
* @param metadata - Injection metadata
|
|
85
|
+
*/
|
|
86
|
+
export const getter = function injectConfigGetter(
|
|
87
|
+
propertyPath?: string | ConfigInjectionMetadata,
|
|
88
|
+
metadata?: ConfigInjectionMetadata,
|
|
89
|
+
) {
|
|
90
|
+
propertyPath = propertyPath ?? '';
|
|
91
|
+
if (typeof propertyPath === 'object') {
|
|
92
|
+
metadata = propertyPath;
|
|
93
|
+
propertyPath = '';
|
|
94
|
+
}
|
|
95
|
+
metadata = Object.assign(
|
|
96
|
+
{propertyPath, decorator: '@config.getter', optional: true},
|
|
97
|
+
metadata,
|
|
98
|
+
);
|
|
99
|
+
return inject('', metadata, resolveAsGetterFromConfig);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* `@inject.view` decorator to inject a config context view to allow dynamic
|
|
104
|
+
* changes in configuration
|
|
105
|
+
* @param propertyPath - Optional property path of the config object
|
|
106
|
+
* @param metadata - Injection metadata
|
|
107
|
+
*/
|
|
108
|
+
export const view = function injectConfigView(
|
|
109
|
+
propertyPath?: string | ConfigInjectionMetadata,
|
|
110
|
+
metadata?: ConfigInjectionMetadata,
|
|
111
|
+
) {
|
|
112
|
+
propertyPath = propertyPath ?? '';
|
|
113
|
+
if (typeof propertyPath === 'object') {
|
|
114
|
+
metadata = propertyPath;
|
|
115
|
+
propertyPath = '';
|
|
116
|
+
}
|
|
117
|
+
metadata = Object.assign(
|
|
118
|
+
{propertyPath, decorator: '@config.view', optional: true},
|
|
119
|
+
metadata,
|
|
120
|
+
);
|
|
121
|
+
return inject('', metadata, resolveAsViewFromConfig);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get the key for the current binding on which dependency injection is
|
|
127
|
+
* performed
|
|
128
|
+
* @param session - Resolution session
|
|
129
|
+
*/
|
|
130
|
+
function getCurrentBindingKey(session: ResolutionSession) {
|
|
131
|
+
// The current binding is not set if `instantiateClass` is invoked directly
|
|
132
|
+
return session.currentBinding?.key;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get the target binding key from which the configuration should be resolved
|
|
137
|
+
* @param injection - Injection
|
|
138
|
+
* @param session - Resolution session
|
|
139
|
+
*/
|
|
140
|
+
function getTargetBindingKey(injection: Injection, session: ResolutionSession) {
|
|
141
|
+
return injection.metadata.fromBinding || getCurrentBindingKey(session);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Resolver for `@config`
|
|
146
|
+
* @param ctx - Context object
|
|
147
|
+
* @param injection - Injection metadata
|
|
148
|
+
* @param session - Resolution session
|
|
149
|
+
*/
|
|
150
|
+
function resolveFromConfig(
|
|
151
|
+
ctx: Context,
|
|
152
|
+
injection: Injection,
|
|
153
|
+
session: ResolutionSession,
|
|
154
|
+
): ValueOrPromise<unknown> {
|
|
155
|
+
const bindingKey = getTargetBindingKey(injection, session);
|
|
156
|
+
// Return `undefined` if no current binding is present
|
|
157
|
+
if (!bindingKey) return undefined;
|
|
158
|
+
const meta = injection.metadata;
|
|
159
|
+
return ctx.getConfigAsValueOrPromise(bindingKey, meta.propertyPath, {
|
|
160
|
+
session,
|
|
161
|
+
optional: meta.optional,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Resolver from `@config.getter`
|
|
167
|
+
* @param ctx - Context object
|
|
168
|
+
* @param injection - Injection metadata
|
|
169
|
+
* @param session - Resolution session
|
|
170
|
+
*/
|
|
171
|
+
function resolveAsGetterFromConfig(
|
|
172
|
+
ctx: Context,
|
|
173
|
+
injection: Injection,
|
|
174
|
+
session: ResolutionSession,
|
|
175
|
+
) {
|
|
176
|
+
assertTargetType(injection, Function, 'Getter function');
|
|
177
|
+
const bindingKey = getTargetBindingKey(injection, session);
|
|
178
|
+
// We need to clone the session for the getter as it will be resolved later
|
|
179
|
+
const forkedSession = ResolutionSession.fork(session);
|
|
180
|
+
const meta = injection.metadata;
|
|
181
|
+
return async function getter() {
|
|
182
|
+
// Return `undefined` if no current binding is present
|
|
183
|
+
if (!bindingKey) return undefined;
|
|
184
|
+
return ctx.getConfigAsValueOrPromise(bindingKey, meta.propertyPath, {
|
|
185
|
+
session: forkedSession,
|
|
186
|
+
optional: meta.optional,
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Resolver for `@config.view`
|
|
193
|
+
* @param ctx - Context object
|
|
194
|
+
* @param injection - Injection metadata
|
|
195
|
+
* @param session - Resolution session
|
|
196
|
+
*/
|
|
197
|
+
function resolveAsViewFromConfig(
|
|
198
|
+
ctx: Context,
|
|
199
|
+
injection: Injection,
|
|
200
|
+
session: ResolutionSession,
|
|
201
|
+
) {
|
|
202
|
+
assertTargetType(injection, ContextView);
|
|
203
|
+
const bindingKey = getTargetBindingKey(injection, session);
|
|
204
|
+
// Return `undefined` if no current binding is present
|
|
205
|
+
if (!bindingKey) return undefined;
|
|
206
|
+
const view = new ConfigView(
|
|
207
|
+
ctx,
|
|
208
|
+
binding =>
|
|
209
|
+
binding.key === BindingKey.buildKeyForConfig(bindingKey).toString(),
|
|
210
|
+
injection.metadata.propertyPath,
|
|
211
|
+
);
|
|
212
|
+
view.open();
|
|
213
|
+
return view;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* A subclass of `ContextView` to handle dynamic configuration as its
|
|
218
|
+
* `values()` honors the `propertyPath`.
|
|
219
|
+
*/
|
|
220
|
+
class ConfigView extends ContextView {
|
|
221
|
+
constructor(
|
|
222
|
+
ctx: Context,
|
|
223
|
+
filter: BindingFilter,
|
|
224
|
+
private propertyPath?: string,
|
|
225
|
+
) {
|
|
226
|
+
super(ctx, filter);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get values for the configuration with a property path
|
|
231
|
+
* @param session - Resolution session
|
|
232
|
+
*/
|
|
233
|
+
async values(session?: ResolutionSession) {
|
|
234
|
+
const configValues = await super.values(session);
|
|
235
|
+
const propertyPath = this.propertyPath;
|
|
236
|
+
if (!propertyPath) return configValues;
|
|
237
|
+
return configValues.map(v => getDeepProperty(v, propertyPath));
|
|
238
|
+
}
|
|
239
|
+
}
|