Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(OpenApi3.1-Yaml): add support for Responses and Response #129

Merged
merged 1 commit into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,34 @@ 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;
}
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;
}
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);
});
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -219,6 +222,16 @@ const specification = {
$visitor: RequestBodyVisitor,
fixedFields: {},
},
Responses: {
$visitor: ResponsesVisitor,
fixedFields: {
default: ResponsesDefaultVisitor,
},
},
Response: {
$visitor: ResponseVisitor,
fixedFields: {},
},
Callback: {
$visitor: CallbackVisitor,
fixedFields: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
},
Expand All @@ -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 });
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;