Skip to content

Commit

Permalink
feat(AsyncApi2.0): add support for ChannelItem object
Browse files Browse the repository at this point in the history
Refs #67
  • Loading branch information
char0n committed Sep 10, 2020
1 parent a86241a commit 2a06d98
Show file tree
Hide file tree
Showing 15 changed files with 297 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

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

export default ChannelBindings;
36 changes: 36 additions & 0 deletions apidom/packages/apidom-ns-asyncapi2-0/src/elements/ChannelItem.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Attributes, Meta, ObjectElement, StringElement } from 'minim';

import OperationElement from './Operation';
import ParametersElement from './Parameters';
import ChannelBindingsElement from './ChannelBindings';

class ChannelItem extends ObjectElement {
constructor(content?: Array<unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
Expand All @@ -21,6 +25,38 @@ class ChannelItem extends ObjectElement {
set description(description: StringElement) {
this.set('description', description);
}

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

set subscribe(subscribe: OperationElement) {
this.set('subscribe', subscribe);
}

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

set publish(publish: OperationElement) {
this.set('publish', publish);
}

get parameters(): ParametersElement {
return this.get('parameters');
}

set parameters(parameters: ParametersElement) {
this.set('parameters', parameters);
}

get bindings(): ChannelBindingsElement {
return this.get('bindings');
}

set bindings(bindings: ChannelBindingsElement) {
this.set('bindings', bindings);
}
}

export default ChannelItem;
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-asyncapi2-0/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;
10 changes: 10 additions & 0 deletions apidom/packages/apidom-ns-asyncapi2-0/src/elements/Parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Attributes, Meta, ObjectElement } from 'minim';

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

export default Parameters;
6 changes: 5 additions & 1 deletion apidom/packages/apidom-ns-asyncapi2-0/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export {
isLicenseElement,
isSchemaElement,
isChannelsElement,
isChannelItemElement,
} from './predicates';

export { default as AsyncapiElement } from './elements/Asyncapi';
Expand All @@ -34,4 +35,7 @@ export { default as InfoElement } from './elements/Info';
export { default as LicenseElement } from './elements/License';
export { default as SchemaElement } from './elements/Schema';
export { default as ChannelsElement } from './elements/Channels';
export { default as ChannelItem } from './elements/ChannelItem';
export { default as ChannelItemElement } from './elements/ChannelItem';
export { default as OperationElement } from './elements/Operation';
export { default as ParametersElement } from './elements/Parameters';
export { default as ChannelBindingsElement } from './elements/ChannelBindings';
6 changes: 6 additions & 0 deletions apidom/packages/apidom-ns-asyncapi2-0/src/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import Components from './elements/Components';
import Schema from './elements/Schema';
import Channels from './elements/Channels';
import ChannelItem from './elements/ChannelItem';
import Operation from './elements/Operation';
import Parameters from './elements/Parameters';
import ChannelBindings from './elements/ChannelBindings';

const asyncApi2_0 = {
namespace: (options: NamespacePluginOptions) => {
Expand All @@ -24,6 +27,9 @@ const asyncApi2_0 = {
base.register('schema', Schema);
base.register('channels', Channels);
base.register('channelItem', ChannelItem);
base.register('operation', Operation);
base.register('parameters', Parameters);
base.register('channelBindings', ChannelBindings);

return base;
},
Expand Down
29 changes: 29 additions & 0 deletions apidom/packages/apidom-ns-asyncapi2-0/src/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ContactElement from './elements/Contact';
import ComponentsElement from './elements/Components';
import SchemaElement from './elements/Schema';
import ChannelsElement from './elements/Channels';
import ChannelItemElement from './elements/ChannelItem';

export const isAsycApi2_0Element = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq, hasGetter, hasClass }) => {
Expand Down Expand Up @@ -167,3 +168,31 @@ export const isChannelsElement = createPredicate(
);
},
);

export const isChannelItemElement = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq, hasGetter }) => {
const isElementTypeChannelItem = isElementType('channelItem');
const primitiveEqObject = primitiveEq('object');
const hasGetter$Ref = hasGetter('$ref');
const hasGetterDescription = hasGetter('description');
const hasGetterSubscribe = hasGetter('subscribe');
const hasGetterPublish = hasGetter('publish');
const hasGetterParameters = hasGetter('parameters');
const hasGetterBindings = hasGetter('bindings');

return either(
is(ChannelItemElement),
allPass([
hasBasicElementProps,
isElementTypeChannelItem,
primitiveEqObject,
hasGetter$Ref,
hasGetterDescription,
hasGetterSubscribe,
hasGetterPublish,
hasGetterParameters,
hasGetterBindings,
]),
);
},
);
70 changes: 70 additions & 0 deletions apidom/packages/apidom-ns-asyncapi2-0/test/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
isAsycapiElement,
isAsycApi2_0Element,
isChannelsElement,
isChannelItemElement,
AsyncApi2_0Element,
AsyncapiElement,
SchemaElement,
Expand All @@ -20,6 +21,7 @@ import {
LicenseElement,
ContactElement,
ChannelsElement,
ChannelItemElement,
} from '../src';

