Skip to content

Commit

Permalink
chore: clean up extension generator
Browse files Browse the repository at this point in the history
Clean up the extension generator.

Signed-off-by: Yaapa Hage <[email protected]>
  • Loading branch information
Yaapa Hage authored and hacksparrow committed Aug 31, 2020
1 parent 1de7194 commit a4d9b15
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 24 deletions.
58 changes: 58 additions & 0 deletions docs/site/Component.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,64 @@ const app = new RestApplication();
app.component(AuthenticationComponent);
```

## Official components

Here is a list of components officially created and maintained by the LoopBack
team.

### Core components

These components implement the primary LoopBack capabilities.

- [@loopback/authentication](https://github.com/strongloop/loopback-next/tree/master/packages/authentication) -
A LoopBack component for authentication support
- [@loopback/authorization](https://github.com/strongloop/loopback-next/tree/master/packages/authorization) -
A LoopBack component for authorization support
- [@loopback/boot](https://github.com/strongloop/loopback-next/tree/master/packages/boot) -
A collection of Booters for LoopBack 4 Applications
- [@loopback/booter-lb3app](https://github.com/strongloop/loopback-next/tree/master/packages/booter-lb3app) -
A booter component for LoopBack 3 applications to expose their REST API via
LoopBack 4
- [@loopback/rest](https://github.com/strongloop/loopback-next/tree/master/packages/rest) -
Expose controllers as REST endpoints and route REST API requests to controller
methods
- [@loopback/rest-crud](https://github.com/strongloop/loopback-next/tree/master/packages/rest-crud) -
REST API controller implementing default CRUD semantics
- [@loopback/rest-explorer](https://github.com/strongloop/loopback-next/tree/master/packages/rest-explorer) -
LoopBack's API Explorer

### Extensions

These components add additional capabilities to LoopBack.

- [@loopback/apiconnect](https://github.com/strongloop/loopback-next/tree/master/extensions/apiconnect) -
An extension for integrating with
[IBM API Connect](https://www.ibm.com/cloud/api-connect)
- [@loopback/authentication-jwt](https://github.com/strongloop/loopback-next/tree/master/extensions/authentication-jwt) -
Extension for JWT authentication
- [@loopback/authentication-passport](https://github.com/strongloop/loopback-next/tree/master/extensions/authentication-passport) -
A package creating adapters between the passport module and
@loopback/authentication
- [@loopback/context-explorer](https://github.com/strongloop/loopback-next/tree/master/extensions/context-explorer) -
Visualize context hierarchy, bindings, configurations, and dependencies
- [@loopback/cron](https://github.com/strongloop/loopback-next/tree/master/extensions/cron) -
Schedule tasks using cron-like syntax
- [@loopback/extension-health](https://github.com/strongloop/loopback-next/tree/master/extensions/health) -
An extension exposes health check related endpoints with LoopBack 4
- [@loopback/extension-logging](https://github.com/strongloop/loopback-next/tree/master/extensions/logging) -
An extension exposes logging for Winston and Fluentd with LoopBack 4
- [@loopback/extension-metrics](https://github.com/strongloop/loopback-next/tree/master/extensions/metrics) -
An extension exposes metrics for Prometheus with LoopBack 4
- [@loopback/pooling](https://github.com/strongloop/loopback-next/tree/master/extensions/pooling) -
Resource pooling service for LoopBack 4
- [@loopback/typeorm](https://github.com/strongloop/loopback-next/tree/master/extensions/typeorm) -
Adds support for TypeORM in LoopBack

### Community extensions

For a list of components created by community members, refer to
[Community extensions](./Community-extensions.html).

## Creating components

Please refer to [Creating components](Creating-components.md) for more
Expand Down
40 changes: 26 additions & 14 deletions docs/site/Creating-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,23 +441,35 @@ app.find('repositories.*');

## Configuring components

More often than not, the component may want to offer different value providers
depending on the configuration. For example, a component providing an email API
may offer different transports (stub, SMTP, and so on).
Components can be configured by an app by calling `this.configure()` in its
constructor, and the configuration object can be injected into the component
constructor using the `@config()` decorator.

Components should use constructor-level
[Dependency Injection](Context.md#dependency-injection) to receive the
configuration from the application.
{% include code-caption.html content="mycomponent.ts" %}

```ts
class EmailComponent {
constructor(@inject('config#components.email') config) {
this.providers = {
sendEmail:
this.config.transport == 'stub'
? StubTransportProvider
: SmtpTransportProvider,
};
export class MyComponent implements Component {
constructor(
@config()
options: MyComponentOptions = {enableLogging: false},
) {
if (options.enableLogging) {
// do logging
} else {
// no logging
}
}
}
```

{% include code-caption.html content="application.ts" %}

```ts
...
// MyComponent.COMPONENT is the binding key of MyComponent
this.configure(MyComponent.COMPONENT).to({
enableLogging: true,
});
this.component(MyComponent);
...
```
6 changes: 3 additions & 3 deletions docs/site/Extending-LoopBack-4.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ ctx.bind('utilities.PasswordHash').to(PasswordHasher)
// Bind the UserController class as the user management implementation
ctx.bind('controllers.UserController').toClass(UserController);

// Locate the an instance of UserController from the context
// Locate the instance of UserController from the context
const userController: UserController = await ctx.get<UserController>('controller.UserController');
// Run the login()
const ok = await userController.login('John', 'MyPassWord');
Expand Down Expand Up @@ -189,8 +189,8 @@ An application-level component usually contributes:

### Learn from existing ones

- [loopback4-example-log-extension](https://github.com/strongloop/loopback-next/tree/master/examples/log-extension)
- [@loopback/authentication](https://github.com/strongloop/loopback-next/tree/master/packages/authentication)
Refer to the list of [official components](./Component.md#official-components)
for an idea about how different types of components are written.

### Create your own extension

Expand Down
8 changes: 8 additions & 0 deletions packages/cli/generators/extension/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ module.exports = class ExtensionGenerator extends ProjectGenerator {
}

scaffold() {
if (this.projectInfo) {
this.projectInfo.optionsInterface = `${this.projectInfo.componentName}Options`;
this.projectInfo.bindingsNamespace = `${this.projectInfo.componentName}Bindings`;
const uppercaseUnderscore = this.projectInfo.name
.toUpperCase()
.replace(/\W/g, '_');
this.projectInfo.defaultOptions = `DEFAULT_${uppercaseUnderscore}_OPTIONS`;
}
return super.scaffold();
}

Expand Down
26 changes: 20 additions & 6 deletions packages/cli/generators/extension/templates/src/component.ts.ejs
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import {Component, ProviderMap} from '@loopback/core';
import {
Application,
bind,
Component,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
config,
ContextTags,
CoreBindings,
inject,
} from '@loopback/core';
import {<%= project.bindingsNamespace %>} from './keys'
import {<%= project.defaultOptions %>, <%= project.optionsInterface %>} from './types';

// Configure the binding for <%= project.componentName %>
@bind({tags: {[ContextTags.KEY]: <%= project.bindingsNamespace %>.COMPONENT}})
export class <%= project.componentName %> implements Component {
constructor() {}

providers?: ProviderMap = {
};

constructor(
@inject(CoreBindings.APPLICATION_INSTANCE)
private application: Application,
@config()
private options: <%= project.optionsInterface %> = <%= project.defaultOptions %>,
) {}
}
2 changes: 2 additions & 0 deletions packages/cli/generators/extension/templates/src/index.ts.ejs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './component';
export * from './keys';
export * from './types';
11 changes: 11 additions & 0 deletions packages/cli/generators/extension/templates/src/keys.ts.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {BindingKey, CoreBindings} from '@loopback/core';
import {<%= project.componentName %>} from './component';

/**
* Binding keys used by this component.
*/
export namespace <%= project.bindingsNamespace %> {
export const COMPONENT = BindingKey.create<<%= project.componentName %>>(
`${CoreBindings.COMPONENTS}.<%= project.componentName %>`,
);
}
15 changes: 15 additions & 0 deletions packages/cli/generators/extension/templates/src/types.ts.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Interface defining the component's options object
*/
export interface <%= project.optionsInterface %> {
// Add the definitions here

}

/**
* Default options for the component
*/
export const <%= project.defaultOptions %>: <%= project.optionsInterface %> = {
// Specify the values here

};
29 changes: 29 additions & 0 deletions packages/cli/generators/project/templates/README.md.ejs
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
# <%= project.name %>

[![LoopBack](https://github.com/strongloop/loopback-next/raw/master/docs/site/imgs/branding/Powered-by-LoopBack-Badge-(blue)[email protected])](http://loopback.io/)

## Installation

Install <%= project.componentName %> using `npm`;

```sh
$ npm install <%= project.name %>
```

## Basic Use

Configure and load <%= project.componentName %> in the application constructor
as shown below.

```ts
import {<%= project.componentName %>, <%= project.optionsInterface %>, <%= project.defaultOptions %>} from '<%= project.name %>';
// ...
export class MyApplication extends BootMixin(ServiceMixin(RepositoryMixin(RestApplication))) {
constructor(options: ApplicationConfig = {}) {
const opts: <%= project.optionsInterface %> = <%= project.defaultOptions %>;
this.configure(<%= project.bindingsNamespace %>.COMPONENT).to(opts);
// Put the configuration options here
});
this.component(<%= project.componentName %>);
// ...
}
// ...
}
```
2 changes: 1 addition & 1 deletion packages/core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface ClassMap {
}

/**
* A component declares a set of artifacts so that they cane be contributed to
* A component declares a set of artifacts so that they can be contributed to
* an application as a group
*/
export interface Component {
Expand Down

0 comments on commit a4d9b15

Please sign in to comment.