diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/predicates.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/predicates.ts index 812717c17e..45818b6512 100644 --- a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/predicates.ts +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/predicates.ts @@ -31,7 +31,7 @@ export const isServerObject = curry((options, node) => { return hasKeys(['url'], node.content); }); -// isParameterObject :: Options -> JsonObject -> Boolean +// isParameterObject :: Options -> YamlMapping -> Boolean export const isParameterObject = curry((options, node) => { if (!isYamlMapping(node)) { return false; @@ -39,7 +39,7 @@ export const isParameterObject = curry((options, node) => { return hasKeys(['name', 'in'], node.content); }); -// isReferenceObject :: Options -> JsonObject -> Boolean +// isReferenceObject :: Options -> YamlMapping -> Boolean export const isReferenceObject = curry((options, node) => { if (!isYamlMapping(node)) { return false; @@ -47,10 +47,18 @@ export const isReferenceObject = curry((options, node) => { return hasKeys(['$ref'], node.content); }); -// isRequestBodyObject :: Options -> JsonObject -> Boolean +// isRequestBodyObject :: Options -> YamlMapping -> Boolean export const isRequestBodyObject = curry((options, node) => { if (!isYamlMapping(node)) { return false; } return hasKeys(['content'], node.content); }); + +// isResponseObject :: Options -> YamlMapping -> Boolean +export const isResponseObject = curry((options, node) => { + if (!isYamlMapping(node)) { + return false; + } + return hasKeys(['description'], node.content); +}); diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/specification.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/specification.ts index dd88fd84da..cc1f3951b5 100644 --- a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/specification.ts +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/specification.ts @@ -54,6 +54,9 @@ import ExternalDocumentationUrlVisitor from './visitors/open-api-3-1/external-do import RequestBodyVisitor from './visitors/open-api-3-1/request-body'; import ReferenceVisitor from './visitors/open-api-3-1/reference'; import CallbackVisitor from './visitors/open-api-3-1/callback'; +import ResponsesVisitor from './visitors/open-api-3-1/responses'; +import ResponsesDefaultVisitor from './visitors/open-api-3-1/responses/DefaultVisitor'; +import ResponseVisitor from './visitors/open-api-3-1/response'; /** * Specification object allows us to have complete control over visitors @@ -199,9 +202,9 @@ const specification = { operationId: OperationOperationIdVisitor, parameters: ParametersVisitor, requestBody: OperationRequestBodyVisitor, - // responses: { - // $ref: '#/visitors/document/objects/Responses', - // }, + responses: { + $ref: '#/visitors/document/objects/Responses', + }, callbacks: OperationCallbacksVisitor, deprecated: OperationDeprecatedVisitor, security: SecurityVisitor, @@ -219,6 +222,16 @@ const specification = { $visitor: RequestBodyVisitor, fixedFields: {}, }, + Responses: { + $visitor: ResponsesVisitor, + fixedFields: { + default: ResponsesDefaultVisitor, + }, + }, + Response: { + $visitor: ResponseVisitor, + fixedFields: {}, + }, Callback: { $visitor: CallbackVisitor, fixedFields: {}, diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/SpecificationVisitor.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/SpecificationVisitor.ts index 5f35828be7..054cd1713f 100644 --- a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/SpecificationVisitor.ts +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/SpecificationVisitor.ts @@ -17,6 +17,10 @@ const SpecificationVisitor = stampit(Visitor, { this.specObj = specObj; }, methods: { + retrievePassingOptions() { + return pick(['namespace', 'sourceMap', 'specObj'], this); + }, + retrieveFixedFields(specPath) { return pipe(path(['visitors', ...specPath, 'fixedFields']), keys)(this.specObj); }, @@ -30,7 +34,7 @@ const SpecificationVisitor = stampit(Visitor, { }, retrieveVisitorInstance(specPath, options = {}) { - const passingOpts = pick(['namespace', 'sourceMap', 'specObj'], this); + const passingOpts = this.retrievePassingOptions(); return this.retrieveVisitor(specPath)({ ...passingOpts, ...options }); }, diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/Visitor.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/Visitor.ts index 842c4c6783..6198f8b97e 100644 --- a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/Visitor.ts +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/Visitor.ts @@ -9,9 +9,10 @@ const Visitor = stampit({ keyMap: null, }, // @ts-ignore - init({ namespace = this.namespace, sourceMap = this.sourceMap } = {}) { + init({ namespace = this.namespace, sourceMap = this.sourceMap, element = this.element } = {}) { this.namespace = namespace; this.sourceMap = sourceMap; + this.element = element; }, methods: { maybeAddSourceMap(node, element) { diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/MixedFieldsYamlMappingVisitor.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/MixedFieldsYamlMappingVisitor.ts new file mode 100644 index 0000000000..a6414ab65e --- /dev/null +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/MixedFieldsYamlMappingVisitor.ts @@ -0,0 +1,43 @@ +import stampit from 'stampit'; +import { noop } from 'ramda-adjunct'; +import { YamlMapping } from 'apidom-ast'; + +import { BREAK, visit } from '..'; +import FixedFieldsYamlMappingVisitor from './FixedFieldsYamlMappingVisitor'; +import PatternedFieldsYamlMappingVisitor from './PatternedFieldsYamlMappingVisitor'; +import SpecificationVisitor from '../SpecificationVisitor'; + +const MixedFieldsYamlMappingVisitor = stampit(SpecificationVisitor, { + props: { + specPathFixedFields: noop, + specPathPatternedFields: noop, + }, + methods: { + mapping(mappingNode: YamlMapping) { + const fixedFieldsVisitor = FixedFieldsYamlMappingVisitor({ + ...this.retrievePassingOptions(), + ignoredFields: this.ignoredFields, + canSupportSpecificationExtensions: this.canSupportSpecificationExtensions, + element: this.element, + specPath: this.specPathFixedFields, + }); + + visit(mappingNode, fixedFieldsVisitor); + + const patternedFieldsVisitor = PatternedFieldsYamlMappingVisitor({ + ...this.retrievePassingOptions(), + ignoredFields: this.ignoredFields, + canSupportSpecificationExtensions: this.canSupportSpecificationExtensions, + element: this.element, + fieldPatternPredicate: this.fieldPatternPredicate, + specPath: this.specPathPatternedFields, + }); + + visit(mappingNode, patternedFieldsVisitor); + + return BREAK; + }, + }, +}); + +export default MixedFieldsYamlMappingVisitor; diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/PatternedFieldsYamlMappingVisitor.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/PatternedFieldsYamlMappingVisitor.ts index d51c7ae203..2c7c76e765 100644 --- a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/PatternedFieldsYamlMappingVisitor.ts +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/generics/PatternedFieldsYamlMappingVisitor.ts @@ -22,11 +22,14 @@ const PatternedFieldsYamlMappingVisitor = stampit(SpecificationVisitor, { // @ts-ignore specPath = this.specPath, // @ts-ignore + fieldPatternPredicate = this.fieldPatternPredicate, + // @ts-ignore ignoredFields = this.ignoredFields, // @ts-ignore canSupportSpecificationExtensions = this.canSupportSpecificationExtensions, } = {}) { this.specPath = specPath; + this.fieldPatternPredicate = fieldPatternPredicate; this.ignoredFields = ignoredFields; this.canSupportSpecificationExtensions = canSupportSpecificationExtensions; }, diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/response/index.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/response/index.ts new file mode 100644 index 0000000000..eb3e60c3bb --- /dev/null +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/response/index.ts @@ -0,0 +1,16 @@ +import stampit from 'stampit'; +import { always } from 'ramda'; + +import FixedFieldsYamlMappingVisitor from '../../generics/FixedFieldsYamlMappingVisitor'; +import { KindVisitor } from '../../generics'; + +const ResponseVisitor = stampit(KindVisitor, FixedFieldsYamlMappingVisitor, { + props: { + specPath: always(['document', 'objects', 'Response']), + }, + init() { + this.element = new this.namespace.elements.Response(); + }, +}); + +export default ResponseVisitor; diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/responses/DefaultVisitor.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/responses/DefaultVisitor.ts new file mode 100644 index 0000000000..11c428af0d --- /dev/null +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/responses/DefaultVisitor.ts @@ -0,0 +1,17 @@ +import stampit from 'stampit'; +import { T as stubTrue } from 'ramda'; + +import { isReferenceObject, isResponseObject } from '../../../predicates'; +import AlternatingVisitor from '../../generics/AlternatingVisitor'; + +const DefaultVisitor = stampit(AlternatingVisitor, { + props: { + alternator: [ + { predicate: isReferenceObject({}), specPath: ['document', 'objects', 'Reference'] }, + { predicate: isResponseObject({}), specPath: ['document', 'objects', 'Response'] }, + { predicate: stubTrue, specPath: ['kind'] }, + ], + }, +}); + +export default DefaultVisitor; diff --git a/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/responses/index.ts b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/responses/index.ts new file mode 100644 index 0000000000..e533606540 --- /dev/null +++ b/apidom/packages/apidom-parser-adapter-openapi3-1-yaml/src/parser/visitors/open-api-3-1/responses/index.ts @@ -0,0 +1,28 @@ +import stampit from 'stampit'; +import { test, always } from 'ramda'; + +import { isReferenceObject, isResponseObject } from '../../../predicates'; +import MixedFieldsYamlMappingVisitor from '../../generics/MixedFieldsYamlMappingVisitor'; +import { KindVisitor } from '../../generics'; + +const ResponsesVisitor = stampit(KindVisitor, MixedFieldsYamlMappingVisitor, { + props: { + specPathFixedFields: always(['document', 'objects', 'Responses']), + specPathPatternedFields: (node: unknown) => { + /* eslint-disable no-nested-ternary */ + return isReferenceObject({}, node) + ? ['document', 'objects', 'Reference'] + : isResponseObject({}, node) + ? ['document', 'objects', 'Response'] + : ['kind']; + /* eslint-enable */ + }, + fieldPatternPredicate: test(/^\d{3}$/), + canSupportSpecificationExtensions: true, + }, + init() { + this.element = new this.namespace.elements.Responses(); + }, +}); + +export default ResponsesVisitor;