@loopback/context 3.5.1 → 3.8.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 (71) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/binding-config.js +1 -0
  3. package/dist/binding-config.js.map +1 -1
  4. package/dist/binding-decorator.d.ts +1 -2
  5. package/dist/binding-decorator.js +1 -0
  6. package/dist/binding-decorator.js.map +1 -1
  7. package/dist/binding-filter.d.ts +2 -2
  8. package/dist/binding-filter.js +4 -3
  9. package/dist/binding-filter.js.map +1 -1
  10. package/dist/binding-inspector.d.ts +14 -7
  11. package/dist/binding-inspector.js +14 -6
  12. package/dist/binding-inspector.js.map +1 -1
  13. package/dist/binding-key.d.ts +5 -0
  14. package/dist/binding-key.js +104 -90
  15. package/dist/binding-key.js.map +1 -1
  16. package/dist/binding-sorter.js +1 -0
  17. package/dist/binding-sorter.js.map +1 -1
  18. package/dist/binding.d.ts +84 -7
  19. package/dist/binding.js +120 -35
  20. package/dist/binding.js.map +1 -1
  21. package/dist/context-subscription.js +1 -0
  22. package/dist/context-subscription.js.map +1 -1
  23. package/dist/context-tag-indexer.js +1 -0
  24. package/dist/context-tag-indexer.js.map +1 -1
  25. package/dist/context-view.js +1 -0
  26. package/dist/context-view.js.map +1 -1
  27. package/dist/context.js +2 -2
  28. package/dist/context.js.map +1 -1
  29. package/dist/index.js +4 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/inject-config.js +1 -0
  32. package/dist/inject-config.js.map +1 -1
  33. package/dist/inject.d.ts +13 -6
  34. package/dist/inject.js +6 -8
  35. package/dist/inject.js.map +1 -1
  36. package/dist/interception-proxy.js +1 -0
  37. package/dist/interception-proxy.js.map +1 -1
  38. package/dist/interceptor-chain.d.ts +39 -4
  39. package/dist/interceptor-chain.js +26 -4
  40. package/dist/interceptor-chain.js.map +1 -1
  41. package/dist/interceptor.d.ts +28 -3
  42. package/dist/interceptor.js +54 -0
  43. package/dist/interceptor.js.map +1 -1
  44. package/dist/invocation.js +1 -0
  45. package/dist/invocation.js.map +1 -1
  46. package/dist/keys.d.ts +5 -0
  47. package/dist/keys.js +6 -0
  48. package/dist/keys.js.map +1 -1
  49. package/dist/resolution-session.d.ts +26 -6
  50. package/dist/resolution-session.js +1 -0
  51. package/dist/resolution-session.js.map +1 -1
  52. package/dist/resolver.js +1 -0
  53. package/dist/resolver.js.map +1 -1
  54. package/dist/value-promise.d.ts +8 -4
  55. package/dist/value-promise.js +17 -0
  56. package/dist/value-promise.js.map +1 -1
  57. package/package.json +13 -13
  58. package/src/binding-decorator.ts +2 -3
  59. package/src/binding-filter.ts +8 -7
  60. package/src/binding-inspector.ts +32 -9
  61. package/src/binding-key.ts +12 -0
  62. package/src/binding.ts +210 -44
  63. package/src/context.ts +2 -2
  64. package/src/inject.ts +22 -16
  65. package/src/interceptor-chain.ts +66 -7
  66. package/src/interceptor.ts +85 -2
  67. package/src/keys.ts +6 -0
  68. package/src/resolution-session.ts +30 -2
  69. package/src/value-promise.ts +13 -0
  70. package/index.d.ts +0 -6
  71. package/index.js +0 -6
@@ -15,7 +15,13 @@ import assert from 'assert';
15
15
  import debugFactory from 'debug';
16
16
  import {Binding, BindingTemplate} from './binding';
17
17
  import {bind} from './binding-decorator';
