diff --git a/_data/sidebars/lb4_sidebar.yml b/_data/sidebars/lb4_sidebar.yml index 9f463b32d..a357da771 100644 --- a/_data/sidebars/lb4_sidebar.yml +++ b/_data/sidebars/lb4_sidebar.yml @@ -111,13 +111,18 @@ children: output: 'web, pdf' children: - - title: 'Defining and validating the API' - url: Defining-and-validating-the-API.html + - title: 'Defining the API using code-first approach' + url: Defining-the-API-using-code-first-approach.html output: 'web, pdf' - - title: 'Testing the API' - url: Testing-the-API.html + - title: 'Defining the API using design-first approach' + url: Defining-the-API-using-design-first-approach.html output: 'web, pdf' + children: + + - title: 'Testing the API' + url: Testing-the-API.html + output: 'web, pdf' - title: 'Defining your testing strategy' url: Defining-your-testing-strategy.html diff --git a/pages/en/lb4/Best-practices-with-Loopback-4.md b/pages/en/lb4/Best-practices-with-Loopback-4.md index 6ec16bcef..c9a6bc072 100644 --- a/pages/en/lb4/Best-practices-with-Loopback-4.md +++ b/pages/en/lb4/Best-practices-with-Loopback-4.md @@ -8,12 +8,21 @@ permalink: /doc/en/lb4/Best-practices-with-Loopback-4.html summary: --- +{% include important.html content=" +The API-first approach for building LoopBack +applications is not yet fully supported. Therefore, some of the sections in this +page are outdated and may not work out of the box. They will be revisited after +our MVP release. +" %} + LoopBack 4 is more than just a framework: It’s an ecosystem that encourages developers to follow best practices through predefined standards. This section will walk through some important guidelines by building an example API for a catalog of products. Our best practice follows an "API first" and test-driven development approach: -1. [**Defining and validating the API**](./Defining-and-validating-the-API.html): This section guides you through constructing your API first before any internal logic is added. -2. [**Testing the API**](./Testing-the-API.html): This section describes the process of writing smoke test for your API and its spec. -3. [**Defining your testing strategy**](./Defining-your-testing-strategy.html): This section discusses the advantages and the process of building a strong testing suite. -4. [**Implementing features**](./Implementing-features.html): This section demonstrates how the tests for each feature of your application should be written, and how to write the logic to make these tests pass. In the example, the tests for the controller, model, repository, data source, and sequence are written and then implemented. -5. [**Preparing the API for consumption**](./Preparing-the-API-for-consumption.html): This section shows how the endpoints can be physically tested using the Swagger UI. +1. **Defining the API**: There are two possible approaches to take in this section + - [**Defining the API using code-first approach**](./Defining-the-API-using-code-first-approach.html): This section guides you through setting up a skeleton of your application so that its full OpenAPI specification can be automatically generated. + - [**Defining the API using design-first approach**](./Defining-the-API-using-design-first-approach.html): This section guides you through constructing your API first before any internal logic is added. __*Not fully supported*__ + - [**Testing the API**](./Testing-the-API.html): This section describes the process of writing smoke test for your API and its spec. __*Not fully supported*__ +2. [**Defining your testing strategy**](./Defining-your-testing-strategy.html): This section discusses the advantages and the process of building a strong testing suite. +3. [**Implementing features**](./Implementing-features.html): This section demonstrates how the tests for each feature of your application should be written, and how to write the logic to make these tests pass. In the example, the tests for the controller, model, repository, data source, and sequence are written and then implemented. +4. [**Preparing the API for consumption**](./Preparing-the-API-for-consumption.html): This section shows how the endpoints can be physically tested using the Swagger UI. diff --git a/pages/en/lb4/Defining-the-API-using-code-first-approach.md b/pages/en/lb4/Defining-the-API-using-code-first-approach.md new file mode 100644 index 000000000..cf97d48ae --- /dev/null +++ b/pages/en/lb4/Defining-the-API-using-code-first-approach.md @@ -0,0 +1,186 @@ +--- +lang: en +title: 'Defining the API using code-first approach' +keywords: LoopBack 4.0, LoopBack 4 +tags: +sidebar: lb4_sidebar +permalink: /doc/en/lb4/Defining-the-API-using-code-first-approach.html +summary: +--- + +## Define the API from code-first approach + +You may want to build your application from the 'bottom up' if you: + +* do not have a complete understanding of what your existing tools can offer. +* want to capture already existing domain models so that they can be reflected + as APIs for external consumption. +* need to grow and change your API from the initial implementation +* want to set up and run an API from an early stage of the production to + easily envision the big picture of the end product. + +There are various tools available to LoopBack which allows this bottom-up +approach of building your application to be simple through the usages of +metadata and decorators. + +### Start with LoopBack artfiacts + +With TypeScript's [experimental decorator](https://www.typescriptlang.org/docs/handbook/decorators.html) +feature, APIs can be automatically built and exposed as your application +continues development. Some key concepts utilize decorators to gather +_metadata_ about your code and then assemble them into a valid OpenAPI +specification, which provide a description of your API. +These concepts and their decorators include: + +* [Model](Model.html) + * `@model()` + * `@property()` +* [Routes](Routes.html) + * `@operation()` + * `@param()` + +### Define your models + +Your models act as common definitions between data being handled by the API +layer and the datasource layer. Since your API is going to be built around the +manipulation of models and their properties, they will be the first to be +defined. + +{% include note.html content=" +`Todo` model from [tutorial](https://github.com/strongloop/loopback-next/blob/master/packages/example-getting-started/docs/model.md#srcmodelstodomodelts) +is used for demonstration here. +" %} + +First, write a simple TypeScript class describing your model and its +properties: + +{% include code-caption.html content="src/models/todo.model.ts" %} + +```ts +export class Todo { + id?: number; + title: string; + desc?: string; + isComplete: boolean; +} +``` + +To this representation of your model, we can use the `@model` and `@property` +decorators to create the model's _metadata_; a model definition. +LoopBack and LoopBack extensions can use this model definition for +a wide variety of uses, such as: + +* generating OpenAPI schema for your APIs +* validating instances of the models during the request/response lifecycle +* automatically inferring relationships between models during datasource + operations + +To apply these decorators to your model, you simply prefix the class definition +with the `@model` decorator, and prefix each property with the +`@property` decorator: + +{% include code-caption.html content="src/models/todo.model.ts" %} + +```ts +import {model, property} from '@loopback/repository'; + +@model() +export class Todo { + @property() id?: number; + @property({ + required: true, + }) + title: string; + @property() desc?: string; + @property() isComplete: boolean; +} +``` + +### Define your routes + +{% include note.html content=" +`TodoController` from [tutorial](https://github.com/strongloop/loopback-next/blob/master/packages/example-getting-started/docs/controller.md#srccontrollerstodocontrollerts-2) +is used for +demonstration here. +" %} + +Once your models are defined, create a controller to host your routes +for each [paths](https://swagger.io/specification/#pathsObject) of your API: + +{% include code-caption.html content="src/controllers/todo.controller.ts" %} + +```ts +import {Todo} from '../models/todo.model'; + +export class TodoController { + constructor() {} + + async createTodo(todo: Todo) { + // data creating logic goes here + } + + async findTodoById(id: number, items?: boolean): Promise { + // data retrieving logic goes here + } + + // ... +} +``` + +The controller's routes in their current state has no information on which +API endpoints they belong to. Add them in by appending `@operation` to each +method of your routes and `@param` or `@requestBody` to its parameters: + +{% include code-caption.html content="src/controllers/todo.controller.ts" %} + +```ts +import {Todo} from '../models/todo.model'; +import {post, get, param, requestBody} from '@loopback/openapi-v3'; + +export class TodoController { + constructor() {} + + @post('/todo') // same as @operation('post', '/todo'); + async createTodo(@requestBody() todo: Todo) { + // data creating logic goes here + } + + @get('/todo/{id}') + async findTodoById( + @param.path.number('id') id: number, + @param.query.boolean('items') items?: boolean, + ): Promise { + // data retrieving logic goes here + } + + // ... +} +``` + +Once your routes have been decorated, your application is ready to serve +its API. When an instance of `RestServer` is run, an OpenAPI specification +representing your application's API is built. The spec is generated +entirely from the decorated elements' metadata, which in turn provides +routing logic for your API when your application is running. + +### Reviewing your API specification + +To review your complete API specification, run your application with the +decorated controllers registered. Once it is running, visit `/openapi.json` +endpoint to access your API specification in JSON format or `/openapi.yaml` +for YAML. Alternatively, the specification file can also be accessed +in code through the `getApiSpec()` function from your `RestServer` instance. + +For a complete walkthrough of developing an application with the bottom-up +approach, see our [Todo application](https://github.com/strongloop/loopback-next/blob/master/packages/example-getting-started/README.md#loopbackexample-getting-started) +tutorial. + +{% include note.html content=" +If you would like to create your API manually or already have one designed, +refer to [Defining the API using design-first approach](Defining-the-API-using-design-first-approach) +page for best practices. +" %} + +{% include next.html content= " +[Defining your testing strategy](./Defining-your-testing-strategy.html) +" %} diff --git a/pages/en/lb4/Defining-and-validating-the-API.md b/pages/en/lb4/Defining-the-API-using-design-first-approach.md similarity index 96% rename from pages/en/lb4/Defining-and-validating-the-API.md rename to pages/en/lb4/Defining-the-API-using-design-first-approach.md index 65cb22be7..9aedfd2e8 100644 --- a/pages/en/lb4/Defining-and-validating-the-API.md +++ b/pages/en/lb4/Defining-the-API-using-design-first-approach.md @@ -1,10 +1,10 @@ --- lang: en -title: 'Defining and validating the API' +title: 'Defining the API using design-first approach' keywords: LoopBack 4.0, LoopBack 4 tags: sidebar: lb4_sidebar -permalink: /doc/en/lb4/Defining-and-validating-the-API.html +permalink: /doc/en/lb4/Defining-the-API-using-design-first-approach.html summary: --- {% include important.html content="The top-down approach for building LoopBack @@ -13,7 +13,7 @@ page are outdated and may not work out of the box. They will be revisited after our MVP release. "%} -## Define the API +## Define the API from top to bottom (design-first) ### Start with data @@ -352,6 +352,12 @@ describe('API specification', () => { See [Validate your OpenAPI specification](Testing-your-application.html#validate-your-openapi-specification) from [Testing your application](Testing-your-application.html) for more details. +{% include note.html content=" + If you would like to make tweaks to your API as you develop your application, + refer to [Defining the API using code-first approach](Defining-the-API-using-code-first-approach) + page for best practices. +" %} + {% include next.html content= " [Testing the API](./Testing-the-API.html) " %} \ No newline at end of file diff --git a/pages/en/lb4/Defining-your-testing-strategy.md b/pages/en/lb4/Defining-your-testing-strategy.md index 8ad7f49a5..efe370595 100644 --- a/pages/en/lb4/Defining-your-testing-strategy.md +++ b/pages/en/lb4/Defining-your-testing-strategy.md @@ -9,7 +9,7 @@ summary: --- {% include previous.html content=" -This article continues off from [Testing the API](./Testing-the-API.html). +This article continues from [Testing the API](./Testing-the-API.html) and [Defining the API using code-first approach](./Defining-the-API-using-code-first-approach.html). " %} ## Define your testing strategy diff --git a/pages/en/lb4/Examples-and-tutorials.md b/pages/en/lb4/Examples-and-tutorials.md index ab4594474..1854b82f8 100644 --- a/pages/en/lb4/Examples-and-tutorials.md +++ b/pages/en/lb4/Examples-and-tutorials.md @@ -14,7 +14,8 @@ LoopBack 4 comes with the following example projects: Tutorial on setting up a simple hello-world application using LoopBack 4. - **[getting-started](https://github.com/strongloop/loopback-next/tree/master/packages/example-getting-started)**: - Tutorial on building a simple application with LoopBack 4 key concepts. + Tutorial on building a simple application with LoopBack 4 key concepts using + bottom-up approach. - **[log-extension](https://github.com/strongloop/loopback-next/tree/master/packages/example-log-extension)**: Tutorial on building a log extension. diff --git a/pages/en/lb4/Implementing-features.md b/pages/en/lb4/Implementing-features.md index f30ddf230..f13bbc701 100644 --- a/pages/en/lb4/Implementing-features.md +++ b/pages/en/lb4/Implementing-features.md @@ -9,7 +9,7 @@ summary: --- {% include previous.html content=" -This article continues off from [Defining your testing stategy](./Defining-your-testing-strategy.html). +This article continues from [Defining your testing stategy](./Defining-your-testing-strategy.html). " %} ## Incrementally implement features diff --git a/pages/en/lb4/Preparing-the-API-for-consumption.md b/pages/en/lb4/Preparing-the-API-for-consumption.md index 891f7e735..d8c842f01 100644 --- a/pages/en/lb4/Preparing-the-API-for-consumption.md +++ b/pages/en/lb4/Preparing-the-API-for-consumption.md @@ -9,7 +9,7 @@ summary: --- {% include previous.html content=" -This article continues off from [Implementing features](./Implementing-features.html). +This article continues from [Implementing features](./Implementing-features.html). " %} ## Preparing your API for consumption diff --git a/pages/en/lb4/Testing-the-API.md b/pages/en/lb4/Testing-the-API.md index 62be53eaa..4978f3fa5 100644 --- a/pages/en/lb4/Testing-the-API.md +++ b/pages/en/lb4/Testing-the-API.md @@ -9,7 +9,7 @@ summary: --- {% include previous.html content=" -This article continues off from [Defining and validating the API](./Defining-and-validating-the-API.html). +This article continues from [Defining the API using design-first approach](./Defining-the-API-using-design-first-approach.html). " %} {% include important.html content="The top-down approach for building LoopBack diff --git a/users/index.html b/users/index.html index afde72794..7c97d1e0e 100644 --- a/users/index.html +++ b/users/index.html @@ -1,6 +1,7 @@ --- layout: page - title: Who's Using LoopBack item: using + title: Who's Using LoopBack + item: using ---