Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(boot): implement Service booter #1652

Merged
merged 4 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/site/Booting-an-Application.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,33 @@ The `datasources` object support the following options:
| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for DataSource artifacts |
| `glob` | `string` | | A `glob` pattern string. This takes precendence over above 3 options (which are used to make a glob pattern). |

### Service Booter

#### Description

Discovers and binds Service providers using `app.serviceProvider()` (Application
must use `ServiceMixin` from `@loopback/service-proxy`).

**IMPORTANT:** For a class to be recognized by `ServiceBooter` as a service
provider, its name must end with `Provider` suffix and its prototype must have a
`value()` method.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, this is a sign that we should have something like #992 to make it possible to explicit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for #992, it's certainly needed.


#### Options

The options for this can be passed via `BootOptions` when calling
`app.boot(options: BootOptions)`.

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

Available options on the `services` object on `BootOptions` are as follows:

| Options | Type | Default | Description |
| ------------ | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------ |
| `dirs` | `string \| string[]` | `['repositories']` | Paths relative to projectRoot to look in for Service artifacts |
| `extensions` | `string \| string[]` | `['.repository.js']` | File extensions to match for Service artifacts |
| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for Service artifacts |
| `glob` | `string` | | A `glob` pattern string. This takes precedence over above 3 options (which are used to make a glob pattern). |

### Custom Booters

A custom Booter can be written as a Class that implements the `Booter`
Expand Down
4 changes: 0 additions & 4 deletions docs/site/sidebars/lb4_sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,6 @@ children:
url: soap-calculator-tutorial-add-controller.html
output: 'web, pdf'

- title: 'Register the Service'
url: soap-calculator-tutorial-register-service.html
output: 'web, pdf'

- title: 'Run and Test it'
url: soap-calculator-tutorial-run-and-test.html
output: 'web, pdf'
Expand Down
3 changes: 2 additions & 1 deletion docs/site/soap-calculator-tutorial-add-controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,5 @@ the divide end point method.

Previous step: [Add a Service](soap-calculator-tutorial-add-service.md)

Next step: [Register the Service](soap-calculator-tutorial-register-service.md)
Next step:
[Run and Test the Application](soap-calculator-tutorial-run-and-test.md)
80 changes: 0 additions & 80 deletions docs/site/soap-calculator-tutorial-register-service.md

This file was deleted.

