From d8180efc4b020d61b026c2fd04233b1396b09dd8 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 25 Sep 2018 20:27:41 -0700 Subject: [PATCH] feat(boot): bind content of package.json to app context --- packages/boot/src/mixins/boot.mixin.ts | 7 +++++++ .../controller.booter.acceptance.ts | 12 ++++++++++++ packages/boot/test/fixtures/package.json | 19 +++++++++++++++++++ packages/core/src/application.ts | 15 +++++++++++++++ packages/core/src/keys.ts | 9 ++++++++- 5 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 packages/boot/test/fixtures/package.json diff --git a/packages/boot/src/mixins/boot.mixin.ts b/packages/boot/src/mixins/boot.mixin.ts index 0ce2171442b2..f36f1900235a 100644 --- a/packages/boot/src/mixins/boot.mixin.ts +++ b/packages/boot/src/mixins/boot.mixin.ts @@ -8,6 +8,8 @@ import {Booter, BootOptions, Bootable} from '../interfaces'; import {BootComponent} from '../boot.component'; import {Bootstrapper} from '../bootstrapper'; import {BootBindings} from '../keys'; +import {CoreBindings} from '@loopback/core'; +import * as path from 'path'; // Binding is re-exported as Binding / Booter types are needed when consuming // BootMixin and this allows a user to import them from the same package (UX!) @@ -53,6 +55,11 @@ export function BootMixin>(superClass: T) { this.bind(BootBindings.BOOT_OPTIONS).toDynamicValue( () => this.bootOptions, ); + + this.bind(CoreBindings.APPLICATION_PACKAGE_JSON).toDynamicValue(() => { + const pkgFile = path.resolve(this.projectRoot, 'package.json'); + return require(pkgFile); + }); } /** diff --git a/packages/boot/test/acceptance/controller.booter.acceptance.ts b/packages/boot/test/acceptance/controller.booter.acceptance.ts index 05508dc1bd4c..3b4970e755bd 100644 --- a/packages/boot/test/acceptance/controller.booter.acceptance.ts +++ b/packages/boot/test/acceptance/controller.booter.acceptance.ts @@ -7,9 +7,11 @@ import { createRestAppClient, givenHttpServerConfig, TestSandbox, + expect, } from '@loopback/testlab'; import {resolve} from 'path'; import {BooterApp} from '../fixtures/application'; +import {CoreBindings} from '@loopback/core'; describe('controller booter acceptance tests', () => { let app: BooterApp; @@ -21,6 +23,15 @@ describe('controller booter acceptance tests', () => { afterEach(stopApp); + it('binds package.json', async () => { + const pkg = await app.get(CoreBindings.APPLICATION_PACKAGE_JSON); + expect(pkg).containEql({ + name: 'boot-test-app', + version: '1.0.0', + description: 'boot-test-app', + }); + }); + it('binds controllers using ControllerDefaults and REST endpoints work', async () => { await app.boot(); await app.start(); @@ -33,6 +44,7 @@ describe('controller booter acceptance tests', () => { }); async function getApp() { + await sandbox.copyFile(resolve(__dirname, '../fixtures/package.json')); await sandbox.copyFile(resolve(__dirname, '../fixtures/application.js')); await sandbox.copyFile( resolve(__dirname, '../fixtures/multiple.artifact.js'), diff --git a/packages/boot/test/fixtures/package.json b/packages/boot/test/fixtures/package.json new file mode 100644 index 000000000000..e827db359b36 --- /dev/null +++ b/packages/boot/test/fixtures/package.json @@ -0,0 +1,19 @@ +{ + "name": "boot-test-app", + "version": "1.0.0", + "description": "boot-test-app", + "keywords": [ + "loopback-application", + "loopback" + ], + "engines": { + "node": ">=8.9" + }, + "scripts": { + }, + "repository": { + "type": "git" + }, + "author": "", + "license": "" +} diff --git a/packages/core/src/application.ts b/packages/core/src/application.ts index a94596ae36bf..9e0ad9b0ba54 100644 --- a/packages/core/src/application.ts +++ b/packages/core/src/application.ts @@ -192,6 +192,10 @@ export class Application extends Context { const instance = this.getSync(componentKey); mountComponent(this, instance); } + + public packageJson(pkg: PackageJson) { + this.bind(CoreBindings.APPLICATION_PACKAGE_JSON).to(pkg); + } } /** @@ -207,3 +211,14 @@ export interface ApplicationConfig { // tslint:disable-next-line:no-any export type ControllerClass = Constructor; + +/** + * Type description for `package.json` + */ +export interface PackageJson { + name: string; + version: string; + description: string; + // tslint:disable-next-line:no-any + [name: string]: any; +} diff --git a/packages/core/src/keys.ts b/packages/core/src/keys.ts index 3050150bdefe..4e3a92bc5d37 100644 --- a/packages/core/src/keys.ts +++ b/packages/core/src/keys.ts @@ -4,7 +4,7 @@ // License text available at https://opensource.org/licenses/MIT import {BindingKey} from '@loopback/context'; -import {Application, ControllerClass} from './application'; +import {Application, ControllerClass, PackageJson} from './application'; /** * Namespace for core binding keys @@ -25,6 +25,13 @@ export namespace CoreBindings { 'application.config', ); + /** + * Binding key for the content of `package.json` + */ + export const APPLICATION_PACKAGE_JSON = BindingKey.create( + 'application.package-json', + ); + // server /** * Binding key for servers