feat: add resolve pathItems for webhooks

This commit is contained in:
Alex Varchuk 2021-05-24 17:37:58 +03:00
parent 84b944939c
commit e627583da8
4 changed files with 33 additions and 16 deletions

View File

@ -6,6 +6,7 @@ import {
Referenced,
OpenAPIServer,
OpenAPIPaths,
OpenAPIPath,
} from '../types';
import {
isOperationName,
@ -53,7 +54,7 @@ export class MenuBuilder {
const spec = parser.spec;
const items: ContentItemModel[] = [];
const tagsMap = MenuBuilder.getTagsWithOperations(spec);
const tagsMap = MenuBuilder.getTagsWithOperations(parser, spec);
items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '', undefined, 1, options));
if (spec['x-tagGroups'] && spec['x-tagGroups'].length > 0) {
items.push(
@ -215,7 +216,7 @@ export class MenuBuilder {
/**
* collects tags and maps each tag to list of operations belonging to this tag
*/
static getTagsWithOperations(spec: OpenAPISpec): TagsInfoMap {
static getTagsWithOperations(parser: OpenAPIParser, spec: OpenAPISpec): TagsInfoMap {
const tags: TagsInfoMap = {};
const webhooks = spec['x-webhooks'] || spec.webhooks;
for (const tag of spec.tags || []) {
@ -223,19 +224,26 @@ export class MenuBuilder {
}
if (webhooks) {
getTags(webhooks, true);
getTags(parser, webhooks, true);
}
if (spec.paths){
getTags(spec.paths);
getTags(parser, spec.paths);
}
function getTags(paths: OpenAPIPaths, isWebhook?: boolean) {
function getTags(parser: OpenAPIParser, paths: OpenAPIPaths, isWebhook?: boolean) {
for (const pathName of Object.keys(paths)) {
const path = paths[pathName];
const operations = Object.keys(path).filter(isOperationName);
for (const operationName of operations) {
const operationInfo = path[operationName];
const operations = Object.keys(path);
for (let operationName of operations) {
let operationInfo = isOperationName(operationName) && path[operationName];
if (!isOperationName(operationName) && path[operationName].$ref) {
const resolvedOperationInfo = parser.deref<OpenAPIPath>(path[operationName] || {})
operationInfo = resolvedOperationInfo
delete operationInfo.put
operationName = resolvedOperationInfo[Object.keys(resolvedOperationInfo)[0]]
}
let operationTags = operationInfo.tags;
if (!operationTags || !operationTags.length) {

View File

@ -1,4 +1,4 @@
import { OpenAPIExternalDocumentation, OpenAPISpec } from '../types';
import { OpenAPIExternalDocumentation, OpenAPIPath, OpenAPISpec, Referenced } from '../types';
import { ContentItemModel, MenuBuilder } from './MenuBuilder';
import { ApiInfoModel } from './models/ApiInfo';
@ -28,6 +28,7 @@ export class SpecStore {
this.externalDocs = this.parser.spec.externalDocs;
this.contentItems = MenuBuilder.buildStructure(this.parser, this.options);
this.securitySchemes = new SecuritySchemesModel(this.parser);
this.webhooks = new WebhookModel(this.parser, options, this.parser.spec['x-webhooks']);
const webhookPath: Referenced<OpenAPIPath> = {...this.parser?.spec?.['x-webhooks'], ...this.parser?.spec.webhooks};
this.webhooks = new WebhookModel(this.parser, options, webhookPath);
}
}

View File

@ -1,8 +1,8 @@
import { OpenAPIPath, Referenced } from '../../types';
import { OpenAPIParser } from '../OpenAPIParser';
import { OperationModel } from './Operation';
import { isOperationName } from '../..';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { isOperationName } from '../..';
export class WebhookModel {
operations: OperationModel[] = [];
@ -17,9 +17,17 @@ export class WebhookModel {
for (const webhookName of Object.keys(webhooks)) {
const webhook = webhooks[webhookName];
const operations = Object.keys(webhook).filter(isOperationName);
for (const operationName of operations) {
const operationInfo = webhook[operationName];
const operations = Object.keys(webhook);
for (let operationName of operations) {
let operationInfo = isOperationName(operationName) && webhook[operationName];
if (!isOperationName(operationName) && webhook[operationName].$ref) {
const resolvedOperationInfo = parser.deref<OpenAPIPath>(webhook[operationName] || {})
operationInfo = resolvedOperationInfo
operationName = resolvedOperationInfo[Object.keys(resolvedOperationInfo)[0]]
}
if (!operationInfo) continue;
const operation = new OperationModel(
parser,
{

View File

@ -369,12 +369,12 @@ export function langFromMime(contentType: string): string {
}
export function isNamedDefinition(pointer?: string): boolean {
return /^#\/components\/schemas\/[^\/]+$/.test(pointer || '');
return /^#\/components\/(schemas|pathItems)\/[^\/]+$/.test(pointer || '');
}
export function getDefinitionName(pointer?: string): string | undefined {
if (!pointer) return undefined;
const match = pointer.match(/^#\/components\/schemas\/([^\/]+)$/);
const match = pointer.match(/^#\/components\/(schemas|pathItems)\/([^\/]+)$/);
return match === null ? undefined : match[1]
}