mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-06 05:10:20 +03:00
feat: Option to reverse readOnly/writeOnly properties #1720
This commit is contained in:
parent
1487b24776
commit
2a0b0866ef
|
@ -248,7 +248,7 @@ You can use all of the following options with standalone version on <redoc> tag
|
|||
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
||||
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one.
|
||||
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
||||
* `reverseEventsReadOnlyProps`, `reverseEventsWriteOnlyProps` - reverse readOnly/writeOnly schema key for webhooks and callbacks.
|
||||
* `reverseEventsReadWriteProps` - reverse readOnly/writeOnly schema key for webhooks and callbacks.
|
||||
* `scrollYOffset` - If set, specifies a vertical scroll-offset. This is often useful when there are fixed positioned elements at the top of the page, such as navbars, headers etc;
|
||||
`scrollYOffset` can be specified in various ways:
|
||||
* **number**: A fixed number of pixels to be used as offset.
|
||||
|
|
|
@ -1193,7 +1193,7 @@ x-webhooks:
|
|||
summary: New pet
|
||||
description: Information about a new pet in the systems
|
||||
operationId: newPet
|
||||
tags:
|
||||
tags:
|
||||
- pet
|
||||
requestBody:
|
||||
content:
|
||||
|
@ -1202,4 +1202,4 @@ x-webhooks:
|
|||
$ref: "#/components/schemas/Pet"
|
||||
responses:
|
||||
"200":
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
description: Return a 200 status to indicate that the data was received successfully
|
||||
|
|
|
@ -69,13 +69,14 @@ function DropdownWithinHeader(props) {
|
|||
|
||||
export function BodyContent(props: { content: MediaContentModel; description?: string }): JSX.Element {
|
||||
const { content, description } = props;
|
||||
const { isRequestType } = content;
|
||||
return (
|
||||
<MediaTypesSwitch content={content} renderDropdown={DropdownWithinHeader}>
|
||||
{({ schema }) => {
|
||||
return (
|
||||
<>
|
||||
{description !== undefined && <Markdown source={description} />}
|
||||
<Schema skipReadOnly={true} key="schema" schema={schema} />
|
||||
<Schema skipReadOnly={isRequestType} key="schema" schema={schema} />
|
||||
</>
|
||||
);
|
||||
}}
|
||||
|
|
|
@ -42,6 +42,7 @@ export interface RedocRawOptions {
|
|||
maxDisplayedEnumValues?: number;
|
||||
ignoreNamedSchemas?: string[] | string;
|
||||
hideSchemaPattern?: boolean;
|
||||
reverseEventsReadWriteProps?: boolean;
|
||||
}
|
||||
|
||||
export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
|
||||
|
@ -49,7 +50,7 @@ export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean
|
|||
return defaultValue || false;
|
||||
}
|
||||
if (typeof val === 'string') {
|
||||
return val === 'false' ? false : true;
|
||||
return val !== 'false';
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -196,6 +197,7 @@ export class RedocNormalizedOptions {
|
|||
|
||||
ignoreNamedSchemas: Set<string>;
|
||||
hideSchemaPattern: boolean;
|
||||
reverseEventsReadWriteProps: boolean;
|
||||
|
||||
constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) {
|
||||
raw = { ...defaults, ...raw };
|
||||
|
@ -257,5 +259,6 @@ export class RedocNormalizedOptions {
|
|||
: raw.ignoreNamedSchemas?.split(',').map((s) => s.trim());
|
||||
this.ignoreNamedSchemas = new Set(ignoreNamedSchemas);
|
||||
this.hideSchemaPattern = argValueToBoolean(raw.hideSchemaPattern);
|
||||
this.reverseEventsReadWriteProps = argValueToBoolean(raw.reverseEventsReadWriteProps);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,8 @@ export class MediaTypeModel {
|
|||
generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) {
|
||||
const samplerOptions = {
|
||||
skipReadOnly: this.isRequestType,
|
||||
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
|
||||
skipWriteOnly: !this.isRequestType,
|
||||
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
|
||||
maxSampleDepth: 10,
|
||||
};
|
||||
if (this.schema && this.schema.oneOf) {
|
||||
|
|
|
@ -76,6 +76,7 @@ export class OperationModel implements IMenuItem {
|
|||
extensions: Record<string, any>;
|
||||
isCallback: boolean;
|
||||
isWebhook: boolean;
|
||||
reverseEventsReadWriteProps: boolean;
|
||||
|
||||
constructor(
|
||||
private parser: OpenAPIParser,
|
||||
|
@ -98,7 +99,9 @@ export class OperationModel implements IMenuItem {
|
|||
this.operationId = operationSpec.operationId;
|
||||
this.path = operationSpec.pathName;
|
||||
this.isCallback = isCallback;
|
||||
this.isWebhook = !!operationSpec.isWebhook;
|
||||
this.isWebhook = operationSpec.isWebhook;
|
||||
this.reverseEventsReadWriteProps = options.reverseEventsReadWriteProps &&
|
||||
(this.isCallback || this.isWebhook);
|
||||
|
||||
this.name = getOperationSummary(operationSpec);
|
||||
|
||||
|
@ -171,8 +174,12 @@ export class OperationModel implements IMenuItem {
|
|||
@memoize
|
||||
get requestBody() {
|
||||
return (
|
||||
this.operationSpec.requestBody &&
|
||||
new RequestBodyModel(this.parser, this.operationSpec.requestBody, this.options)
|
||||
this.operationSpec.requestBody && new RequestBodyModel({
|
||||
parser: this.parser,
|
||||
infoOrRef: this.operationSpec.requestBody,
|
||||
options: this.options,
|
||||
reverseEventsReadWriteProps: this.reverseEventsReadWriteProps,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -240,13 +247,14 @@ export class OperationModel implements IMenuItem {
|
|||
return isStatusCode(code);
|
||||
}) // filter out other props (e.g. x-props)
|
||||
.map((code) => {
|
||||
return new ResponseModel(
|
||||
this.parser,
|
||||
return new ResponseModel({
|
||||
parser: this.parser,
|
||||
code,
|
||||
hasSuccessResponses,
|
||||
this.operationSpec.responses[code],
|
||||
this.options,
|
||||
);
|
||||
defaultAsError: hasSuccessResponses,
|
||||
infoOrRef: this.operationSpec.responses[code],
|
||||
options: this.options,
|
||||
reverseEventsReadWriteProps: this.reverseEventsReadWriteProps,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,22 +4,27 @@ import { OpenAPIParser } from '../OpenAPIParser';
|
|||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||
import { MediaContentModel } from './MediaContent';
|
||||
|
||||
type RequestBodyProps = {
|
||||
parser: OpenAPIParser;
|
||||
infoOrRef: Referenced<OpenAPIRequestBody>;
|
||||
options: RedocNormalizedOptions;
|
||||
reverseEventsReadWriteProps: boolean;
|
||||
}
|
||||
|
||||
export class RequestBodyModel {
|
||||
description: string;
|
||||
required: boolean;
|
||||
content?: MediaContentModel;
|
||||
|
||||
constructor(
|
||||
parser: OpenAPIParser,
|
||||
infoOrRef: Referenced<OpenAPIRequestBody>,
|
||||
options: RedocNormalizedOptions,
|
||||
) {
|
||||
constructor(props: RequestBodyProps) {
|
||||
const { parser, infoOrRef, options, reverseEventsReadWriteProps } = props;
|
||||
const isRequest = reverseEventsReadWriteProps ? false : true;
|
||||
const info = parser.deref(infoOrRef);
|
||||
this.description = info.description || '';
|
||||
this.required = !!info.required;
|
||||
parser.exitRef(infoOrRef);
|
||||
if (info.content !== undefined) {
|
||||
this.content = new MediaContentModel(parser, info.content, true, options);
|
||||
this.content = new MediaContentModel(parser, info.content, isRequest, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,15 @@ import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
|||
import { FieldModel } from './Field';
|
||||
import { MediaContentModel } from './MediaContent';
|
||||
|
||||
type ResponseProps = {
|
||||
parser: OpenAPIParser,
|
||||
code: string,
|
||||
defaultAsError: boolean,
|
||||
infoOrRef: Referenced<OpenAPIResponse>,
|
||||
options: RedocNormalizedOptions,
|
||||
reverseEventsReadWriteProps: boolean,
|
||||
}
|
||||
|
||||
export class ResponseModel {
|
||||
@observable
|
||||
expanded: boolean = false;
|
||||
|
@ -19,13 +28,9 @@ export class ResponseModel {
|
|||
type: string;
|
||||
headers: FieldModel[] = [];
|
||||
|
||||
constructor(
|
||||
parser: OpenAPIParser,
|
||||
code: string,
|
||||
defaultAsError: boolean,
|
||||
infoOrRef: Referenced<OpenAPIResponse>,
|
||||
options: RedocNormalizedOptions,
|
||||
) {
|
||||
constructor(props: ResponseProps) {
|
||||
const { parser, code, defaultAsError, infoOrRef, options, reverseEventsReadWriteProps } = props;
|
||||
const isRequest = reverseEventsReadWriteProps ? true : false;
|
||||
makeObservable(this);
|
||||
|
||||
this.expanded = options.expandResponses === 'all' || options.expandResponses[code];
|
||||
|
@ -34,7 +39,7 @@ export class ResponseModel {
|
|||
parser.exitRef(infoOrRef);
|
||||
this.code = code;
|
||||
if (info.content !== undefined) {
|
||||
this.content = new MediaContentModel(parser, info.content, false, options);
|
||||
this.content = new MediaContentModel(parser, info.content, isRequest, options);
|
||||
}
|
||||
|
||||
if (info['x-summary'] !== undefined) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user