18
- import {BindingSpec} from './binding-inspector';
18
+ import {
19
+ BindingFromClassOptions,
20
+ BindingSpec,
21
+ createBindingFromClass,
22
+ isProviderClass,
23
+ } from './binding-inspector';
24
+ import {BindingAddress, BindingKey} from './binding-key';
19
25
  import {sortBindingsByPhase} from './binding-sorter';
20
26
  import {Context} from './context';
21
27
  import {
@@ -33,8 +39,10 @@ import {
33
39
  ContextBindings,
34
40
  ContextTags,
35
41
  GLOBAL_INTERCEPTOR_NAMESPACE,
42
+ LOCAL_INTERCEPTOR_NAMESPACE,
36
43
  } from './keys';
37
- import {tryWithFinally, ValueOrPromise} from './value-promise';
44
+ import {Provider} from './provider';
45
+ import {Constructor, tryWithFinally, ValueOrPromise} from './value-promise';
38
46
  const debug = debugFactory('loopback:context:interceptor');
39
47
 
40
48
  /**
@@ -345,3 +353,78 @@ export function invokeMethodWithInterceptors(
345
353
  () => invocationCtx.close(),
346
354
  );
347
355
  }
356
+
357
+ /**
358
+ * Options for an interceptor binding
359
+ */
360
+ export interface InterceptorBindingOptions extends BindingFromClassOptions {
361
+ /**
362
+ * Global or local interceptor
363
+ */
364
+ global?: boolean;
365
+ /**
366
+ * Group name for a global interceptor
367
+ */
368
+ group?: string;
369
+ /**
370
+ * Source filter for a global interceptor
371
+ */
372
+ source?: string | string[];
373
+ }
374
+
375
+ /**
376
+ * Register an interceptor function or provider class to the given context
377
+ * @param ctx - Context object
378
+ * @param interceptor - An interceptor function or provider class
379
+ * @param options - Options for the interceptor binding
380
+ */
381
+ export function registerInterceptor(
382
+ ctx: Context,
383
+ interceptor: Interceptor | Constructor<Provider<Interceptor>>,
384
+ options: InterceptorBindingOptions = {},
385
+ ) {
386
+ let {global} = options;
387
+ const {group, source} = options;
388
+ if (group != null || source != null) {
389
+ // If group or source is set, assuming global
390
+ global = global !== false;
391
+ }
392
+
393
+ const namespace =
394
+ options.namespace ?? options.defaultNamespace ?? global
395
+ ? GLOBAL_INTERCEPTOR_NAMESPACE
396
+ : LOCAL_INTERCEPTOR_NAMESPACE;
397
+
398
+ let binding: Binding<Interceptor>;
399
+ if (isProviderClass(interceptor)) {
400
+ binding = createBindingFromClass(interceptor, {
401
+ defaultNamespace: namespace,
402
+ ...options,
403
+ });
404
+ if (binding.tagMap[ContextTags.GLOBAL_INTERCEPTOR]) {
405
+ global = true;
406
+ }
407
+ ctx.add(binding);
408
+ } else {
409
+ let key = options.key;
410
+ if (!key) {
411
+ const name = options.name ?? interceptor.name;
412
+ if (!name) {
413
+ key = BindingKey.generate<Interceptor>(namespace).key;
414
+ } else {
415
+ key = `${namespace}.${name}`;
416
+ }
417
+ }
418
+ binding = ctx
419
+ .bind(key as BindingAddress<Interceptor>)
420
+ .to(interceptor as Interceptor);
421
+ }
422
+ if (global) {
423
+ binding.apply(asGlobalInterceptor(group));
424
+ if (source) {
425
+ binding.tag({[ContextTags.GLOBAL_INTERCEPTOR_SOURCE]: source});
426
+ }
427
+ }
428
+
429
+ return binding;
430
+ }
package/src/keys.ts CHANGED
@@ -12,6 +12,7 @@ import {BindingKey} from './binding-key';
12
12
  export namespace ContextTags {
13
13
  export const CLASS = 'class';
14
14
  export const PROVIDER = 'provider';
15
+ export const DYNAMIC_VALUE_PROVIDER = 'dynamicValueProvider';
15
16
 
16
17
  /**
17
18
  * Type of the artifact
@@ -58,6 +59,11 @@ export namespace ContextTags {
58
59
  */
59
60
  export const GLOBAL_INTERCEPTOR_NAMESPACE = 'globalInterceptors';
60
61
 
62
+ /**
63
+ * Default namespace for local interceptors
64
+ */
65
+ export const LOCAL_INTERCEPTOR_NAMESPACE = 'interceptors';
66
+
61
67
  /**
62
68
  * Namespace for context bindings
63
69
  */
@@ -6,7 +6,9 @@
6
6
  import {DecoratorFactory} from '@loopback/metadata';
7
7
  import debugModule from 'debug';
8
8
  import {Binding} from './binding';
9
- import {Injection} from './inject';
9
+ import {BindingSelector} from './binding-filter';
10
+ import {Context} from './context';
11
+ import {Injection, InjectionMetadata} from './inject';
10
12
  import {BoundValue, tryWithFinally, ValueOrPromise} from './value-promise';
11
13
 
12
14
  const debugSession = debugModule('loopback:context:resolver:session');
@@ -35,6 +37,12 @@ export interface InjectionElement {
35
37
  value: Readonly<Injection>;
36
38
  }
37
39
 
40
+ export interface InjectionDescriptor {
41
+ targetName: string;
42
+ bindingSelector: BindingSelector;
43
+ metadata: InjectionMetadata;
44
+ }
45
+
38
46
  /**
39
47
  * Binding or injection elements tracked by resolution sessions
40
48
  */
@@ -155,7 +163,9 @@ export class ResolutionSession {
155
163
  * Describe the injection for debugging purpose
156
164
  * @param injection - Injection object
157
165
  */
158
- static describeInjection(injection: Readonly<Injection>) {
166
+ static describeInjection(
167
+ injection: Readonly<Injection>,
168
+ ): InjectionDescriptor {
159
169
  const name = getTargetName(
160
170
  injection.target,
161
171
  injection.member,
@@ -366,3 +376,21 @@ export function asResolutionOptions(
366
376
  }
367
377
  return optionsOrSession ?? {};
368
378
  }
379
+
380
+ /**
381
+ * Contextual metadata for resolution
382
+ */
383
+ export interface ResolutionContext<T = unknown> {
384
+ /**
385
+ * The context for resolution
386
+ */
387
+ readonly context: Context;
388
+ /**
389
+ * The binding to be resolved
390
+ */
391
+ readonly binding: Readonly<Binding<T>>;
392
+ /**
393
+ * The options used for resolution
394
+ */
395
+ readonly options: ResolutionOptions;
396
+ }
@@ -8,6 +8,7 @@
8
8
  * utility methods to handle values and/or promises.
9
9
  */
10
10
 
11
+ import {v4 as uuidv4} from 'uuid';
11
12
  /**
12
13
  * A class constructor accepting arbitrary arguments.
13
14
  */
@@ -270,3 +271,15 @@ export function transformValueOrPromise<T, V>(
270
271
  return transformer(valueOrPromise);
271
272
  }
272
273
  }
274
+
275
+ /**
276
+ * A utility to generate uuid v4
277
+ */
278
+ export function uuid() {
279
+ return uuidv4();
280
+ }
281
+
282
+ /**
283
+ * A regular expression for testing uuid v4 PATTERN
284
+ */
285
+ export const 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;
package/index.d.ts DELETED
@@ -1,6 +0,0 @@
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
- export * from './dist';
package/index.js DELETED
@@ -1,6 +0,0 @@
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
- module.exports = require('./dist');