@loopback/docs
Version:
Documentation for LoopBack 4
154 lines (121 loc) • 4.84 kB
Markdown
---
lang: en
title: 'Extending OpenAPI Specification'
keywords: LoopBack 4.0, LoopBack 4
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Extending-OpenAPI-specification.html
---
## OpenAPI Specification Enhancer
The APIs in a LoopBack `RestApplication` are described by the
[OpenAPI Specification (short for OAS)](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md).
An application's OAS is mainly generated from
[controllers](https://loopback.io/doc/en/lb4/Controllers.html) and their
members' metadata. Besides this, we would also like to contribute specifications
from other places. Therefore, an extension point `OASEnhancerService` is created
to allow registered extensions to provide their OAS fragments and modify a rest
application's specification.
_Read about the extension point/extension pattern in
[documentation](Extension-point-and-extensions.md)_
## Adding a New OAS Enhancer
Interface `OASEnhancer` is created in `/openapi-v3` to describe the
specification enhancers. A typical OAS enhancer class should have a string type
`name` field and a function `modifySpec()` to modify the current specification.
For example, to modify the `info` field of an OAS, you can create an
`InfoSpecEnhancer` that implements interface `OASEnhancer` as follows:
```ts
import {bind} from '/core';
import {
mergeOpenAPISpec,
asSpecEnhancer,
OASEnhancer,
OpenApiSpec,
} from '/openapi-v3';
/**
* A spec enhancer to add OpenAPI info spec
*/
(asSpecEnhancer)
export class InfoSpecEnhancer implements OASEnhancer {
// give your enhancer a proper name
name = 'info';
// takes in the current spec, modifies it, and returns a new one
modifySpec(spec: OpenApiSpec): OpenApiSpec {
const InfoPatchSpec = {
info: {title: 'LoopBack Test Application', version: '1.0.1'},
};
// the example calls a default helper function to merge the fragment spec.
const mergedSpec = mergeOpenAPISpec(spec, InfoPatchSpec);
return mergedSpec;
}
}
```
- The class is decorated with a binding template `asSpecEnhancer`.
- The enhancer has a name as `info`. Name can be used to retrieve a certain
enhancer (explained in the
[extension point section](#oas-enhancer-service-as-extension-point)).
- The enhancer changes the current specification's `info` object in function
`modifySpec`.
- It calls [`mergeOpenAPISpec`](#default-merge-function) to merge the
specification fragment into the current spec.
### Default Merge Function
Since `modifySpec` has full access to the current spec, it can perform any
operation: merge, delete, or more complicated changes. This is totally
determined by the extension contributor.
To apply the basic merging, we provide a default helper function called
`mergeOpenAPISpec` that leverages
[`json-merge-patch`](https://github.com/pierreinglebert/json-merge-patch) to
merge two json objects. You can find its usage in the
[previous section](#adding-a-new-oas-enhancer)
### Registering an Enhancer
After decorating your enhancer properly with `(asSpecEnhancer)`, you can
bind it to your application as follows:
```ts
import {createBindingFromClass} from '/core';
import {InfoSpecEnhancer} from './enhancers/infoSpecEnhancer';
class MyApplication extends RestApplication {
constructor() {
super();
this.add(createBindingFromClass(InfoSpecEnhancer));
}
}
```
## OAS Enhancer Service as Extension Point
The OAS enhancer extension point is created in package `/openapi-v3`.
It organizes the registered OAS enhancers, and provides APIs to either apply one
enhancer by name, or apply all enhancers automatically.
### Registering an Enhancer Service
You can bind the OAS enhancer extension point to your app via key
`OAS_ENHANCER_SERVICE`:
```ts
import {RestApplication} from '/rest';
import {OASEnhancerService, OAS_ENHANCER_SERVICE} from '/openapi-v3';
class MyApplication extends RestApplication {
constructor() {
super();
this.add(
createBindingFromClass(OASEnhancerService, {
key: OAS_ENHANCER_SERVICE,
}),
);
}
// define a function to return a spec service by the same key
getSpecService() {
return this.get(OAS_ENHANCER_SERVICE);
}
}
```
### Applying Registered Enhancers
To automatically apply all the registered enhancers, call `applyAllEnhancers`:
```ts
await app.getSpecService.applyAllEnhancers();
```
_In the future we will support applying enhancers by a custom sequence. The
sequence will be determined by a combination of group names and the alphabetical
order._
To retrieve an enhancer by name, call `getEnhancerByName`:
```ts
await app.getSpecService.getEnhancerByName('info');
```
To apply an enhancer by name, call `applyEnhancerByName`:
```ts
await app.getSpecService.applyEnhancerByName('info');
```