Skip to content
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
2 changes: 2 additions & 0 deletions apidom/packages/@types/minim.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ declare module 'minim' {
contains(value: any): boolean;

push(value: any): ArrayElement;

[Symbol.iterator](): IterableIterator<any>;
}

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

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

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

import ServerElement from './Server';
import OperationElement from './Operation';

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

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

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

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

get GET(): OperationElement {
return this.get('get');
}

get PUT(): OperationElement {
return this.get('put');
}

get POST(): OperationElement {
return this.get('post');
}

get DELETE(): OperationElement {
return this.get('delete');
}

get OPTIONS(): OperationElement {
return this.get('options');
}

get HEAD(): OperationElement {
return this.get('head');
}

get PATCH(): OperationElement {
return this.get('patch');
}

get TRACE(): OperationElement {
return this.get('trace');
}

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

// @todo(vladimir.gorej@gmail.com): implement `parameters` field here
}
export default PathItem;
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/elements/Paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

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

export default Paths;
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 @@ -23,6 +23,8 @@ export {
isOpenapiElement,
isServerElement,
isServerVariableElement,
isPathsElement,
isPathItemElement,
} from './predicates';

export { default as ComponentsElement } from './elements/Components';
Expand All @@ -34,3 +36,6 @@ export { default as OpenApi3_1Element } from './elements/OpenApi3-1';
export { default as SchemaElement } from './elements/Schema';
export { default as ServerElement } from './elements/Server';
export { default as ServerVariableElement } from './elements/ServerVariable';
export { default as PathsElement } from './elements/Paths';
export { default as PathItemElement } from './elements/PathItem';
export { default as OperationElement } from './elements/Operation';
6 changes: 6 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import Components from './elements/Components';
import Schema from './elements/Schema';
import Server from './elements/Server';
import ServerVariable from './elements/ServerVariable';
import Paths from './elements/Paths';
import PathItem from './elements/PathItem';
import Operation from './elements/Operation';

const openApi3_1 = {
namespace: (options: NamespacePluginOptions) => {
Expand All @@ -22,6 +25,9 @@ const openApi3_1 = {
base.register('schema', Schema);
base.register('server', Server);
base.register('serverVariable', ServerVariable);
base.register('paths', Paths);
base.register('pathItem', PathItem);
base.register('operation', Operation);

return base;
},
Expand Down
52 changes: 52 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/src/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import OpenApi3_1Element from './elements/OpenApi3-1';
import SchemaElement from './elements/Schema';
import ServerElement from './elements/Server';
import ServerVariableElement from './elements/ServerVariable';
import PathsElement from './elements/Paths';
import PathItemElement from './elements/PathItem';

export const isOpenApiApi3_1Element = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq, hasGetter, hasClass }) => {
Expand Down Expand Up @@ -192,3 +194,53 @@ export const isServerVariableElement = createPredicate(
);
},
);

export const isPathsElement = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq }) => {
const isElementTypeInfo = isElementType('paths');
const primitiveEqObject = primitiveEq('object');

return either(
is(PathsElement),
allPass([hasBasicElementProps, isElementTypeInfo, primitiveEqObject]),
);
},
);

export const isPathItemElement = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq, hasGetter }) => {
const isElementTypeInfo = isElementType('pathItem');
const primitiveEqObject = primitiveEq('object');
const hasGetter$Ref = hasGetter('$ref');
const hasGetterSummary = hasGetter('summary');
const hasGetterDescription = hasGetter('description');
const hasGetterGET = hasGetter('GET');
const hasGetterPUT = hasGetter('PUT');
const hasGetterPOST = hasGetter('POST');
const hasGetterDELETE = hasGetter('DELETE');
const hasGetterOPTIONS = hasGetter('OPTIONS');
const hasGetterHEAD = hasGetter('HEAD');
const hasGetterPATCH = hasGetter('PATCH');
const hasGetterTRACE = hasGetter('TRACE');

return either(
is(PathItemElement),
allPass([
hasBasicElementProps,
isElementTypeInfo,
primitiveEqObject,
hasGetter$Ref,
hasGetterSummary,
hasGetterDescription,
hasGetterGET,
hasGetterPUT,
hasGetterPOST,
hasGetterDELETE,
hasGetterOPTIONS,
hasGetterHEAD,
hasGetterPATCH,
hasGetterTRACE,
]),
);
},
);
140 changes: 140 additions & 0 deletions apidom/packages/apidom-ns-openapi3-1/test/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
isOpenApiApi3_1Element,
isServerElement,
isServerVariableElement,
isPathsElement,
isPathItemElement,
OpenApi3_1Element,
OpenapiElement,
SchemaElement,
Expand All @@ -20,6 +22,8 @@ import {
ContactElement,
ServerElement,
ServerVariableElement,
PathsElement,
PathItemElement,
} from '../src';

