Skip to content

Commit

Permalink
feat(boot): bind content of package.json to app context
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed Oct 4, 2018
1 parent 9ae93d8 commit 083d8d4
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 1 deletion.
2 changes: 2 additions & 0 deletions packages/boot/src/boot.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
RepositoryBooter,
DataSourceBooter,
ServiceBooter,
ApplicationMetadataBooter,
} from './booters';
import {BootBindings} from './keys';

Expand All @@ -23,6 +24,7 @@ export class BootComponent implements Component {
// Export a list of default booters in the component so they get bound
// automatically when this component is mounted.
booters = [
ApplicationMetadataBooter,
ControllerBooter,
RepositoryBooter,
ServiceBooter,
Expand Down
36 changes: 36 additions & 0 deletions packages/boot/src/booters/application-metadata.booter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: @loopback/boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {CoreBindings, Application} from '@loopback/core';
import {inject} from '@loopback/context';
import {BootBindings} from '../keys';
import {Booter} from '../interfaces';
import path = require('path');

import * as debugModule from 'debug';
const debug = debugModule('loopback:boot:booter:application-metadata');

/**
*
* Configure the application with metadata from `package.json`
*
* @param app Application instance
* @param projectRoot Root of User Project
*/
export class ApplicationMetadataBooter implements Booter {
constructor(
@inject(CoreBindings.APPLICATION_INSTANCE) public app: Application,
@inject(BootBindings.PROJECT_ROOT) private projectRoot: string,
) {}

async configure() {
try {
const pkg = require(path.resolve(this.projectRoot, 'package.json'));
this.app.setMetadata(pkg);
} catch (err) {
debug('package.json not found', err);
}
}
}
1 change: 1 addition & 0 deletions packages/boot/src/booters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './controller.booter';
export * from './datasource.booter';
export * from './repository.booter';
export * from './service.booter';
export * from './application-metadata.booter';
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: @loopback/boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {givenHttpServerConfig, TestSandbox, expect} from '@loopback/testlab';
import {resolve} from 'path';
import {BooterApp} from '../fixtures/application';
import {CoreBindings} from '@loopback/core';

describe('application metadata booter acceptance tests', () => {
let app: BooterApp;
const SANDBOX_PATH = resolve(__dirname, '../../.sandbox');
const sandbox = new TestSandbox(SANDBOX_PATH);

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

afterEach(stopApp);

it('binds content of package.json to application metadata', async () => {
await app.boot();
const metadata = await app.get(CoreBindings.APPLICATION_METADATA);
expect(metadata).containEql({
name: 'boot-test-app',
version: '1.0.0',
description: 'boot-test-app',
});
});

async function getApp() {
await sandbox.copyFile(resolve(__dirname, '../fixtures/package.json'));
await sandbox.copyFile(resolve(__dirname, '../fixtures/application.js'));

const MyApp = require(resolve(SANDBOX_PATH, 'application.js')).BooterApp;
app = new MyApp({
rest: givenHttpServerConfig(),
});
}

async function stopApp() {
try {
await app.stop();
} catch (err) {
console.log(`Stopping the app threw an error: ${err}`);
}
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,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'),
Expand Down
19 changes: 19 additions & 0 deletions packages/boot/test/fixtures/package.json
Original file line number Diff line number Diff line change
@@ -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": ""
}
21 changes: 21 additions & 0 deletions packages/core/src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ export class Application extends Context {
const instance = this.getSync<Component>(componentKey);
mountComponent(this, instance);
}

/**
* Set application metadata. By default, the content of `package.json` is
* loaded and populated.
*
* @param metadata Application metadata
*/
public setMetadata(metadata: ApplicationMetadata) {
this.bind(CoreBindings.APPLICATION_METADATA).to(metadata);
}
}

/**
Expand All @@ -207,3 +217,14 @@ export interface ApplicationConfig {

// tslint:disable-next-line:no-any
export type ControllerClass = Constructor<any>;

/**
* Type description for `package.json`
*/
export interface ApplicationMetadata {
name: string;
version: string;
description: string;
// tslint:disable-next-line:no-any
[name: string]: any;
}
9 changes: 8 additions & 1 deletion packages/core/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, ApplicationMetadata} from './application';

/**
* Namespace for core binding keys
Expand All @@ -25,6 +25,13 @@ export namespace CoreBindings {
'application.config',
);

/**
* Binding key for the content of `package.json`
*/
export const APPLICATION_METADATA = BindingKey.create<ApplicationMetadata>(
'application.metadata',
);

// server
/**
* Binding key for servers
Expand Down

0 comments on commit 083d8d4

Please sign in to comment.