From c5e90b2de53557cca180d3b6e1b94fb5b4779e7a Mon Sep 17 00:00:00 2001 From: Yaapa Hage Date: Thu, 20 Aug 2020 22:05:42 +0530 Subject: [PATCH] chore: clean up extension generator Clean up the extension generator. Signed-off-by: Yaapa Hage --- docs/site/Component.md | 58 +++++++++++++++++++ docs/site/Creating-components.md | 40 ++++++++----- docs/site/Extending-LoopBack-4.md | 6 +- packages/cli/generators/extension/index.js | 8 +++ .../extension/templates/src/component.ts.ejs | 26 +++++++-- .../extension/templates/src/index.ts.ejs | 2 + .../extension/templates/src/keys.ts.ejs | 11 ++++ .../extension/templates/src/types.ts.ejs | 15 +++++ .../project/templates/README.md.ejs | 29 ++++++++++ packages/core/src/component.ts | 2 +- 10 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 packages/cli/generators/extension/templates/src/keys.ts.ejs create mode 100644 packages/cli/generators/extension/templates/src/types.ts.ejs diff --git a/docs/site/Component.md b/docs/site/Component.md index ac41ca894b5a..1a260ce345db 100644 --- a/docs/site/Component.md +++ b/docs/site/Component.md @@ -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 diff --git a/docs/site/Creating-components.md b/docs/site/Creating-components.md index 4d2f5798eca0..83fff992e382 100644 --- a/docs/site/Creating-components.md +++ b/docs/site/Creating-components.md @@ -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); +... +``` diff --git a/docs/site/Extending-LoopBack-4.md b/docs/site/Extending-LoopBack-4.md index e63b906c23ac..60ba66134907 100644 --- a/docs/site/Extending-LoopBack-4.md +++ b/docs/site/Extending-LoopBack-4.md @@ -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('controller.UserController'); // Run the login() const ok = await userController.login('John', 'MyPassWord'); @@ -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 diff --git a/packages/cli/generators/extension/index.js b/packages/cli/generators/extension/index.js index 027fb28366ee..32d00af14c0c 100644 --- a/packages/cli/generators/extension/index.js +++ b/packages/cli/generators/extension/index.js @@ -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(); } diff --git a/packages/cli/generators/extension/templates/src/component.ts.ejs b/packages/cli/generators/extension/templates/src/component.ts.ejs index d4c65c56cdab..4497bcd97255 100644 --- a/packages/cli/generators/extension/templates/src/component.ts.ejs +++ b/packages/cli/generators/extension/templates/src/component.ts.ejs @@ -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 %>, + ) {} } diff --git a/packages/cli/generators/extension/templates/src/index.ts.ejs b/packages/cli/generators/extension/templates/src/index.ts.ejs index bb824842ced8..a31115f3abee 100644 --- a/packages/cli/generators/extension/templates/src/index.ts.ejs +++ b/packages/cli/generators/extension/templates/src/index.ts.ejs @@ -1 +1,3 @@ export * from './component'; +export * from './keys'; +export * from './types'; diff --git a/packages/cli/generators/extension/templates/src/keys.ts.ejs b/packages/cli/generators/extension/templates/src/keys.ts.ejs new file mode 100644 index 000000000000..3a3dbd02fd2e --- /dev/null +++ b/packages/cli/generators/extension/templates/src/keys.ts.ejs @@ -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 %>`, + ); +} diff --git a/packages/cli/generators/extension/templates/src/types.ts.ejs b/packages/cli/generators/extension/templates/src/types.ts.ejs new file mode 100644 index 000000000000..d95266b98bb7 --- /dev/null +++ b/packages/cli/generators/extension/templates/src/types.ts.ejs @@ -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 + +}; diff --git a/packages/cli/generators/project/templates/README.md.ejs b/packages/cli/generators/project/templates/README.md.ejs index 1cbae54fd242..d5fdc3d0f0e4 100644 --- a/packages/cli/generators/project/templates/README.md.ejs +++ b/packages/cli/generators/project/templates/README.md.ejs @@ -1,3 +1,32 @@ # <%= project.name %> [![LoopBack](https://github.com/strongloop/loopback-next/raw/master/docs/site/imgs/branding/Powered-by-LoopBack-Badge-(blue)-@2x.png)](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 %>); + // ... + } + // ... +} +``` diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 7ef70aa3f943..a86868047b15 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -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 {