describe('predicates', function () {
Expand Down Expand Up @@ -551,4 +555,140 @@ describe('predicates', function () {
assert.isFalse(isServerVariableElement(serverVariableElementSwan));
});
});

context('isPathsElement', function () {
context('given PathsElement instance value', function () {
specify('should return true', function () {
const element = new PathsElement();

assert.isTrue(isPathsElement(element));
});
});

context('given subtype instance value', function () {
specify('should return true', function () {
class PathsSubElement extends PathsElement {}

assert.isTrue(isPathsElement(new PathsSubElement()));
});
});

context('given non PathsElement instance value', function () {
specify('should return false', function () {
assert.isFalse(isPathsElement(1));
assert.isFalse(isPathsElement(null));
assert.isFalse(isPathsElement(undefined));
assert.isFalse(isPathsElement({}));
assert.isFalse(isPathsElement([]));
assert.isFalse(isPathsElement('string'));
});
});

specify('should support duck-typing', function () {
const pathsElementDuck = {
element: 'paths',
content: [],
primitive() {
return 'object';
},
};

const pathsElementSwan = {
element: undefined,
content: undefined,
primitive() {
return 'swan';
},
};

assert.isTrue(isPathsElement(pathsElementDuck));
assert.isFalse(isPathsElement(pathsElementSwan));
});
});

context('isPathItemElement', function () {
context('given PathItemElement instance value', function () {
specify('should return true', function () {
const element = new PathItemElement();

assert.isTrue(isPathItemElement(element));
});
});

context('given subtype instance value', function () {
specify('should return true', function () {
class PathItemSubElement extends PathItemElement {}

assert.isTrue(isPathItemElement(new PathItemSubElement()));
});
});

context('given non PathItemElement instance value', function () {
specify('should return false', function () {
assert.isFalse(isPathItemElement(1));
assert.isFalse(isPathItemElement(null));
assert.isFalse(isPathItemElement(undefined));
assert.isFalse(isPathItemElement({}));
assert.isFalse(isPathItemElement([]));
assert.isFalse(isPathItemElement('string'));
});
});

specify('should support duck-typing', function () {
const pathItemElementDuck = {
element: 'pathItem',
content: [],
primitive() {
return 'object';
},
get $ref() {
return '$ref';
},
get summary() {
return 'summary';
},
get description() {
return 'description';
},
get GET() {
return 'get';
},
get PUT() {
return 'put';
},
get POST() {
return 'post';
},
get DELETE() {
return 'delete';
},
get OPTIONS() {
return 'options';
},
get HEAD() {
return 'head';
},
get PATCH() {
return 'patch';
},
get TRACE() {
return 'trace';
},
get servers() {
return 'servers';
},
};

const pathItemElementSwan = {
element: undefined,
content: undefined,
primitive() {
return 'swan';
},
};

assert.isTrue(isPathItemElement(pathItemElementDuck));
assert.isFalse(isPathItemElement(pathItemElementSwan));
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ import ServerVariableDescriptionVisitor from './visitors/open-api-3-1/server-var
import ComponentsVisitor from './visitors/open-api-3-1/components';
import SchemasVisitor from './visitors/open-api-3-1/components/SchemasVisitor';
import SchemaVisitor from './visitors/open-api-3-1/SchemaVisitor';
import PathsVisitor from './visitors/open-api-3-1/PathsVisitor';
import PathItemVisitor from './visitors/open-api-3-1/path-item';
import PathItem$RefVisitor from './visitors/open-api-3-1/path-item/$RefVisitor';
import PathItemSummaryVisitor from './visitors/open-api-3-1/path-item/SummaryVisitor';
import PathItemDescriptionVisitor from './visitors/open-api-3-1/path-item/DescriptionVisitor';
import ErrorVisitor from './visitors/ErrorVisitor';
import { ValueVisitor, ObjectVisitor, ArrayVisitor } from './visitors/generics';

Expand Down Expand Up @@ -59,6 +64,9 @@ const specification = {
components: {
$ref: '#/visitors/document/objects/Components',
},
paths: {
$ref: '#/visitors/document/objects/Paths',
},
},
},
Info: {
Expand Down Expand Up @@ -118,6 +126,17 @@ const specification = {
schemas: SchemasVisitor,
},
},
Paths: {
$visitor: PathsVisitor,
},
PathItem: {
$visitor: PathItemVisitor,
fields: {
$ref: PathItem$RefVisitor,
summary: PathItemSummaryVisitor,
description: PathItemDescriptionVisitor,
},
},
},
extension: SpecificationExtensionVisitor,
},
Expand Down
Loading