@loopback/core 4.0.0-alpha.9 → 4.0.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.
- package/LICENSE +25 -0
- package/README.md +77 -2
- package/dist/application.d.ts +341 -0
- package/dist/application.js +554 -0
- package/dist/application.js.map +1 -0
- package/dist/component.d.ts +80 -0
- package/dist/component.js +59 -0
- package/dist/component.js.map +1 -0
- package/dist/extension-point.d.ts +121 -0
- package/dist/extension-point.js +227 -0
- package/dist/extension-point.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +97 -0
- package/dist/keys.js +109 -0
- package/dist/keys.js.map +1 -0
- package/dist/lifecycle-registry.d.ts +91 -0
- package/dist/lifecycle-registry.js +191 -0
- package/dist/lifecycle-registry.js.map +1 -0
- package/dist/lifecycle.d.ts +47 -0
- package/dist/lifecycle.js +56 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/mixin-target.d.ts +60 -0
- package/{lib6/internal-types.js → dist/mixin-target.js} +2 -3
- package/dist/mixin-target.js.map +1 -0
- package/dist/server.d.ts +16 -0
- package/{lib6/component.js → dist/server.js} +2 -2
- package/dist/server.js.map +1 -0
- package/dist/service.d.ts +63 -0
- package/dist/service.js +151 -0
- package/dist/service.js.map +1 -0
- package/package.json +39 -37
- package/src/application.ts +719 -0
- package/src/component.ts +155 -0
- package/src/extension-point.ts +312 -0
- package/src/index.ts +29 -0
- package/src/keys.ts +144 -0
- package/src/lifecycle-registry.ts +268 -0
- package/src/lifecycle.ts +90 -0
- package/src/mixin-target.ts +69 -0
- package/src/server.ts +22 -0
- package/src/service.ts +211 -0
- package/index.d.ts +0 -6
- package/index.js +0 -9
- package/lib/application.d.ts +0 -54
- package/lib/application.js +0 -81
- package/lib/application.js.map +0 -1
- package/lib/component.d.ts +0 -2
- package/lib/component.js +0 -7
- package/lib/component.js.map +0 -1
- package/lib/http-handler.d.ts +0 -16
- package/lib/http-handler.js +0 -62
- package/lib/http-handler.js.map +0 -1
- package/lib/index.d.ts +0 -17
- package/lib/index.js +0 -37
- package/lib/index.js.map +0 -1
- package/lib/internal-types.d.ts +0 -29
- package/lib/internal-types.js +0 -8
- package/lib/internal-types.js.map +0 -1
- package/lib/keys.d.ts +0 -7
- package/lib/keys.js +0 -16
- package/lib/keys.js.map +0 -1
- package/lib/parser.d.ts +0 -11
- package/lib/parser.js +0 -96
- package/lib/parser.js.map +0 -1
- package/lib/promisify.d.ts +0 -3
- package/lib/promisify.js +0 -34
- package/lib/promisify.js.map +0 -1
- package/lib/router/metadata.d.ts +0 -12
- package/lib/router/metadata.js +0 -30
- package/lib/router/metadata.js.map +0 -1
- package/lib/router/routing-table.d.ts +0 -16
- package/lib/router/routing-table.js +0 -97
- package/lib/router/routing-table.js.map +0 -1
- package/lib/sequence.d.ts +0 -55
- package/lib/sequence.js +0 -99
- package/lib/sequence.js.map +0 -1
- package/lib/server.d.ts +0 -23
- package/lib/server.js +0 -64
- package/lib/server.js.map +0 -1
- package/lib/writer.d.ts +0 -11
- package/lib/writer.js +0 -34
- package/lib/writer.js.map +0 -1
- package/lib6/application.d.ts +0 -54
- package/lib6/application.js +0 -81
- package/lib6/application.js.map +0 -1
- package/lib6/component.d.ts +0 -2
- package/lib6/component.js.map +0 -1
- package/lib6/http-handler.d.ts +0 -16
- package/lib6/http-handler.js +0 -72
- package/lib6/http-handler.js.map +0 -1
- package/lib6/index.d.ts +0 -17
- package/lib6/index.js +0 -37
- package/lib6/index.js.map +0 -1
- package/lib6/internal-types.d.ts +0 -29
- package/lib6/internal-types.js.map +0 -1
- package/lib6/keys.d.ts +0 -7
- package/lib6/keys.js +0 -16
- package/lib6/keys.js.map +0 -1
- package/lib6/parser.d.ts +0 -11
- package/lib6/parser.js +0 -106
- package/lib6/parser.js.map +0 -1
- package/lib6/promisify.d.ts +0 -3
- package/lib6/promisify.js +0 -34
- package/lib6/promisify.js.map +0 -1
- package/lib6/router/metadata.d.ts +0 -12
- package/lib6/router/metadata.js +0 -30
- package/lib6/router/metadata.js.map +0 -1
- package/lib6/router/routing-table.d.ts +0 -16
- package/lib6/router/routing-table.js +0 -97
- package/lib6/router/routing-table.js.map +0 -1
- package/lib6/sequence.d.ts +0 -55
- package/lib6/sequence.js +0 -109
- package/lib6/sequence.js.map +0 -1
- package/lib6/server.d.ts +0 -23
- package/lib6/server.js +0 -74
- package/lib6/server.js.map +0 -1
- package/lib6/writer.d.ts +0 -11
- package/lib6/writer.js +0 -34
- package/lib6/writer.js.map +0 -1
package/src/component.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2017,2019. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/core
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Binding,
|
|
8
|
+
BoundValue,
|
|
9
|
+
Constructor,
|
|
10
|
+
createBindingFromClass,
|
|
11
|
+
Provider,
|
|
12
|
+
} from '@loopback/context';
|
|
13
|
+
import {
|
|
14
|
+
Application,
|
|
15
|
+
ControllerClass,
|
|
16
|
+
ServiceOrProviderClass,
|
|
17
|
+
} from './application';
|
|
18
|
+
import {LifeCycleObserver} from './lifecycle';
|
|
19
|
+
import {Server} from './server';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A map of provider classes to be bound to a context
|
|
23
|
+
*/
|
|
24
|
+
export interface ProviderMap {
|
|
25
|
+
[key: string]: Constructor<Provider<BoundValue>>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A map of classes to be bound to a context
|
|
30
|
+
*/
|
|
31
|
+
export interface ClassMap {
|
|
32
|
+
[key: string]: Constructor<BoundValue>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A component declares a set of artifacts so that they can be contributed to
|
|
37
|
+
* an application as a group
|
|
38
|
+
*/
|
|
39
|
+
export interface Component {
|
|
40
|
+
/**
|
|
41
|
+
* An array of controller classes
|
|
42
|
+
*/
|
|
43
|
+
controllers?: ControllerClass[];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A map of providers to be bound to the application context
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* {
|
|
51
|
+
* 'authentication.strategies.ldap': LdapStrategyProvider
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
providers?: ProviderMap;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A map of classes to be bound to the application context.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* {
|
|
63
|
+
* 'rest.body-parsers.xml': XmlBodyParser
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
classes?: ClassMap;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A map of name/class pairs for servers
|
|
71
|
+
*/
|
|
72
|
+
servers?: {
|
|
73
|
+
[name: string]: Constructor<Server>;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
lifeCycleObservers?: Constructor<LifeCycleObserver>[];
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* An array of service or provider classes
|
|
80
|
+
*/
|
|
81
|
+
services?: ServiceOrProviderClass[];
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* An array of bindings to be aded to the application context.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const bindingX = Binding.bind('x').to('Value X');
|
|
89
|
+
* this.bindings = [bindingX]
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
bindings?: Binding[];
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Other properties
|
|
96
|
+
*/
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
|
+
[prop: string]: any;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Mount a component to an Application.
|
|
103
|
+
*
|
|
104
|
+
* @param app - Application
|
|
105
|
+
* @param component - Component instance
|
|
106
|
+
*/
|
|
107
|
+
export function mountComponent(app: Application, component: Component) {
|
|
108
|
+
if (component.classes) {
|
|
109
|
+
for (const classKey in component.classes) {
|
|
110
|
+
const binding = createBindingFromClass(component.classes[classKey], {
|
|
111
|
+
key: classKey,
|
|
112
|
+
});
|
|
113
|
+
app.add(binding);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (component.providers) {
|
|
118
|
+
for (const providerKey in component.providers) {
|
|
119
|
+
const binding = createBindingFromClass(component.providers[providerKey], {
|
|
120
|
+
key: providerKey,
|
|
121
|
+
});
|
|
122
|
+
app.add(binding);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (component.bindings) {
|
|
127
|
+
for (const binding of component.bindings) {
|
|
128
|
+
app.add(binding);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (component.controllers) {
|
|
133
|
+
for (const controllerCtor of component.controllers) {
|
|
134
|
+
app.controller(controllerCtor);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (component.servers) {
|
|
139
|
+
for (const serverKey in component.servers) {
|
|
140
|
+
app.server(component.servers[serverKey], serverKey);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (component.lifeCycleObservers) {
|
|
145
|
+
for (const observer of component.lifeCycleObservers) {
|
|
146
|
+
app.lifeCycleObserver(observer);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (component.services) {
|
|
151
|
+
for (const service of component.services) {
|
|
152
|
+
app.service(service);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2017,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/core
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
asResolutionOptions,
|
|
8
|
+
assertTargetType,
|
|
9
|
+
Binding,
|
|
10
|
+
BindingFilter,
|
|
11
|
+
BindingFromClassOptions,
|
|
12
|
+
BindingSpec,
|
|
13
|
+
BindingTemplate,
|
|
14
|
+
Constructor,
|
|
15
|
+
Context,
|
|
16
|
+
ContextTags,
|
|
17
|
+
ContextView,
|
|
18
|
+
createBindingFromClass,
|
|
19
|
+
createViewGetter,
|
|
20
|
+
filterByTag,
|
|
21
|
+
includesTagValue,
|
|
22
|
+
inject,
|
|
23
|
+
injectable,
|
|
24
|
+
Injection,
|
|
25
|
+
InjectionMetadata,
|
|
26
|
+
ResolutionSession,
|
|
27
|
+
} from '@loopback/context';
|
|
28
|
+
import {CoreTags} from './keys';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Decorate a class as a named extension point. If the decoration is not
|
|
32
|
+
* present, the name of the class will be used.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import {extensionPoint} from '@loopback/core';
|
|
37
|
+
*
|
|
38
|
+
* @extensionPoint(GREETER_EXTENSION_POINT_NAME)
|
|
39
|
+
* export class GreetingService {
|
|
40
|
+
* // ...
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @param name - Name of the extension point
|
|
45
|
+
*/
|
|
46
|
+
export function extensionPoint(name: string, ...specs: BindingSpec[]) {
|
|
47
|
+
return injectable({tags: {[CoreTags.EXTENSION_POINT]: name}}, ...specs);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Shortcut to inject extensions for the given extension point.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import {Getter} from '@loopback/context';
|
|
56
|
+
* import {extensionPoint, extensions} from '@loopback/core';
|
|
57
|
+
*
|
|
58
|
+
* @extensionPoint(GREETER_EXTENSION_POINT_NAME)
|
|
59
|
+
* export class GreetingService {
|
|
60
|
+
* constructor(
|
|
61
|
+
* @extensions() // Inject extensions for the extension point
|
|
62
|
+
* private getGreeters: Getter<Greeter[]>,
|
|
63
|
+
* // ...
|
|
64
|
+
* ) {
|
|
65
|
+
* // ...
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @param extensionPointName - Name of the extension point. If not supplied, we
|
|
70
|
+
* use the `name` tag from the extension point binding or the class name of the
|
|
71
|
+
* extension point class. If a class needs to inject extensions from multiple
|
|
72
|
+
* extension points, use different `extensionPointName` for different types of
|
|
73
|
+
* extensions.
|
|
74
|
+
* @param metadata - Optional injection metadata
|
|
75
|
+
*/
|
|
76
|
+
export function extensions(
|
|
77
|
+
extensionPointName?: string,
|
|
78
|
+
metadata?: InjectionMetadata,
|
|
79
|
+
) {
|
|
80
|
+
return inject(
|
|
81
|
+
'',
|
|
82
|
+
{...metadata, decorator: '@extensions'},
|
|
83
|
+
(ctx, injection, session) => {
|
|
84
|
+
assertTargetType(injection, Function, 'Getter function');
|
|
85
|
+
const bindingFilter = filterByExtensionPoint(
|
|
86
|
+
injection,
|
|
87
|
+
session,
|
|
88
|
+
extensionPointName,
|
|
89
|
+
);
|
|
90
|
+
return createViewGetter(
|
|
91
|
+
ctx,
|
|
92
|
+
bindingFilter,
|
|
93
|
+
injection.metadata.bindingComparator,
|
|
94
|
+
{...metadata, ...asResolutionOptions(session)},
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export namespace extensions {
|
|
101
|
+
/**
|
|
102
|
+
* Inject a `ContextView` for extensions of the extension point. The view can
|
|
103
|
+
* then be listened on events such as `bind`, `unbind`, or `refresh` to react
|
|
104
|
+
* on changes of extensions.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* import {extensionPoint, extensions} from '@loopback/core';
|
|
109
|
+
*
|
|
110
|
+
* @extensionPoint(GREETER_EXTENSION_POINT_NAME)
|
|
111
|
+
* export class GreetingService {
|
|
112
|
+
* constructor(
|
|
113
|
+
* @extensions.view() // Inject a context view for extensions of the extension point
|
|
114
|
+
* private greetersView: ContextView<Greeter>,
|
|
115
|
+
* // ...
|
|
116
|
+
* ) {
|
|
117
|
+
* // ...
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
* @param extensionPointName - Name of the extension point. If not supplied, we
|
|
121
|
+
* use the `name` tag from the extension point binding or the class name of the
|
|
122
|
+
* extension point class. If a class needs to inject extensions from multiple
|
|
123
|
+
* extension points, use different `extensionPointName` for different types of
|
|
124
|
+
* extensions.
|
|
125
|
+
* @param metadata - Optional injection metadata
|
|
126
|
+
*/
|
|
127
|
+
export function view(
|
|
128
|
+
extensionPointName?: string,
|
|
129
|
+
metadata?: InjectionMetadata,
|
|
130
|
+
) {
|
|
131
|
+
return inject(
|
|
132
|
+
'',
|
|
133
|
+
{...metadata, decorator: '@extensions.view'},
|
|
134
|
+
(ctx, injection, session) => {
|
|
135
|
+
assertTargetType(injection, ContextView);
|
|
136
|
+
const bindingFilter = filterByExtensionPoint(
|
|
137
|
+
injection,
|
|
138
|
+
session,
|
|
139
|
+
extensionPointName,
|
|
140
|
+
);
|
|
141
|
+
return ctx.createView(
|
|
142
|
+
bindingFilter,
|
|
143
|
+
injection.metadata.bindingComparator,
|
|
144
|
+
metadata,
|
|
145
|
+
);
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Inject an array of resolved extension instances for the extension point.
|
|
152
|
+
* The list is a snapshot of registered extensions when the injection is
|
|
153
|
+
* fulfilled. Extensions added or removed afterward won't impact the list.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* import {extensionPoint, extensions} from '@loopback/core';
|
|
158
|
+
*
|
|
159
|
+
* @extensionPoint(GREETER_EXTENSION_POINT_NAME)
|
|
160
|
+
* export class GreetingService {
|
|
161
|
+
* constructor(
|
|
162
|
+
* @extensions.list() // Inject an array of extensions for the extension point
|
|
163
|
+
* private greeters: Greeter[],
|
|
164
|
+
* // ...
|
|
165
|
+
* ) {
|
|
166
|
+
* // ...
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
* @param extensionPointName - Name of the extension point. If not supplied, we
|
|
170
|
+
* use the `name` tag from the extension point binding or the class name of the
|
|
171
|
+
* extension point class. If a class needs to inject extensions from multiple
|
|
172
|
+
* extension points, use different `extensionPointName` for different types of
|
|
173
|
+
* extensions.
|
|
174
|
+
* @param metadata - Optional injection metadata
|
|
175
|
+
*/
|
|
176
|
+
export function list(
|
|
177
|
+
extensionPointName?: string,
|
|
178
|
+
metadata?: InjectionMetadata,
|
|
179
|
+
) {
|
|
180
|
+
return inject(
|
|
181
|
+
'',
|
|
182
|
+
{...metadata, decorator: '@extensions.instances'},
|
|
183
|
+
(ctx, injection, session) => {
|
|
184
|
+
assertTargetType(injection, Array);
|
|
185
|
+
const bindingFilter = filterByExtensionPoint(
|
|
186
|
+
injection,
|
|
187
|
+
session,
|
|
188
|
+
extensionPointName,
|
|
189
|
+
);
|
|
190
|
+
const viewForExtensions = new ContextView(
|
|
191
|
+
ctx,
|
|
192
|
+
bindingFilter,
|
|
193
|
+
injection.metadata.bindingComparator,
|
|
194
|
+
);
|
|
195
|
+
return viewForExtensions.resolve({
|
|
196
|
+
...metadata,
|
|
197
|
+
...asResolutionOptions(session),
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Create a binding filter for `@extensions.*`
|
|
206
|
+
* @param injection - Injection object
|
|
207
|
+
* @param session - Resolution session
|
|
208
|
+
* @param extensionPointName - Extension point name
|
|
209
|
+
*/
|
|
210
|
+
function filterByExtensionPoint(
|
|
211
|
+
injection: Readonly<Injection<unknown>>,
|
|
212
|
+
session: ResolutionSession,
|
|
213
|
+
extensionPointName?: string,
|
|
214
|
+
) {
|
|
215
|
+
extensionPointName =
|
|
216
|
+
extensionPointName ??
|
|
217
|
+
inferExtensionPointName(injection.target, session.currentBinding);
|
|
218
|
+
return extensionFilter(extensionPointName);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Infer the extension point name from binding tags/class name
|
|
223
|
+
* @param injectionTarget - Target class or prototype
|
|
224
|
+
* @param currentBinding - Current binding
|
|
225
|
+
*/
|
|
226
|
+
function inferExtensionPointName(
|
|
227
|
+
injectionTarget: object,
|
|
228
|
+
currentBinding?: Readonly<Binding<unknown>>,
|
|
229
|
+
): string {
|
|
230
|
+
if (currentBinding) {
|
|
231
|
+
const name =
|
|
232
|
+
currentBinding.tagMap[CoreTags.EXTENSION_POINT] ||
|
|
233
|
+
currentBinding.tagMap[ContextTags.NAME];
|
|
234
|
+
|
|
235
|
+
if (name) return name;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let target: Function;
|
|
239
|
+
if (typeof injectionTarget === 'function') {
|
|
240
|
+
// Constructor injection
|
|
241
|
+
target = injectionTarget;
|
|
242
|
+
} else {
|
|
243
|
+
// Injection on the prototype
|
|
244
|
+
target = injectionTarget.constructor;
|
|
245
|
+
}
|
|
246
|
+
return target.name;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* A factory function to create binding filter for extensions of a named
|
|
251
|
+
* extension point
|
|
252
|
+
* @param extensionPointNames - A list of names of extension points
|
|
253
|
+
*/
|
|
254
|
+
export function extensionFilter(
|
|
255
|
+
...extensionPointNames: string[]
|
|
256
|
+
): BindingFilter {
|
|
257
|
+
return filterByTag({
|
|
258
|
+
[CoreTags.EXTENSION_FOR]: includesTagValue(...extensionPointNames),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* A factory function to create binding template for extensions of the given
|
|
264
|
+
* extension point
|
|
265
|
+
* @param extensionPointNames - Names of the extension point
|
|
266
|
+
*/
|
|
267
|
+
export function extensionFor(
|
|
268
|
+
...extensionPointNames: string[]
|
|
269
|
+
): BindingTemplate {
|
|
270
|
+
return binding => {
|
|
271
|
+
if (extensionPointNames.length === 0) return;
|
|
272
|
+
let extensionPoints = binding.tagMap[CoreTags.EXTENSION_FOR];
|
|
273
|
+
// Normalize extensionPoints to string[]
|
|
274
|
+
if (extensionPoints == null) {
|
|
275
|
+
extensionPoints = [];
|
|
276
|
+
} else if (typeof extensionPoints === 'string') {
|
|
277
|
+
extensionPoints = [extensionPoints];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Add extension points
|
|
281
|
+
for (const extensionPointName of extensionPointNames) {
|
|
282
|
+
if (!extensionPoints.includes(extensionPointName)) {
|
|
283
|
+
extensionPoints.push(extensionPointName);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (extensionPoints.length === 1) {
|
|
287
|
+
// Keep the value as string for backward compatibility
|
|
288
|
+
extensionPoints = extensionPoints[0];
|
|
289
|
+
}
|
|
290
|
+
binding.tag({[CoreTags.EXTENSION_FOR]: extensionPoints});
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Register an extension for the given extension point to the context
|
|
296
|
+
* @param context - Context object
|
|
297
|
+
* @param extensionPointName - Name of the extension point
|
|
298
|
+
* @param extensionClass - Class or a provider for an extension
|
|
299
|
+
* @param options - Options Options for the creation of binding from class
|
|
300
|
+
*/
|
|
301
|
+
export function addExtension(
|
|
302
|
+
context: Context,
|
|
303
|
+
extensionPointName: string,
|
|
304
|
+
extensionClass: Constructor<unknown>,
|
|
305
|
+
options?: BindingFromClassOptions,
|
|
306
|
+
) {
|
|
307
|
+
const binding = createBindingFromClass(extensionClass, options).apply(
|
|
308
|
+
extensionFor(extensionPointName),
|
|
309
|
+
);
|
|
310
|
+
context.add(binding);
|
|
311
|
+
return binding;
|
|
312
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2017,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/core
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The core foundation for LoopBack 4. It can also serve as the platform to
|
|
8
|
+
* build large-scale Node.js applications and frameworks.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* For examples of how to leverage `@loopback/core` to build composable and
|
|
12
|
+
* extensible projects, check out the
|
|
13
|
+
* {@link https://loopback.io/doc/en/lb4/core-tutorial.html | core tutorial}.
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Re-export public Core API coming from dependencies
|
|
19
|
+
export * from '@loopback/context';
|
|
20
|
+
// Export APIs
|
|
21
|
+
export * from './application';
|
|
22
|
+
export * from './component';
|
|
23
|
+
export * from './extension-point';
|
|
24
|
+
export * from './keys';
|
|
25
|
+
export * from './lifecycle';
|
|
26
|
+
export * from './lifecycle-registry';
|
|
27
|
+
export * from './mixin-target';
|
|
28
|
+
export * from './server';
|
|
29
|
+
export * from './service';
|
package/src/keys.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2017,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/core
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {BindingKey} from '@loopback/context';
|
|
7
|
+
import {
|
|
8
|
+
Application,
|
|
9
|
+
ApplicationConfig,
|
|
10
|
+
ApplicationMetadata,
|
|
11
|
+
ControllerClass,
|
|
12
|
+
} from './application';
|
|
13
|
+
import {
|
|
14
|
+
LifeCycleObserverOptions,
|
|
15
|
+
LifeCycleObserverRegistry,
|
|
16
|
+
} from './lifecycle-registry';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Namespace for core binding keys
|
|
20
|
+
*/
|
|
21
|
+
export namespace CoreBindings {
|
|
22
|
+
// application
|
|
23
|
+
/**
|
|
24
|
+
* Binding key for application instance itself
|
|
25
|
+
*/
|
|
26
|
+
export const APPLICATION_INSTANCE = BindingKey.create<Application>(
|
|
27
|
+
'application.instance',
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Binding key for application configuration
|
|
32
|
+
*/
|
|
33
|
+
export const APPLICATION_CONFIG: BindingKey<ApplicationConfig> =
|
|
34
|
+
BindingKey.create<ApplicationConfig>('application.config');
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Binding key for the content of `package.json`
|
|
38
|
+
*/
|
|
39
|
+
export const APPLICATION_METADATA = BindingKey.create<ApplicationMetadata>(
|
|
40
|
+
'application.metadata',
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// server
|
|
44
|
+
/**
|
|
45
|
+
* Binding key for servers
|
|
46
|
+
*/
|
|
47
|
+
export const SERVERS = 'servers';
|
|
48
|
+
|
|
49
|
+
// component
|
|
50
|
+
/**
|
|
51
|
+
* Binding key for components
|
|
52
|
+
*/
|
|
53
|
+
export const COMPONENTS = 'components';
|
|
54
|
+
|
|
55
|
+
// controller
|
|
56
|
+
export const CONTROLLERS = 'controllers';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Binding key for the controller class resolved in the current request
|
|
60
|
+
* context
|
|
61
|
+
*/
|
|
62
|
+
export const CONTROLLER_CLASS: BindingKey<ControllerClass> =
|
|
63
|
+
BindingKey.create<ControllerClass>('controller.current.ctor');
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Binding key for the controller method resolved in the current request
|
|
67
|
+
* context
|
|
68
|
+
*/
|
|
69
|
+
export const CONTROLLER_METHOD_NAME = BindingKey.create<string>(
|
|
70
|
+
'controller.current.operation',
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Binding key for the controller method metadata resolved in the current
|
|
75
|
+
* request context
|
|
76
|
+
*/
|
|
77
|
+
export const CONTROLLER_METHOD_META = 'controller.method.meta';
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Binding key for the controller instance resolved in the current request
|
|
81
|
+
* context
|
|
82
|
+
*/
|
|
83
|
+
export const CONTROLLER_CURRENT = BindingKey.create('controller.current');
|
|
84
|
+
|
|
85
|
+
export const LIFE_CYCLE_OBSERVERS = 'lifeCycleObservers';
|
|
86
|
+
/**
|
|
87
|
+
* Binding key for life cycle observer options
|
|
88
|
+
*/
|
|
89
|
+
export const LIFE_CYCLE_OBSERVER_REGISTRY =
|
|
90
|
+
BindingKey.create<LifeCycleObserverRegistry>('lifeCycleObserver.registry');
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Binding key for life cycle observer options
|
|
94
|
+
*/
|
|
95
|
+
export const LIFE_CYCLE_OBSERVER_OPTIONS =
|
|
96
|
+
BindingKey.create<LifeCycleObserverOptions>('lifeCycleObserver.options');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export namespace CoreTags {
|
|
100
|
+
/**
|
|
101
|
+
* Binding tag for components
|
|
102
|
+
*/
|
|
103
|
+
export const COMPONENT = 'component';
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Binding tag for servers
|
|
107
|
+
*/
|
|
108
|
+
export const SERVER = 'server';
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Binding tag for controllers
|
|
112
|
+
*/
|
|
113
|
+
export const CONTROLLER = 'controller';
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Binding tag for services
|
|
117
|
+
*/
|
|
118
|
+
export const SERVICE = 'service';
|
|
119
|
+
/**
|
|
120
|
+
* Binding tag for the service interface
|
|
121
|
+
*/
|
|
122
|
+
export const SERVICE_INTERFACE = 'serviceInterface';
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Binding tag for life cycle observers
|
|
126
|
+
*/
|
|
127
|
+
export const LIFE_CYCLE_OBSERVER = 'lifeCycleObserver';
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Binding tag for group name of life cycle observers
|
|
131
|
+
*/
|
|
132
|
+
export const LIFE_CYCLE_OBSERVER_GROUP = 'lifeCycleObserverGroup';
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Binding tag for extensions to specify name of the extension point that an
|
|
136
|
+
* extension contributes to.
|
|
137
|
+
*/
|
|
138
|
+
export const EXTENSION_FOR = 'extensionFor';
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Binding tag for an extension point to specify name of the extension point
|
|
142
|
+
*/
|
|
143
|
+
export const EXTENSION_POINT = 'extensionPoint';
|
|
144
|
+
}
|