Skip to content

Commit

Permalink
feat(OpenApi3.1): add support for additional fields to Operation (#88)
Browse files Browse the repository at this point in the history
- externalDocs
- parameters
- requestBody        
- servers

Refs #66
  • Loading branch information
char0n authored Sep 7, 2020
1 parent 3aabe26 commit e69b47a
Show file tree
Hide file tree
Showing 20 changed files with 248 additions and 5 deletions.
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/elements/Callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

class Callback extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
this.element = 'callback';
}
}

export default Callback;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Contact extends ObjectElement {
}

get name(): StringElement {
return this.get('name').toValue();
return this.get('name');
}

set name(name: StringElement) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Attributes, Meta, ObjectElement, StringElement } from 'minim';

class ExternalDocumentation extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
this.element = 'externalDocumentation';
}

get description(): StringElement {
return this.get('description');
}

set description(description: StringElement) {
this.set('description', description);
}

get url(): StringElement {
return this.get('url');
}

set url(url: StringElement) {
this.set('url', url);
}
}

export default ExternalDocumentation;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Attributes, BooleanElement, Meta, ObjectElement, StringElement } from 'minim';
import ParameterElement from './Parameter';
import ReferenceElement from './Reference';
import ServerElement from './Server';

class Operation extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
Expand Down Expand Up @@ -59,6 +60,14 @@ class Operation extends ObjectElement {
this.set('parameters', parameters);
}

get servers(): ServerElement[] {
return this.get('severs');
}

set servers(servers: ServerElement[]) {
this.set('servers', servers);
}

// TODO([email protected]): need to implement the rest of the fileds
}

Expand Down
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/elements/RequestBody.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

class RequestBody extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
this.element = 'requestBody';
}
}

export default RequestBody;
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/elements/Responses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

class Responses extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
this.element = 'responses';
}
}

export default Responses;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

class SecurityRequirement extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
this.element = 'securityRequirement';
}
}

export default SecurityRequirement;
5 changes: 5 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ export { default as PathsElement } from './elements/Paths';
export { default as PathItemElement } from './elements/PathItem';
export { default as OperationElement } from './elements/Operation';
export { default as ParameterElement } from './elements/Parameter';
export { default as ExternalDocumentationElement } from './elements/ExternalDocumentation';
export { default as RequestBodyElement } from './elements/RequestBody';
export { default as ResponsesElement } from './elements/Responses';
export { default as CallbackElement } from './elements/Callback';
export { default as SecurityRequirementElement } from './elements/SecurityRequirement';
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import PathItem from './elements/PathItem';
import Operation from './elements/Operation';
import Parameter from './elements/Parameter';
import Reference from './elements/Reference';
import ExternalDocumentation from './elements/ExternalDocumentation';
import RequestBody from './elements/RequestBody';
import Responses from './elements/Responses';
import Callback from './elements/Callback';
import SecurityRequirement from './elements/SecurityRequirement';

