feat: support x-response-samples to render code responses

This commit is contained in:
Emmanuel Quentin 2018-10-03 21:09:39 +02:00
parent 3c8d6b623c
commit 5ea3dc68dd
7 changed files with 94 additions and 9 deletions

View File

@ -194,6 +194,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica
* [`x-logo`](docs/redoc-vendor-extensions.md#x-logo) - is used to specify API logo
* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for handling out common things like Pagination, Rate-Limits, etc
* [`x-code-samples`](docs/redoc-vendor-extensions.md#x-code-samples) - specify operation code samples
* [`x-response-samples`](docs/redoc-vendor-extensions.md#x-response-samples) - specify operation response code samples
* [`x-examples`](docs/redoc-vendor-extensions.md#x-examples) - specify JSON example for requests
* [`x-nullable`](docs/redoc-vendor-extensions.md#nullable) - mark schema param as a nullable
* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories

View File

@ -187,6 +187,27 @@ paths:
description: Invalid ID supplied
'404':
description: Pet not found
x-code-samples:
- lang: 'Javascript'
source: |
const pet = new PetStore.v1.Pet();
await pet.get(1, (err, pet);
x-response-samples:
- lang: 'Javascript'
source: |
Pet {
id: number;
name: String;
getName(): String;
}
- lang: 'Javascript'
label: 'Javascript error'
source: |
ServerResponse {
status: number;
message: String;
}
security:
- api_key: []
post:

View File

@ -183,13 +183,52 @@ Operation code sample
###### Code Sample Object example
json
```json
[
{
"lang": "JavaScript",
"source": "console.log('Hello World');"
}
]
```
yaml
```yaml
-
lang: JavaScript
source: console.log('Hello World');
```
#### x-response-samples
| Field Name | Type | Description |
| :----------------- | :------: | :---------- |
| x-response-samples | [ [Code Sample Object](#responseSampleObject) ] | A list of response samples associated with operation, useful when your SDK renders different structure of your API |
###### Usage in ReDoc
`x-response-samples` are rendered on the right panel of ReDoc, after response tabs.
#### <a name="codeSampleObject"></a>Code Sample Object
Operation code sample
###### Fixed fields
| Field Name | Type | Description |
| :---------- | :------: | :----------- |
| lang | string | Code sample language. Value should be one of the following [list](https://github.com/github/linguist/blob/master/lib/linguist/popular.yml) |
| label | string? | Code sample label e.g. `Node` or `Python2.7`, _optional_, `lang` will be used by default |
| source | string | Code sample source code |
###### Response Sample Object example
json
```json
[
{
"lang": "JavaScript",
"source": "console.log('Hello World');"
}
]
```
yaml
```yaml
-
lang: JavaScript
source: console.log('Hello World');
```

View File

@ -5,6 +5,7 @@ import { OperationModel } from '../../services/models';
import { RightPanelHeader, Tab, TabList, TabPanel, Tabs } from '../../common-elements';
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
import { SourceCodeWithCopy } from '../SourceCode/SourceCode';
export interface ResponseSamplesProps {
operation: OperationModel;
@ -16,6 +17,8 @@ export class ResponseSamples extends React.Component<ResponseSamplesProps> {
render() {
const { operation } = this.props;
const samples = operation.responseSamples;
const responses = operation.responses.filter(response => {
return response.content && response.content.hasSample;
});
@ -32,6 +35,11 @@ export class ResponseSamples extends React.Component<ResponseSamplesProps> {
{response.code}
</Tab>
))}
{samples.map(sample => (
<Tab key={`response-${sample.label || sample.lang}`}>
{sample.label || sample.lang}
</Tab>
))}
</TabList>
{responses.map(response => (
<TabPanel key={response.code}>
@ -40,6 +48,11 @@ export class ResponseSamples extends React.Component<ResponseSamplesProps> {
</div>
</TabPanel>
))}
{samples.map(sample => (
<TabPanel key={`response-${sample.label || sample.lang}`}>
<SourceCodeWithCopy lang={sample.lang} source={sample.source} />
</TabPanel>
))}
</Tabs>
</div>
)) ||

View File

@ -9,6 +9,7 @@ import {
OpenAPIPath,
OpenAPIServer,
OpenAPIXCodeSample,
OpenAPIXResponseSample,
} from '../../types';
import {
@ -62,6 +63,7 @@ export class OperationModel implements IMenuItem {
servers: OpenAPIServer[];
security: SecurityRequirementModel[];
codeSamples: OpenAPIXCodeSample[];
responseSamples: OpenAPIXResponseSample[];
extensions: Dict<any>;
constructor(
@ -89,6 +91,7 @@ export class OperationModel implements IMenuItem {
this.deprecated = !!operationSpec.deprecated;
this.operationId = operationSpec.operationId;
this.codeSamples = operationSpec['x-code-samples'] || [];
this.responseSamples = operationSpec['x-response-samples'] || [];
this.path = operationSpec.pathName;
const pathInfo = parser.byRef<OpenAPIPath>(

View File

@ -63,6 +63,12 @@ export interface OpenAPIXCodeSample {
source: string;
}
export interface OpenAPIXResponseSample {
lang: string;
label?: string;
source: string;
}
export interface OpenAPIOperation {
tags?: string[];
summary?: string;
@ -77,6 +83,7 @@ export interface OpenAPIOperation {
security?: OpenAPISecurityRequirement[];
servers?: OpenAPIServer[];
'x-code-samples'?: OpenAPIXCodeSample[];
'x-response-samples'?: OpenAPIXResponseSample[];
}
export interface OpenAPIParameter {

View File

@ -291,6 +291,7 @@ export function isRedocExtension(key: string): boolean {
const redocExtensions = {
'x-circular-ref': true,
'x-code-samples': true,
'x-response-samples': true,
'x-displayName': true,
'x-examples': true,
'x-ignoredHeaderParameters': true,