From 85a93917ec5a5bd730e0073cce90fc4975bd9fcc Mon Sep 17 00:00:00 2001 From: Nora Date: Thu, 26 Mar 2020 15:37:25 -0400 Subject: [PATCH] docs: add model to rest api docs Documentation for application developers to use `@loopback/rest-crud` and extension developers to use `@loopback/model-api-builder`. --- docs/site/Creating-CRUD-REST-apis.md | 192 ++++++++++++++++++++++- docs/site/Extending-Model-API-builder.md | 132 ++++++++++++++++ docs/site/Using-components.md | 2 +- docs/site/sidebars/lb4_sidebar.yml | 4 + 4 files changed, 326 insertions(+), 4 deletions(-) create mode 100644 docs/site/Extending-Model-API-builder.md diff --git a/docs/site/Creating-CRUD-REST-apis.md b/docs/site/Creating-CRUD-REST-apis.md index 48249ce098a4..0e8c21504e7b 100644 --- a/docs/site/Creating-CRUD-REST-apis.md +++ b/docs/site/Creating-CRUD-REST-apis.md @@ -2,12 +2,198 @@ lang: en title: 'Creating CRUD REST APIs from a model' keywords: LoopBack 4.0, LoopBack 4 -layout: readme -source: loopback-next -file: packages/rest-crud/README.md sidebar: lb4_sidebar permalink: /doc/en/lb4/Creating-crud-rest-apis.html summary: Use `@loopback/rest-crud` module to create CRUD REST APIs from a model and a datasource --- + +Starting with a [model class](Model.md) and [datasource](DataSources.md), +LoopBack 4 allows you to easily use CRUD REST APIs by convention through +[`@loopback/rest-crud`](https://github.com/strongloop/loopback-next/tree/master/packages/rest-crud). +The package allows the application to use a default CRUD repository and +controller class without creating a custom class for either. + +The +[`rest-crud` example](https://github.com/strongloop/loopback-next/tree/master/examples/rest-crud) +is a simplified version of the +[`Todo` example](https://github.com/strongloop/loopback-next/tree/master/examples/todo) +that uses `@loopback/rest-crud`. To see the `rest-crud` example, use the +following command: + +```sh +lb4 example rest-crud +``` + +## Use + +To use this functionality, you must already have: + +- A LoopBack 4 application (e.g. `ExampleApplication`) +- At least one model class (e.g. `Product`) +- At least one datasource (e.g. `db`) + +### Model Configuration Options + +The +[`ModelCrudRestApiConfig`](https://loopback.io/doc/en/lb4/apidocs.rest-crud.modelcrudrestapiconfig.html) +interface provides some options to define and customize the REST API: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionDescriptionExample
modelName of the model classProduct
patternName of data-access patternAlways use CrudRest
dataSourceName of the datasourcedb
basePathBase path for the REST API/products
+ +Using the example attributes above, a model configuration file would be defined +as follows: + +{% include code-caption.html content="/src/model-endpoints/product.rest-config.ts" %} + +```ts +import {ModelCrudRestApiConfig} from '@loopback/rest-crud'; +import {Product} from '../models'; + +module.exports = { + model: Product, + pattern: 'CrudRest', // make sure to use this pattern + dataSource: 'db', + basePath: '/products', +}; +``` + +### CLI Command + +LoopBack 4 offers a CLI command to generate the CRUD REST API: + +```sh +lb4 rest-crud [options] +``` + +For example to create CRUD REST API for `Product` and `db`: + +```sh +lb4 rest-crud --datasource db --model Product +``` + +You can also create it for multiple models at the same time. For more +information on the command, see the +[Rest Crud generator](Rest-Crud-generator.md). + +This will generate a model configuration file and add the `CrudRestComponent` to +the application file. For more details, see the following section, +[under the hood](#Under-the-hood). + +## Under the Hood + +The CLI command installs the `@loopback/rest-crud` dependency. Then, from +`@loopback/rest-crud`, the +[`CrudRestComponent`](https://loopback.io/doc/en/lb4/apidocs.rest-crud.crudrestcomponent.html) +is added to the application class, as it enables the functionality of creating +the CRUD REST APIs from the model and datasource. For example: + +{% include code-caption.html content="/src/application.ts" %} + +```ts +// adds the following import +import {CrudRestComponent} from '@loopback/rest-crud'; + +export class ExampleApplication extends BootMixin( + RepositoryMixin(RestApplication), +) { + constructor(options: ApplicationConfig = {}) { + // other code + + // adds the following line + this.component(CrudRestComponent); + } +} +``` + +Then it takes the model class and datasource and creates a model configuration +file. For example: + +{% include code-caption.html content="/src/model-endpoints/product.rest-config.ts" %} + +```ts +import {ModelCrudRestApiConfig} from '@loopback/rest-crud'; +import {Product} from '../models'; + +module.exports = { + model: Product, + pattern: 'CrudRest', + dataSource: 'db', + basePath: '/products', +}; +``` + +Under the hood, a default CRUD controller and repository are created using +[`defineCrudControllerClass`](https://loopback.io/doc/en/lb4/apidocs.rest-crud.definecrudrestcontroller.html) +and +[`defineCrudRepositoryClass`](https://loopback.io/doc/en/lb4/apidocs.rest-crud.definecrudrepositoryclass.html), +respectively. These two functions can also be used at the application level. For +example: + +```ts +export class ExampleApplication extends BootMixin( + RepositoryMixin(RestApplication), +) { + constructor(options: ApplicationConfig = {}) { + // ... + } + + async boot(): Promise { + await super.boot(); + + const ProductRepository = defineCrudRepositoryClass(Product); + const repoBinding = this.repository(ProductRepository); + + inject('datasources.db')(ProductRepository, undefined, 0); + + const ProductController = defineCrudRestController< + Product, + typeof Product.prototype.id, + 'id' + >(Product, {basePath: '/products'}); + + inject(repoBinding.key)(ProductController, undefined, 0); + this.controller(ProductController); + } +} +``` + +Creating it in the application file allows you to create your own repository and +only use the default CRUD controller, for example. + +## Limitations + +Currently, the module doesn't support service-oriented datasources such as REST +or SOAP. diff --git a/docs/site/Extending-Model-API-builder.md b/docs/site/Extending-Model-API-builder.md new file mode 100644 index 000000000000..a35296147b54 --- /dev/null +++ b/docs/site/Extending-Model-API-builder.md @@ -0,0 +1,132 @@ +--- +lang: en +title: 'Extending Model API builder' +keywords: LoopBack 4.0, LoopBack 4 +sidebar: lb4_sidebar +permalink: /doc/en/lb4/Extending-Model-API-builder.html +--- + +The +[`@loopback/model-api-builder`](https://github.com/strongloop/loopback-next/tree/master/packages/model-api-builder) +package provides types and helpers for packages contributing Model API builders. +From a model class, this module can be used to define a contract to create a +corresponding repository and controller. An example Model API builder is the +[`CrudRestApiBuilder`](https://loopback.io/doc/en/lb4/apidocs.rest-crud.crudrestapibuilder.html) +which is used to create a CRUD REST repository and controller. You can see more +details in [Creating CRUD REST APIs](Creating-crud-rest-apis.md). + +`@loopback/model-api-builder` helps create a configuration for the repository +and controllers and +[`@loopback/boot`](https://github.com/strongloop/loopback-next/tree/master/packages/boot) +processes this configuration and registers appropriate repositories and +controllers with the app. + +To create your own API builder, you need to install the +`@loopback/model-api-builder` dependency: + +```sh +npm install --save @loopback/model-api-builder +``` + +Then you can define class to define your builder. For example: + +{% include code-caption.html content="sample.api-builder.ts" %} + +```ts +import {ModelApiBuilder} from '@loopback/model-api-builder'; + +export class SampleApiBuilder implements ModelApiBuilder {} +``` + +Then bind the builder with +[`@asModelApiBuilder`](https://loopback.io/doc/en/lb4/apidocs.model-api-builder.asmodelapibuilder.html) +so it can be used as an API builder option. + +```ts +import {bind} from '@loopback/core'; +import {asModelApiBulder, ModelApiBuilder} from '@loopback/model-api-builder'; + +@bind(asModelApiBuilder) +export class SampleApiBuilder implements ModelApiBuilder {} +``` + +Since the builder implements `ModelApiBuilder`, the `build` function must be +defined: + +```ts +import {bind} from '@loopback/core'; +import { + asModelApiBuilder, + ModelApiBuilder, + ModelApiConfig, +} from '@loopback/model-api-builder'; +import {ApplicationWithRepositories} from '@loopback/repository'; +import {Model} from '@loopback/rest'; + +@bind(asModelApiBuilder) +export class SampleApiBuilder implements ModelApiBuilder { + readonly pattern: string = 'Sample'; // put the name of your builder here + + build( + application: ApplicationWithRepositories, + modelClass: typeof Model & {prototype: Model}, + cfg: ModelApiConfig, + ): Promise { + // here you can define how the repository and controller classes are built + } +} +``` + +Additionally, you can add configuration options to be used: + +```ts +// imports + +export interface SampleApiConfig extends ModelApiConfig { + // add configuration options here +} + +@bind(asModelApiBuilder) +export class SampleApiBuilder implements ModelApiBuilder { + // other code here +} +``` + +After the builder is created, it must be exported as a component in order for it +to be selected by +[`ModelApiBooter`](https://loopback.io/doc/en/lb4/apidocs.boot.modelapibooter.html) +and to then be used in an application. Create a class for the component to +export the builder: + +{% include code-caption.html content="sample.component.ts" %} + +```ts +import {Component, createBindingFromClass} from '@loopback/core'; +import {SampleApiBuilder} from './sample.api-builder'; + +export class SampleComponent implements Component { + bindings = [createBindingFromClass(SampleApiBuilder)]; +} +``` + +To use the component, add it to your application class: + +{% include code-caption.html content="sample.api-builder.ts" %} + +```ts +// other imports + +// add an import for your component +import {SampleComponent} from '../sample.component'; + +export class ExampleApplication extends BootMixin( + RepositoryMixin(RestApplication), +) { + constructor(options: ApplicationConfig = {}) { + // other code + + // add the following line + this.component(SampleComponent); + } +} +``` diff --git a/docs/site/Using-components.md b/docs/site/Using-components.md index a3f81a2259b7..119baa2240c7 100644 --- a/docs/site/Using-components.md +++ b/docs/site/Using-components.md @@ -48,7 +48,7 @@ LoopBack ships the following components: - [@loopback/rest-explorer](Self-hosted-REST-API-Explorer.md) -### CruRestComponent +### CrudRestComponent - [@loopback/rest-crud](Creating-CRUD-REST-apis.md) diff --git a/docs/site/sidebars/lb4_sidebar.yml b/docs/site/sidebars/lb4_sidebar.yml index 3d48fa86508d..7507800198f8 100644 --- a/docs/site/sidebars/lb4_sidebar.yml +++ b/docs/site/sidebars/lb4_sidebar.yml @@ -320,6 +320,10 @@ children: url: Extending-OpenAPI-specification.html output: 'web, pdf' + - title: 'Extending Model API builder' + url: Extending-Model-API-builder.html + output: 'web, pdf' + - title: 'Testing your extension' url: Testing-your-extension.html output: 'web, pdf'