const openApi3_1 = {
namespace: (options: NamespacePluginOptions) => {
Expand All @@ -32,6 +37,11 @@ const openApi3_1 = {
base.register('operation', Operation);
base.register('parameter', Parameter);
base.register('reference', Reference);
base.register('externalDocumentation', ExternalDocumentation);
base.register('requestBody', RequestBody);
base.register('responses', Responses);
base.register('callback', Callback);
base.register('securityRequirement', SecurityRequirement);

return base;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,10 @@ export const isServerObject = curry((options, node) => {
}
return hasKeys(['url'], node.properties);
});

export const isRequestBodyObject = curry((options, node) => {
if (!isJsonObject(node)) {
return false;
}
return hasKeys(['content'], node.properties);
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ import OperationDescriptionVisitor from './visitors/open-api-3-1/operation/Descr
import OperationOperationIdVisitor from './visitors/open-api-3-1/operation/OperationIdVisitor';
import OperationTagsVisitor from './visitors/open-api-3-1/operation/TagsVisitor';
import OperationDeprecatedVisitor from './visitors/open-api-3-1/operation/DeprecatedVisitor';
import OperationRequestBodyVisitor from './visitors/open-api-3-1/operation/RequestBodyVisitor';
import ExternalDocumentationVisitor from './visitors/open-api-3-1/external-documentation';
import ExternalDocumentationDescriptionVisitor from './visitors/open-api-3-1/external-documentation/DescriptionVisitor';
import ExternalDocumentationUrlVisitor from './visitors/open-api-3-1/external-documentation/UrlVisitor';
import RequestBodyVisitor from './visitors/open-api-3-1/request-body';
import ReferenceVisitor from './visitors/open-api-3-1/reference';

import ErrorVisitor from './visitors/ErrorVisitor';
import { ValueVisitor, ObjectVisitor, ArrayVisitor } from './visitors/generics';
Expand Down Expand Up @@ -177,10 +183,31 @@ const specification = {
tags: OperationTagsVisitor,
summary: OperationSummaryVisitor,
description: OperationDescriptionVisitor,
externalDocs: {
$ref: '#/visitors/document/objects/ExternalDocumentation',
},
operationId: OperationOperationIdVisitor,
parameters: ParametersVisitor,
requestBody: OperationRequestBodyVisitor,
deprecated: OperationDeprecatedVisitor,
servers: ServersVisitor,
},
},
ExternalDocumentation: {
$visitor: ExternalDocumentationVisitor,
fields: {
description: ExternalDocumentationDescriptionVisitor,
url: ExternalDocumentationUrlVisitor,
},
},
RequestBody: {
$visitor: RequestBodyVisitor,
fields: {},
},
Reference: {
$visitor: ReferenceVisitor,
fields: {},
},
},
extension: SpecificationExtensionVisitor,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import stampit from 'stampit';
import { ifElse, always, Pred } from 'ramda';
import { dispatch, stubUndefined } from 'ramda-adjunct';

import { BREAK } from '..';
import SpecificationVisitor from '../SpecificationVisitor';

const AlternatingVisitor = stampit(SpecificationVisitor, {
props: {
alternator: [],
},
methods: {
object(jsonObject) {
const functions = this.alternator.map(
({ predicate, specPath }: { predicate: Pred; specPath: string[] }) =>
ifElse(predicate, always(specPath), stubUndefined),
);
const specPath = dispatch(functions)(jsonObject);

this.element = this.nodeToElement(specPath, jsonObject);

this.maybeAddSourceMap(jsonObject, this.element);

return BREAK;
},
},
});

export default AlternatingVisitor;
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import { isParameterObject, isReferenceObject } from '../../predicates';
const ParametersVisitor = stampit(SpecificationVisitor, {
init() {
this.element = new this.namespace.elements.Array();
this.element.classes.push('parameters');
},
methods: {
array(arrayNode) {
this.maybeAddSourceMap(arrayNode, this.element);
},
object(objectNode) {
if (isParameterObject({}, objectNode)) {
// TODO([email protected]): replace with real Parameter Object implementation
this.element.content.push(new this.namespace.elements.Object());
this.element.content.push(new this.namespace.elements.Parameter());
} else if (isReferenceObject({}, objectNode)) {
// TODO([email protected]): replace with real Reference Object implementation
this.element.content.push(new this.namespace.elements.Object());
this.element.content.push(new this.namespace.elements.Reference());
}
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import stampit from 'stampit';
import JsonStringVisitor from '../../generics/JsonStringVisitor';

const DescriptionVisitor = stampit(JsonStringVisitor);

export default DescriptionVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import stampit from 'stampit';
import JsonStringVisitor from '../../generics/JsonStringVisitor';

const UrlVisitor = stampit(JsonStringVisitor);

export default UrlVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import stampit from 'stampit';

import FixedFieldsJsonObjectVisitor from '../../generics/FixedFieldsJsonObjectVisitor';

const ExternalDocumentationVisitor = stampit(FixedFieldsJsonObjectVisitor, {
props: {
specPath: ['document', 'objects', 'ExternalDocumentation'],
},
init() {
this.element = new this.namespace.elements.ExternalDocumentation();
},
});

export default ExternalDocumentationVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import stampit from 'stampit';

import { isRequestBodyObject, isReferenceObject } from '../../../predicates';
import AlternatingVisitor from '../../generics/AlternatingVisitor';

const RequestBodyVisitor = stampit(AlternatingVisitor, {
props: {
alternator: [
{ predicate: isRequestBodyObject({}), specPath: ['document', 'objects', 'RequestBody'] },
{ predicate: isReferenceObject({}), specPath: ['document', 'objects', 'Reference'] },
],
},
});

export default RequestBodyVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import stampit from 'stampit';

import FixedFieldsJsonObjectVisitor from '../../generics/FixedFieldsJsonObjectVisitor';

const ReferenceVisitor = stampit(FixedFieldsJsonObjectVisitor, {
props: {
specPath: ['document', 'objects', 'Reference'],
},
init() {
this.element = new this.namespace.elements.Reference();
},
});

export default ReferenceVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import stampit from 'stampit';

import FixedFieldsJsonObjectVisitor from '../../generics/FixedFieldsJsonObjectVisitor';

const RequestBodyVisitor = stampit(FixedFieldsJsonObjectVisitor, {
props: {
specPath: ['document', 'objects', 'RequestBody'],
},
init() {
this.element = new this.namespace.elements.RequestBody();
},
});

export default RequestBodyVisitor;
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,25 @@
"description": "Optional extended description in CommonMark or HTML.",
"operationId": "getUserList",
"deprecated": true,
"externalDocs": {
"description": "Find more info here",
"url": "https://example.com"
},
"parameters": {
"name": "userId",
"in": "query",
"description": "ID of the user",
"required": true
},
"requestBody": {
"content": {}
},
"servers": [
{
"url": "http://api.example.com/v3",
"description": "Redundant server description, e.g. redundant server"
}
],
"responses": {
"200": {
"description": "A JSON array of user names",
Expand Down

0 comments on commit e69b47a

Please sign in to comment.