@loopback/context 3.8.1 → 3.9.2

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 (44) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/binding-decorator.js +1 -1
  3. package/dist/binding-inspector.js +2 -2
  4. package/dist/binding-inspector.js.map +1 -1
  5. package/dist/binding-key.d.ts +5 -1
  6. package/dist/binding-key.js +104 -103
  7. package/dist/binding-key.js.map +1 -1
  8. package/dist/binding.d.ts +20 -2
  9. package/dist/binding.js +26 -16
  10. package/dist/binding.js.map +1 -1
  11. package/dist/context-view.d.ts +82 -0
  12. package/dist/context-view.js +8 -0
  13. package/dist/context-view.js.map +1 -1
  14. package/dist/context.d.ts +21 -3
  15. package/dist/context.js +29 -16
  16. package/dist/context.js.map +1 -1
  17. package/dist/inject-config.js +2 -1
  18. package/dist/inject-config.js.map +1 -1
  19. package/dist/inject.js +3 -0
  20. package/dist/inject.js.map +1 -1
  21. package/dist/resolution-session.d.ts +15 -0
  22. package/dist/resolution-session.js +40 -1
  23. package/dist/resolution-session.js.map +1 -1
  24. package/dist/resolver.js +6 -13
  25. package/dist/resolver.js.map +1 -1
  26. package/dist/unique-id.d.ts +14 -0
  27. package/dist/unique-id.js +26 -0
  28. package/dist/unique-id.js.map +1 -0
  29. package/dist/value-promise.d.ts +21 -0
  30. package/dist/value-promise.js +45 -16
  31. package/dist/value-promise.js.map +1 -1
  32. package/package.json +16 -12
  33. package/src/binding-decorator.ts +1 -1
  34. package/src/binding-inspector.ts +2 -2
  35. package/src/binding-key.ts +7 -3
  36. package/src/binding.ts +61 -19
  37. package/src/context-view.ts +120 -0
  38. package/src/context.ts +63 -19
  39. package/src/inject-config.ts +1 -1
  40. package/src/inject.ts +5 -0
  41. package/src/resolution-session.ts +48 -0
  42. package/src/resolver.ts +14 -17
  43. package/src/unique-id.ts +24 -0
  44. package/src/value-promise.ts +50 -18
@@ -4,7 +4,7 @@
4
4
  // This file is licensed under the MIT License.
5
5
  // License text available at https://opensource.org/licenses/MIT
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.UUID_PATTERN = exports.uuid = exports.transformValueOrPromise = exports.resolveUntil = exports.tryWithFinally = exports.resolveList = exports.resolveMap = exports.getDeepProperty = exports.isPromiseLike = void 0;
7
+ exports.UUID_PATTERN = exports.uuid = exports.transformValueOrPromise = exports.resolveUntil = exports.tryCatchFinally = exports.tryWithFinally = exports.resolveList = exports.resolveMap = exports.getDeepProperty = exports.isPromiseLike = void 0;
8
8
  /**
9
9
  * This module contains types for values and/or promises as well as a set of
10
10
  * utility methods to handle values and/or promises.
@@ -156,34 +156,58 @@ exports.resolveList = resolveList;
156
156
  * @param action - A function that returns a promise or a value
157
157
  * @param finalAction - A function to be called once the action
158
158
  * is fulfilled or rejected (synchronously or asynchronously)
159
+ *
160
+ * @typeParam T - Type for the return value
159
161
  */
