diff --git a/_data/sidebars/lb4_sidebar.yml b/_data/sidebars/lb4_sidebar.yml index fcb482e57..9f463b32d 100644 --- a/_data/sidebars/lb4_sidebar.yml +++ b/_data/sidebars/lb4_sidebar.yml @@ -41,6 +41,10 @@ children: url: Dependency-injection.html output: 'web, pdf' + - title: 'Booting an Application' + url: Booting-an-Application.html + output: 'web, pdf' + - title: 'Controllers' url: Controllers.html output: 'web, pdf' diff --git a/pages/en/lb4/Booting-an-Application.md b/pages/en/lb4/Booting-an-Application.md new file mode 100644 index 000000000..291175059 --- /dev/null +++ b/pages/en/lb4/Booting-an-Application.md @@ -0,0 +1,238 @@ +--- +lang: en +title: 'Booting an Application' +keywords: LoopBack 4.0, LoopBack 4 +tags: +sidebar: lb4_sidebar +permalink: /doc/en/lb4/Booting-an-Application.html +summary: +--- + +## What does Booting an Application mean? + +A typical LoopBack application is made up of many artifacts in different files, +organized in different folders. **Booting an Application** means: + +* Discovering artifacts automatically based on a convention (a specific folder + containing files with a given suffix) +* Processing those artifacts (this usually means automatically binding them to the Application's Context) + +`@loopback/boot` provides a Bootstrapper that uses Booters to automatically +discover and bind artifacts, all packaged in an easy-to-use Mixin. + +### What is an artifact? + +An artifact is any LoopBack construct usually defined in code as a Class. LoopBack +constructs include Controllers, Repositories, Models, etc. + +## Usage + +### @loopback/cli + +New projects generated using `@loopback/cli` or `lb4` are automatically enabled +to use `@loopback/boot` for booting the Application using the conventions +followed by the CLI. + +### Adding to existing project + +See [Using the BootMixin](#using-the-bootmixin) to add Boot to your Project manually. + +--- + +The rest of this page describes the inner workings of `@loopback/boot` for advanced use +cases, manual usage or using `@loopback/boot` as a standalone package (with custom +booters). + +## BootMixin + +Boot functionality can be added to a LoopBack 4 Application by mixing it with the +`BootMixin`. The Mixin adds the `BootComponent` to your Application as well as +convenience methods such as `app.boot()` and `app.booters()`. The Mixin also allows +Components to set the property `booters` as an Array of `Booters`. They will be bound +to the Application and called by the `Bootstrapper`. + +Since this is a convention-based Bootstrapper, it is important to set a `projectRoot`, +as all other artifact paths will be resolved relative to this path. + +_Tip_: `application.ts` will likely be at the root of your project, so its path can be +used to set the `projectRoot` by using the `__dirname` variable. _(See example below)_ + +### Using the BootMixin + +`Booter` and `Binding` types must be imported alongside `BootMixin` to allow TypeScript +to infer types and avoid errors. _If using `tslint` with the `no-unused-variable` rule, +you can disable it for the import line by adding `// tslint:disable-next-line:no-unused-variable` +above the import statement_. + +```ts +import {BootMixin, Booter, Binding} from "@loopback/boot"; + +class MyApplication extends BootMixin(Application) { + constructor(options?: ApplicationConfig) { + super(options); + // Setting the projectRoot + this.projectRoot = __dirname; + // Set project conventions + this.bootOptions: BootOptions = { + controllers: { + dirs: ['controllers'], + extensions: ['.controller.js'], + nested: true, + } + } + } +} +``` + +Now just call `app.boot()` from `index.ts` before starting your Application using `app.start()`. + +#### app.boot() + +A convenience method to retrieve the `Bootstrapper` instance bound to the +Application and calls its `boot` function. This should be called before an +Application's `start()` method is called. _This is an `async` function and should +be called with `await`._ + +```ts +class MyApp extends BootMixin(Application) {} + +async main() { + const app = new MyApp(); + app.projectRoot = __dirname; + await app.boot(); + await app.start(); +} +``` + +#### app.booters() + +A convenience method to manually bind `Booters`. You can pass any number of `Booter` +classes to this method and they will all be bound to the Application using the +prefix (`booters.`) and tag (`booter`) used by the `Bootstrapper`. + +```ts +// Binds MyCustomBooter to `booters.MyCustomBooter` +// Binds AnotherCustomBooter to `booters.AnotherCustomBooter` +// Both will have the `booter` tag set. +app.booters(MyCustomBooter, AnotherCustomBooter); +``` + +## BootComponent + +This component is added to an Application by `BootMixin` if used. This Component: + +* Provides a list of default `booters` as a property of the component +* Binds the conventional Bootstrapper to the Application + +_If using this as a standalone component without the `BootMixin`, you will need to +bind the `booters` of a component manually._ + +```ts +app.component(BootComponent); +``` + +## Bootstrapper + +A Class that acts as the "manager" for Booters. The Bootstrapper is designed to be +bound to an Application as a `SINGLETON`. The Bootstrapper class provides a `boot()` +method. This method is responsible for getting all bound `Booters` and running +their `phases`. A `phase` is a method on a `Booter` class. + +Each `boot()` method call creates a new `Context` that sets the `app` context +as its parent. This is done so each `Context` for `boot` gets a new instance of +`booters` but the same context can be passed into `boot` so selective `phases` can be +run in different calls of `boot`. + +The Bootstrapper can be configured to run specific booters or boot phases +by passing in `BootExecOptions`. **This is experimental and subject to change. Hence, +this functionality is not exposed when calling `boot()` via `BootMixin`**. + +To use `BootExecOptions`, you must directly call `bootstrapper.boot()` instead of `app.boot()`. +You can pass in the `BootExecOptions` object with the following properties: + +| Property | Type | Description | +| ---------------- | ----------------------- | ------------------------------------------------ | +| `booters` | `Constructor[]` | Array of Booters to bind before running `boot()` | +| `filter.booters` | `string[]` | Names of Booter classes that should be run | +| `filter.phases` | `string[]` | Names of Booter phases to run | + +### Example + +```ts +import { BootMixin, Booter, Binding, Bootstrapper } from "@loopback/boot"; + +class MyApp extends BootMixin(Application) {} +const app = new MyApp(); +app.projectRoot = __dirname; + +const bootstrapper: Bootstrapper = await this.get( + BootBindings.BOOTSTRAPPER_KEY +); +bootstrapper.boot({ + booters: [MyCustomBooter], + filter: { + booters: ["MyCustomBooter"], + phases: ["configure", "discover"] // Skip the `load` phase. + } +}); +``` + +## Booters + +A Booter is a class that is responsible for booting an artifact. A Booter does its +work in `phases` which are called by the Bootstrapper. The following Booters are +a part of the `@loopback/boot` package and loaded automatically via `BootMixin`. + +### Controller Booter + +This Booter's purpose is to discover [Controller](http://loopback.io/doc/en/lb4/Controllers.html) type Artifacts and to bind +them to the Application's Context. + +You can configure the conventions used in your +project for a Controller by passing a `controllers` object on `BootOptions` property +of your Application. The `controllers` object supports the following options: + +| 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 | +| `glob` | `string` | | A `glob` pattern string. This takes precendence over above 3 options (which are used to make a glob pattern). | + +### Repository Booter + +This Booter's purpose is to discover [Repository]() type Artifacts and to bind +them to the Application's Context. The use of this Booter requires `RepositoryMixin` +from `@loopback/repository` to be mixed into your Application class. + +You can configure the conventions used in your +project for a Repository by passing a `repositories` object on `BootOptions` property +of your Application. The `repositories` object supports the following options: + +| Options | Type | Default | Description | +| ------------ | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------- | +| `dirs` | `string \| string[]` | `['repositories']` | Paths relative to projectRoot to look in for Repository artifacts | +| `extensions` | `string \| string[]` | `['.repository.js']` | File extensions to match for Repository artifacts | +| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for Repository artifacts | +| `glob` | `string` | | A `glob` pattern string. This takes precendence 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` interface. The Class +must implement methods that corresponds to a `phase` name. The `phases` are called +by the Bootstrapper in a pre-determined order (unless overridden by `BootExecOptions`). +The next phase is only called once the previous phase has been completed for all Booters. + +#### Phases + +**configure** + +Used to configure the `Booter` with its default options. + +**discover** + +Used to discover the artifacts supported by the `Booter` based on convention. + +**load** + +Used to bind the discovered artifacts to the Application. diff --git a/pages/en/lb4/Concepts.md b/pages/en/lb4/Concepts.md index db175297c..935ea23ee 100644 --- a/pages/en/lb4/Concepts.md +++ b/pages/en/lb4/Concepts.md @@ -10,22 +10,24 @@ summary: LoopBack 4 introduces some new concepts that are important to understand: -- [**Application**](Application.html): In LoopBack 4, the Application class is -the central class for setting up all of your module’s components, controllers, -servers and bindings. The Application class extends [Context](Context.html), and -provides the controls for starting and stopping itself and its associated -servers. -- [**Server**](Server.html): Represents implementation for inbound transports and/or protocols such as REST over http, gRPC over http2, and graphQL over https. It typically listens for requests on a specific port, handle them, and return appropriate responses. -- [**Context**](Context.html): An abstraction of all state and dependencies in your application, that LoopBack uses to “manage” everything. It's a global registry for everything in your app (configurations, state, dependencies, classes, and so on). -- [**Dependency Injection**](Dependency-injection.html): Technique that separates the construction of dependencies of a class or function from its behavior, to keep the code loosely coupled. -- [**Controller**](Controllers.html): Class that implements operations defined by application’s REST API. It implements an application’s business logic and acts as a bridge between the HTTP/REST API and domain/database models. A Controller operates only on processed input and abstractions of backend services / databases. -- [**Route**](Routes.html): Mapping between your API specification and an Operation (JavaScript implementation). It tells LoopBack which function to invoke() given an HTTP request. -- [**Sequence**](Sequence.html): A stateless grouping of [Actions](Sequence.html#actions) that control how a Server responds to requests. -- [**Model**](Model.html): Represents the definition of a model in LoopBack, with respect to the datasource juggler. The `@loopback/repository` module provides special decorators for adding metadata to TypeScript/JavaScript classes to use them with the legacy implementation of Datasource Juggler. In addition, `@loopback/repository-json-schema` module uses the decorators' metadata to build a matching JSON Schema. -- [**Repository**](Repositories.html): Type of Service that represents a collection of data within a DataSource. -- [**Decorator**](Decorators.html): Enables you to annotate or modify your class declarations and members with metadata. -- **Component**: A package that bundles one or more Loopback extensions. - - See [Using components](Using-components.html) and [Creating components](Creating-components.html) for more information. +* [**Application**](Application.html): In LoopBack 4, the Application class is + the central class for setting up all of your module’s components, controllers, + servers and bindings. The Application class extends [Context](Context.html), and + provides the controls for starting and stopping itself and its associated + servers. +* [**Server**](Server.html): Represents implementation for inbound transports and/or protocols such as REST over http, gRPC over http2, and graphQL over https. It typically listens for requests on a specific port, handle them, and return appropriate responses. +* [**Context**](Context.html): An abstraction of all state and dependencies in your application, that LoopBack uses to “manage” everything. It's a global registry for everything in your app (configurations, state, dependencies, classes, and so on). +* [**Dependency Injection**](Dependency-injection.html): Technique that separates the construction of dependencies of a class or function from its behavior, to keep the code loosely coupled. +* [**Booting an Application**](Booting-an-Application.html): A convention-based + bootstrapper that can find and bind artifacts such as Controllers, Repositories, etc. +* [**Controller**](Controllers.html): Class that implements operations defined by application’s REST API. It implements an application’s business logic and acts as a bridge between the HTTP/REST API and domain/database models. A Controller operates only on processed input and abstractions of backend services / databases. +* [**Route**](Routes.html): Mapping between your API specification and an Operation (JavaScript implementation). It tells LoopBack which function to invoke() given an HTTP request. +* [**Sequence**](Sequence.html): A stateless grouping of [Actions](Sequence.html#actions) that control how a Server responds to requests. +* [**Model**](Model.html): Represents the definition of a model in LoopBack, with respect to the datasource juggler. The `@loopback/repository` module provides special decorators for adding metadata to TypeScript/JavaScript classes to use them with the legacy implementation of Datasource Juggler. In addition, `@loopback/repository-json-schema` module uses the decorators' metadata to build a matching JSON Schema. +* [**Repository**](Repositories.html): Type of Service that represents a collection of data within a DataSource. +* [**Decorator**](Decorators.html): Enables you to annotate or modify your class declarations and members with metadata. +* **Component**: A package that bundles one or more Loopback extensions. + * See [Using components](Using-components.html) and [Creating components](Creating-components.html) for more information. {% include note.html title="Review Note" content="_Perhaps this should include some of the material in Thinking in LoopBack_. " %}