@loopback/boot 1.6.0 → 1.7.4

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 CHANGED
@@ -3,6 +3,49 @@
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.7.4](https://github.com/strongloop/loopback-next/compare/@loopback/boot@1.7.3...@loopback/boot@1.7.4) (2020-02-06)
7
+
8
+ **Note:** Version bump only for package @loopback/boot
9
+
10
+
11
+
12
+
13
+
14
+ ## [1.7.3](https://github.com/strongloop/loopback-next/compare/@loopback/boot@1.7.2...@loopback/boot@1.7.3) (2020-02-05)
15
+
16
+ **Note:** Version bump only for package @loopback/boot
17
+
18
+
19
+
20
+
21
+
22
+ ## [1.7.2](https://github.com/strongloop/loopback-next/compare/@loopback/boot@1.7.1...@loopback/boot@1.7.2) (2020-01-27)
23
+
24
+ **Note:** Version bump only for package @loopback/boot
25
+
26
+
27
+
28
+
29
+
30
+ ## [1.7.1](https://github.com/strongloop/loopback-next/compare/@loopback/boot@1.7.0...@loopback/boot@1.7.1) (2020-01-07)
31
+
32
+ **Note:** Version bump only for package @loopback/boot
33
+
34
+
35
+
36
+
37
+
38
+ # [1.7.0](https://github.com/strongloop/loopback-next/compare/@loopback/boot@1.6.0...@loopback/boot@1.7.0) (2020-01-07)
39
+
40
+
41
+ ### Features
42
+
43
+ * add model-api-builder and model-api-booter ([bacadcc](https://github.com/strongloop/loopback-next/commit/bacadcc22f6c813ee384d1d040f518190d9aae17))
44
+
45
+
46
+
47
+
48
+
6
49
  # [1.6.0](https://github.com/strongloop/loopback-next/compare/@loopback/boot@1.5.12...@loopback/boot@1.6.0) (2019-12-09)
7
50
 
8
51
 
@@ -17,4 +17,4 @@ class GeocoderServiceProvider {
17
17
  }
18
18
  exports.GeocoderServiceProvider = GeocoderServiceProvider;
19
19
  //# sourceMappingURL=service-provider.artifact.js.map
20
- //# sourceMappingURL=/Users/dhmlau/loopback-release/loopback-next/packages/boot/dist/__tests__/fixtures/service-provider.artifact.js.map
20
+ //# sourceMappingURL=/Users/rfeng/Projects/loopback4/loopback-next/packages/boot/dist/__tests__/fixtures/service-provider.artifact.js.map
@@ -1,12 +1,12 @@
1
1
  import { Application, Component } from '@loopback/core';
2
- import { ApplicationMetadataBooter, ControllerBooter, DataSourceBooter, InterceptorProviderBooter, LifeCycleObserverBooter, RepositoryBooter, ServiceBooter } from './booters';
2
+ import { ApplicationMetadataBooter, ControllerBooter, DataSourceBooter, InterceptorProviderBooter, LifeCycleObserverBooter, ModelApiBooter, RepositoryBooter, ServiceBooter } from './booters';
3
3
  /**
4
4
  * BootComponent is used to export the default list of Booter's made
5
5
  * available by this module as well as bind the BootStrapper to the app so it
6
6
  * can be used to run the Booters.
7
7
  */
8
8
  export declare class BootComponent implements Component {
9
- booters: (typeof ApplicationMetadataBooter | typeof ControllerBooter | typeof DataSourceBooter | typeof InterceptorProviderBooter | typeof LifeCycleObserverBooter | typeof RepositoryBooter | typeof ServiceBooter)[];
9
+ booters: (typeof ApplicationMetadataBooter | typeof ControllerBooter | typeof DataSourceBooter | typeof InterceptorProviderBooter | typeof LifeCycleObserverBooter | typeof ModelApiBooter | typeof RepositoryBooter | typeof ServiceBooter)[];
10
10
  /**
11
11
  *
12
12
  * @param app - Application instance
@@ -42,6 +42,7 @@ let BootComponent = class BootComponent {
42
42
  booters_1.DataSourceBooter,
43
43
  booters_1.LifeCycleObserverBooter,
44
44
  booters_1.InterceptorProviderBooter,
45
+ booters_1.ModelApiBooter,
45
46
  ];
46
47
  // Bound as a SINGLETON so it can be cached as it has no state
47
48
  app
@@ -1 +1 @@
1
- {"version":3,"file":"boot.component.js","sourceRoot":"","sources":["../src/boot.component.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;;;;;;;;;;;AAEhE,+CAAuD;AACvD,yCAAoE;AACpE,uCAQmB;AACnB,iDAA4C;AAC5C,iCAAoC;AAEpC;;;;GAIG;AACH,IAAa,aAAa,GAA1B,MAAa,aAAa;IAaxB;;;OAGG;IACH,YAAuD,GAAgB;QAhBvE,sEAAsE;QACtE,gDAAgD;QAChD,YAAO,GAAG;YACR,mCAAyB;YACzB,0BAAgB;YAChB,0BAAgB;YAChB,uBAAa;YACb,0BAAgB;YAChB,iCAAuB;YACvB,mCAAyB;SAC1B,CAAC;QAOA,8DAA8D;QAC9D,GAAG;aACA,IAAI,CAAC,mBAAY,CAAC,gBAAgB,CAAC;aACnC,OAAO,CAAC,2BAAY,CAAC;aACrB,OAAO,CAAC,sBAAY,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;CACF,CAAA;AAxBY,aAAa;IAiBX,WAAA,gBAAM,CAAC,mBAAY,CAAC,oBAAoB,CAAC,CAAA;qCAAM,kBAAW;GAjB5D,aAAa,CAwBzB;AAxBY,sCAAa"}
1
+ {"version":3,"file":"boot.component.js","sourceRoot":"","sources":["../src/boot.component.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;;;;;;;;;;;AAEhE,+CAAuD;AACvD,yCAAoE;AACpE,uCASmB;AACnB,iDAA4C;AAC5C,iCAAoC;AAEpC;;;;GAIG;AACH,IAAa,aAAa,GAA1B,MAAa,aAAa;IAcxB;;;OAGG;IACH,YAAuD,GAAgB;QAjBvE,sEAAsE;QACtE,gDAAgD;QAChD,YAAO,GAAG;YACR,mCAAyB;YACzB,0BAAgB;YAChB,0BAAgB;YAChB,uBAAa;YACb,0BAAgB;YAChB,iCAAuB;YACvB,mCAAyB;YACzB,wBAAc;SACf,CAAC;QAOA,8DAA8D;QAC9D,GAAG;aACA,IAAI,CAAC,mBAAY,CAAC,gBAAgB,CAAC;aACnC,OAAO,CAAC,2BAAY,CAAC;aACrB,OAAO,CAAC,sBAAY,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;CACF,CAAA;AAzBY,aAAa;IAkBX,WAAA,gBAAM,CAAC,mBAAY,CAAC,oBAAoB,CAAC,CAAA;qCAAM,kBAAW;GAlB5D,aAAa,CAyBzB;AAzBY,sCAAa"}
@@ -5,5 +5,6 @@ export * from './controller.booter';
5
5
  export * from './datasource.booter';
6
6
  export * from './interceptor.booter';
7
7
  export * from './lifecyle-observer.booter';
8
+ export * from './model-api.booter';
8
9
  export * from './repository.booter';
9
10
  export * from './service.booter';
@@ -14,6 +14,7 @@ __export(require("./controller.booter"));
14
14
  __export(require("./datasource.booter"));
15
15
  __export(require("./interceptor.booter"));
16
16
  __export(require("./lifecyle-observer.booter"));
17
+ __export(require("./model-api.booter"));
17
18
  __export(require("./repository.booter"));
18
19
  __export(require("./service.booter"));
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/booters/index.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;;AAEhE,mDAA8C;AAC9C,4CAAuC;AACvC,oCAA+B;AAC/B,yCAAoC;AACpC,yCAAoC;AACpC,0CAAqC;AACrC,gDAA2C;AAC3C,yCAAoC;AACpC,sCAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/booters/index.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;;AAEhE,mDAA8C;AAC9C,4CAAuC;AACvC,oCAA+B;AAC/B,yCAAoC;AACpC,yCAAoC;AACpC,0CAAqC;AACrC,gDAA2C;AAC3C,wCAAmC;AACnC,yCAAoC;AACpC,sCAAiC"}
@@ -0,0 +1,28 @@
1
+ import { Getter } from '@loopback/core';
2
+ import { ModelApiBuilder } from '@loopback/model-api-builder';
3
+ import { ApplicationWithRepositories } from '@loopback/repository';
4
+ import { ArtifactOptions } from '../types';
5
+ import { BaseArtifactBooter } from './base-artifact.booter';
6
+ export declare class ModelApiBooter extends BaseArtifactBooter {
7
+ app: ApplicationWithRepositories;
8
+ getModelApiBuilders: Getter<ModelApiBuilder[]>;
9
+ booterConfig: ArtifactOptions;
10
+ constructor(app: ApplicationWithRepositories, projectRoot: string, getModelApiBuilders: Getter<ModelApiBuilder[]>, booterConfig?: ArtifactOptions);
11
+ /**
12
+ * Load the the model config files
13
+ */
14
+ load(): Promise<void>;
15
+ /**
16
+ * Set up the loaded model classes
17
+ */
18
+ setupModel(configFile: string): Promise<void>;
19
+ /**
20
+ * Retrieve the API builder that matches the pattern provided
21
+ * @param pattern - name of pattern for an API builder
22
+ */
23
+ getApiBuilderForPattern(pattern: string): Promise<ModelApiBuilder>;
24
+ }
25
+ /**
26
+ * Default ArtifactOptions for ControllerBooter.
27
+ */
28
+ export declare const RestDefaults: ArtifactOptions;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2019. All Rights Reserved.
3
+ // Node module: @loopback/boot
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ var __metadata = (this && this.__metadata) || function (k, v) {
13
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
14
+ };
15
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
16
+ return function (target, key) { decorator(target, key, paramIndex); }
17
+ };
18
+ var __importDefault = (this && this.__importDefault) || function (mod) {
19
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ };
21
+ var __importStar = (this && this.__importStar) || function (mod) {
22
+ if (mod && mod.__esModule) return mod;
23
+ var result = {};
24
+ if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
25
+ result["default"] = mod;
26
+ return result;
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const core_1 = require("@loopback/core");
30
+ const model_api_builder_1 = require("@loopback/model-api-builder");
31
+ const debug_1 = __importDefault(require("debug"));
32
+ const path = __importStar(require("path"));
33
+ const keys_1 = require("../keys");
34
+ const types_1 = require("../types");
35
+ const base_artifact_booter_1 = require("./base-artifact.booter");
36
+ const debug = debug_1.default('loopback:boot:model-api');
37
+ let ModelApiBooter = class ModelApiBooter extends base_artifact_booter_1.BaseArtifactBooter {
38
+ constructor(app, projectRoot, getModelApiBuilders, booterConfig = {}) {
39
+ // TODO assert that `app` has RepositoryMixin members
40
+ super(projectRoot,
41
+ // Set booter options if passed in via bootConfig
42
+ Object.assign({}, exports.RestDefaults, booterConfig));
43
+ this.app = app;
44
+ this.getModelApiBuilders = getModelApiBuilders;
45
+ this.booterConfig = booterConfig;
46
+ }
47
+ /**
48
+ * Load the the model config files
49
+ */
50
+ async load() {
51
+ // Important: don't call `super.load()` here, it would try to load
52
+ // classes via `loadClassesFromFiles` - that won't work for JSON files
53
+ await Promise.all(this.discovered.map(async (f) => {
54
+ try {
55
+ // It's important to await before returning,
56
+ // otherwise the catch block won't receive errors
57
+ await this.setupModel(f);
58
+ }
59
+ catch (err) {
60
+ const shortPath = path.relative(this.projectRoot, f);
61
+ err.message += ` (while loading ${shortPath})`;
62
+ throw err;
63
+ }
64
+ }));
65
+ }
66
+ /**
67
+ * Set up the loaded model classes
68
+ */
69
+ async setupModel(configFile) {
70
+ const cfg = require(configFile);
71
+ debug('Loaded model config from %s', path.relative(this.projectRoot, configFile), cfg);
72
+ const modelClass = cfg.model;
73
+ if (typeof modelClass !== 'function') {
74
+ throw new Error(`Invalid "model" field. Expected a Model class, found ${modelClass}`);
75
+ }
76
+ const builder = await this.getApiBuilderForPattern(cfg.pattern);
77
+ await builder.build(this.app, modelClass, cfg);
78
+ }
79
+ /**
80
+ * Retrieve the API builder that matches the pattern provided
81
+ * @param pattern - name of pattern for an API builder
82
+ */
83
+ async getApiBuilderForPattern(pattern) {
84
+ const allBuilders = await this.getModelApiBuilders();
85
+ const builder = allBuilders.find(b => b.pattern === pattern);
86
+ if (!builder) {
87
+ const availableBuilders = allBuilders.map(b => b.pattern).join(', ');
88
+ throw new Error(`Unsupported API pattern "${pattern}". ` +
89
+ `Available patterns: ${availableBuilders || '<none>'}`);
90
+ }
91
+ return builder;
92
+ }
93
+ };
94
+ ModelApiBooter = __decorate([
95
+ types_1.booter('modelApi'),
96
+ core_1.extensionPoint(model_api_builder_1.MODEL_API_BUILDER_PLUGINS),
97
+ __param(0, core_1.inject(core_1.CoreBindings.APPLICATION_INSTANCE)),
98
+ __param(1, core_1.inject(keys_1.BootBindings.PROJECT_ROOT)),
99
+ __param(2, core_1.extensions()),
100
+ __param(3, core_1.config()),
101
+ __metadata("design:paramtypes", [Object, String, Function, Object])
102
+ ], ModelApiBooter);
103
+ exports.ModelApiBooter = ModelApiBooter;
104
+ /**
105
+ * Default ArtifactOptions for ControllerBooter.
106
+ */
107
+ exports.RestDefaults = {
108
+ dirs: ['model-endpoints'],
109
+ extensions: ['-config.js'],
110
+ nested: true,
111
+ };
112
+ //# sourceMappingURL=model-api.booter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-api.booter.js","sourceRoot":"","sources":["../../src/booters/model-api.booter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loopback/boot",
3
- "version": "1.6.0",
3
+ "version": "1.7.4",
4
4
  "description": "A collection of Booters for LoopBack 4 Applications",
5
5
  "engines": {
6
6
  "node": ">=8.9"
@@ -22,22 +22,23 @@
22
22
  "copyright.owner": "IBM Corp.",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@loopback/context": "^1.25.0",
26
- "@loopback/core": "^1.12.0",
27
- "@loopback/repository": "^1.16.0",
28
- "@loopback/service-proxy": "^1.3.13",
25
+ "@loopback/context": "^2.1.1",
26
+ "@loopback/core": "^1.12.4",
27
+ "@loopback/model-api-builder": "^1.1.4",
28
+ "@loopback/repository": "^1.19.1",
29
+ "@loopback/service-proxy": "^1.3.17",
29
30
  "@types/debug": "^4.1.5",
30
31
  "@types/glob": "^7.1.1",
31
32
  "debug": "^4.1.1",
32
33
  "glob": "^7.1.6"
33
34
  },
34
35
  "devDependencies": {
35
- "@loopback/build": "^3.0.0",
36
- "@loopback/eslint-config": "^5.0.0",
37
- "@loopback/openapi-v3": "^1.10.3",
38
- "@loopback/rest": "^1.25.0",
39
- "@loopback/testlab": "^1.10.0",
40
- "@types/node": "^10.17.6"
36
+ "@loopback/build": "^3.1.1",
37
+ "@loopback/eslint-config": "^5.0.3",
38
+ "@loopback/openapi-v3": "^2.0.0",
39
+ "@loopback/rest": "^2.0.0",
40
+ "@loopback/testlab": "^1.10.3",
41
+ "@types/node": "^10.17.14"
41
42
  },
42
43
  "files": [
43
44
  "README.md",
@@ -52,5 +53,5 @@
52
53
  "url": "https://github.com/strongloop/loopback-next.git",
53
54
  "directory": "packages/boot"
54
55
  },
55
- "gitHead": "89eb61bacaed75e6eb61ae6840cea266cb888659"
56
+ "gitHead": "6eea5e428b145cafb84a998bd53979da8c8fba07"
56
57
  }
@@ -11,6 +11,7 @@ import {
11
11
  DataSourceBooter,
12
12
  InterceptorProviderBooter,
13
13
  LifeCycleObserverBooter,
14
+ ModelApiBooter,
14
15
  RepositoryBooter,
15
16
  ServiceBooter,
16
17
  } from './booters';
@@ -33,6 +34,7 @@ export class BootComponent implements Component {
33
34
  DataSourceBooter,
34
35
  LifeCycleObserverBooter,
35
36
  InterceptorProviderBooter,
37
+ ModelApiBooter,
36
38
  ];
37
39
 
38
40
  /**
@@ -10,5 +10,6 @@ export * from './controller.booter';
10
10
  export * from './datasource.booter';
11
11
  export * from './interceptor.booter';
12
12
  export * from './lifecyle-observer.booter';
13
+ export * from './model-api.booter';
13
14
  export * from './repository.booter';
14
15
  export * from './service.booter';
@@ -0,0 +1,117 @@
1
+ // Copyright IBM Corp. 2019. 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
+ config,
8
+ CoreBindings,
9
+ extensionPoint,
10
+ extensions,
11
+ Getter,
12
+ inject,
13
+ } from '@loopback/core';
14
+ import {
15
+ ModelApiBuilder,
16
+ ModelApiConfig,
17
+ MODEL_API_BUILDER_PLUGINS,
18
+ } from '@loopback/model-api-builder';
19
+ import {ApplicationWithRepositories} from '@loopback/repository';
20
+ import debugFactory from 'debug';
21
+ import * as path from 'path';
22
+ import {BootBindings} from '../keys';
23
+ import {ArtifactOptions, booter} from '../types';
24
+ import {BaseArtifactBooter} from './base-artifact.booter';
25
+
26
+ const debug = debugFactory('loopback:boot:model-api');
27
+
28
+ @booter('modelApi')
29
+ @extensionPoint(MODEL_API_BUILDER_PLUGINS)
30
+ export class ModelApiBooter extends BaseArtifactBooter {
31
+ constructor(
32
+ @inject(CoreBindings.APPLICATION_INSTANCE)
33
+ public app: ApplicationWithRepositories,
34
+ @inject(BootBindings.PROJECT_ROOT) projectRoot: string,
35
+ @extensions()
36
+ public getModelApiBuilders: Getter<ModelApiBuilder[]>,
37
+ @config()
38
+ public booterConfig: ArtifactOptions = {},
39
+ ) {
40
+ // TODO assert that `app` has RepositoryMixin members
41
+
42
+ super(
43
+ projectRoot,
44
+ // Set booter options if passed in via bootConfig
45
+ Object.assign({}, RestDefaults, booterConfig),
46
+ );
47
+ }
48
+
49
+ /**
50
+ * Load the the model config files
51
+ */
52
+ async load(): Promise<void> {
53
+ // Important: don't call `super.load()` here, it would try to load
54
+ // classes via `loadClassesFromFiles` - that won't work for JSON files
55
+ await Promise.all(
56
+ this.discovered.map(async f => {
57
+ try {
58
+ // It's important to await before returning,
59
+ // otherwise the catch block won't receive errors
60
+ await this.setupModel(f);
61
+ } catch (err) {
62
+ const shortPath = path.relative(this.projectRoot, f);
63
+ err.message += ` (while loading ${shortPath})`;
64
+ throw err;
65
+ }
66
+ }),
67
+ );
68
+ }
69
+
70
+ /**
71
+ * Set up the loaded model classes
72
+ */
73
+ async setupModel(configFile: string): Promise<void> {
74
+ const cfg: ModelApiConfig = require(configFile);
75
+ debug(
76
+ 'Loaded model config from %s',
77
+ path.relative(this.projectRoot, configFile),
78
+ cfg,
79
+ );
80
+
81
+ const modelClass = cfg.model;
82
+ if (typeof modelClass !== 'function') {
83
+ throw new Error(
84
+ `Invalid "model" field. Expected a Model class, found ${modelClass}`,
85
+ );
86
+ }
87
+
88
+ const builder = await this.getApiBuilderForPattern(cfg.pattern);
89
+ await builder.build(this.app, modelClass, cfg);
90
+ }
91
+
92
+ /**
93
+ * Retrieve the API builder that matches the pattern provided
94
+ * @param pattern - name of pattern for an API builder
95
+ */
96
+ async getApiBuilderForPattern(pattern: string): Promise<ModelApiBuilder> {
97
+ const allBuilders = await this.getModelApiBuilders();
98
+ const builder = allBuilders.find(b => b.pattern === pattern);
99
+ if (!builder) {
100
+ const availableBuilders = allBuilders.map(b => b.pattern).join(', ');
101
+ throw new Error(
102
+ `Unsupported API pattern "${pattern}". ` +
103
+ `Available patterns: ${availableBuilders || '<none>'}`,
104
+ );
105
+ }
106
+ return builder;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Default ArtifactOptions for ControllerBooter.
112
+ */
113
+ export const RestDefaults: ArtifactOptions = {
114
+ dirs: ['model-endpoints'],
115
+ extensions: ['-config.js'],
116
+ nested: true,
117
+ };