describe('predicates', function () {
Expand Down Expand Up @@ -527,4 +529,72 @@ describe('predicates', function () {
assert.isFalse(isChannelsElement(channelsElementSwan));
});
});

context('isChannelItemElement', function () {
context('given ChannelItem instance value', function () {
specify('should return true', function () {
const element = new ChannelItemElement();

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

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

assert.isTrue(isChannelItemElement(new ChannelItemSubElement()));
});
});

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

specify('should support duck-typing', function () {
const channelItemElementDuck = {
element: 'channelItem',
content: [],
primitive() {
return 'object';
},
get $ref() {
return '$ref';
},
get description() {
return 'description';
},
get subscribe() {
return 'subscribe';
},
get publish() {
return 'publish';
},
get parameters() {
return 'parameters';
},
get bindings() {
return 'bindings';
},
};

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

assert.isTrue(isChannelItemElement(channelItemElementDuck));
assert.isFalse(isChannelItemElement(channelItemElementSwan));
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ import ComponentsVisitor from './visitors/async-api-2-0/components';
import SchemasVisitor from './visitors/async-api-2-0/components/SchemasVisitor';
import ChannelsVisitor from './visitors/async-api-2-0/channels';
import ChannelItemVisitor from './visitors/async-api-2-0/channel-item';
import ChannelItem$RefVisitor from './visitors/async-api-2-0/channel-item/$RefVisitor';
import ChannelItemDescriptionVisitor from './visitors/async-api-2-0/channel-item/DescriptionVisitor';
import ChannelBindingsVisitor from './visitors/async-api-2-0/channel-bindings';
import OperationVisitor from './visitors/async-api-2-0/operation';
import ParametersVisitor from './visitors/async-api-2-0/parameters';

/**
* Specification object allows us to have complete control over visitors
Expand Down Expand Up @@ -96,8 +101,34 @@ const specification = {
},
ChannelItem: {
$visitor: ChannelItemVisitor,
fields: {
$ref: ChannelItem$RefVisitor,
description: ChannelItemDescriptionVisitor,
subscribe: {
$ref: '#/visitors/document/objects/Operation',
},
publish: {
$ref: '#/visitors/document/objects/Operation',
},
parameters: {
$ref: '#/visitors/document/objects/Parameters',
},
bindings: {
$ref: '#/visitors/document/objects/ChannelBindings',
},
},
},
ChannelBindings: {
$visitor: ChannelBindingsVisitor,
fields: {},
},
Operation: {
$visitor: OperationVisitor,
fields: {},
},
Parameters: {
$visitor: ParametersVisitor,
},
Components: {
$visitor: ComponentsVisitor,
fields: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import stampit from 'stampit';
import { always } from 'ramda';

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

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

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

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

const $RefVisitor = stampit(SpecificationVisitor, {
methods: {
string(stringNode) {
const refElement = new this.namespace.elements.Ref(stringNode.value);
refElement.path = stringNode.value;
this.element = this.maybeAddSourceMap(stringNode, refElement);

return BREAK;
},
},
});

export default $RefVisitor;
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,15 @@
import stampit from 'stampit';
import { always } from 'ramda';

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

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

export default OperationVisitor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import stampit from 'stampit';
import { test } from 'ramda';

import PatternedFieldsJsonObjectVisitor from '../../generics/PatternedFieldsJsonObjectVisitor';

const ParametersVisitor = stampit(PatternedFieldsJsonObjectVisitor, {
props: {
fieldPatternPredicate: test(/^[A-Za-z0-9_\\-]+$/),
},
});

export default ParametersVisitor;
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,31 @@
},
"channels": {
"user/signup": {
"description": "This channel is used to exchange messages about users signing up",
"subscribe": {
"$ref": "#/components/messages/userSignUp"
"summary": "A user signed up.",
"message": {
"description": "A longer description of the message",
"payload": {
"type": "object",
"properties": {
"user": {
"$ref": "#/components/schemas/user"
},
"signup": {
"$ref": "#/components/schemas/signup"
}
}
}
}
},
"bindings": {
"amqp": {
"is": "queue",
"queue": {
"exclusive": true
}
}
}
}
},
Expand Down

0 comments on commit 2a06d98

Please sign in to comment.