From a4cee05d67f85de38fcbd0f722b860332584f13f Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 7 Apr 2020 13:09:32 +0300 Subject: [PATCH] chore: refactor path servers and pointers --- demo/openapi.yaml | 18 +++++----- src/components/__tests__/Callbacks.test.tsx | 2 ++ src/services/MenuBuilder.ts | 14 +++++++- .../__tests__/models/Callback.test.ts | 2 +- src/services/models/Callback.ts | 15 ++++---- src/services/models/Operation.ts | 36 +++++++------------ src/services/models/index.ts | 2 +- src/types/open-api.d.ts | 2 +- 8 files changed, 48 insertions(+), 43 deletions(-) diff --git a/demo/openapi.yaml b/demo/openapi.yaml index 6a097a66..5bf4c419 100644 --- a/demo/openapi.yaml +++ b/demo/openapi.yaml @@ -522,7 +522,7 @@ paths: description: Subscription added content: application/json: - schema: + schema: type: object properties: subscriptionId: @@ -620,13 +620,13 @@ paths: description: Order in Progress (Only Description) servers: - url: //callback-url.operation-level/v1 - description: Operation level server 1 (Path override) + description: Operation level server 1 (Operation override) - url: //callback-url.operation-level/v2 - description: Operation level server 2 (Path override) + description: Operation level server 2 (Operation override) requestBody: content: application/json: - schema: + schema: type: object properties: orderId: @@ -667,18 +667,18 @@ paths: orderShipped: '{$request.body#/callbackUrl}?event={$request.body#/eventName}': post: - description: | + description: | Very long description - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor - incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu - fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. requestBody: content: application/json: - schema: + schema: type: object properties: orderId: diff --git a/src/components/__tests__/Callbacks.test.tsx b/src/components/__tests__/Callbacks.test.tsx index 9d219ce8..b5d3aa5d 100644 --- a/src/components/__tests__/Callbacks.test.tsx +++ b/src/components/__tests__/Callbacks.test.tsx @@ -19,6 +19,7 @@ describe('Components', () => { parser, 'Test.Callback', { $ref: '#/components/callbacks/Test' }, + '', options, ); // There should be 1 operation defined in simple-callback.json, just get it manually for readability. @@ -53,6 +54,7 @@ describe('Components', () => { parser, 'Test.Callback', { $ref: '#/components/callbacks/Test' }, + '', options, ); const callbacksListViewElement = shallow( diff --git a/src/services/MenuBuilder.ts b/src/services/MenuBuilder.ts index f61f6189..23516a66 100644 --- a/src/services/MenuBuilder.ts +++ b/src/services/MenuBuilder.ts @@ -1,8 +1,16 @@ -import { OpenAPIOperation, OpenAPIParameter, OpenAPISpec, OpenAPITag, Referenced } from '../types'; +import { + OpenAPIOperation, + OpenAPIParameter, + OpenAPISpec, + OpenAPITag, + Referenced, + OpenAPIServer, +} from '../types'; import { isOperationName, SECURITY_DEFINITIONS_COMPONENT_NAME, setSecuritySchemePrefix, + JsonPointer, } from '../utils'; import { MarkdownRenderer } from './MarkdownRenderer'; import { GroupModel, OperationModel } from './models'; @@ -15,9 +23,11 @@ export type TagInfo = OpenAPITag & { }; export type ExtendedOpenAPIOperation = { + pointer: string; pathName: string; httpVerb: string; pathParameters: Array>; + pathServers: Array; } & OpenAPIOperation; export type TagsInfoMap = Dict; @@ -237,8 +247,10 @@ export class MenuBuilder { tag.operations.push({ ...operationInfo, pathName, + pointer: JsonPointer.compile(['paths', pathName, operationName]), httpVerb: operationName, pathParameters: path.parameters || [], + pathServers: path.servers || [], }); } } diff --git a/src/services/__tests__/models/Callback.test.ts b/src/services/__tests__/models/Callback.test.ts index d79d89dc..9fb67799 100644 --- a/src/services/__tests__/models/Callback.test.ts +++ b/src/services/__tests__/models/Callback.test.ts @@ -15,11 +15,11 @@ describe('Models', () => { parser, 'Test.Callback', { $ref: '#/components/callbacks/Test' }, + '', opts, ); expect(callback.name).toEqual('Test.Callback'); expect(callback.operations.length).toEqual(0); - expect(callback.paths).toBeDefined(); expect(callback.expanded).toBeUndefined(); }); }); diff --git a/src/services/models/Callback.ts b/src/services/models/Callback.ts index bbb04d37..4870f539 100644 --- a/src/services/models/Callback.ts +++ b/src/services/models/Callback.ts @@ -1,29 +1,30 @@ import { action, observable } from 'mobx'; import { OpenAPICallback, Referenced } from '../../types'; -import { isOperationName } from '../../utils'; +import { isOperationName, JsonPointer } from '../../utils'; import { OpenAPIParser } from '../OpenAPIParser'; import { OperationModel } from './Operation'; +import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; export class CallbackModel { @observable expanded: boolean; name: string; - paths: Referenced; operations: OperationModel[] = []; constructor( parser: OpenAPIParser, name: string, infoOrRef: Referenced, - options, + pointer: string, + options: RedocNormalizedOptions, ) { this.name = name; - this.paths = parser.deref(infoOrRef); + const paths = parser.deref(infoOrRef); parser.exitRef(infoOrRef); - for (const pathName of Object.keys(this.paths)) { - const path = this.paths[pathName]; + 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]; @@ -33,8 +34,10 @@ export class CallbackModel { { ...operationInfo, pathName, + pointer: JsonPointer.compile([pointer, name, pathName, operationName]), httpVerb: operationName, pathParameters: path.parameters || [], + pathServers: path.servers || [], }, undefined, options, diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts index e35a1c58..fc2d41ce 100644 --- a/src/services/models/Operation.ts +++ b/src/services/models/Operation.ts @@ -4,19 +4,13 @@ import { IMenuItem } from '../MenuStore'; import { GroupModel } from './Group.model'; import { SecurityRequirementModel } from './SecurityRequirement'; -import { - OpenAPIExternalDocumentation, - OpenAPIPath, - OpenAPIServer, - OpenAPIXCodeSample, -} from '../../types'; +import { OpenAPIExternalDocumentation, OpenAPIServer, OpenAPIXCodeSample } from '../../types'; import { extractExtensions, getOperationSummary, getStatusCodeType, isStatusCode, - JsonPointer, memoize, mergeParams, normalizeServers, @@ -87,14 +81,7 @@ export class OperationModel implements IMenuItem { private options: RedocNormalizedOptions, isCallback: boolean = false, ) { - this.pointer = JsonPointer.compile(['paths', operationSpec.pathName, operationSpec.httpVerb]); - - this.id = - operationSpec.operationId !== undefined - ? 'operation/' + operationSpec.operationId - : parent !== undefined - ? parent.id + this.pointer - : this.pointer; + this.pointer = operationSpec.pointer; this.description = operationSpec.description; this.parent = parent; @@ -107,10 +94,6 @@ export class OperationModel implements IMenuItem { this.path = operationSpec.pathName; this.isCallback = isCallback; - const pathInfo = parser.byRef( - JsonPointer.compile(['paths', operationSpec.pathName]), - ); - this.name = getOperationSummary(operationSpec); if (this.isCallback) { @@ -121,18 +104,22 @@ export class OperationModel implements IMenuItem { ); // TODO: update getting pathInfo for overriding servers on path level - this.servers = normalizeServers( - '', - operationSpec.servers || (pathInfo && pathInfo.servers) || [], - ); + this.servers = normalizeServers('', operationSpec.servers || operationSpec.pathServers || []); } else { + this.id = + operationSpec.operationId !== undefined + ? 'operation/' + operationSpec.operationId + : parent !== undefined + ? parent.id + this.pointer + : this.pointer; + this.security = (operationSpec.security || parser.spec.security || []).map( security => new SecurityRequirementModel(security, parser), ); this.servers = normalizeServers( parser.specUrl, - operationSpec.servers || (pathInfo && pathInfo.servers) || parser.spec.servers || [], + operationSpec.servers || operationSpec.pathServers || parser.spec.servers || [], ); } @@ -259,6 +246,7 @@ export class OperationModel implements IMenuItem { this.parser, callbackEventName, this.operationSpec.callbacks![callbackEventName], + this.pointer, this.options, ); }); diff --git a/src/services/models/index.ts b/src/services/models/index.ts index b373b392..a3569c5a 100644 --- a/src/services/models/index.ts +++ b/src/services/models/index.ts @@ -1,4 +1,3 @@ -export * from './Callback'; export * from '../SpecStore'; export * from './Group.model'; export * from './Operation'; @@ -11,3 +10,4 @@ export * from './Schema'; export * from './Field'; export * from './ApiInfo'; export * from './SecuritySchemes'; +export * from './Callback'; diff --git a/src/types/open-api.d.ts b/src/types/open-api.d.ts index 891d7a0f..12344ec5 100644 --- a/src/types/open-api.d.ts +++ b/src/types/open-api.d.ts @@ -196,7 +196,7 @@ export interface OpenAPILink { export type OpenAPIHeader = Omit; export interface OpenAPICallback { - $ref?: string; + [name: string]: OpenAPIPath; } export interface OpenAPIComponents {