@loopback/boot 2.1.1 → 2.3.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/.sandbox/{11889PRvhvm → 635411GGsm1}/model-endpoints/no-entity.rest-config.js +0 -0
- package/dist/.sandbox/635411GGsm1/models/no-entity.model.js +28 -0
- package/dist/.sandbox/{11889wtTpPA → 635415cxfJi}/service-provider.artifact.js +1 -0
- package/dist/.sandbox/{118893KtxoA → 635419mu8mo}/application.js +1 -0
- package/dist/.sandbox/{11889S6GDvS → 635419mu8mo}/services/bindable-classes.service.js +26 -19
- package/dist/.sandbox/{11889S6GDvS → 635419mu8mo}/services/geocoder.service.js +1 -0
- package/dist/.sandbox/{11889S6GDvS → 635419mu8mo}/services/greeting.service.js +1 -0
- package/dist/.sandbox/{11889K8KL2J → 635419t6TqH}/datasource.artifact.js +9 -5
- package/dist/.sandbox/63541BtDxTa/multiple.artifact.js +45 -0
- package/dist/.sandbox/{11889CQQ0nI → 63541DlS0Ic}/application.js +1 -0
- package/dist/.sandbox/63541DlS0Ic/repositories/multiple.repository.js +45 -0
- package/dist/.sandbox/{118896Rj4ze → 63541DshyBF}/application.js +1 -0
- package/dist/.sandbox/{118893KtxoA → 63541DshyBF}/observers/lifecycle-observer.observer.js +1 -0
- package/dist/.sandbox/{11889DQbyT8 → 63541IEce5V}/application.js +1 -0
- package/dist/.sandbox/{11889zAsxZb → 63541IEce5V}/datasources/db.datasource.js +9 -5
- package/dist/.sandbox/63541ik89oh/application.js +20 -0
- package/dist/.sandbox/63541ik89oh/models/multiple-models.model.js +16 -0
- package/dist/.sandbox/63541ik89oh/models/no-entity.model.js +28 -0
- package/dist/.sandbox/63541ik89oh/models/product.model.js +28 -0
- package/dist/.sandbox/63541meTxP7/application.js +20 -0
- package/dist/.sandbox/63541meTxP7/controllers/multiple.controller.js +45 -0
- package/dist/.sandbox/{11889DQbyT8 → 63541meTxP7}/package.json +0 -0
- package/dist/.sandbox/63541nGmQFL/application.js +20 -0
- package/dist/.sandbox/63541nGmQFL/controllers/multiple.controller.js +45 -0
- package/dist/.sandbox/{11889mdaOd9 → 63541odlHvc}/model-endpoints/product.rest-config.js +0 -0
- package/dist/.sandbox/63541odlHvc/models/product.model.js +28 -0
- package/dist/.sandbox/63541ruUDNf/application.js +20 -0
- package/dist/.sandbox/63541ruUDNf/interceptors/interceptor.interceptor.js +54 -0
- package/dist/.sandbox/63541ruUDNf/interceptors/non-global-interceptor.interceptor.js +54 -0
- package/dist/.sandbox/63541vSi6af/multiple.artifact.js +45 -0
- package/dist/.sandbox/application.js +20 -0
- package/dist/.sandbox/controllers/multiple.controller.js +45 -0
- package/dist/boot.component.d.ts +2 -2
- package/dist/boot.component.js +34 -29
- package/dist/boot.component.js.map +1 -1
- package/dist/booters/application-metadata.booter.js +23 -19
- package/dist/booters/application-metadata.booter.js.map +1 -1
- package/dist/booters/base-artifact.booter.js +1 -0
- package/dist/booters/base-artifact.booter.js.map +1 -1
- package/dist/booters/booter-utils.js +1 -0
- package/dist/booters/booter-utils.js.map +1 -1
- package/dist/booters/component-application.booter.d.ts +25 -0
- package/dist/booters/component-application.booter.js +99 -0
- package/dist/booters/component-application.booter.js.map +1 -0
- package/dist/booters/controller.booter.js +30 -26
- package/dist/booters/controller.booter.js.map +1 -1
- package/dist/booters/datasource.booter.d.ts +1 -1
- package/dist/booters/datasource.booter.js +40 -36
- package/dist/booters/datasource.booter.js.map +1 -1
- package/dist/booters/index.d.ts +2 -0
- package/dist/booters/index.js +2 -0
- package/dist/booters/index.js.map +1 -1
- package/dist/booters/interceptor.booter.js +32 -31
- package/dist/booters/interceptor.booter.js.map +1 -1
- package/dist/booters/lifecyle-observer.booter.js +32 -28
- package/dist/booters/lifecyle-observer.booter.js.map +1 -1
- package/dist/booters/model-api.booter.js +67 -63
- package/dist/booters/model-api.booter.js.map +1 -1
- package/dist/booters/model.booter.d.ts +26 -0
- package/dist/booters/model.booter.js +74 -0
- package/dist/booters/model.booter.js.map +1 -0
- package/dist/booters/repository.booter.js +39 -35
- package/dist/booters/repository.booter.js.map +1 -1
- package/dist/booters/service.booter.d.ts +1 -1
- package/dist/booters/service.booter.js +34 -30
- package/dist/booters/service.booter.js.map +1 -1
- package/dist/bootstrapper.js +85 -81
- package/dist/bootstrapper.js.map +1 -1
- package/dist/keys.js +1 -0
- package/dist/keys.js.map +1 -1
- package/dist/mixins/boot.mixin.d.ts +84 -15
- package/dist/mixins/boot.mixin.js +40 -20
- package/dist/mixins/boot.mixin.js.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +17 -17
- package/src/boot.component.ts +2 -0
- package/src/booters/component-application.booter.ts +123 -0
- package/src/booters/datasource.booter.ts +1 -1
- package/src/booters/index.ts +2 -0
- package/src/booters/interceptor.booter.ts +1 -6
- package/src/booters/model.booter.ts +76 -0
- package/src/booters/service.booter.ts +1 -1
- package/src/mixins/boot.mixin.ts +84 -20
- package/dist/.sandbox/118896Rj4ze/repositories/multiple.repository.js +0 -38
- package/dist/.sandbox/11889CQQ0nI/controllers/multiple.controller.js +0 -38
- package/dist/.sandbox/11889DQbyT8/controllers/multiple.controller.js +0 -38
- package/dist/.sandbox/11889PRvhvm/models/no-entity.model.js +0 -24
- package/dist/.sandbox/11889S6GDvS/application.js +0 -19
- package/dist/.sandbox/11889SgiPny/multiple.artifact.js +0 -38
- package/dist/.sandbox/11889SuGYhr/application.js +0 -19
- package/dist/.sandbox/11889SuGYhr/interceptors/interceptor.interceptor.js +0 -50
- package/dist/.sandbox/11889SuGYhr/interceptors/non-global-interceptor.interceptor.js +0 -50
- package/dist/.sandbox/11889mdaOd9/models/product.model.js +0 -24
- package/dist/.sandbox/11889t5aVl4/multiple.artifact.js +0 -38
- package/dist/.sandbox/11889zAsxZb/application.js +0 -19
- package/dist/.sandbox/dist/application.js +0 -19
- package/index.d.ts +0 -6
- package/index.js +0 -6
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
// This file is licensed under the MIT License.
|
|
5
5
|
// License text available at https://opensource.org/licenses/MIT
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports._bindBooter = exports.BootMixin = exports.Binding = void 0;
|
|
7
8
|
const context_1 = require("@loopback/context");
|
|
8
|
-
exports
|
|
9
|
+
Object.defineProperty(exports, "Binding", { enumerable: true, get: function () { return context_1.Binding; } });
|
|
9
10
|
const boot_component_1 = require("../boot.component");
|
|
11
|
+
const component_application_booter_1 = require("../booters/component-application.booter");
|
|
10
12
|
const keys_1 = require("../keys");
|
|
11
13
|
/**
|
|
12
14
|
* Mixin for @loopback/boot. This Mixin provides the following:
|
|
@@ -19,17 +21,7 @@ const keys_1 = require("../keys");
|
|
|
19
21
|
* - Provides the `booter()` convenience method to bind a Booter(s) to the Application
|
|
20
22
|
* - Override `component()` to call `mountComponentBooters`
|
|
21
23
|
* - Adds `mountComponentBooters` which binds Booters to the application from `component.booters[]`
|
|
22
|
-
*
|
|
23
|
-
* ******************** NOTE ********************
|
|
24
|
-
* Trying to constrain the type of this Mixin (or any Mixin) will cause errors.
|
|
25
|
-
* For example, constraining this Mixin to type Application require all types using by
|
|
26
|
-
* Application to be imported (including it's dependencies such as ResolutionSession).
|
|
27
|
-
* Another issue was that if a Mixin that is type constrained is used with another Mixin
|
|
28
|
-
* that is not, it will result in an error.
|
|
29
|
-
* Example (class MyApp extends BootMixin(RepositoryMixin(Application))) {};
|
|
30
|
-
********************* END OF NOTE ********************
|
|
31
24
|
*/
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
25
|
function BootMixin(superClass) {
|
|
34
26
|
return class extends superClass {
|
|
35
27
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -39,23 +31,33 @@ function BootMixin(superClass) {
|
|
|
39
31
|
// We Dynamically bind the Project Root and Boot Options so these values can
|
|
40
32
|
// be used to resolve an instance of the Bootstrapper (as they are dependencies)
|
|
41
33
|
this.bind(keys_1.BootBindings.PROJECT_ROOT).toDynamicValue(() => this.projectRoot);
|
|
42
|
-
this.bind(keys_1.BootBindings.BOOT_OPTIONS).toDynamicValue(() => this.bootOptions);
|
|
34
|
+
this.bind(keys_1.BootBindings.BOOT_OPTIONS).toDynamicValue(() => { var _a; return (_a = this.bootOptions) !== null && _a !== void 0 ? _a : {}; });
|
|
43
35
|
}
|
|
44
36
|
/**
|
|
45
37
|
* Convenience method to call bootstrapper.boot() by resolving bootstrapper
|
|
46
38
|
*/
|
|
47
39
|
async boot() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this
|
|
51
|
-
this.
|
|
40
|
+
/* eslint-disable @typescript-eslint/ban-ts-ignore */
|
|
41
|
+
// A workaround to access protected Application methods
|
|
42
|
+
const self = this;
|
|
43
|
+
if (this.state === 'booting') {
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
return self.awaitState('booted');
|
|
46
|
+
}
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
self.assertNotInProcess('boot');
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
self.assertInStates('boot', 'created', 'booted');
|
|
52
51
|
if (this.state === 'booted')
|
|
53
52
|
return;
|
|
54
|
-
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
self.setState('booting');
|
|
55
55
|
// Get a instance of the BootStrapper
|
|
56
56
|
const bootstrapper = await this.get(keys_1.BootBindings.BOOTSTRAPPER_KEY);
|
|
57
57
|
await bootstrapper.boot();
|
|
58
|
+
// @ts-ignore
|
|
58
59
|
this.setState('booted');
|
|
60
|
+
/* eslint-enable @typescript-eslint/ban-ts-ignore */
|
|
59
61
|
}
|
|
60
62
|
/**
|
|
61
63
|
* Given a N number of Booter Classes, this method binds them using the
|
|
@@ -71,6 +73,19 @@ function BootMixin(superClass) {
|
|
|
71
73
|
booters(...booterCls) {
|
|
72
74
|
return booterCls.map(cls => _bindBooter(this, cls));
|
|
73
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Register a booter to boot a sub-application. See
|
|
78
|
+
* {@link createComponentApplicationBooterBinding} for more details.
|
|
79
|
+
*
|
|
80
|
+
* @param subApp - A sub-application with artifacts to be booted
|
|
81
|
+
* @param filter - A binding filter to select what bindings from the sub
|
|
82
|
+
* application should be added to the main application.
|
|
83
|
+
*/
|
|
84
|
+
applicationBooter(subApp, filter) {
|
|
85
|
+
const binding = component_application_booter_1.createComponentApplicationBooterBinding(subApp, filter);
|
|
86
|
+
this.add(binding);
|
|
87
|
+
return binding;
|
|
88
|
+
}
|
|
74
89
|
/**
|
|
75
90
|
* Override to ensure any Booter's on a Component are also mounted.
|
|
76
91
|
*
|
|
@@ -90,9 +105,14 @@ function BootMixin(superClass) {
|
|
|
90
105
|
* app.component(ProductComponent);
|
|
91
106
|
* ```
|
|
92
107
|
*/
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
// Unfortunately, TypeScript does not allow overriding methods inherited
|
|
109
|
+
// from mapped types. https://github.com/microsoft/TypeScript/issues/38496
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
component(componentCtor, nameOrOptions) {
|
|
113
|
+
const binding = super.component(componentCtor, nameOrOptions);
|
|
114
|
+
this.mountComponentBooters(componentCtor);
|
|
115
|
+
return binding;
|
|
96
116
|
}
|
|
97
117
|
/**
|
|
98
118
|
* Get an instance of a component and mount all it's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot.mixin.js","sourceRoot":"","sources":["../../src/mixins/boot.mixin.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE
|
|
1
|
+
{"version":3,"file":"boot.mixin.js","sourceRoot":"","sources":["../../src/mixins/boot.mixin.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// This file is licensed under the MIT License.
|
|
5
5
|
// License text available at https://opensource.org/licenses/MIT
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.booter = exports.BOOTER_PHASES = void 0;
|
|
7
8
|
const context_1 = require("@loopback/context");
|
|
8
9
|
const keys_1 = require("./keys");
|
|
9
10
|
/**
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;AAEhE,+CAA0E;AAC1E,iCAAgC;AAoDhC;;;GAGG;AACU,QAAA,aAAa,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAmE/D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,MAAM,CAAC,iBAAyB,EAAE,GAAG,KAAoB;IACvE,OAAO,cAAI,CACT,EAAC,IAAI,EAAE,EAAC,iBAAiB,EAAE,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,eAAQ,CAAC,MAAM,EAAC,EAAC,EAC/D,GAAG,KAAK,CACT,CAAC;AACJ,CAAC;AALD,wBAKC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopback/boot",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "A collection of Booters for LoopBack 4 Applications",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
5
7
|
"engines": {
|
|
6
8
|
"node": ">=10"
|
|
7
9
|
},
|
|
@@ -22,30 +24,28 @@
|
|
|
22
24
|
"copyright.owner": "IBM Corp.",
|
|
23
25
|
"license": "MIT",
|
|
24
26
|
"dependencies": {
|
|
25
|
-
"@loopback/context": "^3.
|
|
26
|
-
"@loopback/core": "^2.
|
|
27
|
-
"@loopback/model-api-builder": "^2.1.
|
|
28
|
-
"@loopback/repository": "^2.
|
|
29
|
-
"@loopback/service-proxy": "^2.
|
|
27
|
+
"@loopback/context": "^3.8.1",
|
|
28
|
+
"@loopback/core": "^2.7.0",
|
|
29
|
+
"@loopback/model-api-builder": "^2.1.5",
|
|
30
|
+
"@loopback/repository": "^2.5.1",
|
|
31
|
+
"@loopback/service-proxy": "^2.3.0",
|
|
30
32
|
"@types/debug": "^4.1.5",
|
|
31
33
|
"@types/glob": "^7.1.1",
|
|
32
34
|
"debug": "^4.1.1",
|
|
33
35
|
"glob": "^7.1.6",
|
|
34
|
-
"tslib": "^
|
|
36
|
+
"tslib": "^2.0.0"
|
|
35
37
|
},
|
|
36
38
|
"devDependencies": {
|
|
37
|
-
"@loopback/build": "^5.
|
|
38
|
-
"@loopback/eslint-config": "^
|
|
39
|
-
"@loopback/openapi-v3": "^3.
|
|
40
|
-
"@loopback/rest": "^
|
|
41
|
-
"@loopback/rest-crud": "^0.8.
|
|
42
|
-
"@loopback/testlab": "^3.1.
|
|
43
|
-
"@types/node": "^10.17.
|
|
39
|
+
"@loopback/build": "^5.4.1",
|
|
40
|
+
"@loopback/eslint-config": "^7.0.1",
|
|
41
|
+
"@loopback/openapi-v3": "^3.4.1",
|
|
42
|
+
"@loopback/rest": "^5.0.1",
|
|
43
|
+
"@loopback/rest-crud": "^0.8.5",
|
|
44
|
+
"@loopback/testlab": "^3.1.5",
|
|
45
|
+
"@types/node": "^10.17.24"
|
|
44
46
|
},
|
|
45
47
|
"files": [
|
|
46
48
|
"README.md",
|
|
47
|
-
"index.js",
|
|
48
|
-
"index.d.ts",
|
|
49
49
|
"dist",
|
|
50
50
|
"src",
|
|
51
51
|
"!*/__tests__"
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"url": "https://github.com/strongloop/loopback-next.git",
|
|
56
56
|
"directory": "packages/boot"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "62aea854bf85c5a5995b59e6908fe5409f7eea96"
|
|
59
59
|
}
|
package/src/boot.component.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
InterceptorProviderBooter,
|
|
13
13
|
LifeCycleObserverBooter,
|
|
14
14
|
ModelApiBooter,
|
|
15
|
+
ModelBooter,
|
|
15
16
|
RepositoryBooter,
|
|
16
17
|
ServiceBooter,
|
|
17
18
|
} from './booters';
|
|
@@ -35,6 +36,7 @@ export class BootComponent implements Component {
|
|
|
35
36
|
LifeCycleObserverBooter,
|
|
36
37
|
InterceptorProviderBooter,
|
|
37
38
|
ModelApiBooter,
|
|
39
|
+
ModelBooter,
|
|
38
40
|
];
|
|
39
41
|
|
|
40
42
|
/**
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/boot
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Application,
|
|
8
|
+
Binding,
|
|
9
|
+
BindingFilter,
|
|
10
|
+
Constructor,
|
|
11
|
+
CoreBindings,
|
|
12
|
+
createBindingFromClass,
|
|
13
|
+
inject,
|
|
14
|
+
} from '@loopback/core';
|
|
15
|
+
import debugFactory from 'debug';
|
|
16
|
+
import {BootBindings} from '../keys';
|
|
17
|
+
import {Bootable, Booter, booter} from '../types';
|
|
18
|
+
|
|
19
|
+
const debug = debugFactory('loopback:boot:booter:component-application');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Binding keys excluded from a sub application. These bindings booted from the
|
|
23
|
+
* sub application won't be added to the main application.
|
|
24
|
+
*/
|
|
25
|
+
export const bindingKeysExcludedFromSubApp = [
|
|
26
|
+
BootBindings.BOOT_OPTIONS.key,
|
|
27
|
+
BootBindings.PROJECT_ROOT.key,
|
|
28
|
+
BootBindings.BOOTSTRAPPER_KEY.key,
|
|
29
|
+
CoreBindings.APPLICATION_CONFIG.key,
|
|
30
|
+
CoreBindings.APPLICATION_INSTANCE.key,
|
|
31
|
+
CoreBindings.APPLICATION_METADATA.key,
|
|
32
|
+
CoreBindings.LIFE_CYCLE_OBSERVER_REGISTRY.key,
|
|
33
|
+
CoreBindings.LIFE_CYCLE_OBSERVER_OPTIONS.key,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a booter that boots the component application. Bindings that exist
|
|
38
|
+
* in the component application before `boot` are skipped. Locked bindings in
|
|
39
|
+
* the main application will not be overridden.
|
|
40
|
+
*
|
|
41
|
+
* @param componentApp - The application exposing a component
|
|
42
|
+
* @param filter Binding filter to selected bindings to be added
|
|
43
|
+
*/
|
|
44
|
+
export function createBooterForComponentApplication(
|
|
45
|
+
componentApp: Application & Bootable,
|
|
46
|
+
filter: BindingFilter = () => true,
|
|
47
|
+
): Constructor<Booter> {
|
|
48
|
+
/**
|
|
49
|
+
* A booter to boot artifacts for the component application
|
|
50
|
+
*/
|
|
51
|
+
@booter('componentApplications')
|
|
52
|
+
class ComponentApplicationBooter implements Booter {
|
|
53
|
+
constructor(
|
|
54
|
+
@inject(CoreBindings.APPLICATION_INSTANCE) private mainApp: Application,
|
|
55
|
+
) {}
|
|
56
|
+
|
|
57
|
+
async load() {
|
|
58
|
+
/**
|
|
59
|
+
* List all bindings before boot
|
|
60
|
+
*/
|
|
61
|
+
let bindings = componentApp.find(() => true);
|
|
62
|
+
const bindingsBeforeBoot = new Set(bindings);
|
|
63
|
+
// Boot the component application
|
|
64
|
+
await componentApp.boot();
|
|
65
|
+
/**
|
|
66
|
+
* Add bindings from the component application to the main application
|
|
67
|
+
*/
|
|
68
|
+
bindings = componentApp.find(filter);
|
|
69
|
+
for (const binding of bindings) {
|
|
70
|
+
// Exclude boot related bindings
|
|
71
|
+
if (bindingKeysExcludedFromSubApp.includes(binding.key)) continue;
|
|
72
|
+
|
|
73
|
+
// Exclude bindings from the app before boot
|
|
74
|
+
if (bindingsBeforeBoot.has(binding)) {
|
|
75
|
+
debug(
|
|
76
|
+
'Skipping binding %s that exists before booting %s',
|
|
77
|
+
binding.key,
|
|
78
|
+
componentApp.name,
|
|
79
|
+
);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Do not override locked bindings
|
|
84
|
+
const locked = this.mainApp.find(binding.key).some(b => b.isLocked);
|
|
85
|
+
if (locked) {
|
|
86
|
+
debug(
|
|
87
|
+
'Skipping binding %s from %s - locked in %s',
|
|
88
|
+
binding.key,
|
|
89
|
+
componentApp.name,
|
|
90
|
+
this.mainApp.name,
|
|
91
|
+
);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
debug(
|
|
96
|
+
'Adding binding from %s to %s',
|
|
97
|
+
componentApp.name,
|
|
98
|
+
this.mainApp.name,
|
|
99
|
+
binding,
|
|
100
|
+
);
|
|
101
|
+
this.mainApp.add(binding as Binding);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return ComponentApplicationBooter;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Create a binding to register a booter that boots the component application.
|
|
110
|
+
* Bindings that exist in the component application before `boot` are skipped.
|
|
111
|
+
* Locked bindings in the main application will not be overridden.
|
|
112
|
+
*
|
|
113
|
+
* @param componentApp - The application exposing a component
|
|
114
|
+
* @param filter Binding filter to selected bindings to be added
|
|
115
|
+
*/
|
|
116
|
+
export function createComponentApplicationBooterBinding(
|
|
117
|
+
componentApp: Application & Bootable,
|
|
118
|
+
filter?: BindingFilter,
|
|
119
|
+
) {
|
|
120
|
+
return createBindingFromClass(
|
|
121
|
+
createBooterForComponentApplication(componentApp, filter),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
@@ -16,7 +16,7 @@ import {BaseArtifactBooter} from './base-artifact.booter';
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* A class that extends BaseArtifactBooter to boot the 'DataSource' artifact type.
|
|
19
|
-
* Discovered DataSources are bound using `app.
|
|
19
|
+
* Discovered DataSources are bound using `app.dataSource()`.
|
|
20
20
|
*
|
|
21
21
|
* Supported phases: configure, discover, load
|
|
22
22
|
*
|
package/src/booters/index.ts
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
export * from './application-metadata.booter';
|
|
7
7
|
export * from './base-artifact.booter';
|
|
8
8
|
export * from './booter-utils';
|
|
9
|
+
export * from './component-application.booter';
|
|
9
10
|
export * from './controller.booter';
|
|
10
11
|
export * from './datasource.booter';
|
|
11
12
|
export * from './interceptor.booter';
|
|
12
13
|
export * from './lifecyle-observer.booter';
|
|
13
14
|
export * from './model-api.booter';
|
|
15
|
+
export * from './model.booter';
|
|
14
16
|
export * from './repository.booter';
|
|
15
17
|
export * from './service.booter';
|
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
BindingScope,
|
|
8
7
|
config,
|
|
9
8
|
Constructor,
|
|
10
|
-
createBindingFromClass,
|
|
11
9
|
inject,
|
|
12
10
|
Interceptor,
|
|
13
11
|
Provider,
|
|
@@ -59,10 +57,7 @@ export class InterceptorProviderBooter extends BaseArtifactBooter {
|
|
|
59
57
|
this.interceptors = this.classes as InterceptorProviderClass[];
|
|
60
58
|
for (const interceptor of this.interceptors) {
|
|
61
59
|
debug('Bind interceptor: %s', interceptor.name);
|
|
62
|
-
const binding =
|
|
63
|
-
defaultScope: BindingScope.TRANSIENT,
|
|
64
|
-
});
|
|
65
|
-
this.app.add(binding);
|
|
60
|
+
const binding = this.app.interceptor(interceptor);
|
|
66
61
|
debug('Binding created for interceptor: %j', binding);
|
|
67
62
|
}
|
|
68
63
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/boot
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {config, Constructor, inject} from '@loopback/context';
|
|
7
|
+
import {CoreBindings} from '@loopback/core';
|
|
8
|
+
import {
|
|
9
|
+
ApplicationWithRepositories,
|
|
10
|
+
ModelMetadataHelper,
|
|
11
|
+
} from '@loopback/repository';
|
|
12
|
+
import debugFactory from 'debug';
|
|
13
|
+
import {BootBindings} from '../keys';
|
|
14
|
+
import {ArtifactOptions, booter} from '../types';
|
|
15
|
+
import {BaseArtifactBooter} from './base-artifact.booter';
|
|
16
|
+
|
|
17
|
+
const debug = debugFactory('loopback:boot:model-booter');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A class that extends BaseArtifactBooter to boot the 'Model' artifact type.
|
|
21
|
+
*
|
|
22
|
+
* Supported phases: configure, discover, load
|
|
23
|
+
*
|
|
24
|
+
* @param app - Application instance
|
|
25
|
+
* @param projectRoot - Root of User Project relative to which all paths are resolved
|
|
26
|
+
* @param bootConfig - Model Artifact Options Object
|
|
27
|
+
*/
|
|
28
|
+
@booter('models')
|
|
29
|
+
export class ModelBooter extends BaseArtifactBooter {
|
|
30
|
+
constructor(
|
|
31
|
+
@inject(CoreBindings.APPLICATION_INSTANCE)
|
|
32
|
+
public app: ApplicationWithRepositories,
|
|
33
|
+
@inject(BootBindings.PROJECT_ROOT) projectRoot: string,
|
|
34
|
+
@config()
|
|
35
|
+
public modelConfig: ArtifactOptions = {},
|
|
36
|
+
) {
|
|
37
|
+
super(
|
|
38
|
+
projectRoot,
|
|
39
|
+
// Set Model Booter Options if passed in via bootConfig
|
|
40
|
+
Object.assign({}, ModelDefaults, modelConfig),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Uses super method to get a list of Artifact classes. Boot each file by
|
|
46
|
+
* creating a DataSourceConstructor and binding it to the application class.
|
|
47
|
+
*/
|
|
48
|
+
async load() {
|
|
49
|
+
await super.load();
|
|
50
|
+
|
|
51
|
+
for (const cls of this.classes) {
|
|
52
|
+
if (!isModelClass(cls)) {
|
|
53
|
+
debug('Skipping class %s - no @model is found', cls.name);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
debug('Bind class: %s', cls.name);
|
|
58
|
+
// We are binding the model class itself
|
|
59
|
+
const binding = this.app.model(cls);
|
|
60
|
+
debug('Binding created for model class %s: %j', cls.name, binding);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Default ArtifactOptions for DataSourceBooter.
|
|
67
|
+
*/
|
|
68
|
+
export const ModelDefaults: ArtifactOptions = {
|
|
69
|
+
dirs: ['models'],
|
|
70
|
+
extensions: ['.model.js'],
|
|
71
|
+
nested: true,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
function isModelClass(cls: Constructor<unknown>) {
|
|
75
|
+
return ModelMetadataHelper.getModelMetadata(cls) != null;
|
|
76
|
+
}
|
|
@@ -21,7 +21,7 @@ const debug = debugFactory('loopback:boot:service-booter');
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* A class that extends BaseArtifactBooter to boot the 'Service' artifact type.
|
|
24
|
-
* Discovered
|
|
24
|
+
* Discovered services are bound using `app.service()`.
|
|
25
25
|
*
|
|
26
26
|
* Supported phases: configure, discover, load
|
|
27
27
|
*
|
package/src/mixins/boot.mixin.ts
CHANGED
|
@@ -5,16 +5,50 @@
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
Binding,
|
|
8
|
+
BindingFilter,
|
|
9
|
+
BindingFromClassOptions,
|
|
8
10
|
BindingScope,
|
|
9
11
|
Constructor,
|
|
10
12
|
Context,
|
|
11
13
|
createBindingFromClass,
|
|
12
14
|
} from '@loopback/context';
|
|
15
|
+
import {Application, Component, MixinTarget} from '@loopback/core';
|
|
13
16
|
import {BootComponent} from '../boot.component';
|
|
17
|
+
import {createComponentApplicationBooterBinding} from '../booters/component-application.booter';
|
|
14
18
|
import {Bootstrapper} from '../bootstrapper';
|
|
15
19
|
import {BootBindings, BootTags} from '../keys';
|
|
16
20
|
import {Bootable, Booter, BootOptions} from '../types';
|
|
17
21
|
|
|
22
|
+
// FIXME(rfeng): Workaround for https://github.com/microsoft/rushstack/pull/1867
|
|
23
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
24
|
+
import {
|
|
25
|
+
BindingAddress,
|
|
26
|
+
JSONObject,
|
|
27
|
+
Provider,
|
|
28
|
+
ContextSubscriptionManager,
|
|
29
|
+
ContextEvent,
|
|
30
|
+
Interceptor,
|
|
31
|
+
InterceptorBindingOptions,
|
|
32
|
+
ResolutionOptions,
|
|
33
|
+
BindingKey,
|
|
34
|
+
ValueOrPromise,
|
|
35
|
+
ContextEventObserver,
|
|
36
|
+
ContextObserver,
|
|
37
|
+
Subscription,
|
|
38
|
+
BindingComparator,
|
|
39
|
+
ContextView,
|
|
40
|
+
ResolutionSession,
|
|
41
|
+
BindingCreationPolicy,
|
|
42
|
+
ContextInspectOptions,
|
|
43
|
+
} from '@loopback/context';
|
|
44
|
+
import {
|
|
45
|
+
Server,
|
|
46
|
+
ApplicationConfig,
|
|
47
|
+
ApplicationMetadata,
|
|
48
|
+
LifeCycleObserver,
|
|
49
|
+
ServiceOptions,
|
|
50
|
+
} from '@loopback/core';
|
|
51
|
+
|
|
18
52
|
// Binding is re-exported as Binding / Booter types are needed when consuming
|
|
19
53
|
// BootMixin and this allows a user to import them from the same package (UX!)
|
|
20
54
|
export {Binding};
|
|
@@ -30,18 +64,8 @@ export {Binding};
|
|
|
30
64
|
* - Provides the `booter()` convenience method to bind a Booter(s) to the Application
|
|
31
65
|
* - Override `component()` to call `mountComponentBooters`
|
|
32
66
|
* - Adds `mountComponentBooters` which binds Booters to the application from `component.booters[]`
|
|
33
|
-
*
|
|
34
|
-
* ******************** NOTE ********************
|
|
35
|
-
* Trying to constrain the type of this Mixin (or any Mixin) will cause errors.
|
|
36
|
-
* For example, constraining this Mixin to type Application require all types using by
|
|
37
|
-
* Application to be imported (including it's dependencies such as ResolutionSession).
|
|
38
|
-
* Another issue was that if a Mixin that is type constrained is used with another Mixin
|
|
39
|
-
* that is not, it will result in an error.
|
|
40
|
-
* Example (class MyApp extends BootMixin(RepositoryMixin(Application))) {};
|
|
41
|
-
********************* END OF NOTE ********************
|
|
42
67
|
*/
|
|
43
|
-
|
|
44
|
-
export function BootMixin<T extends Constructor<any>>(superClass: T) {
|
|
68
|
+
export function BootMixin<T extends MixinTarget<Application>>(superClass: T) {
|
|
45
69
|
return class extends superClass implements Bootable {
|
|
46
70
|
projectRoot: string;
|
|
47
71
|
bootOptions?: BootOptions;
|
|
@@ -57,7 +81,7 @@ export function BootMixin<T extends Constructor<any>>(superClass: T) {
|
|
|
57
81
|
() => this.projectRoot,
|
|
58
82
|
);
|
|
59
83
|
this.bind(BootBindings.BOOT_OPTIONS).toDynamicValue(
|
|
60
|
-
() => this.bootOptions,
|
|
84
|
+
() => this.bootOptions ?? {},
|
|
61
85
|
);
|
|
62
86
|
}
|
|
63
87
|
|
|
@@ -65,18 +89,34 @@ export function BootMixin<T extends Constructor<any>>(superClass: T) {
|
|
|
65
89
|
* Convenience method to call bootstrapper.boot() by resolving bootstrapper
|
|
66
90
|
*/
|
|
67
91
|
async boot(): Promise<void> {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this
|
|
92
|
+
/* eslint-disable @typescript-eslint/ban-ts-ignore */
|
|
93
|
+
// A workaround to access protected Application methods
|
|
94
|
+
const self = (this as unknown) as Application;
|
|
95
|
+
|
|
96
|
+
if (this.state === 'booting') {
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
return self.awaitState('booted');
|
|
99
|
+
}
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
self.assertNotInProcess('boot');
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
self.assertInStates('boot', 'created', 'booted');
|
|
104
|
+
|
|
71
105
|
if (this.state === 'booted') return;
|
|
72
|
-
|
|
106
|
+
// @ts-ignore
|
|
107
|
+
self.setState('booting');
|
|
108
|
+
|
|
73
109
|
// Get a instance of the BootStrapper
|
|
74
110
|
const bootstrapper: Bootstrapper = await this.get(
|
|
75
111
|
BootBindings.BOOTSTRAPPER_KEY,
|
|
76
112
|
);
|
|
77
113
|
|
|
78
114
|
await bootstrapper.boot();
|
|
115
|
+
|
|
116
|
+
// @ts-ignore
|
|
79
117
|
this.setState('booted');
|
|
118
|
+
|
|
119
|
+
/* eslint-enable @typescript-eslint/ban-ts-ignore */
|
|
80
120
|
}
|
|
81
121
|
|
|
82
122
|
/**
|
|
@@ -96,6 +136,20 @@ export function BootMixin<T extends Constructor<any>>(superClass: T) {
|
|
|
96
136
|
);
|
|
97
137
|
}
|
|
98
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Register a booter to boot a sub-application. See
|
|
141
|
+
* {@link createComponentApplicationBooterBinding} for more details.
|
|
142
|
+
*
|
|
143
|
+
* @param subApp - A sub-application with artifacts to be booted
|
|
144
|
+
* @param filter - A binding filter to select what bindings from the sub
|
|
145
|
+
* application should be added to the main application.
|
|
146
|
+
*/
|
|
147
|
+
applicationBooter(subApp: Application & Bootable, filter?: BindingFilter) {
|
|
148
|
+
const binding = createComponentApplicationBooterBinding(subApp, filter);
|
|
149
|
+
this.add(binding);
|
|
150
|
+
return binding;
|
|
151
|
+
}
|
|
152
|
+
|
|
99
153
|
/**
|
|
100
154
|
* Override to ensure any Booter's on a Component are also mounted.
|
|
101
155
|
*
|
|
@@ -115,9 +169,17 @@ export function BootMixin<T extends Constructor<any>>(superClass: T) {
|
|
|
115
169
|
* app.component(ProductComponent);
|
|
116
170
|
* ```
|
|
117
171
|
*/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
172
|
+
// Unfortunately, TypeScript does not allow overriding methods inherited
|
|
173
|
+
// from mapped types. https://github.com/microsoft/TypeScript/issues/38496
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
|
175
|
+
// @ts-ignore
|
|
176
|
+
public component<C extends Component = Component>(
|
|
177
|
+
componentCtor: Constructor<C>,
|
|
178
|
+
nameOrOptions?: string | BindingFromClassOptions,
|
|
179
|
+
) {
|
|
180
|
+
const binding = super.component(componentCtor, nameOrOptions);
|
|
181
|
+
this.mountComponentBooters(componentCtor);
|
|
182
|
+
return binding;
|
|
121
183
|
}
|
|
122
184
|
|
|
123
185
|
/**
|
|
@@ -129,7 +191,9 @@ export function BootMixin<T extends Constructor<any>>(superClass: T) {
|
|
|
129
191
|
*/
|
|
130
192
|
mountComponentBooters(component: Constructor<{}>) {
|
|
131
193
|
const componentKey = `components.${component.name}`;
|
|
132
|
-
const compInstance = this.getSync
|
|
194
|
+
const compInstance = this.getSync<{
|
|
195
|
+
booters?: Constructor<Booter>[];
|
|
196
|
+
}>(componentKey);
|
|
133
197
|
|
|
134
198
|
if (compInstance.booters) {
|
|
135
199
|
this.booters(...compInstance.booters);
|