@loopback/booter-lb3app
Version:
A booter component for LoopBack 3 applications to expose their REST API via LoopBack 4
124 lines • 5.36 kB
JavaScript
;
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
// Node module: @loopback/booter-lb3app
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
Object.defineProperty(exports, "__esModule", { value: true });
exports.Lb3AppBooter = void 0;
const tslib_1 = require("tslib");
const boot_1 = require("@loopback/boot");
const core_1 = require("@loopback/core");
const rest_1 = require("@loopback/rest");
const debug_1 = tslib_1.__importDefault(require("debug"));
const events_1 = require("events");
const path_1 = tslib_1.__importDefault(require("path"));
const { generateSwaggerSpec } = require('loopback-swagger');
const swagger2openapi = require('swagger2openapi');
const debug = (0, debug_1.default)('loopback:boot:lb3app');
const DefaultOptions = {
// from "/dist/application.ts" to "/lb3app"
path: '../lb3app/server/server',
mode: 'fullApp',
restApiRoot: '/api',
};
let Lb3AppBooter = class Lb3AppBooter {
constructor(app, projectRoot, options = {}) {
this.app = app;
this.projectRoot = projectRoot;
this.options = Object.assign({}, DefaultOptions, options);
if (typeof app.mountExpressRouter !== 'function') {
throw new Error('Lb3AppBooter requires RestApplication with mountExpressRouter API');
}
}
async configure() {
this.appPath = path_1.default.join(this.projectRoot, this.options.path);
}
async load() {
const lb3App = await this.loadAndBootTheApp();
const spec = await this.buildOpenApiSpec(lb3App);
if (this.options.mode === 'fullApp') {
this.mountFullApp(lb3App, spec);
}
else {
this.mountRoutesOnly(lb3App, spec);
}
const dataSources = lb3App.dataSources;
if (dataSources) {
const visitedDs = new Set();
for (const k in dataSources) {
const ds = dataSources[k];
if (visitedDs.has(ds))
continue;
this.app.bind(`lb3-datasources.${k}`).to(ds).tag('lb3-datasource');
visitedDs.add(ds);
}
}
const models = lb3App.models;
if (models) {
const visitedModels = new Set();
for (const k in models) {
const model = models[k];
if (visitedModels.has(model))
continue;
this.app.bind(`lb3-models.${k}`).to(model).tag('lb3-model');
visitedModels.add(model);
}
}
// TODO(bajtos) Listen for the following events to update the OpenAPI spec:
// - modelRemoted
// - modelDeleted
// - remoteMethodAdded
// - remoteMethodDisabled
// Note: LB4 does not support live spec updates yet. See
// https://github.com/loopbackio/loopback-next/issues/2394 for details.
}
async loadAndBootTheApp() {
debug('Loading LB3 app from', this.appPath);
const lb3App = require(this.appPath);
debug('If your LB3 app does not boot correctly then make sure it is using loopback-boot version 3.2.1 or higher.');
if (lb3App.booting) {
debug(' waiting for boot process to finish');
// Wait until the legacy LB3 app boots
await (0, events_1.once)(lb3App, 'booted');
}
return lb3App;
}
async buildOpenApiSpec(lb3App) {
const swaggerSpec = generateSwaggerSpec(lb3App, {
generateOperationScopedModels: true,
});
// remove any properties that have values that are functions before
// converting, as `convertObj` can't handle function values
const fixedSwaggerSpec = JSON.parse(JSON.stringify(swaggerSpec));
const result = await swagger2openapi.convertObj(fixedSwaggerSpec, {
// swagger2openapi options
});
let spec = result.openapi;
if (typeof this.options.specTransformer === 'function') {
spec = this.options.specTransformer(spec);
}
return spec;
}
mountFullApp(lb3App, spec) {
const restApiRoot = lb3App.get('restApiRoot') || '/';
debug('Mounting the entire LB3 app at %s', restApiRoot);
const specInRoot = (0, rest_1.rebaseOpenApiSpec)(spec, restApiRoot);
this.app.mountExpressRouter('/', lb3App, specInRoot);
}
mountRoutesOnly(lb3App, spec) {
const restApiRoot = this.options.restApiRoot;
debug('Mounting LB3 REST router at %s', restApiRoot);
this.app.mountExpressRouter(restApiRoot,
// TODO(bajtos) reload the handler when a model/method was added/removed
// See https://github.com/loopbackio/loopback-next/issues/2394 for details.
lb3App.handler('rest'), spec);
}
};
exports.Lb3AppBooter = Lb3AppBooter;
exports.Lb3AppBooter = Lb3AppBooter = tslib_1.__decorate([
tslib_1.__param(0, (0, core_1.inject)(core_1.CoreBindings.APPLICATION_INSTANCE)),
tslib_1.__param(1, (0, core_1.inject)(boot_1.BootBindings.PROJECT_ROOT)),
tslib_1.__param(2, (0, core_1.inject)(`${boot_1.BootBindings.BOOT_OPTIONS}#lb3app`)),
tslib_1.__metadata("design:paramtypes", [rest_1.RestApplication, String, Object])
], Lb3AppBooter);
//# sourceMappingURL=lb3app.booter.js.map