@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
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,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
|
+
import {generateUniqueId} from './unique-id';
|
|
7
|
+
|
|
8
|
+
export type BindingAddress<T = unknown> = string | BindingKey<T>;
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
|
+
export class BindingKey<ValueType> {
|
|
12
|
+
static readonly PROPERTY_SEPARATOR = '#';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create a new key for a binding bound to a value of type `ValueType`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* BindingKey.create<string>('application.name');
|
|
21
|
+
* BindingKey.create<number>('config', 'rest.port);
|
|
22
|
+
* BindingKey.create<number>('config#rest.port');
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @param key - The binding key. When propertyPath is not provided, the key
|
|
26
|
+
* is allowed to contain propertyPath as encoded via `BindingKey#toString()`
|
|
27
|
+
* @param propertyPath - Optional path to a deep property of the bound value.
|
|
28
|
+
*/
|
|
29
|
+
public static create<V>(key: string, propertyPath?: string): BindingKey<V> {
|
|
30
|
+
// TODO(bajtos) allow chaining of propertyPaths, e.g.
|
|
31
|
+
// BindingKey.create('config#rest', 'port')
|
|
32
|
+
// should create {key: 'config', path: 'rest.port'}
|
|
33
|
+
if (propertyPath) {
|
|
34
|
+
BindingKey.validate(key);
|
|
35
|
+
return new BindingKey<V>(key, propertyPath);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return BindingKey.parseKeyWithPath(key);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private constructor(
|
|
42
|
+
public readonly key: string,
|
|
43
|
+
public readonly propertyPath?: string,
|
|
44
|
+
) {}
|
|
45
|
+
|
|
46
|
+
toString() {
|
|
47
|
+
return this.propertyPath
|
|
48
|
+
? `${this.key}${BindingKey.PROPERTY_SEPARATOR}${this.propertyPath}`
|
|
49
|
+
: this.key;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get a binding address for retrieving a deep property of the object
|
|
54
|
+
* bound to the current binding key.
|
|
55
|
+
*
|
|
56
|
+
* @param propertyPath - A dot-separated path to a (deep) property, e.g. "server.port".
|
|
57
|
+
*/
|
|
58
|
+
deepProperty<PropertyValueType>(propertyPath: string) {
|
|
59
|
+
// TODO(bajtos) allow chaining of propertyPaths, e.g.
|
|
60
|
+
// BindingKey.create('config', 'rest').deepProperty('port')
|
|
61
|
+
// should create {key: 'config', path: 'rest.port'}
|
|
62
|
+
return BindingKey.create<PropertyValueType>(this.key, propertyPath);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Validate the binding key format. Please note that `#` is reserved.
|
|
67
|
+
* Returns a string representation of the binding key.
|
|
68
|
+
*
|
|
69
|
+
* @param key - Binding key, such as `a`, `a.b`, `a:b`, or `a/b`
|
|
70
|
+
*/
|
|
71
|
+
static validate<T>(key: BindingAddress<T>): string {
|
|
72
|
+
if (!key) throw new Error('Binding key must be provided.');
|
|
73
|
+
key = key.toString();
|
|
74
|
+
if (key.includes(BindingKey.PROPERTY_SEPARATOR)) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Binding key ${key} cannot contain` +
|
|
77
|
+
` '${BindingKey.PROPERTY_SEPARATOR}'.`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return key;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Parse a string containing both the binding key and the path to the deeply
|
|
85
|
+
* nested property to retrieve.
|
|
86
|
+
*
|
|
87
|
+
* @param keyWithPath - The key with an optional path,
|
|
88
|
+
* e.g. "application.instance" or "config#rest.port".
|
|
89
|
+
*/
|
|
90
|
+
static parseKeyWithPath<T>(keyWithPath: BindingAddress<T>): BindingKey<T> {
|
|
91
|
+
if (typeof keyWithPath !== 'string') {
|
|
92
|
+
return BindingKey.create<T>(keyWithPath.key, keyWithPath.propertyPath);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const index = keyWithPath.indexOf(BindingKey.PROPERTY_SEPARATOR);
|
|
96
|
+
if (index === -1) {
|
|
97
|
+
return new BindingKey<T>(keyWithPath);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return BindingKey.create<T>(
|
|
101
|
+
keyWithPath.substr(0, index).trim(),
|
|
102
|
+
keyWithPath.substr(index + 1),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Name space for configuration binding keys
|
|
108
|
+
*/
|
|
109
|
+
static CONFIG_NAMESPACE = '$config';
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Build a binding key for the configuration of the given binding.
|
|
113
|
+
* The format is `<key>:$config`
|
|
114
|
+
*
|
|
115
|
+
* @param key - Key of the target binding to be configured
|
|
116
|
+
*/
|
|
117
|
+
static buildKeyForConfig<T>(key: BindingAddress = ''): BindingAddress<T> {
|
|
118
|
+
const suffix = BindingKey.CONFIG_NAMESPACE;
|
|
119
|
+
const bindingKey = key ? `${key}:${suffix}` : suffix;
|
|
120
|
+
return bindingKey;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Generate a universally unique binding key.
|
|
125
|
+
*
|
|
126
|
+
* Please note the format of they generated key is not specified, you must
|
|
127
|
+
* not rely on any specific formatting (e.g. UUID style).
|
|
128
|
+
*
|
|
129
|
+
* @param namespace - Namespace for the binding
|
|
130
|
+
*/
|
|
131
|
+
static generate<T>(namespace = ''): BindingKey<T> {
|
|
132
|
+
const prefix = namespace ? `${namespace}.` : '';
|
|
133
|
+
const name = generateUniqueId();
|
|
134
|
+
return BindingKey.create(`${prefix}${name}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
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 {Binding} from './binding';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Compare function to sort an array of bindings.
|
|
10
|
+
* It is used by `Array.prototype.sort()`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const compareByKey: BindingComparator = (a, b) => a.key.localeCompare(b.key);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export interface BindingComparator {
|
|
18
|
+
/**
|
|
19
|
+
* Compare two bindings
|
|
20
|
+
* @param bindingA - First binding
|
|
21
|
+
* @param bindingB - Second binding
|
|
22
|
+
* @returns A number to determine order of bindingA and bindingB
|
|
23
|
+
* - 0 leaves bindingA and bindingB unchanged
|
|
24
|
+
* - <0 bindingA comes before bindingB
|
|
25
|
+
* - >0 bindingA comes after bindingB
|
|
26
|
+
*/
|
|
27
|
+
(
|
|
28
|
+
bindingA: Readonly<Binding<unknown>>,
|
|
29
|
+
bindingB: Readonly<Binding<unknown>>,
|
|
30
|
+
): number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a binding compare function to sort bindings by tagged phase name.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* Two bindings are compared as follows:
|
|
38
|
+
*
|
|
39
|
+
* 1. Get values for the given tag as `phase` for bindings, if the tag is not
|
|
40
|
+
* present, default `phase` to `''`.
|
|
41
|
+
* 2. If both bindings have `phase` value in `orderOfPhases`, honor the order
|
|
42
|
+
* specified by `orderOfPhases`.
|
|
43
|
+
* 3. If a binding's `phase` does not exist in `orderOfPhases`, it comes before
|
|
44
|
+
* the one with `phase` exists in `orderOfPhases`.
|
|
45
|
+
* 4. If both bindings have `phase` value outside of `orderOfPhases`, they are
|
|
46
|
+
* ordered by phase names alphabetically and symbol values come before string
|
|
47
|
+
* values.
|
|
48
|
+
*
|
|
49
|
+
* @param phaseTagName - Name of the binding tag for phase
|
|
50
|
+
* @param orderOfPhases - An array of phase names as the predefined order
|
|
51
|
+
*/
|
|
52
|
+
export function compareBindingsByTag(
|
|
53
|
+
phaseTagName = 'phase',
|
|
54
|
+
orderOfPhases: (string | symbol)[] = [],
|
|
55
|
+
): BindingComparator {
|
|
56
|
+
return (a: Readonly<Binding<unknown>>, b: Readonly<Binding<unknown>>) => {
|
|
57
|
+
return compareByOrder(
|
|
58
|
+
a.tagMap[phaseTagName],
|
|
59
|
+
b.tagMap[phaseTagName],
|
|
60
|
+
orderOfPhases,
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Compare two values by the predefined order
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
*
|
|
70
|
+
* The comparison is performed as follows:
|
|
71
|
+
*
|
|
72
|
+
* 1. If both values are included in `order`, they are sorted by their indexes in
|
|
73
|
+
* `order`.
|
|
74
|
+
* 2. The value included in `order` comes after the value not included in `order`.
|
|
75
|
+
* 3. If neither values are included in `order`, they are sorted:
|
|
76
|
+
* - symbol values come before string values
|
|
77
|
+
* - alphabetical order for two symbols or two strings
|
|
78
|
+
*
|
|
79
|
+
* @param a - First value
|
|
80
|
+
* @param b - Second value
|
|
81
|
+
* @param order - An array of values as the predefined order
|
|
82
|
+
*/
|
|
83
|
+
export function compareByOrder(
|
|
84
|
+
a: string | symbol | undefined | null,
|
|
85
|
+
b: string | symbol | undefined | null,
|
|
86
|
+
order: (string | symbol)[] = [],
|
|
87
|
+
) {
|
|
88
|
+
a = a ?? '';
|
|
89
|
+
b = b ?? '';
|
|
90
|
+
const i1 = order.indexOf(a);
|
|
91
|
+
const i2 = order.indexOf(b);
|
|
92
|
+
if (i1 !== -1 || i2 !== -1) {
|
|
93
|
+
// Honor the order
|
|
94
|
+
return i1 - i2;
|
|
95
|
+
} else {
|
|
96
|
+
// Neither value is in the pre-defined order
|
|
97
|
+
|
|
98
|
+
// symbol comes before string
|
|
99
|
+
if (typeof a === 'symbol' && typeof b === 'string') return -1;
|
|
100
|
+
if (typeof a === 'string' && typeof b === 'symbol') return 1;
|
|
101
|
+
|
|
102
|
+
// both a and b are symbols or both a and b are strings
|
|
103
|
+
if (typeof a === 'symbol') a = a.toString();
|
|
104
|
+
if (typeof b === 'symbol') b = b.toString();
|
|
105
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Sort bindings by phase names denoted by a tag and the predefined order
|
|
111
|
+
*
|
|
112
|
+
* @param bindings - An array of bindings
|
|
113
|
+
* @param phaseTagName - Tag name for phase, for example, we can use the value
|
|
114
|
+
* `'a'` of tag `order` as the phase name for `binding.tag({order: 'a'})`.
|
|
115
|
+
*
|
|
116
|
+
* @param orderOfPhases - An array of phase names as the predefined order
|
|
117
|
+
*/
|
|
118
|
+
export function sortBindingsByPhase<T = unknown>(
|
|
119
|
+
bindings: Readonly<Binding<T>>[],
|
|
120
|
+
phaseTagName?: string,
|
|
121
|
+
orderOfPhases?: (string | symbol)[],
|
|
122
|
+
) {
|
|
123
|
+
return bindings.sort(compareBindingsByTag(phaseTagName, orderOfPhases));
|
|
124
|
+
}
|