3 changes: 1 addition & 2 deletions docs/site/soap-calculator-tutorial-run-and-test.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,4 @@ options = Object.assign(

### Navigation

Previous step:
[Register the Service](soap-calculator-tutorial-register-service.md)
Previous step: [Add a Controller](soap-calculator-tutorial-add-controller.md)
13 changes: 8 additions & 5 deletions docs/site/soap-calculator-tutorial-scaffolding.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ Let's start by creating the initial application by running the following
command:

```sh
lb4 app soap-calculator --enableRepository
lb4 app soap-calculator --enableRepository --enableServices
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, now we have enableRepository vs enableServices. The naming is inconsistent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Should we rename --enableRepository to --enableRepositories? I can do that in a follow-up pull request.

```

**Note:** The option **--enableRepository** instructs the **CLI** to include a
RepositoryMixin class in the application constructor which will be needed when
we create the datasource.
`RepositoryMixin` class in the application constructor which will be needed when
we create the datasource. The option **--enableServices** instructs the **CLI**
to include a `ServiceMixin` class in the application constructor which will be
needed to register our SOAP service client.

**LB4** will ask you a few questions _(you can leave the default options)_. The
description and the root directory are obvious. The class name referes to the
Expand All @@ -31,8 +33,9 @@ application.ts file.
```

Next you will see a list of options for the build settings, if you did not
specify --enableRepository in the last command, then you will see it in this
list, make sure you enable the repository for the application.
specify `--enableRepository` and `--enableServices` in the last command, then
you will see them in this list, make sure you enable both the repository and the
services for the application.

**Note:** Enable all options, unless you know what you are doing, see
[The Getting Started guide](Getting-started.md) for more information.
Expand Down
35 changes: 3 additions & 32 deletions docs/site/todo-tutorial-geocoding-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ docs here: [REST connector](/doc/en/lb3/REST-connector.html).

Create a new directory `src/services` and add the following two new files:

- `src/geocoder.service.ts` defining TypeScript interfaces for Geocoder service
and implementing a service proxy provider.
- `src/services/geocoder.service.ts` defining TypeScript interfaces for Geocoder
service and implementing a service proxy provider.
- `src/index.ts` providing a conventient access to all services via a single
`import` statement.

#### src/geocoder.service.ts
#### src/services/geocoder.service.ts

```ts
import {getService, juggler} from '@loopback/service-proxy';
Expand Down Expand Up @@ -140,35 +140,6 @@ export class GeocoderServiceProvider implements Provider<GeocoderService> {
export * from './geocoder.service';
```

### Register the service for dependency injection

Because `@loopback/boot` does not support loading of services yet (see
[issue #1439](https://github.com/strongloop/loopback-next/issues/1439)), we need
to add few code snippets to our Application class to take care of this task.

#### src/application.ts

```ts
import {ServiceMixin} from '@loopback/service-proxy';

export class TodoListApplication extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
) {
constructor(options?: ApplicationConfig) {
super(options);
// etc., keep the existing code without changes

// ADD THE FOLLOWING LINE AT THE END
this.setupServices();
}

// ADD THE FOLLOWING TWO METHODS
setupServices() {
this.serviceProvider(GeocoderServiceProvider);
}
}
```

### Enhance Todo model with location data

Add two new properties to our Todo model: `remindAtAddress` and `remindAtGeo`.
Expand Down
8 changes: 0 additions & 8 deletions examples/soap-calculator/src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {RepositoryMixin} from '@loopback/repository';
import {RestApplication} from '@loopback/rest';
import {ServiceMixin} from '@loopback/service-proxy';
import {MySequence} from './sequence';
import {CalculatorServiceProvider} from './services/calculator.service';

export class SoapCalculatorApplication extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
Expand All @@ -15,9 +14,6 @@ export class SoapCalculatorApplication extends BootMixin(
// Set up the custom sequence
this.sequence(MySequence);

//bind services
this.setupServices();

this.projectRoot = __dirname;
// Customize @loopback/boot Booter Conventions here
this.bootOptions = {
Expand All @@ -29,8 +25,4 @@ export class SoapCalculatorApplication extends BootMixin(
},
};
}

setupServices() {
this.serviceProvider(CalculatorServiceProvider);
}
}
9 changes: 0 additions & 9 deletions examples/todo/src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {RepositoryMixin} from '@loopback/repository';
import {RestApplication} from '@loopback/rest';
import {ServiceMixin} from '@loopback/service-proxy';
import {MySequence} from './sequence';
import {GeocoderServiceProvider} from './services';

export class TodoListApplication extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
Expand All @@ -30,13 +29,5 @@ export class TodoListApplication extends BootMixin(
nested: true,
},
};

// TODO(bajtos) Services should be created and registered by @loopback/boot
// See https://github.com/strongloop/loopback-next/issues/1439
this.setupServices();
}

setupServices() {
this.serviceProvider(GeocoderServiceProvider);
}
}
28 changes: 28 additions & 0 deletions packages/boot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ List of Options available on BootOptions Object.
| `controllers` | `ArtifactOptions` | ControllerBooter convention options |
| `repositories` | `ArtifactOptions` | RepositoryBooter convention options |
| `datasources` | `ArtifactOptions` | DataSourceBooter convention options |
| `services` | `ArtifactOptions` | ServiceBooter convention options |

### ArtifactOptions

Expand Down Expand Up @@ -159,6 +160,33 @@ Available options on the `datasources` object on `BootOptions` are as follows:
| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for DataSource artifacts |
| `glob` | `string` | | A `glob` pattern string. This takes precedence over above 3 options (which are used to make a glob pattern). |

### ServiceBooter

#### Description

Discovers and binds Service providers using `app.serviceProvider()` (Application
must use `ServiceMixin` from `@loopback/service-proxy`).

**IMPORTANT:** For a class to be recognized by `ServiceBooter` as a service
provider, its name must end with `Provider` suffix and its prototype must have a
`value()` method.

#### Options

The options for this can be passed via `BootOptions` when calling
`app.boot(options: BootOptions)`.

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

Available options on the `services` object on `BootOptions` are as follows:

| Options | Type | Default | Description |
| ------------ | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------ |
| `dirs` | `string \| string[]` | `['repositories']` | Paths relative to projectRoot to look in for Service artifacts |
| `extensions` | `string \| string[]` | `['.repository.js']` | File extensions to match for Service artifacts |
| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for Service artifacts |
| `glob` | `string` | | A `glob` pattern string. This takes precedence over above 3 options (which are used to make a glob pattern). |

## Contributions

- [Guidelines](https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md)
Expand Down
1 change: 1 addition & 0 deletions packages/boot/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"src/booters/controller.booter.ts",
"src/booters/datasource.booter.ts",
"src/booters/repository.booter.ts",
"src/booters/service.booter.ts",
"src/booters/index.ts",
"src/mixins/boot.mixin.ts",
"src/mixins/index.ts",
Expand Down
1 change: 1 addition & 0 deletions packages/boot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@loopback/core": "^0.11.5",
"@loopback/dist-util": "^0.3.6",
"@loopback/repository": "^0.15.1",
"@loopback/service-proxy": "^0.7.1",
"@types/debug": "0.0.30",
"@types/glob": "^5.0.35",
"debug": "^3.1.0",
Expand Down
14 changes: 12 additions & 2 deletions packages/boot/src/boot.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
import {Bootstrapper} from './bootstrapper';
import {Component, Application, CoreBindings} from '@loopback/core';
import {inject, BindingScope} from '@loopback/context';
import {ControllerBooter, RepositoryBooter, DataSourceBooter} from './booters';
import {
ControllerBooter,
RepositoryBooter,
DataSourceBooter,
ServiceBooter,
} from './booters';
import {BootBindings} from './keys';

/**
Expand All @@ -17,7 +22,12 @@ import {BootBindings} from './keys';
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 = [ControllerBooter, RepositoryBooter, DataSourceBooter];
booters = [
ControllerBooter,
RepositoryBooter,
ServiceBooter,
DataSourceBooter,
];

/**
*
Expand Down
Loading