160
162
  function tryWithFinally(action, finalAction) {
163
+ return tryCatchFinally(action, undefined, finalAction);
164
+ }
165
+ exports.tryWithFinally = tryWithFinally;
166
+ /**
167
+ * Try to run an action that returns a promise or a value with error and final
168
+ * actions to mimic `try {} catch(err) {} finally {}` for a value or promise.
169
+ *
170
+ * @param action - A function that returns a promise or a value
171
+ * @param errorAction - A function to be called once the action
172
+ * is rejected (synchronously or asynchronously). It must either return a new
173
+ * value or throw an error.
174
+ * @param finalAction - A function to be called once the action
175
+ * is fulfilled or rejected (synchronously or asynchronously)
176
+ *
177
+ * @typeParam T - Type for the return value
178
+ */
179
+ function tryCatchFinally(action, errorAction = err => {
180
+ throw err;
181
+ }, finalAction = () => { }) {
161
182
  let result;
162
183
  try {
163
184
  result = action();
164
185
  }
165
186
  catch (err) {
166
- finalAction();
167
- throw err;
187
+ result = reject(err);
168
188
  }
169
189
  if (isPromiseLike(result)) {
170
- // Once (promise.finally)[https://github.com/tc39/proposal-promise-finally
171
- // is supported, the following can be simplifed as
172
- // `result = result.finally(finalAction);`
173
- result = result.then(val => {
174
- finalAction();
175
- return val;
176
- }, err => {
190
+ return result.then(resolve, reject);
191
+ }
192
+ return resolve(result);
193
+ function resolve(value) {
194
+ try {
195
+ return value;
196
+ }
197
+ finally {
177
198
  finalAction();
178
- throw err;
179
- });
199
+ }
180
200
  }
181
- else {
182
- finalAction();
201
+ function reject(err) {
202
+ try {
203
+ return errorAction(err);
204
+ }
205
+ finally {
206
+ finalAction();
207
+ }
183
208
  }
184
- return result;
185
209
  }
186
- exports.tryWithFinally = tryWithFinally;
210
+ exports.tryCatchFinally = tryCatchFinally;
187
211
  /**
188
212
  * Resolve an iterator of source values into a result until the evaluator
189
213
  * returns `true`
@@ -236,6 +260,9 @@ function transformValueOrPromise(valueOrPromise, transformer) {
236
260
  exports.transformValueOrPromise = transformValueOrPromise;
237
261
  /**
238
262
  * A utility to generate uuid v4
263
+ *
264
+ * @deprecated Use [uuid](https://www.npmjs.com/package/uuid) or
265
+ * [hyperid](https://www.npmjs.com/package/hyperid) instead.
239
266
  */
240
267
  function uuid() {
241
268
  return uuid_1.v4();
@@ -243,6 +270,8 @@ function uuid() {
243
270
  exports.uuid = uuid;
244
271
  /**
245
272
  * A regular expression for testing uuid v4 PATTERN
273
+ * @deprecated This pattern is an internal helper used by unit-tests, we are no
274
+ * longer using it.
246
275
  */
247
276
  exports.UUID_PATTERN = /[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/i;
248
277
  //# sourceMappingURL=value-promise.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"value-promise.js","sourceRoot":"","sources":["../src/value-promise.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,iCAAiC;AACjC,+CAA+C;AAC/C,gEAAgE;;;AAEhE;;;GAGG;AAEH,+BAAkC;AAwBlC;;;;;GAKG;AACH,SAAgB,aAAa,CAC3B,KAAqC;IAErC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAC3E,OAAO,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAC9D,CAAC;AAND,sCAMC;AAED;;;;GAIG;AACH,SAAgB,eAAe,CAC7B,KAAS,EACT,IAAY;IAEZ,IAAI,MAAM,GAAe,KAAK,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE;QACrB,IAAI,MAAM,IAAI,IAAI,EAAE;YAClB,OAAO,SAAS,CAAC;SAClB;QACD,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;KACpB;IACD,OAAY,MAAM,CAAC;AACrB,CAAC;AAbD,0CAaC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,UAAU,CACxB,GAAiB,EACjB,QAAuE;IAEvE,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,cAAc,GAAoC,SAAS,CAAC;IAEhE,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,GAAM,EAAE,EAAE;QACzC,IAAI,GAAG,KAAK,SAAS,EAAE;YACrB,qEAAqE;YACrE,4BAA4B;YAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;SACnB;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE;QACrB,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE;YACjC,IAAI,CAAC,cAAc;gBAAE,cAAc,GAAG,EAAE,CAAC;YACzC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACvD;aAAM;YACL,IAAI,cAAc,KAAK,SAAS,EAAE;gBAChC,qEAAqE;gBACrE,4BAA4B;gBAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC;aAC9B;SACF;KACF;IAED,IAAI,cAAc,EAAE;QAClB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;KACvD;SAAM;QACL,OAAO,MAAM,CAAC;KACf;AACH,CAAC;AAlCD,gCAkCC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,WAAW,CACzB,IAAS,EACT,QAAiE;IAEjE,MAAM,MAAM,GAAQ,IAAI,KAAK,CAAI,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,cAAc,GAAoC,SAAS,CAAC;IAEhE,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,GAAM,EAAE,EAAE;QAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;IACtB,CAAC,CAAC;IAEF,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE;QACvC,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QACpD,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE;YACjC,IAAI,CAAC,cAAc;gBAAE,cAAc,GAAG,EAAE,CAAC;YACzC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SACtD;aAAM;YACL,MAAM,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC;SAC7B;KACF;IAED,IAAI,cAAc,EAAE;QAClB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;KACvD;SAAM;QACL,OAAO,MAAM,CAAC;KACf;AACH,CAAC;AA1BD,kCA0BC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAC5B,MAA+B,EAC/B,WAAuB;IAEvB,IAAI,MAAyB,CAAC;IAC9B,IAAI;QACF,MAAM,GAAG,MAAM,EAAE,CAAC;KACnB;IAAC,OAAO,GAAG,EAAE;QACZ,WAAW,EAAE,CAAC;QACd,MAAM,GAAG,CAAC;KACX;IACD,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE;QACzB,0EAA0E;QAC1E,kDAAkD;QAClD,0CAA0C;QAC1C,MAAM,GAAG,MAAM,CAAC,IAAI,CAClB,GAAG,CAAC,EAAE;YACJ,WAAW,EAAE,CAAC;YACd,OAAO,GAAG,CAAC;QACb,CAAC,EACD,GAAG,CAAC,EAAE;YACJ,WAAW,EAAE,CAAC;YACd,MAAM,GAAG,CAAC;QACZ,CAAC,CACF,CAAC;KACH;SAAM;QACL,WAAW,EAAE,CAAC;KACf;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AA7BD,wCA6BC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,MAAmB,EACnB,QAAyD,EACzD,SAA8D;IAE9D,sEAAsE;IACtE,iDAAiD;IACjD,OAAO,IAAI,EAAE;QACX,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC,CAAC,sBAAsB;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7B,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE;YACjC,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAC7B,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE;oBAC3B,OAAO,CAAC,CAAC;iBACV;qBAAM;oBACL,OAAO,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;iBAClD;YACH,CAAC,CAAC,CAAC;SACJ;aAAM;YACL,IAAI,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE;gBACxC,OAAO,cAAc,CAAC;aACvB;YACD,+BAA+B;SAChC;KACF;AACH,CAAC;AA3BD,oCA2BC;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CACrC,cAAiC,EACjC,WAA0C;IAE1C,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE;QACjC,OAAO,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;KACzC;SAAM;QACL,OAAO,WAAW,CAAC,cAAc,CAAC,CAAC;KACpC;AACH,CAAC;AATD,0DASC;AAED;;GAEG;AACH,SAAgB,IAAI;IAClB,OAAO,SAAM,EAAE,CAAC;AAClB,CAAC;AAFD,oBAEC;AAED;;GAEG;AACU,QAAA,YAAY,GAAG,wEAAwE,CAAC"}
1
+ {"version":3,"file":"value-promise.js","sourceRoot":"","sources":["../src/value-promise.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@loopback/context",
3
- "version": "3.8.1",
4
- "description": "LoopBack's container for Inversion of Control",
3
+ "version": "3.9.2",
4
+ "description": "Facilities to manage artifacts and their dependencies in your Node.js applications. The module exposes TypeScript/JavaScript APIs and decorators to register artifacts, declare dependencies, and resolve artifacts by keys. It also serves as an IoC container to support dependency injection",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "engines": {
8
- "node": ">=10"
8
+ "node": ">=10.16"
9
9
  },
10
10
  "scripts": {
11
11
  "acceptance": "lb-mocha \"dist/__tests__/acceptance/**/*.js\"",
@@ -19,20 +19,24 @@
19
19
  "author": "IBM Corp.",
20
20
  "copyright.owner": "IBM Corp.",
21
21
  "license": "MIT",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
22
25
  "dependencies": {
23
- "@loopback/metadata": "^2.1.5",
26
+ "@loopback/metadata": "^2.2.2",
24
27
  "@types/debug": "^4.1.5",
25
28
  "debug": "^4.1.1",
26
- "p-event": "^4.1.0",
29
+ "hyperid": "^2.0.5",
30
+ "p-event": "^4.2.0",
27
31
  "tslib": "^2.0.0",
28
- "uuid": "^8.0.0"
32
+ "uuid": "^8.2.0"
29
33
  },
30
34
  "devDependencies": {
31
- "@loopback/build": "^5.4.1",
32
- "@loopback/eslint-config": "^7.0.1",
33
- "@loopback/testlab": "^3.1.5",
34
- "@types/bluebird": "^3.5.31",
35
- "@types/node": "^10.17.24",
35
+ "@loopback/build": "^6.1.0",
36
+ "@loopback/eslint-config": "^8.0.3",
37
+ "@loopback/testlab": "^3.2.0",
38
+ "@types/bluebird": "^3.5.32",
39
+ "@types/node": "^10.17.26",
36
40
  "@types/uuid": "^8.0.0",
37
41
  "bluebird": "^3.7.2"
38
42
  },
@@ -56,5 +60,5 @@
56
60
  "url": "https://github.com/strongloop/loopback-next.git",
57
61
  "directory": "packages/context"
58
62
  },
59
- "gitHead": "62aea854bf85c5a5995b59e6908fe5409f7eea96"
63
+ "gitHead": "b89db3d3b8be6a36e63e91c2331d217fda7538de"
60
64
  }
@@ -1,4 +1,4 @@
1
- // Copyright IBM Corp. 2018,2019. All Rights Reserved.
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
2
  // Node module: @loopback/context
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
@@ -1,4 +1,4 @@
1
- // Copyright IBM Corp. 2018,2019. All Rights Reserved.
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
2
  // Node module: @loopback/context
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
@@ -178,7 +178,7 @@ export function bindingTemplateFor<T>(
178
178
  for (const t of templateFunctions) {
179
179
  binding.apply(t);
180
180
  }
181
- if (spec && spec.target !== cls) {
181
+ if (spec?.target !== cls) {
182
182
  // Remove name/key tags inherited from base classes
183
183
  binding.apply(removeNameAndKeyTags);
184
184
  }
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {uuid} from './value-promise';
6
+ import {generateUniqueId} from './unique-id';
7
7
 
8
8
  export type BindingAddress<T = unknown> = string | BindingKey<T>;
9
9
 
@@ -123,12 +123,16 @@ export class BindingKey<ValueType> {
123
123
  }
124
124
 
125
125
  /**
126
- * Generate a unique binding key with `uuid`
126
+ * Generate a universally unique binding key.
127
+ *
128
+ * Please note the format of they generated key is not specified, you must
129
+ * not rely on any specific formatting (e.g. UUID style).
130
+ *
127
131
  * @param namespace - Namespace for the binding
128
132
  */
129
133
  static generate<T>(namespace = ''): BindingKey<T> {
130
134
  const prefix = namespace ? `${namespace}.` : '';
131
- const name = uuid();
135
+ const name = generateUniqueId();
132
136
  return BindingKey.create(`${prefix}${name}`);
133
137
  }
134
138
  }
package/src/binding.ts CHANGED
@@ -16,6 +16,7 @@ import {Provider} from './provider';
16
16
  import {
17
17
  asResolutionOptions,
18
18
  ResolutionContext,
19
+ ResolutionError,
19
20
  ResolutionOptions,
20
21
  ResolutionOptionsOrSession,
21
22
  ResolutionSession,
@@ -201,7 +202,7 @@ export type BindingEvent = {
201
202
  /**
202
203
  * Event type
203
204
  */
204
- type: string;
205
+ type: 'changed' | string;
205
206
  /**
206
207
  * Source binding that emits the event
207
208
  */
@@ -209,7 +210,7 @@ export type BindingEvent = {
209
210
  /**
210
211
  * Operation that triggers the event
211
212
  */
212
- operation: string;
213
+ operation: 'tag' | 'scope' | 'value' | string;
213
214
  };
214
215
 
215
216
  /**
@@ -309,7 +310,7 @@ export class Binding<T = BoundValue> extends EventEmitter {
309
310
  return this._source?.type;
310
311
  }
311
312
 
312
- private _cache: WeakMap<Context, T>;
313
+ private _cache: WeakMap<Context, ValueOrPromise<T>>;
313
314
  private _getValue?: ValueFactory<T>;
314
315
 
315
316
  /**
@@ -358,18 +359,16 @@ export class Binding<T = BoundValue> extends EventEmitter {
358
359
  result: ValueOrPromise<T>,
359
360
  ): ValueOrPromise<T> {
360
361
  // Initialize the cache as a weakmap keyed by context
361
- if (!this._cache) this._cache = new WeakMap<Context, T>();
362
- return transformValueOrPromise(result, val => {
363
- if (this.scope === BindingScope.SINGLETON) {
364
- // Cache the value
365
- this._cache.set(ctx.getOwnerContext(this.key)!, val);
366
- } else if (this.scope === BindingScope.CONTEXT) {
367
- // Cache the value at the current context
368
- this._cache.set(ctx, val);
369
- }
370
- // Do not cache for `TRANSIENT`
371
- return val;
372
- });
362
+ if (!this._cache) this._cache = new WeakMap<Context, ValueOrPromise<T>>();
363
+ if (this.scope === BindingScope.SINGLETON) {
364
+ // Cache the value
365
+ this._cache.set(ctx.getOwnerContext(this.key)!, result);
366
+ } else if (this.scope === BindingScope.CONTEXT) {
367
+ // Cache the value at the current context
368
+ this._cache.set(ctx, result);
369
+ }
370
+ // Do not cache for `TRANSIENT`
371
+ return result;
373
372
  }
374
373
 
375
374
  /**
@@ -465,15 +464,19 @@ export class Binding<T = BoundValue> extends EventEmitter {
465
464
  }
466
465
  }
467
466
  const options = asResolutionOptions(optionsOrSession);
467
+ const resolutionCtx = {
468
+ context: ctx,
469
+ binding: this,
470
+ options,
471
+ };
468
472
  if (typeof this._getValue === 'function') {
469
473
  const result = ResolutionSession.runWithBinding(
470
474
  s => {
471
- const optionsWithSession = Object.assign({}, options, {session: s});
475
+ const optionsWithSession = {...options, session: s};
472
476
  // We already test `this._getValue` is a function. It's safe to assert
473
477
  // that `this._getValue` is not undefined.
474
478
  return this._getValue!({
475
- context: ctx,
476
- binding: this,
479
+ ...resolutionCtx,
477
480
  options: optionsWithSession,
478
481
  });
479
482
  },
@@ -485,7 +488,10 @@ export class Binding<T = BoundValue> extends EventEmitter {
485
488
  // `@inject.binding` adds a binding without _getValue
486
489
  if (options.optional) return undefined;
487
490
  return Promise.reject(
488
- new Error(`No value was configured for binding ${this.key}.`),
491
+ new ResolutionError(
492
+ `No value was configured for binding ${this.key}.`,
493
+ resolutionCtx,
494
+ ),
489
495
  );
490
496
  }
491
497
 
@@ -871,6 +877,42 @@ export class Binding<T = BoundValue> extends EventEmitter {
871
877
  [ContextTags.CONFIGURATION_FOR]: key.toString(),
872
878
  });
873
879
  }
880
+
881
+ /**
882
+ * The "changed" event is emitted by methods such as `tag`, `inScope`, `to`,
883
+ * and `toClass`.
884
+ *
885
+ * @param eventName The name of the event - always `changed`.
886
+ * @param listener The listener function to call when the event is emitted.
887
+ */
888
+ on(eventName: 'changed', listener: BindingEventListener): this;
889
+
890
+ // The generic variant inherited from EventEmitter
891
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
892
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
893
+
894
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
895
+ on(event: string | symbol, listener: (...args: any[]) => void): this {
896
+ return super.on(event, listener);
897
+ }
898
+
899
+ /**
900
+ * The "changed" event is emitted by methods such as `tag`, `inScope`, `to`,
901
+ * and `toClass`.
902
+ *
903
+ * @param eventName The name of the event - always `changed`.
904
+ * @param listener The listener function to call when the event is emitted.
905
+ */
906
+ once(eventName: 'changed', listener: BindingEventListener): this;
907
+
908
+ // The generic variant inherited from EventEmitter
909
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
910
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
911
+
912
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
913
+ once(event: string | symbol, listener: (...args: any[]) => void): this {
914
+ return super.once(event, listener);
915
+ }
874
916
  }
875
917
 
876
918
  /**
@@ -241,6 +241,126 @@ export class ContextView<T = unknown> extends EventEmitter
241
241
  'The ContextView has more than one value. Use values() to access them.',
242
242
  );
243
243
  }
244
+
245
+ /**
246
+ * The "bind" event is emitted when a new binding is added to the view.
247
+ *
248
+ * @param eventName The name of the event - always `bind`.
249
+ * @param listener The listener function to call when the event is emitted.
250
+ */
251
+ on(
252
+ eventName: 'bind',
253
+ listener: <T>(event: ContextViewEvent<T>) => void,
254
+ ): this;
255
+
256
+ /**
257
+ * The "unbind" event is emitted a new binding is removed from the view.
258
+ *
259
+ * @param eventName The name of the event - always `unbind`.
260
+ * @param listener The listener function to call when the event is emitted.
261
+ */
262
+ on(
263
+ eventName: 'unbind',
264
+ listener: <T>(event: ContextViewEvent<T> & {cachedValue?: T}) => void,
265
+ ): this;
266
+
267
+ /**
268
+ * The "refresh" event is emitted when the view is refreshed as bindings are
269
+ * added/removed.
270
+ *
271
+ * @param eventName The name of the event - always `refresh`.
272
+ * @param listener The listener function to call when the event is emitted.
273
+ */
274
+ on(eventName: 'refresh', listener: () => void): this;
275
+
276
+ /**
277
+ * The "resolve" event is emitted when the cached values are resolved and
278
+ * updated.
279
+ *
280
+ * @param eventName The name of the event - always `refresh`.
281
+ * @param listener The listener function to call when the event is emitted.
282
+ */
283
+ // eslint-disable-next-line @typescript-eslint/unified-signatures
284
+ on(eventName: 'refresh', listener: <T>(result: T[]) => void): this;
285
+
286
+ /**
287
+ * The "close" event is emitted when the view is closed (stopped observing
288
+ * context events)
289
+ *
290
+ * @param eventName The name of the event - always `close`.
291
+ * @param listener The listener function to call when the event is emitted.
292
+ */
293
+ // eslint-disable-next-line @typescript-eslint/unified-signatures
294
+ on(eventName: 'close', listener: () => void): this;
295
+
296
+ // The generic variant inherited from EventEmitter
297
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
298
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
299
+
300
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
301
+ on(event: string | symbol, listener: (...args: any[]) => void): this {
302
+ return super.on(event, listener);
303
+ }
304
+
305
+ /**
306
+ * The "bind" event is emitted when a new binding is added to the view.
307
+ *
308
+ * @param eventName The name of the event - always `bind`.
309
+ * @param listener The listener function to call when the event is emitted.
310
+ */
311
+ once(
312
+ eventName: 'bind',
313
+ listener: <T>(event: ContextViewEvent<T>) => void,
314
+ ): this;
315
+
316
+ /**
317
+ * The "unbind" event is emitted a new binding is removed from the view.
318
+ *
319
+ * @param eventName The name of the event - always `unbind`.
320
+ * @param listener The listener function to call when the event is emitted.
321
+ */
322
+ once(
323
+ eventName: 'unbind',
324
+ listener: <T>(event: ContextViewEvent<T> & {cachedValue?: T}) => void,
325
+ ): this;
326
+
327
+ /**
328
+ * The "refresh" event is emitted when the view is refreshed as bindings are
329
+ * added/removed.
330
+ *
331
+ * @param eventName The name of the event - always `refresh`.
332
+ * @param listener The listener function to call when the event is emitted.
333
+ */
334
+ once(eventName: 'refresh', listener: () => void): this;
335
+
336
+ /**
337
+ * The "resolve" event is emitted when the cached values are resolved and
338
+ * updated.
339
+ *
340
+ * @param eventName The name of the event - always `refresh`.
341
+ * @param listener The listener function to call when the event is emitted.
342
+ */
343
+ // eslint-disable-next-line @typescript-eslint/unified-signatures
344
+ once(eventName: 'refresh', listener: <T>(result: T[]) => void): this;
345
+
346
+ /**
347
+ * The "close" event is emitted when the view is closed (stopped observing
348
+ * context events)
349
+ *
350
+ * @param eventName The name of the event - always `close`.
351
+ * @param listener The listener function to call when the event is emitted.
352
+ */
353
+ // eslint-disable-next-line @typescript-eslint/unified-signatures
354
+ once(eventName: 'close', listener: () => void): this;
355
+
356
+ // The generic variant inherited from EventEmitter
357
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
358
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
359
+
360
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
361
+ once(event: string | symbol, listener: (...args: any[]) => void): this {
362
+ return super.once(event, listener);
363
+ }
244
364
  }
245
365
 
246
366
  /**
package/src/context.ts CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  } from './binding-filter';
19
19
  import {BindingAddress, BindingKey} from './binding-key';
20
20
  import {BindingComparator} from './binding-sorter';
21
- import {ContextEvent} from './context-event';
21
+ import {ContextEvent, ContextEventListener} from './context-event';
22
22
  import {ContextEventObserver, ContextObserver} from './context-observer';
23
23
  import {ContextSubscriptionManager, Subscription} from './context-subscription';
24
24
  import {ContextTagIndexer} from './context-tag-indexer';
@@ -27,16 +27,18 @@ import {JSONObject} from './json-types';
27
27
  import {ContextBindings} from './keys';
28
28
  import {
29
29
  asResolutionOptions,
30
+ ResolutionError,
30
31
  ResolutionOptions,
31
32
  ResolutionOptionsOrSession,
32
33
  ResolutionSession,
33
34
  } from './resolution-session';
35
+ import {generateUniqueId} from './unique-id';
34
36
  import {
35
37
  BoundValue,
36
38
  Constructor,
37
39
  getDeepProperty,
38
40
  isPromiseLike,
39
- uuid,
41
+ transformValueOrPromise,
40
42
  ValueOrPromise,
41
43
  } from './value-promise';
42
44
 
@@ -108,8 +110,8 @@ export class Context extends EventEmitter {
108
110
  * const reqCtx = new Context(appCtx, 'request');
109
111
  * ```
110
112
  * @param _parent - The optional parent context
111
- * @param name - Name of the context, if not provided, a `uuid` will be
112
- * generated as the name
113
+ * @param name - Name of the context. If not provided, a unique identifier
114
+ * will be generated as the name.
113
115
  */
114
116
  constructor(_parent?: Context | string, name?: string) {
115
117
  super();
@@ -151,7 +153,7 @@ export class Context extends EventEmitter {
151
153
  }
152
154
 
153
155
  private generateName() {
154
- const id = uuid();
156
+ const id = generateUniqueId();
155
157
  if (this.constructor === Context) return id;
156
158
  return `${this.constructor.name}-${id}`;
157
159
  }
@@ -502,7 +504,7 @@ export class Context extends EventEmitter {
502
504
  if (filter(b)) bindings.push(b);
503
505
  }
504
506
 
505
- const parentBindings = this._parent && this._parent.find(filter);
507
+ const parentBindings = this._parent?.find(filter);
506
508
  return this._mergeWithParent(bindings, parentBindings);
507
509
  }
508
510
 
@@ -534,7 +536,7 @@ export class Context extends EventEmitter {
534
536
  tag: BindingTag | RegExp,
535
537
  ): Readonly<Binding<ValueType>>[] {
536
538
  const currentBindings = this.tagIndexer.findByTagIndex(tag);
537
- const parentBindings = this._parent && this._parent?._findByTagIndex(tag);
539
+ const parentBindings = this._parent?._findByTagIndex(tag);
538
540
  return this._mergeWithParent(currentBindings, parentBindings);
539
541
  }
540
542
 
@@ -797,21 +799,27 @@ export class Context extends EventEmitter {
797
799
  ): ValueOrPromise<ValueType | undefined> {
798
800
  const {key, propertyPath} = BindingKey.parseKeyWithPath(keyWithPath);
799
801
 
800
- optionsOrSession = asResolutionOptions(optionsOrSession);
802
+ const options = asResolutionOptions(optionsOrSession);
801
803
 
802
- const binding = this.getBinding<ValueType>(key, optionsOrSession);
803
- if (binding == null) return undefined;
804
-
805
- const boundValue = binding.getValue(this, optionsOrSession);
806
- if (propertyPath === undefined || propertyPath === '') {
807
- return boundValue;
808
- }
809
-
810
- if (isPromiseLike(boundValue)) {
811
- return boundValue.then(v => getDeepProperty<ValueType>(v, propertyPath));
804
+ const binding = this.getBinding<ValueType>(key, {optional: true});
805
+ if (binding == null) {
806
+ if (options.optional) return undefined;
807
+ throw new ResolutionError(
808
+ `The key '${key}' is not bound to any value in context ${this.name}`,
809
+ {
810
+ context: this,
811
+ binding: Binding.bind(key),
812
+ options,
813
+ },
814
+ );
812
815
  }
813
816
 
814
- return getDeepProperty<ValueType>(boundValue, propertyPath);
817
+ const boundValue = binding.getValue(this, options);
818
+ return propertyPath == null || propertyPath === ''
819
+ ? boundValue
820
+ : transformValueOrPromise(boundValue, v =>
821
+ getDeepProperty<ValueType>(v, propertyPath),
822
+ );
815
823
  }
816
824
 
817
825
  /**
@@ -878,6 +886,42 @@ export class Context extends EventEmitter {
878
886
  }
879
887
  return json;
880
888
  }
889
+
890
+ /**
891
+ * The "bind" event is emitted when a new binding is added to the context.
892
+ * The "unbind" event is emitted when an existing binding is removed.
893
+ *
894
+ * @param eventName The name of the event - always `bind` or `unbind`.
895
+ * @param listener The listener function to call when the event is emitted.
896
+ */
897
+ on(eventName: 'bind' | 'unbind', listener: ContextEventListener): this;
898
+
899
+ // The generic variant inherited from EventEmitter
900
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
901
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
902
+
903
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
904
+ on(event: string | symbol, listener: (...args: any[]) => void): this {
905
+ return super.on(event, listener);
906
+ }
907
+
908
+ /**
909
+ * The "bind" event is emitted when a new binding is added to the context.
910
+ * The "unbind" event is emitted when an existing binding is removed.
911
+ *
912
+ * @param eventName The name of the event - always `bind` or `unbind`.
913
+ * @param listener The listener function to call when the event is emitted.
914
+ */
915
+ once(eventName: 'bind' | 'unbind', listener: ContextEventListener): this;
916
+
917
+ // The generic variant inherited from EventEmitter
918
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
919
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
920
+
921
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
922
+ once(event: string | symbol, listener: (...args: any[]) => void): this {
923
+ return super.once(event, listener);
924
+ }
881
925
  }
882
926
 
883
927
  /**
@@ -129,7 +129,7 @@ export namespace config {
129
129
  */
130
130
  function getCurrentBindingKey(session: ResolutionSession) {
131
131
  // The current binding is not set if `instantiateClass` is invoked directly
132
- return session.currentBinding && session.currentBinding.key;
132
+ return session.currentBinding?.key;
133
133
  }
134
134
 
135
135
  /**
package/src/inject.ts CHANGED
@@ -133,6 +133,11 @@ export function inject(
133
133
  if (injectionMetadata.bindingComparator && !resolve) {
134
134
  throw new Error('Binding comparator is only allowed with a binding filter');
135
135
  }
136
+ if (!bindingSelector && typeof resolve !== 'function') {
137
+ throw new Error(
138
+ 'A non-empty binding selector or resolve function is required for @inject',
139
+ );
140
+ }
136
141
  return function markParameterOrPropertyAsInjected(
137
142
  target: Object,
138
143
  member: string | undefined,