@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
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
+ }