-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: first draft of Component Migration - general aspects
Signed-off-by: Miroslav Bajtoš <[email protected]>
- Loading branch information
Showing
7 changed files
with
338 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--- | ||
lang: en | ||
title: 'Migrating access to current context' | ||
keywords: LoopBack 4, LoopBack 3, Migration, Extensions, Components | ||
sidebar: lb4_sidebar | ||
permalink: /doc/en/lb4/migration-extensions-current-context.html | ||
--- | ||
|
||
{% include tip.html content=" | ||
Missing instructions for your LoopBack 3 use case? Please report a [Migration docs issue](https://github.com/strongloop/loopback-next/issues/new?labels=question,Migration,Docs&template=Migration_docs.md) on GitHub to let us know. | ||
" %} | ||
|
||
It's often desirable to share contextual data between different parts of an | ||
application. For example, a REST connector calling a backend web service may | ||
want to forward transaction (correlation) id provided in a HTTP header of the | ||
incoming request, or perhaps an auditing component wants to access the | ||
information about the user making the request to store it in the log. | ||
|
||
LoopBack 3 offers three approaches: | ||
|
||
1. The recommended solution is to explicitly pass any contextual information via | ||
`options` argument. Most LoopBack APIs accept (and forward) this argument and | ||
there are means how to initialize the `options` value based on the incoming | ||
request. | ||
|
||
2. Code working at REST layer can access and store contextual information on the | ||
HTTP request object. | ||
|
||
3. An experimental component | ||
[`loopback-context`](https://github.com/strongloop/loopback-context) uses | ||
continuation-local-storage to provide static per-request storage that can be | ||
accessed from anywhere inside a LoopBack application (an Express middleware, | ||
a model method, a connector, etc.). | ||
|
||
In LoopBack 4, extensions should use `@inject` decorators to access contextual | ||
information. For example: | ||
|
||
- `@inject(key)` and `@inject.getter(key)` to receive values from the context | ||
- `@inject.setter(key)` to obtain a setter function for writing values to the | ||
context | ||
|
||
To keep the contextual data per-request (as opposed to per-application), the | ||
`TRANSIENT` binding scope should be used. | ||
|
||
Components can keep using the old `options`-based approach where it makes more | ||
sense than Dependency Injection, typically when working with existing | ||
`options`-based code like Repository APIs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
--- | ||
lang: en | ||
title: 'Migrating components contributing Model mixins' | ||
keywords: LoopBack 4, LoopBack 3, Migration, Extensions, Components, Mixins | ||
sidebar: lb4_sidebar | ||
permalink: /doc/en/lb4/migration-extensions-mixins.html | ||
--- | ||
|
||
{% include tip.html content=" | ||
Missing instructions for your LoopBack 3 use case? Please report a [Migration docs issue](https://github.com/strongloop/loopback-next/issues/new?labels=question,Migration,Docs&template=Migration_docs.md) on GitHub to let us know. | ||
" %} | ||
|
||
In LoopBack 3, a component contributes mixins by providing files exporting mixin | ||
functions, for example: | ||
|
||
```js | ||
// lib/my-mixin.js | ||
module.exports = myMixin(Model, options) { | ||
// modify the target model provided in `Model` | ||
// apply configuration as specified in `options` | ||
}; | ||
``` | ||
|
||
In LoopBack 4, models are architecturally decoupled into 3 entities (a model, a | ||
repository and a controller), as further explained in | ||
[Migrating models](../models/overview.md) and | ||
[Migrating custom model methods](../models/methods.md). As a result, most | ||
LoopBack 3 mixins become a set of multiple mixins in LoopBack 4. | ||
|
||
To migrate a mixin from a LoopBack 3 component to a LoopBack 4 component: | ||
|
||
1. Follow the steps described in | ||
[Migrating model mixins ](https://loopback.io/doc/en/lb4/migration-models-mixins.html) | ||
to convert your mixin implementation to LB4 style. We recommend to put the | ||
new files to `src/mixins` directory in your LB4 component project. | ||
|
||
2. Modify your LB4 component to export the mixins - add `export` statements to | ||
components `src/index.ts` file. For example: | ||
|
||
```ts | ||
// src/index.ts | ||
export * from './mixins/my-mixin'; | ||
``` | ||
|
||
3. Update your documentation to show how to apply the new mixins in LoopBack 4 | ||
applications, use the content provided in | ||
[Migrating model mixins ](https://loopback.io/doc/en/lb4/migration-models-mixins.html) | ||
for inspiration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
--- | ||
lang: en | ||
title: 'Migrating components and extensions' | ||
keywords: LoopBack 4, LoopBack 3, Migration, Extensions, Components | ||
sidebar: lb4_sidebar | ||
permalink: /doc/en/lb4/migration-extensions-overview.html | ||
redirect_from: /doc/en/lb4/migration-extensions.html | ||
--- | ||
|
||
{% include tip.html content=" | ||
Missing instructions for your LoopBack 3 use case? Please report a [Migration docs issue](https://github.com/strongloop/loopback-next/issues/new?labels=question,Migration,Docs&template=Migration_docs.md) on GitHub to let us know. | ||
" %} | ||
|
||
{% include note.html content=" | ||
This is a placeholder page, the task of adding content is tracked by the | ||
following GitHub issue: | ||
[loopback-next#3955](https://github.com/strongloop/loopback-next/issues/3955) | ||
" %} | ||
|
||
In LoopBack 3, a component is essentially a function that extends and/or patches | ||
the target application. | ||
|
||
LoopBack 3 components can contribute: | ||
|
||
- additional models | ||
- new REST API endpoints (Express routes) | ||
- mixin to be used by application models | ||
|
||
They can also modify application's models to | ||
|
||
- register new | ||
[Operation Hooks](https://loopback.io/doc/en/lb3/Operation-hooks.html) | ||
- register new [Remote Hooks](https://loopback.io/doc/en/lb3/Remote-hooks.html) | ||
- define new relations | ||
|
||
In LoopBack 4, a component is typically a class providing artifacts it wants to | ||
contribute to the application. It is responsibility of the target application to | ||
import those artifacts. | ||
|
||
LoopBack 4 components can contribute: | ||
|
||
- [Model and Entity classes](../../Model.md) | ||
- [Mixins](../../Mixin.md) | ||
- [Decorators](../../Creating-decorators.md) | ||
- [Sequence Actions](../../Sequence.md#actions) | ||
- [Controllers](../../Controllers.md) | ||
- [Life cycle observers](../../Extension-life-cycle.md) | ||
- [Repositories](../../Repositories.md) | ||
- [Service proxies](../../Calling-other-APIs-and-Web-Services.md) | ||
- [Servers](../../Creating-servers.md) | ||
- [HTTP request parsers](../../Extending-request-body-parsing.md) | ||
- Extensions for [Extension Points](../../Extension-point-and-extensions.md) | ||
- [Booters](../../Booting-an-Application.md#custom-booters) | ||
- [Model API builders](../../Extending-Model-API-builder.md) | ||
- Extensions for Extension Points defined by 3rd-party component | ||
- Any other values to be bound in `Application`'s context: | ||
- [Classes](../../Binding.md#a-class) | ||
- [Providers](../../Binding.md#a-provider) | ||
- [Arbitrary bindings](../../Binding.md) (instances of `Binding` class) | ||
|
||
As the last resort, LoopBack 4 components can also modify the target application | ||
directly by calling `Application` APIs (this is similar to LoopBack 3 approach). | ||
|
||
To make the migration guide easier to navigate, we split component-related | ||
instructions into several sub-sections. | ||
|
||
1. [Migrating component project layout](./project-layout.md) describes how to | ||
migrate your LoopBack 3 extension project infrastructure to LoopBack 4 style | ||
and how to update the instructions for using your component. | ||
|
||
1. [Migrating access to current context](./current-context.md) describes how to | ||
migrate code accessing contextual information shared by different parts of a | ||
LoopBack application. | ||
|
||
1. [Migrating components contributing Model mixins](./mixins) explains how to | ||
migrate a component that's contributing Model mixins. | ||
|
||
1. _More sections will be created as part of | ||
[loopback-next#3955](https://github.com/strongloop/loopback-next/issues/3955)._ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
--- | ||
lang: en | ||
title: 'Migrating component project layout' | ||
keywords: LoopBack 4, LoopBack 3, Migration, Extensions, Components | ||
sidebar: lb4_sidebar | ||
permalink: /doc/en/lb4/migration-extensions-project-layout.html | ||
--- | ||
|
||
{% include tip.html content=" | ||
Missing instructions for your LoopBack 3 use case? Please report a [Migration docs issue](https://github.com/strongloop/loopback-next/issues/new?labels=question,Migration,Docs&template=Migration_docs.md) on GitHub to let us know. | ||
" %} | ||
|
||
The first step on the component migration journey is to reorganize the project | ||
files, change component's entry point and documentation for adding the component | ||
to the target application. | ||
|
||
## LoopBack 3 component layout & mounting | ||
|
||
A LB3 component is implemented as a function accepting the target app object and | ||
the configuration options. | ||
|
||
A minimal component consists of a single `index.js` file with the following | ||
content: | ||
|
||
```ts | ||
module.exports = function initializeComponent(loopbackApplication, options) { | ||
// implementation | ||
}; | ||
``` | ||
|
||
A component is typically added to a LB3 application by creating a new entry in | ||
`server/component-config.json`, see | ||
[LoopBack components](https://loopback.io/doc/en/lb3/LoopBack-components.html). | ||
|
||
For example: | ||
|
||
```json | ||
{ | ||
"loopback-explorer": { | ||
"mountPath": "/explorer" | ||
} | ||
} | ||
``` | ||
|
||
This allows the component to receive configuration. App developers can provide | ||
environment-specific configuration by using `component-config.{env}.json` files. | ||
|
||
## LoopBack 4 layout | ||
|
||
As explained in [Creating components](../../Creating-Components.md) and | ||
[Using components](../../Using-components.md), a typical LoopBack 4 component is | ||
an npm package exporting a Component class. | ||
|
||
The component class is usually implemented inside | ||
`src/{component-name}.component.ts` file, for example | ||
[src/metrics.component.ts](https://github.com/strongloop/loopback-next/blob/38f10b240551227d2d030c2fe8ee206880c9e029/extensions/metrics/src/metrics.component.ts): | ||
|
||
```ts | ||
import {Application, Component, CoreBindings} from '@loopback/core'; | ||
import {bind, config, ContextTags, inject} from '@loopback/context'; | ||
import {MetricsBindings} from './keys'; | ||
import {DEFAULT_METRICS_OPTIONS, MetricsOptions} from './types'; | ||
|
||
@bind({tags: {[ContextTags.KEY]: MetricsBindings.COMPONENT}}) | ||
export class MetricsComponent implements Component { | ||
constructor( | ||
@inject(CoreBindings.APPLICATION_INSTANCE) | ||
private application: Application, | ||
@config() | ||
options: MetricsOptions = DEFAULT_METRICS_OPTIONS, | ||
) { | ||
// ... | ||
} | ||
// ... | ||
} | ||
``` | ||
|
||
The code snippet above also shows how a LoopBack 4 component can receive | ||
configuration and the target application object. | ||
|
||
## Usage instructions | ||
|
||
LoopBack 4 components are added to applications inside application constructor. | ||
|
||
First, the application file needs to import the component class: | ||
|
||
```ts | ||
import {MetricsComponent} from '@loopback/extension-metrics'; | ||
``` | ||
|
||
Then in the constructor, add the component to your application: | ||
|
||
```ts | ||
this.component(MetricsComponent); | ||
``` | ||
|
||
Finally, the application can configure the component by adding the following | ||
code to its constructor: | ||
|
||
```ts | ||
this.configure(MetricsBindings.COMPONENT).to({ | ||
// the configuration | ||
}); | ||
``` | ||
|
||
## Migration steps | ||
|
||
It is not feasible to migrate a LoopBack 3 component project to a LoopBack 4 | ||
component project in a series of incremental changes done within the same | ||
repository. We recommend to create a new project using | ||
[`lb4 extension`](../../Extension-generator.md) CLI command and then | ||
incrementally migrate artifacts from the original LoopBack 3 component to the | ||
new project. | ||
|
||
{% include note.html content="The extension project template used by `lb4 extension` is a bit outdated now, please refer to [loopback-next#5336](https://github.com/strongloop/loopback-next/issues/5336) for more details. | ||
" %} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.