-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
docs: component migration - general aspects #5262
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. |
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. |
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should mention #5304 and give an example to show how to use an application as a component to allow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am afraid I don't see how the booter for loading artifacts from a sub-application is related to migrating LB3 extensions to LB4? Can you @raymondfeng please open a follow-up issue to describe in more detail what are you looking for? |
||
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)._ |
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. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should recommend There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am already recommending |
||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mention that
TRANSIENT
scope should be used for such bindings in order to receiveper-request
contextual data.