@loopback/core 1.10.6 → 1.12.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/CHANGELOG.md +42 -0
- package/dist/application.d.ts +83 -3
- package/dist/application.js +137 -24
- package/dist/application.js.map +1 -1
- package/dist/extension-point.js +1 -3
- package/dist/extension-point.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +4 -0
- package/dist/keys.js +4 -0
- package/dist/keys.js.map +1 -1
- package/dist/service.d.ts +63 -0
- package/dist/service.js +128 -0
- package/dist/service.js.map +1 -0
- package/package.json +9 -8
- package/src/application.ts +165 -29
- package/src/extension-point.ts +1 -1
- package/src/index.ts +1 -0
- package/src/keys.ts +4 -0
- package/src/service.ts +180 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,48 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.12.1](https://github.com/strongloop/loopback-next/compare/@loopback/core@1.12.0...@loopback/core@1.12.1) (2020-01-07)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @loopback/core
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [1.12.0](https://github.com/strongloop/loopback-next/compare/@loopback/core@1.11.0...@loopback/core@1.12.0) (2019-12-09)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* **core:** allow application to trap shutdown signals ([2130634](https://github.com/strongloop/loopback-next/commit/213063424c2690aa7ef3f4494d8fc2a7e593b883))
|
|
20
|
+
* **core:** emit stateChanged events for application state transitions ([5257a8f](https://github.com/strongloop/loopback-next/commit/5257a8f68525921028b98a340c75758725d256b9))
|
|
21
|
+
* **core:** enable start/stop/boot to be idempotent ([b614a78](https://github.com/strongloop/loopback-next/commit/b614a7825be1dc1875556388443f72385525fa29))
|
|
22
|
+
* **core:** improve application states for start/stop ([01dac15](https://github.com/strongloop/loopback-next/commit/01dac151260e6c743cc77863f6495a85d19d338c))
|
|
23
|
+
* **core:** simplify state management by checking in process states ([874d2b3](https://github.com/strongloop/loopback-next/commit/874d2b385dd8c1dbf3d3980118898c6b99f145aa))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# [1.11.0](https://github.com/strongloop/loopback-next/compare/@loopback/core@1.10.7...@loopback/core@1.11.0) (2019-11-25)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* **core:** add [@service](https://github.com/service) decorator to inject a service by class/interface ([1d80904](https://github.com/strongloop/loopback-next/commit/1d80904b670724b00cb6a2965b8472f44d23eed0))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## [1.10.7](https://github.com/strongloop/loopback-next/compare/@loopback/core@1.10.6...@loopback/core@1.10.7) (2019-11-12)
|
|
41
|
+
|
|
42
|
+
**Note:** Version bump only for package @loopback/core
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
6
48
|
## [1.10.6](https://github.com/strongloop/loopback-next/compare/@loopback/core@1.10.5...@loopback/core@1.10.6) (2019-10-24)
|
|
7
49
|
|
|
8
50
|
**Note:** Version bump only for package @loopback/core
|
package/dist/application.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { Binding, Constructor, Context, Provider } from '@loopback/context';
|
|
2
3
|
import { Component } from './component';
|
|
3
4
|
import { LifeCycleObserver } from './lifecycle';
|
|
4
5
|
import { Server } from './server';
|
|
6
|
+
import { ServiceOptions } from './service';
|
|
5
7
|
/**
|
|
6
8
|
* Application is the container for various types of artifacts, such as
|
|
7
9
|
* components, servers, controllers, repositories, datasources, connectors,
|
|
@@ -9,6 +11,34 @@ import { Server } from './server';
|
|
|
9
11
|
*/
|
|
10
12
|
export declare class Application extends Context implements LifeCycleObserver {
|
|
11
13
|
readonly options: ApplicationConfig;
|
|
14
|
+
/**
|
|
15
|
+
* A flag to indicate that the application is being shut down
|
|
16
|
+
*/
|
|
17
|
+
private _isShuttingDown;
|
|
18
|
+
/**
|
|
19
|
+
* State of the application
|
|
20
|
+
*/
|
|
21
|
+
private _state;
|
|
22
|
+
/**
|
|
23
|
+
* Get the state of the application. The initial state is `created` and it can
|
|
24
|
+
* transition as follows by `start` and `stop`:
|
|
25
|
+
*
|
|
26
|
+
* 1. start
|
|
27
|
+
* - !started -> starting -> started
|
|
28
|
+
* - started -> started (no-op)
|
|
29
|
+
* 2. stop
|
|
30
|
+
* - started -> stopping -> stopped
|
|
31
|
+
* - !started -> stopped (no-op)
|
|
32
|
+
*
|
|
33
|
+
* Two types of states are expected:
|
|
34
|
+
* - stable, such as `started` and `stopped`
|
|
35
|
+
* - in process, such as `booting` and `starting`
|
|
36
|
+
*
|
|
37
|
+
* Operations such as `start` and `stop` can only be called at a stable state.
|
|
38
|
+
* The logic should immediately set the state to a new one indicating work in
|
|
39
|
+
* process, such as `starting` and `stopping`.
|
|
40
|
+
*/
|
|
41
|
+
get state(): string;
|
|
12
42
|
/**
|
|
13
43
|
* Create an application with the given parent context
|
|
14
44
|
* @param parent - Parent context
|
|
@@ -91,11 +121,37 @@ export declare class Application extends Context implements LifeCycleObserver {
|
|
|
91
121
|
*/
|
|
92
122
|
getServer<T extends Server>(target: Constructor<T> | string): Promise<T>;
|
|
93
123
|
/**
|
|
94
|
-
*
|
|
124
|
+
* Assert there is no other operation is in progress, i.e., the state is not
|
|
125
|
+
* `*ing`, such as `starting` or `stopping`.
|
|
126
|
+
*
|
|
127
|
+
* @param op - The operation name, such as 'boot', 'start', or 'stop'
|
|
128
|
+
*/
|
|
129
|
+
protected assertNotInProcess(op: string): void;
|
|
130
|
+
/**
|
|
131
|
+
* Assert current state of the application to be one of the expected values
|
|
132
|
+
* @param op - The operation name, such as 'boot', 'start', or 'stop'
|
|
133
|
+
* @param states - Valid states
|
|
134
|
+
*/
|
|
135
|
+
protected assertInStates(op: string, ...states: string[]): void;
|
|
136
|
+
/**
|
|
137
|
+
* Transition the application to a new state and emit an event
|
|
138
|
+
* @param state - The new state
|
|
139
|
+
*/
|
|
140
|
+
protected setState(state: string): void;
|
|
141
|
+
protected awaitState(state: string): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Start the application, and all of its registered observers. The application
|
|
144
|
+
* state is checked to ensure the integrity of `start`.
|
|
145
|
+
*
|
|
146
|
+
* If the application is already started, no operation is performed.
|
|
95
147
|
*/
|
|
96
148
|
start(): Promise<void>;
|
|
97
149
|
/**
|
|
98
|
-
* Stop the application instance and all of its registered observers.
|
|
150
|
+
* Stop the application instance and all of its registered observers. The
|
|
151
|
+
* application state is checked to ensure the integrity of `stop`.
|
|
152
|
+
*
|
|
153
|
+
* If the application is already stopped or not started, no operation is
|
|
154
|
+
* performed.
|
|
99
155
|
*/
|
|
100
156
|
stop(): Promise<void>;
|
|
101
157
|
private getLifeCycleObserverRegistry;
|
|
@@ -177,12 +233,36 @@ export declare class Application extends Context implements LifeCycleObserver {
|
|
|
177
233
|
* }
|
|
178
234
|
* ```
|
|
179
235
|
*/
|
|
180
|
-
service<S>(cls: Constructor<S> | Constructor<Provider<S>>, name?: string): Binding<S>;
|
|
236
|
+
service<S>(cls: Constructor<S> | Constructor<Provider<S>>, name?: string | ServiceOptions): Binding<S>;
|
|
237
|
+
/**
|
|
238
|
+
* Set up signals that are captured to shutdown the application
|
|
239
|
+
* @param signals - An array of signals to be trapped
|
|
240
|
+
* @param gracePeriod - A grace period in ms before forced exit
|
|
241
|
+
*/
|
|
242
|
+
protected setupShutdown(signals: NodeJS.Signals[], gracePeriod?: number): void;
|
|
181
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Options to set up application shutdown
|
|
246
|
+
*/
|
|
247
|
+
export declare type ShutdownOptions = {
|
|
248
|
+
/**
|
|
249
|
+
* An array of signals to be trapped for graceful shutdown
|
|
250
|
+
*/
|
|
251
|
+
signals?: NodeJS.Signals[];
|
|
252
|
+
/**
|
|
253
|
+
* Period in milliseconds to wait for the grace shutdown to finish before
|
|
254
|
+
* exiting the process
|
|
255
|
+
*/
|
|
256
|
+
gracePeriod?: number;
|
|
257
|
+
};
|
|
182
258
|
/**
|
|
183
259
|
* Configuration for application
|
|
184
260
|
*/
|
|
185
261
|
export interface ApplicationConfig {
|
|
262
|
+
/**
|
|
263
|
+
* Configuration for signals that shut down the application
|
|
264
|
+
*/
|
|
265
|
+
shutdown?: ShutdownOptions;
|
|
186
266
|
/**
|
|
187
267
|
* Other properties
|
|
188
268
|
*/
|
package/dist/application.js
CHANGED
|
@@ -3,14 +3,20 @@
|
|
|
3
3
|
// Node module: @loopback/core
|
|
4
4
|
// This file is licensed under the MIT License.
|
|
5
5
|
// License text available at https://opensource.org/licenses/MIT
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
6
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
10
|
const context_1 = require("@loopback/context");
|
|
8
|
-
const
|
|
11
|
+
const assert_1 = __importDefault(require("assert"));
|
|
12
|
+
const p_event_1 = __importDefault(require("p-event"));
|
|
13
|
+
const debug_1 = __importDefault(require("debug"));
|
|
9
14
|
const component_1 = require("./component");
|
|
10
15
|
const keys_1 = require("./keys");
|
|
11
16
|
const lifecycle_1 = require("./lifecycle");
|
|
12
17
|
const lifecycle_registry_1 = require("./lifecycle-registry");
|
|
13
|
-
const
|
|
18
|
+
const service_1 = require("./service");
|
|
19
|
+
const debug = debug_1.default('loopback:core:application');
|
|
14
20
|
/**
|
|
15
21
|
* Application is the container for various types of artifacts, such as
|
|
16
22
|
* components, servers, controllers, repositories, datasources, connectors,
|
|
@@ -18,10 +24,19 @@ const debug = debugFactory('loopback:core:application');
|
|
|
18
24
|
*/
|
|
19
25
|
class Application extends context_1.Context {
|
|
20
26
|
constructor(configOrParent, parent) {
|
|
27
|
+
var _a, _b;
|
|
21
28
|
super(configOrParent instanceof context_1.Context ? configOrParent : parent, 'application');
|
|
29
|
+
/**
|
|
30
|
+
* A flag to indicate that the application is being shut down
|
|
31
|
+
*/
|
|
32
|
+
this._isShuttingDown = false;
|
|
33
|
+
/**
|
|
34
|
+
* State of the application
|
|
35
|
+
*/
|
|
36
|
+
this._state = 'created';
|
|
22
37
|
if (configOrParent instanceof context_1.Context)
|
|
23
38
|
configOrParent = {};
|
|
24
|
-
this.options = configOrParent
|
|
39
|
+
this.options = (configOrParent !== null && configOrParent !== void 0 ? configOrParent : {});
|
|
25
40
|
// Bind the life cycle observer registry
|
|
26
41
|
this.bind(keys_1.CoreBindings.LIFE_CYCLE_OBSERVER_REGISTRY)
|
|
27
42
|
.toClass(lifecycle_registry_1.LifeCycleObserverRegistry)
|
|
@@ -30,6 +45,30 @@ class Application extends context_1.Context {
|
|
|
30
45
|
this.bind(keys_1.CoreBindings.APPLICATION_INSTANCE).to(this);
|
|
31
46
|
// Make options available to other modules as well.
|
|
32
47
|
this.bind(keys_1.CoreBindings.APPLICATION_CONFIG).to(this.options);
|
|
48
|
+
const shutdownConfig = (_a = this.options.shutdown, (_a !== null && _a !== void 0 ? _a : {}));
|
|
49
|
+
this.setupShutdown((_b = shutdownConfig.signals, (_b !== null && _b !== void 0 ? _b : ['SIGTERM'])), shutdownConfig.gracePeriod);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the state of the application. The initial state is `created` and it can
|
|
53
|
+
* transition as follows by `start` and `stop`:
|
|
54
|
+
*
|
|
55
|
+
* 1. start
|
|
56
|
+
* - !started -> starting -> started
|
|
57
|
+
* - started -> started (no-op)
|
|
58
|
+
* 2. stop
|
|
59
|
+
* - started -> stopping -> stopped
|
|
60
|
+
* - !started -> stopped (no-op)
|
|
61
|
+
*
|
|
62
|
+
* Two types of states are expected:
|
|
63
|
+
* - stable, such as `started` and `stopped`
|
|
64
|
+
* - in process, such as `booting` and `starting`
|
|
65
|
+
*
|
|
66
|
+
* Operations such as `start` and `stop` can only be called at a stable state.
|
|
67
|
+
* The logic should immediately set the state to a new one indicating work in
|
|
68
|
+
* process, such as `starting` and `stopping`.
|
|
69
|
+
*/
|
|
70
|
+
get state() {
|
|
71
|
+
return this._state;
|
|
33
72
|
}
|
|
34
73
|
/**
|
|
35
74
|
* Register a controller class with this application.
|
|
@@ -49,7 +88,7 @@ class Application extends context_1.Context {
|
|
|
49
88
|
* ```
|
|
50
89
|
*/
|
|
51
90
|
controller(controllerCtor, name) {
|
|
52
|
-
debug('Adding controller %s', name
|
|
91
|
+
debug('Adding controller %s', (name !== null && name !== void 0 ? name : controllerCtor.name));
|
|
53
92
|
const binding = context_1.createBindingFromClass(controllerCtor, {
|
|
54
93
|
name,
|
|
55
94
|
namespace: keys_1.CoreBindings.CONTROLLERS,
|
|
@@ -78,7 +117,7 @@ class Application extends context_1.Context {
|
|
|
78
117
|
*
|
|
79
118
|
*/
|
|
80
119
|
server(ctor, name) {
|
|
81
|
-
debug('Adding server %s', name
|
|
120
|
+
debug('Adding server %s', (name !== null && name !== void 0 ? name : ctor.name));
|
|
82
121
|
const binding = context_1.createBindingFromClass(ctor, {
|
|
83
122
|
name,
|
|
84
123
|
namespace: keys_1.CoreBindings.SERVERS,
|
|
@@ -135,18 +174,73 @@ class Application extends context_1.Context {
|
|
|
135
174
|
return this.get(key);
|
|
136
175
|
}
|
|
137
176
|
/**
|
|
138
|
-
*
|
|
177
|
+
* Assert there is no other operation is in progress, i.e., the state is not
|
|
178
|
+
* `*ing`, such as `starting` or `stopping`.
|
|
179
|
+
*
|
|
180
|
+
* @param op - The operation name, such as 'boot', 'start', or 'stop'
|
|
181
|
+
*/
|
|
182
|
+
assertNotInProcess(op) {
|
|
183
|
+
assert_1.default(!this._state.endsWith('ing'), `Cannot ${op} the application as it is ${this._state}.`);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Assert current state of the application to be one of the expected values
|
|
187
|
+
* @param op - The operation name, such as 'boot', 'start', or 'stop'
|
|
188
|
+
* @param states - Valid states
|
|
189
|
+
*/
|
|
190
|
+
assertInStates(op, ...states) {
|
|
191
|
+
assert_1.default(states.includes(this._state), `Cannot ${op} the application as it is ${this._state}. Valid states are ${states}.`);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Transition the application to a new state and emit an event
|
|
195
|
+
* @param state - The new state
|
|
196
|
+
*/
|
|
197
|
+
setState(state) {
|
|
198
|
+
const oldState = this._state;
|
|
199
|
+
this._state = state;
|
|
200
|
+
if (oldState !== state) {
|
|
201
|
+
this.emit('stateChanged', { from: oldState, to: this._state });
|
|
202
|
+
this.emit(state);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async awaitState(state) {
|
|
206
|
+
await p_event_1.default(this, state);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Start the application, and all of its registered observers. The application
|
|
210
|
+
* state is checked to ensure the integrity of `start`.
|
|
211
|
+
*
|
|
212
|
+
* If the application is already started, no operation is performed.
|
|
139
213
|
*/
|
|
140
214
|
async start() {
|
|
215
|
+
if (this._state === 'starting')
|
|
216
|
+
return this.awaitState('started');
|
|
217
|
+
this.assertNotInProcess('start');
|
|
218
|
+
// No-op if it's started
|
|
219
|
+
if (this._state === 'started')
|
|
220
|
+
return;
|
|
221
|
+
this.setState('starting');
|
|
141
222
|
const registry = await this.getLifeCycleObserverRegistry();
|
|
142
223
|
await registry.start();
|
|
224
|
+
this.setState('started');
|
|
143
225
|
}
|
|
144
226
|
/**
|
|
145
|
-
* Stop the application instance and all of its registered observers.
|
|
227
|
+
* Stop the application instance and all of its registered observers. The
|
|
228
|
+
* application state is checked to ensure the integrity of `stop`.
|
|
229
|
+
*
|
|
230
|
+
* If the application is already stopped or not started, no operation is
|
|
231
|
+
* performed.
|
|
146
232
|
*/
|
|
147
233
|
async stop() {
|
|
234
|
+
if (this._state === 'stopping')
|
|
235
|
+
return this.awaitState('stopped');
|
|
236
|
+
this.assertNotInProcess('stop');
|
|
237
|
+
// No-op if it's created or stopped
|
|
238
|
+
if (this._state !== 'started')
|
|
239
|
+
return;
|
|
240
|
+
this.setState('stopping');
|
|
148
241
|
const registry = await this.getLifeCycleObserverRegistry();
|
|
149
242
|
await registry.stop();
|
|
243
|
+
this.setState('stopped');
|
|
150
244
|
}
|
|
151
245
|
async getLifeCycleObserverRegistry() {
|
|
152
246
|
return this.get(keys_1.CoreBindings.LIFE_CYCLE_OBSERVER_REGISTRY);
|
|
@@ -174,7 +268,7 @@ class Application extends context_1.Context {
|
|
|
174
268
|
* ```
|
|
175
269
|
*/
|
|
176
270
|
component(componentCtor, name) {
|
|
177
|
-
debug('Adding component: %s', name
|
|
271
|
+
debug('Adding component: %s', (name !== null && name !== void 0 ? name : componentCtor.name));
|
|
178
272
|
const binding = context_1.createBindingFromClass(componentCtor, {
|
|
179
273
|
name,
|
|
180
274
|
namespace: keys_1.CoreBindings.COMPONENTS,
|
|
@@ -205,7 +299,7 @@ class Application extends context_1.Context {
|
|
|
205
299
|
* @param name - Optional name for the life cycle observer
|
|
206
300
|
*/
|
|
207
301
|
lifeCycleObserver(ctor, name) {
|
|
208
|
-
debug('Adding life cycle observer %s', name
|
|
302
|
+
debug('Adding life cycle observer %s', (name !== null && name !== void 0 ? name : ctor.name));
|
|
209
303
|
const binding = context_1.createBindingFromClass(ctor, {
|
|
210
304
|
name,
|
|
211
305
|
namespace: keys_1.CoreBindings.LIFE_CYCLE_OBSERVERS,
|
|
@@ -258,24 +352,43 @@ class Application extends context_1.Context {
|
|
|
258
352
|
* ```
|
|
259
353
|
*/
|
|
260
354
|
service(cls, name) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// This is needed to keep backward compatibility
|
|
264
|
-
const templateFn = context_1.bindingTemplateFor(cls);
|
|
265
|
-
const template = context_1.Binding.bind('template').apply(templateFn);
|
|
266
|
-
if (template.tagMap[context_1.ContextTags.PROVIDER] &&
|
|
267
|
-
!template.tagMap[context_1.ContextTags.NAME]) {
|
|
268
|
-
// The class is a provider and no `name` tag is found
|
|
269
|
-
name = cls.name.replace(/Provider$/, '');
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
const binding = context_1.createBindingFromClass(cls, {
|
|
273
|
-
name,
|
|
274
|
-
type: 'service',
|
|
275
|
-
});
|
|
355
|
+
const options = typeof name === 'string' ? { name } : name;
|
|
356
|
+
const binding = service_1.createServiceBinding(cls, options);
|
|
276
357
|
this.add(binding);
|
|
277
358
|
return binding;
|
|
278
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Set up signals that are captured to shutdown the application
|
|
362
|
+
* @param signals - An array of signals to be trapped
|
|
363
|
+
* @param gracePeriod - A grace period in ms before forced exit
|
|
364
|
+
*/
|
|
365
|
+
setupShutdown(signals, gracePeriod) {
|
|
366
|
+
const cleanup = async (signal) => {
|
|
367
|
+
const kill = () => {
|
|
368
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
369
|
+
signals.forEach(sig => process.removeListener(sig, cleanup));
|
|
370
|
+
process.kill(process.pid, signal);
|
|
371
|
+
};
|
|
372
|
+
debug('Signal %s received for process %d', signal, process.pid);
|
|
373
|
+
if (!this._isShuttingDown) {
|
|
374
|
+
this._isShuttingDown = true;
|
|
375
|
+
let timer;
|
|
376
|
+
if (typeof gracePeriod === 'number' && !isNaN(gracePeriod)) {
|
|
377
|
+
timer = setTimeout(kill, gracePeriod);
|
|
378
|
+
}
|
|
379
|
+
try {
|
|
380
|
+
await this.stop();
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
if (timer != null)
|
|
384
|
+
clearTimeout(timer);
|
|
385
|
+
kill();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
390
|
+
signals.forEach(sig => process.on(sig, cleanup));
|
|
391
|
+
}
|
|
279
392
|
}
|
|
280
393
|
exports.Application = Application;
|
|
281
394
|
//# sourceMappingURL=application.js.map
|
package/dist/application.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.js","sourceRoot":"","sources":["../src/application.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE
|
|
1
|
+
{"version":3,"file":"application.js","sourceRoot":"","sources":["../src/application.ts"],"names":[],"mappings":"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"}
|
package/dist/extension-point.js
CHANGED
|
@@ -53,9 +53,7 @@ exports.extensionPoint = extensionPoint;
|
|
|
53
53
|
*/
|
|
54
54
|
function extensions(extensionPointName) {
|
|
55
55
|
return context_1.inject('', { decorator: '@extensions' }, (ctx, injection, session) => {
|
|
56
|
-
extensionPointName =
|
|
57
|
-
extensionPointName ||
|
|
58
|
-
inferExtensionPointName(injection.target, session.currentBinding);
|
|
56
|
+
extensionPointName = (extensionPointName !== null && extensionPointName !== void 0 ? extensionPointName : inferExtensionPointName(injection.target, session.currentBinding));
|
|
59
57
|
const bindingFilter = extensionFilter(extensionPointName);
|
|
60
58
|
return context_1.createViewGetter(ctx, bindingFilter, injection.metadata.bindingComparator, session);
|
|
61
59
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-point.js","sourceRoot":"","sources":["../src/extension-point.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;AAEhE,+CAa2B;AAC3B,iCAAgC;AAEhC;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,GAAG,KAAoB;IAClE,OAAO,cAAI,CAAC,EAAC,IAAI,EAAE,EAAC,CAAC,eAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,EAAC,EAAC,EAAE,GAAG,KAAK,CAAC,CAAC;AACpE,CAAC;AAFD,wCAEC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,UAAU,CAAC,kBAA2B;IACpD,OAAO,gBAAM,CAAC,EAAE,EAAE,EAAC,SAAS,EAAE,aAAa,EAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;QACxE,kBAAkB
|
|
1
|
+
{"version":3,"file":"extension-point.js","sourceRoot":"","sources":["../src/extension-point.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;AAEhE,+CAa2B;AAC3B,iCAAgC;AAEhC;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,GAAG,KAAoB;IAClE,OAAO,cAAI,CAAC,EAAC,IAAI,EAAE,EAAC,CAAC,eAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,EAAC,EAAC,EAAE,GAAG,KAAK,CAAC,CAAC;AACpE,CAAC;AAFD,wCAEC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,UAAU,CAAC,kBAA2B;IACpD,OAAO,gBAAM,CAAC,EAAE,EAAE,EAAC,SAAS,EAAE,aAAa,EAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;QACxE,kBAAkB,IAChB,kBAAkB,aAAlB,kBAAkB,cAAlB,kBAAkB,GAClB,uBAAuB,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA,CAAC;QAEpE,MAAM,aAAa,GAAG,eAAe,CAAC,kBAAkB,CAAC,CAAC;QAC1D,OAAO,0BAAgB,CACrB,GAAG,EACH,aAAa,EACb,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EACpC,OAAO,CACR,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAdD,gCAcC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAC9B,eAAuB,EACvB,cAA2C;IAE3C,IAAI,cAAc,EAAE;QAClB,MAAM,IAAI,GACR,cAAc,CAAC,MAAM,CAAC,eAAQ,CAAC,eAAe,CAAC;YAC/C,cAAc,CAAC,MAAM,CAAC,qBAAW,CAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;KACvB;IAED,IAAI,MAAgB,CAAC;IACrB,IAAI,OAAO,eAAe,KAAK,UAAU,EAAE;QACzC,wBAAwB;QACxB,MAAM,GAAG,eAAe,CAAC;KAC1B;SAAM;QACL,6BAA6B;QAC7B,MAAM,GAAG,eAAe,CAAC,WAAW,CAAC;KACtC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,SAAgB,eAAe,CAAC,kBAA0B;IACxD,OAAO,qBAAW,CAAC;QACjB,CAAC,eAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB;KAC7C,CAAC,CAAC;AACL,CAAC;AAJD,0CAIC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,kBAA0B;IACrD,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAC,CAAC,eAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,EAAC,CAAC,CAAC;AAChF,CAAC;AAFD,oCAEC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,OAAgB,EAChB,kBAA0B,EAC1B,cAAoC,EACpC,OAAiC;IAEjC,MAAM,OAAO,GAAG,gCAAsB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,KAAK,CACnE,YAAY,CAAC,kBAAkB,CAAC,CACjC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,OAAO,CAAC;AACjB,CAAC;AAXD,oCAWC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;;AAEhE,qDAAqD;AACrD,uCAAkC;AAElC,cAAc;AACd,mCAA8B;AAC9B,iCAA4B;AAC5B,uCAAkC;AAClC,4BAAuB;AACvB,iCAA4B;AAC5B,0CAAqC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;;AAEhE,qDAAqD;AACrD,uCAAkC;AAElC,cAAc;AACd,mCAA8B;AAC9B,iCAA4B;AAC5B,uCAAkC;AAClC,4BAAuB;AACvB,iCAA4B;AAC5B,0CAAqC;AAErC,+BAA0B"}
|
package/dist/keys.d.ts
CHANGED
|
@@ -73,6 +73,10 @@ export declare namespace CoreTags {
|
|
|
73
73
|
* Binding tag for services
|
|
74
74
|
*/
|
|
75
75
|
const SERVICE = "service";
|
|
76
|
+
/**
|
|
77
|
+
* Binding tag for the service interface
|
|
78
|
+
*/
|
|
79
|
+
const SERVICE_INTERFACE = "serviceInterface";
|
|
76
80
|
/**
|
|
77
81
|
* Binding tag for life cycle observers
|
|
78
82
|
*/
|
package/dist/keys.js
CHANGED
package/dist/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;AAEhE,+CAA6C;AAY7C;;GAEG;AACH,IAAiB,YAAY,CAgF5B;AAhFD,WAAiB,YAAY;IAC3B,cAAc;IACd;;OAEG;IACU,iCAAoB,GAAG,oBAAU,CAAC,MAAM,CACnD,sBAAsB,CACvB,CAAC;IAEF;;OAEG;IACU,+BAAkB,GAAG,oBAAU,CAAC,MAAM,CACjD,oBAAoB,CACrB,CAAC;IAEF;;OAEG;IACU,iCAAoB,GAAG,oBAAU,CAAC,MAAM,CACnD,sBAAsB,CACvB,CAAC;IAEF,SAAS;IACT;;OAEG;IACU,oBAAO,GAAG,SAAS,CAAC;IAEjC,YAAY;IACZ;;OAEG;IACU,uBAAU,GAAG,YAAY,CAAC;IAEvC,aAAa;IACA,wBAAW,GAAG,aAAa,CAAC;IAEzC;;;OAGG;IACU,6BAAgB,GAAG,oBAAU,CAAC,MAAM,CAC/C,yBAAyB,CAC1B,CAAC;IAEF;;;OAGG;IACU,mCAAsB,GAAG,oBAAU,CAAC,MAAM,CACrD,8BAA8B,CAC/B,CAAC;IAEF;;;OAGG;IACU,mCAAsB,GAAG,wBAAwB,CAAC;IAE/D;;;OAGG;IACU,+BAAkB,GAAG,oBAAU,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAE7D,iCAAoB,GAAG,oBAAoB,CAAC;IACzD;;OAEG;IACU,yCAA4B,GAAG,oBAAU,CAAC,MAAM,CAE3D,4BAA4B,CAAC,CAAC;IAEhC;;OAEG;IACU,wCAA2B,GAAG,oBAAU,CAAC,MAAM,CAE1D,2BAA2B,CAAC,CAAC;AACjC,CAAC,EAhFgB,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QAgF5B;AAED,IAAiB,QAAQ,
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;AAEhE,+CAA6C;AAY7C;;GAEG;AACH,IAAiB,YAAY,CAgF5B;AAhFD,WAAiB,YAAY;IAC3B,cAAc;IACd;;OAEG;IACU,iCAAoB,GAAG,oBAAU,CAAC,MAAM,CACnD,sBAAsB,CACvB,CAAC;IAEF;;OAEG;IACU,+BAAkB,GAAG,oBAAU,CAAC,MAAM,CACjD,oBAAoB,CACrB,CAAC;IAEF;;OAEG;IACU,iCAAoB,GAAG,oBAAU,CAAC,MAAM,CACnD,sBAAsB,CACvB,CAAC;IAEF,SAAS;IACT;;OAEG;IACU,oBAAO,GAAG,SAAS,CAAC;IAEjC,YAAY;IACZ;;OAEG;IACU,uBAAU,GAAG,YAAY,CAAC;IAEvC,aAAa;IACA,wBAAW,GAAG,aAAa,CAAC;IAEzC;;;OAGG;IACU,6BAAgB,GAAG,oBAAU,CAAC,MAAM,CAC/C,yBAAyB,CAC1B,CAAC;IAEF;;;OAGG;IACU,mCAAsB,GAAG,oBAAU,CAAC,MAAM,CACrD,8BAA8B,CAC/B,CAAC;IAEF;;;OAGG;IACU,mCAAsB,GAAG,wBAAwB,CAAC;IAE/D;;;OAGG;IACU,+BAAkB,GAAG,oBAAU,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAE7D,iCAAoB,GAAG,oBAAoB,CAAC;IACzD;;OAEG;IACU,yCAA4B,GAAG,oBAAU,CAAC,MAAM,CAE3D,4BAA4B,CAAC,CAAC;IAEhC;;OAEG;IACU,wCAA2B,GAAG,oBAAU,CAAC,MAAM,CAE1D,2BAA2B,CAAC,CAAC;AACjC,CAAC,EAhFgB,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QAgF5B;AAED,IAAiB,QAAQ,CA6CxB;AA7CD,WAAiB,QAAQ;IACvB;;OAEG;IACU,kBAAS,GAAG,WAAW,CAAC;IAErC;;OAEG;IACU,eAAM,GAAG,QAAQ,CAAC;IAE/B;;OAEG;IACU,mBAAU,GAAG,YAAY,CAAC;IAEvC;;OAEG;IACU,gBAAO,GAAG,SAAS,CAAC;IACjC;;OAEG;IACU,0BAAiB,GAAG,kBAAkB,CAAC;IAEpD;;OAEG;IACU,4BAAmB,GAAG,mBAAmB,CAAC;IAEvD;;OAEG;IACU,kCAAyB,GAAG,wBAAwB,CAAC;IAElE;;;OAGG;IACU,sBAAa,GAAG,cAAc,CAAC;IAE5C;;OAEG;IACU,wBAAe,GAAG,gBAAgB,CAAC;AAClD,CAAC,EA7CgB,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QA6CxB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Binding, BindingFilter, BindingTemplate, Constructor, InjectionMetadata, Provider } from '@loopback/context';
|
|
2
|
+
/**
|
|
3
|
+
* Representing an interface for services. In TypeScript, the `interface` does
|
|
4
|
+
* not have reflections at runtime. We use a string, a symbol or a Function as
|
|
5
|
+
* the type for the service interface.
|
|
6
|
+
*/
|
|
7
|
+
export declare type ServiceInterface = string | symbol | Function;
|
|
8
|
+
/**
|
|
9
|
+
* Options to register a service binding
|
|
10
|
+
*/
|
|
11
|
+
export declare type ServiceOptions = {
|
|
12
|
+
name?: string;
|
|
13
|
+
interface?: ServiceInterface;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* `@service` injects a service instance that matches the class or interface.
|
|
17
|
+
*
|
|
18
|
+
* @param serviceInterface - Interface for the service. It can be in one of the
|
|
19
|
+
* following forms:
|
|
20
|
+
*
|
|
21
|
+
* - A class, such as MyService
|
|
22
|
+
* - A string that identifies the interface, such as `'MyService'`
|
|
23
|
+
* - A symbol that identifies the interface, such as `Symbol('MyService')`
|
|
24
|
+
*
|
|
25
|
+
* If not provided, the value is inferred from the design:type of the parameter
|
|
26
|
+
* or property
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
*
|
|
31
|
+
* const ctx = new Context();
|
|
32
|
+
* ctx.bind('my-service').toClass(MyService);
|
|
33
|
+
* ctx.bind('logger').toClass(Logger);
|
|
34
|
+
*
|
|
35
|
+
* export class MyController {
|
|
36
|
+
* constructor(@service(MyService) private myService: MyService) {}
|
|
37
|
+
*
|
|
38
|
+
* @service()
|
|
39
|
+
* private logger: Logger;
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* ctx.bind('my-controller').toClass(MyController);
|
|
43
|
+
* await myController = ctx.get<MyController>('my-controller');
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function service(serviceInterface?: ServiceInterface, metadata?: InjectionMetadata): (target: Object, member: string | undefined, methodDescriptorOrParameterIndex?: number | TypedPropertyDescriptor<any> | undefined) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Create a binding filter by service class
|
|
49
|
+
* @param serviceInterface - Service class matching the one used by `binding.toClass()`
|
|
50
|
+
* @param options - Options to control if subclasses should be skipped for matching
|
|
51
|
+
*/
|
|
52
|
+
export declare function filterByServiceInterface(serviceInterface: ServiceInterface): BindingFilter;
|
|
53
|
+
/**
|
|
54
|
+
* Create a service binding from a class or provider
|
|
55
|
+
* @param cls - Service class or provider
|
|
56
|
+
* @param options - Service options
|
|
57
|
+
*/
|
|
58
|
+
export declare function createServiceBinding<S>(cls: Constructor<S> | Constructor<Provider<S>>, options?: ServiceOptions): Binding<S>;
|
|
59
|
+
/**
|
|
60
|
+
* Create a binding template for a service interface
|
|
61
|
+
* @param serviceInterface - Service interface
|
|
62
|
+
*/
|
|
63
|
+
export declare function asService(serviceInterface: ServiceInterface): BindingTemplate;
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright IBM Corp. 2019. All Rights Reserved.
|
|
3
|
+
// Node module: @loopback/core
|
|
4
|
+
// This file is licensed under the MIT License.
|
|
5
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const context_1 = require("@loopback/context");
|
|
8
|
+
const keys_1 = require("./keys");
|
|
9
|
+
/**
|
|
10
|
+
* `@service` injects a service instance that matches the class or interface.
|
|
11
|
+
*
|
|
12
|
+
* @param serviceInterface - Interface for the service. It can be in one of the
|
|
13
|
+
* following forms:
|
|
14
|
+
*
|
|
15
|
+
* - A class, such as MyService
|
|
16
|
+
* - A string that identifies the interface, such as `'MyService'`
|
|
17
|
+
* - A symbol that identifies the interface, such as `Symbol('MyService')`
|
|
18
|
+
*
|
|
19
|
+
* If not provided, the value is inferred from the design:type of the parameter
|
|
20
|
+
* or property
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
*
|
|
25
|
+
* const ctx = new Context();
|
|
26
|
+
* ctx.bind('my-service').toClass(MyService);
|
|
27
|
+
* ctx.bind('logger').toClass(Logger);
|
|
28
|
+
*
|
|
29
|
+
* export class MyController {
|
|
30
|
+
* constructor(@service(MyService) private myService: MyService) {}
|
|
31
|
+
*
|
|
32
|
+
* @service()
|
|
33
|
+
* private logger: Logger;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* ctx.bind('my-controller').toClass(MyController);
|
|
37
|
+
* await myController = ctx.get<MyController>('my-controller');
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
function service(serviceInterface, metadata) {
|
|
41
|
+
return context_1.inject('', Object.assign({ decorator: '@service' }, metadata), (ctx, injection, session) => {
|
|
42
|
+
let serviceType = serviceInterface;
|
|
43
|
+
if (!serviceType) {
|
|
44
|
+
if (typeof injection.methodDescriptorOrParameterIndex === 'number') {
|
|
45
|
+
serviceType = context_1.MetadataInspector.getDesignTypeForMethod(injection.target, injection.member).parameterTypes[injection.methodDescriptorOrParameterIndex];
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
serviceType = context_1.MetadataInspector.getDesignTypeForProperty(injection.target, injection.member);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (serviceType === Object || serviceType === Array) {
|
|
52
|
+
throw new Error('Service class cannot be inferred from design type. Use @service(ServiceClass).');
|
|
53
|
+
}
|
|
54
|
+
const view = new context_1.ContextView(ctx, filterByServiceInterface(serviceType));
|
|
55
|
+
const result = view.resolve(session);
|
|
56
|
+
const serviceTypeName = typeof serviceType === 'string'
|
|
57
|
+
? serviceType
|
|
58
|
+
: typeof serviceType === 'symbol'
|
|
59
|
+
? serviceType.toString()
|
|
60
|
+
: serviceType.name;
|
|
61
|
+
return context_1.transformValueOrPromise(result, values => {
|
|
62
|
+
var _a;
|
|
63
|
+
if (values.length === 1)
|
|
64
|
+
return values[0];
|
|
65
|
+
if (values.length >= 1) {
|
|
66
|
+
throw new Error(`More than one bindings found for ${serviceTypeName}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if ((_a = metadata) === null || _a === void 0 ? void 0 : _a.optional) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`No binding found for ${serviceTypeName}. Make sure a service ` +
|
|
73
|
+
`binding is created in context ${ctx.name} with serviceInterface (${serviceTypeName}).`);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
exports.service = service;
|
|
79
|
+
/**
|
|
80
|
+
* Create a binding filter by service class
|
|
81
|
+
* @param serviceInterface - Service class matching the one used by `binding.toClass()`
|
|
82
|
+
* @param options - Options to control if subclasses should be skipped for matching
|
|
83
|
+
*/
|
|
84
|
+
function filterByServiceInterface(serviceInterface) {
|
|
85
|
+
return binding => binding.valueConstructor === serviceInterface ||
|
|
86
|
+
binding.tagMap[keys_1.CoreTags.SERVICE_INTERFACE] === serviceInterface;
|
|
87
|
+
}
|
|
88
|
+
exports.filterByServiceInterface = filterByServiceInterface;
|
|
89
|
+
/**
|
|
90
|
+
* Create a service binding from a class or provider
|
|
91
|
+
* @param cls - Service class or provider
|
|
92
|
+
* @param options - Service options
|
|
93
|
+
*/
|
|
94
|
+
function createServiceBinding(cls, options = {}) {
|
|
95
|
+
var _a;
|
|
96
|
+
let name = options.name;
|
|
97
|
+
if (!name && context_1.isProviderClass(cls)) {
|
|
98
|
+
// Trim `Provider` from the default service name
|
|
99
|
+
// This is needed to keep backward compatibility
|
|
100
|
+
const templateFn = context_1.bindingTemplateFor(cls);
|
|
101
|
+
const template = context_1.Binding.bind('template').apply(templateFn);
|
|
102
|
+
if (template.tagMap[context_1.ContextTags.PROVIDER] &&
|
|
103
|
+
!template.tagMap[context_1.ContextTags.NAME]) {
|
|
104
|
+
// The class is a provider and no `name` tag is found
|
|
105
|
+
name = cls.name.replace(/Provider$/, '');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const binding = context_1.createBindingFromClass(cls, {
|
|
109
|
+
name,
|
|
110
|
+
type: keys_1.CoreTags.SERVICE,
|
|
111
|
+
}).apply(asService((_a = options.interface, (_a !== null && _a !== void 0 ? _a : cls))));
|
|
112
|
+
return binding;
|
|
113
|
+
}
|
|
114
|
+
exports.createServiceBinding = createServiceBinding;
|
|
115
|
+
/**
|
|
116
|
+
* Create a binding template for a service interface
|
|
117
|
+
* @param serviceInterface - Service interface
|
|
118
|
+
*/
|
|
119
|
+
function asService(serviceInterface) {
|
|
120
|
+
return function serviceTemplate(binding) {
|
|
121
|
+
binding.tag({
|
|
122
|
+
[context_1.ContextTags.TYPE]: keys_1.CoreTags.SERVICE,
|
|
123
|
+
[keys_1.CoreTags.SERVICE_INTERFACE]: serviceInterface,
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
exports.asService = asService;
|
|
128
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopback/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.1",
|
|
4
4
|
"description": "LoopBack 4 core",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=8.9"
|
|
@@ -19,15 +19,16 @@
|
|
|
19
19
|
"copyright.owner": "IBM Corp.",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@loopback/context": "^1.
|
|
23
|
-
"debug": "^4.1.1"
|
|
22
|
+
"@loopback/context": "^1.25.1",
|
|
23
|
+
"debug": "^4.1.1",
|
|
24
|
+
"p-event": "^4.1.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"@loopback/build": "^
|
|
27
|
-
"@loopback/eslint-config": "^
|
|
28
|
-
"@loopback/testlab": "^1.
|
|
27
|
+
"@loopback/build": "^3.0.1",
|
|
28
|
+
"@loopback/eslint-config": "^5.0.1",
|
|
29
|
+
"@loopback/testlab": "^1.10.1",
|
|
29
30
|
"@types/debug": "^4.1.5",
|
|
30
|
-
"@types/node": "^10.17.
|
|
31
|
+
"@types/node": "^10.17.13"
|
|
31
32
|
},
|
|
32
33
|
"files": [
|
|
33
34
|
"README.md",
|
|
@@ -42,5 +43,5 @@
|
|
|
42
43
|
"url": "https://github.com/strongloop/loopback-next.git",
|
|
43
44
|
"directory": "packages/core"
|
|
44
45
|
},
|
|
45
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "598baf6e84de3917bb67aff47a1ab1cb1111e3d2"
|
|
46
47
|
}
|
package/src/application.ts
CHANGED
|
@@ -6,15 +6,14 @@
|
|
|
6
6
|
import {
|
|
7
7
|
Binding,
|
|
8
8
|
BindingScope,
|
|
9
|
-
bindingTemplateFor,
|
|
10
9
|
Constructor,
|
|
11
10
|
Context,
|
|
12
|
-
ContextTags,
|
|
13
11
|
createBindingFromClass,
|
|
14
|
-
isProviderClass,
|
|
15
12
|
Provider,
|
|
16
13
|
} from '@loopback/context';
|
|
17
|
-
import
|
|
14
|
+
import assert from 'assert';
|
|
15
|
+
import pEvent from 'p-event';
|
|
16
|
+
import debugFactory from 'debug';
|
|
18
17
|
import {Component, mountComponent} from './component';
|
|
19
18
|
import {CoreBindings, CoreTags} from './keys';
|
|
20
19
|
import {
|
|
@@ -24,6 +23,7 @@ import {
|
|
|
24
23
|
} from './lifecycle';
|
|
25
24
|
import {LifeCycleObserverRegistry} from './lifecycle-registry';
|
|
26
25
|
import {Server} from './server';
|
|
26
|
+
import {createServiceBinding, ServiceOptions} from './service';
|
|
27
27
|
const debug = debugFactory('loopback:core:application');
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -34,6 +34,39 @@ const debug = debugFactory('loopback:core:application');
|
|
|
34
34
|
export class Application extends Context implements LifeCycleObserver {
|
|
35
35
|
public readonly options: ApplicationConfig;
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* A flag to indicate that the application is being shut down
|
|
39
|
+
*/
|
|
40
|
+
private _isShuttingDown = false;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* State of the application
|
|
44
|
+
*/
|
|
45
|
+
private _state = 'created';
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the state of the application. The initial state is `created` and it can
|
|
49
|
+
* transition as follows by `start` and `stop`:
|
|
50
|
+
*
|
|
51
|
+
* 1. start
|
|
52
|
+
* - !started -> starting -> started
|
|
53
|
+
* - started -> started (no-op)
|
|
54
|
+
* 2. stop
|
|
55
|
+
* - started -> stopping -> stopped
|
|
56
|
+
* - !started -> stopped (no-op)
|
|
57
|
+
*
|
|
58
|
+
* Two types of states are expected:
|
|
59
|
+
* - stable, such as `started` and `stopped`
|
|
60
|
+
* - in process, such as `booting` and `starting`
|
|
61
|
+
*
|
|
62
|
+
* Operations such as `start` and `stop` can only be called at a stable state.
|
|
63
|
+
* The logic should immediately set the state to a new one indicating work in
|
|
64
|
+
* process, such as `starting` and `stopping`.
|
|
65
|
+
*/
|
|
66
|
+
public get state() {
|
|
67
|
+
return this._state;
|
|
68
|
+
}
|
|
69
|
+
|
|
37
70
|
/**
|
|
38
71
|
* Create an application with the given parent context
|
|
39
72
|
* @param parent - Parent context
|
|
@@ -53,7 +86,7 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
53
86
|
);
|
|
54
87
|
|
|
55
88
|
if (configOrParent instanceof Context) configOrParent = {};
|
|
56
|
-
this.options = configOrParent
|
|
89
|
+
this.options = configOrParent ?? {};
|
|
57
90
|
|
|
58
91
|
// Bind the life cycle observer registry
|
|
59
92
|
this.bind(CoreBindings.LIFE_CYCLE_OBSERVER_REGISTRY)
|
|
@@ -63,6 +96,12 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
63
96
|
this.bind(CoreBindings.APPLICATION_INSTANCE).to(this);
|
|
64
97
|
// Make options available to other modules as well.
|
|
65
98
|
this.bind(CoreBindings.APPLICATION_CONFIG).to(this.options);
|
|
99
|
+
|
|
100
|
+
const shutdownConfig = this.options.shutdown ?? {};
|
|
101
|
+
this.setupShutdown(
|
|
102
|
+
shutdownConfig.signals ?? ['SIGTERM'],
|
|
103
|
+
shutdownConfig.gracePeriod,
|
|
104
|
+
);
|
|
66
105
|
}
|
|
67
106
|
|
|
68
107
|
/**
|
|
@@ -83,7 +122,7 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
83
122
|
* ```
|
|
84
123
|
*/
|
|
85
124
|
controller(controllerCtor: ControllerClass, name?: string): Binding {
|
|
86
|
-
debug('Adding controller %s', name
|
|
125
|
+
debug('Adding controller %s', name ?? controllerCtor.name);
|
|
87
126
|
const binding = createBindingFromClass(controllerCtor, {
|
|
88
127
|
name,
|
|
89
128
|
namespace: CoreBindings.CONTROLLERS,
|
|
@@ -116,7 +155,7 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
116
155
|
ctor: Constructor<T>,
|
|
117
156
|
name?: string,
|
|
118
157
|
): Binding<T> {
|
|
119
|
-
debug('Adding server %s', name
|
|
158
|
+
debug('Adding server %s', name ?? ctor.name);
|
|
120
159
|
const binding = createBindingFromClass(ctor, {
|
|
121
160
|
name,
|
|
122
161
|
namespace: CoreBindings.SERVERS,
|
|
@@ -177,19 +216,80 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
177
216
|
}
|
|
178
217
|
|
|
179
218
|
/**
|
|
180
|
-
*
|
|
219
|
+
* Assert there is no other operation is in progress, i.e., the state is not
|
|
220
|
+
* `*ing`, such as `starting` or `stopping`.
|
|
221
|
+
*
|
|
222
|
+
* @param op - The operation name, such as 'boot', 'start', or 'stop'
|
|
223
|
+
*/
|
|
224
|
+
protected assertNotInProcess(op: string) {
|
|
225
|
+
assert(
|
|
226
|
+
!this._state.endsWith('ing'),
|
|
227
|
+
`Cannot ${op} the application as it is ${this._state}.`,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Assert current state of the application to be one of the expected values
|
|
233
|
+
* @param op - The operation name, such as 'boot', 'start', or 'stop'
|
|
234
|
+
* @param states - Valid states
|
|
235
|
+
*/
|
|
236
|
+
protected assertInStates(op: string, ...states: string[]) {
|
|
237
|
+
assert(
|
|
238
|
+
states.includes(this._state),
|
|
239
|
+
`Cannot ${op} the application as it is ${this._state}. Valid states are ${states}.`,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Transition the application to a new state and emit an event
|
|
245
|
+
* @param state - The new state
|
|
246
|
+
*/
|
|
247
|
+
protected setState(state: string) {
|
|
248
|
+
const oldState = this._state;
|
|
249
|
+
this._state = state;
|
|
250
|
+
if (oldState !== state) {
|
|
251
|
+
this.emit('stateChanged', {from: oldState, to: this._state});
|
|
252
|
+
this.emit(state);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
protected async awaitState(state: string) {
|
|
257
|
+
await pEvent(this, state);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Start the application, and all of its registered observers. The application
|
|
262
|
+
* state is checked to ensure the integrity of `start`.
|
|
263
|
+
*
|
|
264
|
+
* If the application is already started, no operation is performed.
|
|
181
265
|
*/
|
|
182
266
|
public async start(): Promise<void> {
|
|
267
|
+
if (this._state === 'starting') return this.awaitState('started');
|
|
268
|
+
this.assertNotInProcess('start');
|
|
269
|
+
// No-op if it's started
|
|
270
|
+
if (this._state === 'started') return;
|
|
271
|
+
this.setState('starting');
|
|
183
272
|
const registry = await this.getLifeCycleObserverRegistry();
|
|
184
273
|
await registry.start();
|
|
274
|
+
this.setState('started');
|
|
185
275
|
}
|
|
186
276
|
|
|
187
277
|
/**
|
|
188
|
-
* Stop the application instance and all of its registered observers.
|
|
278
|
+
* Stop the application instance and all of its registered observers. The
|
|
279
|
+
* application state is checked to ensure the integrity of `stop`.
|
|
280
|
+
*
|
|
281
|
+
* If the application is already stopped or not started, no operation is
|
|
282
|
+
* performed.
|
|
189
283
|
*/
|
|
190
284
|
public async stop(): Promise<void> {
|
|
285
|
+
if (this._state === 'stopping') return this.awaitState('stopped');
|
|
286
|
+
this.assertNotInProcess('stop');
|
|
287
|
+
// No-op if it's created or stopped
|
|
288
|
+
if (this._state !== 'started') return;
|
|
289
|
+
this.setState('stopping');
|
|
191
290
|
const registry = await this.getLifeCycleObserverRegistry();
|
|
192
291
|
await registry.stop();
|
|
292
|
+
this.setState('stopped');
|
|
193
293
|
}
|
|
194
294
|
|
|
195
295
|
private async getLifeCycleObserverRegistry() {
|
|
@@ -219,7 +319,7 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
219
319
|
* ```
|
|
220
320
|
*/
|
|
221
321
|
public component(componentCtor: Constructor<Component>, name?: string) {
|
|
222
|
-
debug('Adding component: %s', name
|
|
322
|
+
debug('Adding component: %s', name ?? componentCtor.name);
|
|
223
323
|
const binding = createBindingFromClass(componentCtor, {
|
|
224
324
|
name,
|
|
225
325
|
namespace: CoreBindings.COMPONENTS,
|
|
@@ -255,7 +355,7 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
255
355
|
ctor: Constructor<T>,
|
|
256
356
|
name?: string,
|
|
257
357
|
): Binding<T> {
|
|
258
|
-
debug('Adding life cycle observer %s', name
|
|
358
|
+
debug('Adding life cycle observer %s', name ?? ctor.name);
|
|
259
359
|
const binding = createBindingFromClass(ctor, {
|
|
260
360
|
name,
|
|
261
361
|
namespace: CoreBindings.LIFE_CYCLE_OBSERVERS,
|
|
@@ -310,34 +410,70 @@ export class Application extends Context implements LifeCycleObserver {
|
|
|
310
410
|
*/
|
|
311
411
|
public service<S>(
|
|
312
412
|
cls: Constructor<S> | Constructor<Provider<S>>,
|
|
313
|
-
name?: string,
|
|
413
|
+
name?: string | ServiceOptions,
|
|
314
414
|
): Binding<S> {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
// This is needed to keep backward compatibility
|
|
318
|
-
const templateFn = bindingTemplateFor(cls);
|
|
319
|
-
const template = Binding.bind<S>('template').apply(templateFn);
|
|
320
|
-
if (
|
|
321
|
-
template.tagMap[ContextTags.PROVIDER] &&
|
|
322
|
-
!template.tagMap[ContextTags.NAME]
|
|
323
|
-
) {
|
|
324
|
-
// The class is a provider and no `name` tag is found
|
|
325
|
-
name = cls.name.replace(/Provider$/, '');
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
const binding = createBindingFromClass(cls, {
|
|
329
|
-
name,
|
|
330
|
-
type: 'service',
|
|
331
|
-
});
|
|
415
|
+
const options = typeof name === 'string' ? {name} : name;
|
|
416
|
+
const binding = createServiceBinding(cls, options);
|
|
332
417
|
this.add(binding);
|
|
333
418
|
return binding;
|
|
334
419
|
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Set up signals that are captured to shutdown the application
|
|
423
|
+
* @param signals - An array of signals to be trapped
|
|
424
|
+
* @param gracePeriod - A grace period in ms before forced exit
|
|
425
|
+
*/
|
|
426
|
+
protected setupShutdown(signals: NodeJS.Signals[], gracePeriod?: number) {
|
|
427
|
+
const cleanup = async (signal: string) => {
|
|
428
|
+
const kill = () => {
|
|
429
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
430
|
+
signals.forEach(sig => process.removeListener(sig, cleanup));
|
|
431
|
+
process.kill(process.pid, signal);
|
|
432
|
+
};
|
|
433
|
+
debug('Signal %s received for process %d', signal, process.pid);
|
|
434
|
+
if (!this._isShuttingDown) {
|
|
435
|
+
this._isShuttingDown = true;
|
|
436
|
+
let timer;
|
|
437
|
+
if (typeof gracePeriod === 'number' && !isNaN(gracePeriod)) {
|
|
438
|
+
timer = setTimeout(kill, gracePeriod);
|
|
439
|
+
}
|
|
440
|
+
try {
|
|
441
|
+
await this.stop();
|
|
442
|
+
} finally {
|
|
443
|
+
if (timer != null) clearTimeout(timer);
|
|
444
|
+
kill();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
449
|
+
signals.forEach(sig => process.on(sig, cleanup));
|
|
450
|
+
}
|
|
335
451
|
}
|
|
336
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Options to set up application shutdown
|
|
455
|
+
*/
|
|
456
|
+
export type ShutdownOptions = {
|
|
457
|
+
/**
|
|
458
|
+
* An array of signals to be trapped for graceful shutdown
|
|
459
|
+
*/
|
|
460
|
+
signals?: NodeJS.Signals[];
|
|
461
|
+
/**
|
|
462
|
+
* Period in milliseconds to wait for the grace shutdown to finish before
|
|
463
|
+
* exiting the process
|
|
464
|
+
*/
|
|
465
|
+
gracePeriod?: number;
|
|
466
|
+
};
|
|
467
|
+
|
|
337
468
|
/**
|
|
338
469
|
* Configuration for application
|
|
339
470
|
*/
|
|
340
471
|
export interface ApplicationConfig {
|
|
472
|
+
/**
|
|
473
|
+
* Configuration for signals that shut down the application
|
|
474
|
+
*/
|
|
475
|
+
shutdown?: ShutdownOptions;
|
|
476
|
+
|
|
341
477
|
/**
|
|
342
478
|
* Other properties
|
|
343
479
|
*/
|
package/src/extension-point.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function extensionPoint(name: string, ...specs: BindingSpec[]) {
|
|
|
67
67
|
export function extensions(extensionPointName?: string) {
|
|
68
68
|
return inject('', {decorator: '@extensions'}, (ctx, injection, session) => {
|
|
69
69
|
extensionPointName =
|
|
70
|
-
extensionPointName
|
|
70
|
+
extensionPointName ??
|
|
71
71
|
inferExtensionPointName(injection.target, session.currentBinding);
|
|
72
72
|
|
|
73
73
|
const bindingFilter = extensionFilter(extensionPointName);
|
package/src/index.ts
CHANGED
package/src/keys.ts
CHANGED
|
@@ -120,6 +120,10 @@ export namespace CoreTags {
|
|
|
120
120
|
* Binding tag for services
|
|
121
121
|
*/
|
|
122
122
|
export const SERVICE = 'service';
|
|
123
|
+
/**
|
|
124
|
+
* Binding tag for the service interface
|
|
125
|
+
*/
|
|
126
|
+
export const SERVICE_INTERFACE = 'serviceInterface';
|
|
123
127
|
|
|
124
128
|
/**
|
|
125
129
|
* Binding tag for life cycle observers
|
package/src/service.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// Copyright IBM Corp. 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
|
+
BindingFilter,
|
|
9
|
+
BindingTemplate,
|
|
10
|
+
bindingTemplateFor,
|
|
11
|
+
Constructor,
|
|
12
|
+
ContextTags,
|
|
13
|
+
ContextView,
|
|
14
|
+
createBindingFromClass,
|
|
15
|
+
inject,
|
|
16
|
+
InjectionMetadata,
|
|
17
|
+
isProviderClass,
|
|
18
|
+
MetadataInspector,
|
|
19
|
+
Provider,
|
|
20
|
+
transformValueOrPromise,
|
|
21
|
+
} from '@loopback/context';
|
|
22
|
+
import {CoreTags} from './keys';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Representing an interface for services. In TypeScript, the `interface` does
|
|
26
|
+
* not have reflections at runtime. We use a string, a symbol or a Function as
|
|
27
|
+
* the type for the service interface.
|
|
28
|
+
*/
|
|
29
|
+
export type ServiceInterface = string | symbol | Function;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Options to register a service binding
|
|
33
|
+
*/
|
|
34
|
+
export type ServiceOptions = {
|
|
35
|
+
name?: string;
|
|
36
|
+
interface?: ServiceInterface;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* `@service` injects a service instance that matches the class or interface.
|
|
41
|
+
*
|
|
42
|
+
* @param serviceInterface - Interface for the service. It can be in one of the
|
|
43
|
+
* following forms:
|
|
44
|
+
*
|
|
45
|
+
* - A class, such as MyService
|
|
46
|
+
* - A string that identifies the interface, such as `'MyService'`
|
|
47
|
+
* - A symbol that identifies the interface, such as `Symbol('MyService')`
|
|
48
|
+
*
|
|
49
|
+
* If not provided, the value is inferred from the design:type of the parameter
|
|
50
|
+
* or property
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
*
|
|
55
|
+
* const ctx = new Context();
|
|
56
|
+
* ctx.bind('my-service').toClass(MyService);
|
|
57
|
+
* ctx.bind('logger').toClass(Logger);
|
|
58
|
+
*
|
|
59
|
+
* export class MyController {
|
|
60
|
+
* constructor(@service(MyService) private myService: MyService) {}
|
|
61
|
+
*
|
|
62
|
+
* @service()
|
|
63
|
+
* private logger: Logger;
|
|
64
|
+
* }
|
|
65
|
+
*
|
|
66
|
+
* ctx.bind('my-controller').toClass(MyController);
|
|
67
|
+
* await myController = ctx.get<MyController>('my-controller');
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function service(
|
|
71
|
+
serviceInterface?: ServiceInterface,
|
|
72
|
+
metadata?: InjectionMetadata,
|
|
73
|
+
) {
|
|
74
|
+
return inject(
|
|
75
|
+
'',
|
|
76
|
+
{decorator: '@service', ...metadata},
|
|
77
|
+
(ctx, injection, session) => {
|
|
78
|
+
let serviceType = serviceInterface;
|
|
79
|
+
if (!serviceType) {
|
|
80
|
+
if (typeof injection.methodDescriptorOrParameterIndex === 'number') {
|
|
81
|
+
serviceType = MetadataInspector.getDesignTypeForMethod(
|
|
82
|
+
injection.target,
|
|
83
|
+
injection.member!,
|
|
84
|
+
).parameterTypes[injection.methodDescriptorOrParameterIndex];
|
|
85
|
+
} else {
|
|
86
|
+
serviceType = MetadataInspector.getDesignTypeForProperty(
|
|
87
|
+
injection.target,
|
|
88
|
+
injection.member!,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (serviceType === Object || serviceType === Array) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
'Service class cannot be inferred from design type. Use @service(ServiceClass).',
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const view = new ContextView(ctx, filterByServiceInterface(serviceType));
|
|
98
|
+
const result = view.resolve(session);
|
|
99
|
+
|
|
100
|
+
const serviceTypeName =
|
|
101
|
+
typeof serviceType === 'string'
|
|
102
|
+
? serviceType
|
|
103
|
+
: typeof serviceType === 'symbol'
|
|
104
|
+
? serviceType.toString()
|
|
105
|
+
: serviceType.name;
|
|
106
|
+
return transformValueOrPromise(result, values => {
|
|
107
|
+
if (values.length === 1) return values[0];
|
|
108
|
+
if (values.length >= 1) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`More than one bindings found for ${serviceTypeName}`,
|
|
111
|
+
);
|
|
112
|
+
} else {
|
|
113
|
+
if (metadata?.optional) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
throw new Error(
|
|
117
|
+
`No binding found for ${serviceTypeName}. Make sure a service ` +
|
|
118
|
+
`binding is created in context ${ctx.name} with serviceInterface (${serviceTypeName}).`,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Create a binding filter by service class
|
|
128
|
+
* @param serviceInterface - Service class matching the one used by `binding.toClass()`
|
|
129
|
+
* @param options - Options to control if subclasses should be skipped for matching
|
|
130
|
+
*/
|
|
131
|
+
export function filterByServiceInterface(
|
|
132
|
+
serviceInterface: ServiceInterface,
|
|
133
|
+
): BindingFilter {
|
|
134
|
+
return binding =>
|
|
135
|
+
binding.valueConstructor === serviceInterface ||
|
|
136
|
+
binding.tagMap[CoreTags.SERVICE_INTERFACE] === serviceInterface;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Create a service binding from a class or provider
|
|
141
|
+
* @param cls - Service class or provider
|
|
142
|
+
* @param options - Service options
|
|
143
|
+
*/
|
|
144
|
+
export function createServiceBinding<S>(
|
|
145
|
+
cls: Constructor<S> | Constructor<Provider<S>>,
|
|
146
|
+
options: ServiceOptions = {},
|
|
147
|
+
): Binding<S> {
|
|
148
|
+
let name = options.name;
|
|
149
|
+
if (!name && isProviderClass(cls)) {
|
|
150
|
+
// Trim `Provider` from the default service name
|
|
151
|
+
// This is needed to keep backward compatibility
|
|
152
|
+
const templateFn = bindingTemplateFor(cls);
|
|
153
|
+
const template = Binding.bind<S>('template').apply(templateFn);
|
|
154
|
+
if (
|
|
155
|
+
template.tagMap[ContextTags.PROVIDER] &&
|
|
156
|
+
!template.tagMap[ContextTags.NAME]
|
|
157
|
+
) {
|
|
158
|
+
// The class is a provider and no `name` tag is found
|
|
159
|
+
name = cls.name.replace(/Provider$/, '');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const binding = createBindingFromClass(cls, {
|
|
163
|
+
name,
|
|
164
|
+
type: CoreTags.SERVICE,
|
|
165
|
+
}).apply(asService(options.interface ?? cls));
|
|
166
|
+
return binding;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Create a binding template for a service interface
|
|
171
|
+
* @param serviceInterface - Service interface
|
|
172
|
+
*/
|
|
173
|
+
export function asService(serviceInterface: ServiceInterface): BindingTemplate {
|
|
174
|
+
return function serviceTemplate(binding: Binding) {
|
|
175
|
+
binding.tag({
|
|
176
|
+
[ContextTags.TYPE]: CoreTags.SERVICE,
|
|
177
|
+
[CoreTags.SERVICE_INTERFACE]: serviceInterface,
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
}
|