Skip to content

Commit

Permalink
feat: apply feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
virkt25 committed Jan 18, 2018
1 parent 48bed0f commit 3da2a4b
Show file tree
Hide file tree
Showing 28 changed files with 301 additions and 172 deletions.
40 changes: 22 additions & 18 deletions packages/boot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ A collection of Booters for LoopBack Applications

A Booter is a Class that can be bound to an Application and is called
to perform a task before the Application is started. A Booter may have multiple
phases to complete it's task.
phases to complete its task.

An example task of a Booter may be to discover and bind all artifacts of a
given type.

BootComponent is responsible for handling Booter artifacts and running the
phases. It must be added to an `Application` to use `await app.booter()`
or `await app.boot()`.

## Installation

```shell
Expand All @@ -20,9 +24,18 @@ $ npm i @loopback/boot
## Basic Use

```ts
import {ControllerBooter} from '@loopback/boot';
app.booter(ControllerBooter); // register booter
await app.boot(); // Booter gets run by the Application
import {Application} from '@loopback/core';
import {ControllerBooter, BootComponent} from '@loopback/boot';
const app = new Application({components:[BootComponent]});
await app.booter(ControllerBooter); // register booter
await app.boot({
projectRoot: __dirname,
controllers: {
dirs: ['controllers'],
extensions: ['.controller.js'],
nested: true
}
}); // Booter gets run by the Application
```

## Available Booters
Expand All @@ -33,31 +46,22 @@ await app.boot(); // Booter gets run by the Application
Discovers and binds Controller Classes using `app.controller()`.

#### Options
The Options for this can be passed via `ApplicationConfig` in the Application
constructor or via `BootOptions` when calling `app.boot(options:BootOptions)`.
The Options for this can be passed via `BootOptions` when calling `app.boot(options:BootOptions)`.

The options for this are passed in a `controllers` object on `BootOptions`.

The options for this are passed in a `controllers` object on `boot`.
Available Options on the `controllers` object are as follows:

Available Options on the `boot.controllers` are as follows:
|Options|Type|Default|Description|
|-|-|-|-|
|`dirs`|`string | string[]`|`['controllers']`|Paths relative to projectRoot to look in for Controller artifacts|
|`extensions`|`string | string[]`|`['.controller.js']`|File extensions to match for Controller artifacts|
|`nested`|`boolean`|`true`|Look in nested directories in `dirs` for Controller artifacts|

#### Examples
**Via Application Config**
```ts
new Application({
boot: {
projectRoot: '',
controllers: {...}
}
});
```

**Via BootOptions**
```ts
new Application({components: [BootComponent]});
app.boot({
boot: {
projectRoot: '',
Expand Down
9 changes: 8 additions & 1 deletion packages/boot/docs.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
{
"content": ["index.ts", "src/index.ts", "src/controller.booter.ts"],
"content": [
"index.ts",
"src/booters/controller.booter.ts",
"src/booters/index.ts",
"src/boot.component.ts",
"src/index.ts",
"src/keys.ts"
],
"codeSectionDepth": 4,
"assets": {
"/": "/docs",
Expand Down
2 changes: 1 addition & 1 deletion packages/boot/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
2 changes: 1 addition & 1 deletion packages/boot/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
2 changes: 1 addition & 1 deletion packages/boot/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
33 changes: 21 additions & 12 deletions packages/boot/src/boot.component.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
// 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 {
Context,
inject,
Constructor,
Binding,
BindingScope,
} from '@loopback/context';
import {Component} from '@loopback/core';
import {
Component,
Booter,
BootOptions,
BOOTER_PHASES,
CoreBindings,
Application,
} from '@loopback/core';
import {resolve} from 'path';
import {BootBindings} from './keys';
import {Booter, BootOptions} from './types';

import * as debugModule from 'debug';
const debug = debugModule('loopback:boot:bootstrapper');

export class BootComponent extends Context implements Component {
bootOptions: BootOptions;

constructor() {
super();
constructor(@inject(CoreBindings.APPLICATION_INSTANCE) app: Application) {
super(app);
}

/**
Expand All @@ -43,14 +54,12 @@ export class BootComponent extends Context implements Component {
this.bind(BootBindings.BOOT_CONFIG).to(this.bootOptions);

// Find Bindings and get instance
const bindings = this.findByTag(BootBindings.BOOTER_PREFIX);
const bindings = this.findByTag(BootBindings.BOOTER_TAG);
// tslint:disable-next-line:no-any
let booterInsts: any[] = await bindings.map(binding =>
this.get(binding.key),
);
let booterInsts: any[] = bindings.map(binding => this.getSync(binding.key));

// Run phases of booters
for (const phase of BootBindings.PHASES) {
for (const phase of BOOTER_PHASES) {
for (const inst of booterInsts) {
if (inst[phase]) {
await inst[phase]();
Expand All @@ -73,11 +82,11 @@ export class BootComponent extends Context implements Component {
.inScope(BindingScope.SINGLETON);
}

booter<T extends Booter>(booterCls: Constructor<T>, name?: string): Binding;
booter<T extends Booter>(booterCls: Constructor<T>[]): Binding[];
booter(booterCls: Constructor<Booter>, name?: string): Binding;
booter(booterCls: Constructor<Booter>[]): Binding[];

// tslint:disable-next-line:no-any
booter<T extends Booter>(booterCls: any, name?: string): any {
booter(booterCls: any, name?: string): any {
if (Array.isArray(booterCls)) {
return booterCls.map(cls => this._bindBooter(cls));
} else {
Expand Down
8 changes: 4 additions & 4 deletions packages/boot/src/booters/controller.booter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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 {CoreBindings, Application, Booter, BootOptions} from '@loopback/core';
import {inject} from '@loopback/context';
import {Booter, BootOptions} from '../types';
import {BootBindings} from '../keys';
import {relative} from 'path';
import * as glob from 'glob';

/**
Expand Down Expand Up @@ -86,7 +86,7 @@ export class ControllerBooter implements Booter {
this.app.controller(ctrl[cls]);
});
} catch (err) {
errFiles.push(file.substring(this.projectRoot.length));
errFiles.push(relative(this.projectRoot, file));
}
});

Expand Down
5 changes: 5 additions & 0 deletions packages/boot/src/booters/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
// 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

export * from './controller.booter';
3 changes: 1 addition & 2 deletions packages/boot/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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

export * from './booters';
export * from './boot.component';
export * from './keys';
export * from './types';
4 changes: 0 additions & 4 deletions packages/boot/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {BOOTER_PHASES} from './types';

/**
* Namespace for core binding keys
*/
Expand All @@ -16,6 +14,4 @@ export namespace BootBindings {

export const BOOTER_TAG = 'booter';
export const BOOTER_PREFIX = 'booters';

export const PHASES = BOOTER_PHASES;
}
20 changes: 0 additions & 20 deletions packages/boot/src/types.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import {Client, createClientForHandler} from '@loopback/testlab';
import {ControllerBooterApp} from '../fixtures/booterApp/application';
import {RestServer} from '@loopback/rest';
import {ControllerBooter, BootOptions} from '../../index';
import {BootOptions} from '@loopback/core';
import {ControllerBooter, BootComponent} from '../../index';
// @ts-ignore
import {getCompilationTarget} from '@loopback/build/bin/utils';

Expand All @@ -22,7 +23,7 @@ describe('controller booter acceptance tests', () => {
afterEach(stopApp);

it('binds controllers using ControllerDefaults and REST endpoints work', async () => {
app.booter(ControllerBooter);
await app.booter(ControllerBooter);
await app.boot(bootConfig);
await app.start();

Expand Down Expand Up @@ -52,7 +53,7 @@ describe('controller booter acceptance tests', () => {
}

function getApp() {
app = new ControllerBooterApp();
app = new ControllerBooterApp({components: [BootComponent]});
}

async function stopApp() {
Expand Down
6 changes: 2 additions & 4 deletions packages/boot/test/fixtures/booterApp/application.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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 {RestApplication, RestServer} from '@loopback/rest';
import {ApplicationConfig} from '@loopback/core';
import {ControllerBooter} from '../../../src';

export class ControllerBooterApp extends RestApplication {
constructor(options?: ApplicationConfig) {
super(options);
this.booter(ControllerBooter);
}

async start() {
const server = await this.getServer(RestServer);
const port = await server.get('rest.port');
console.log(`Server is running at http://127.0.0.1:${port}`);
console.log(`Try http://127.0.0.1:${port}/ping`);
return await super.start();
await super.start();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// 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

// THIS FILE IS INTENTIONALLY LEFT EMPTY!
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
// 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 {expect} from '@loopback/testlab';
import {CoreBindings} from '@loopback/core';
import {CoreBindings, BootOptions} from '@loopback/core';
import {ControllerBooterApp} from '../fixtures/booterApp/application';
import {
ControllerBooter,
ControllerDefaults,
BootOptions,
BootBindings,
BootComponent,
} from '../../index';
Expand Down Expand Up @@ -48,17 +47,19 @@ describe('controller booter intengration tests', () => {
`${CoreBindings.CONTROLLERS}.MultipleFolderController`,
];

app.booter(ControllerBooter);
await app.booter(ControllerBooter);
await app.boot(bootOptions);
const bootComponent = await app.get(CoreBindings.BOOTCOMPONENT);
const booter = await bootComponent.get(
const bootComponent: BootComponent = await app.get(
CoreBindings.BOOTCOMPONENT,
);
const booter: ControllerBooter = await bootComponent.get(
`${BootBindings.BOOTER_PREFIX}.ControllerBooter`,
);

// Check Config Phase Ran as expected
expect(booter.dirs.sort()).to.eql(bootOptions.boot.controllers.dirs.sort());
expect(booter.dirs.sort()).to.eql(bootOptions.controllers.dirs.sort());
expect(booter.extensions.sort()).to.eql(
bootOptions.boot.controllers.extensions.sort(),
bootOptions.controllers.extensions.sort(),
);
expect(booter.options.nested).to.equal(ControllerDefaults.nested);

Expand Down
Loading

0 comments on commit 3da2a4b

Please sign in to comment.