Skip to content

Commit

Permalink
feat(apidom-ls): add AsyncAPI IBM MQ Channel Bindings rules
Browse files Browse the repository at this point in the history
Refs #1647
  • Loading branch information
char0n committed Jul 5, 2022
1 parent 5d2bae1 commit 1591cfe
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const exchangeTypeLint: LinterMeta = {
const queueTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_AMQP_CHANNEL_BINDING_FIELD_QUEUE_TYPE,
source: 'apilint',
message: "'queue' value must be an object",
Expand All @@ -13,4 +13,4 @@ const exchangeTypeLint: LinterMeta = {
data: {},
};

export default exchangeTypeLint;
export default queueTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
ApidomCompletionItem,
CompletionFormat,
CompletionType,
} from '../../../../../apidom-language-types';

const completion: ApidomCompletionItem[] = [
{
label: 'destinationType',
insertText: 'destinationType',
kind: 14,
format: CompletionFormat.QUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value: 'Defines the type of AsyncAPI channel.',
},
},
{
label: 'queue',
insertText: 'queue',
kind: 14,
format: CompletionFormat.OBJECT,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value: 'Defines the properties of a queue.',
},
},
{
label: 'topic',
insertText: 'topic',
kind: 14,
format: CompletionFormat.OBJECT,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value: 'Defines the properties of a topic.',
},
},
{
label: 'maxMsgLength',
insertText: 'maxMsgLength',
kind: 14,
format: CompletionFormat.UNQUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value:
'The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.adm.doc/q085520_.html#q085520___maxmsgl) in the IBM MQ Knowledge Center.',
},
},
{
label: 'bindingVersion',
insertText: 'bindingVersion',
kind: 14,
format: CompletionFormat.QUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value: 'The version of this binding.',
},
},
{
target: 'destinationType',
label: 'topic',
insertText: 'topic',
kind: 12,
format: CompletionFormat.QUOTED,
type: CompletionType.VALUE,
insertTextFormat: 2,
},
{
target: 'destinationType',
label: 'queue',
insertText: 'queue',
kind: 12,
format: CompletionFormat.QUOTED,
type: CompletionType.VALUE,
insertTextFormat: 2,
},
{
target: 'bindingVersion',
label: 'latest',
insertText: 'latest',
kind: 12,
format: CompletionFormat.QUOTED,
type: CompletionType.VALUE,
insertTextFormat: 2,
},
];

export default completion;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const documentation = [
{
target: 'destinationType',
docs: 'Defines the type of AsyncAPI channel.',
},
{
target: 'queue',
docs: 'Defines the properties of a queue.',
},
{
target: 'topic',
docs: 'Defines the properties of a topic.',
},
{
target: 'maxMsgLength',
docs: 'The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.adm.doc/q085520_.html#q085520___maxmsgl) in the IBM MQ Knowledge Center.',
},
{
target: 'bindingVersion',
docs: 'The version of this binding.',
},
{
docs: '#### [Channel Binding Object](https://github.com/asyncapi/bindings/blob/master/ibmmq/README.md#channel-binding-object)\n\nThis object contains information about the channel representation in IBM MQ. Each channel corresponds to a Queue or Topic within IBM MQ.\n\n##### Fixed Fields\n\nField Name | Type | Description | Applicability [default] | Constraints\n---|:---:|---|:---|:---\n`destinationType` | string | Defines the type of AsyncAPI channel. | OPTIONAL [`topic`] | MUST be either `topic` or `queue`. For type `topic`, the AsyncAPI channel name MUST be assumed for the IBM MQ topic string unless overridden.\n`queue` | Map[string, any] | Defines the properties of a queue. | REQUIRED if `destinationType` = `queue` | `queue` and `topic` fields MUST NOT coexist within a channel binding\n`queue.objectic` | `queue` and `topic` fields MUST NOT coexist within a channel binding.\n`topic.string` | string | The value of the IBM MQ topic string to be used. | OPTIONAL *Note: if specified, SHALL override AsyncAPI channel name.* | MUST NOT exceed 10240 characters in length. MAY coexist with `topic.objectName`\n`topic.objectName` | string | The name of the IBM MQ topic object. | OPTIONAL *Note: if specified, SHALL override AsyncAPI channel name.*| MUST NOT exceed 48 characters in length. MAY coexist with `topic.string`\n`topic.durablePermitted` | boolean | Defines if the subscription may be durable. | OPTIONAL [`true`] | -\n`topic.lastMsgRetained` | boolean | Defines if the last message published will be made available to new subscriptions. | OPTIONAL [`false`] | -\n`maxMsgLength` | integer | The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.adm.doc/q085520_.html#q085520___maxmsgl) in the IBM MQ Knowledge Center. | OPTIONAL [negotiated on IBM MQ channel]| MUST be `0-104,857,600` bytes (100 MB).\n`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | -\n\n\nThis object MUST contain only the properties defined above.\n\n##### Example for an IBM MQ Topic where topic string is defined by AsyncAPI channel\n\n\n\\\nYAML\n```yaml\nchannels:\n user/signedup:\n```\n\n##### Example for AsyncAPI channel mapping to an IBM MQ topic with a specified MQ Topic object\n\n```yaml\nchannels:\n user/signedup:\n bindings:\n ibmmq:\n destinationType: topic\n topic:\n objectName: myTopicName\n bindingVersion: 0.1.0\n```\n\n##### Example for AsyncAPI channel mapping to an IBM MQ Queue\n\n```yaml\nchannels:\n user/signedup:\n bindings:\n ibmmq:\n destinationType: queue\n queue:\n objectName: myQueueName\n exclusive: true\n bindingVersion: 0.1.0\n```',
},
];
export default documentation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const allowedFieldsLint: LinterMeta = {
code: ApilintCodes.NOT_ALLOWED_FIELDS,
source: 'apilint',
message: 'Object includes not allowed fields',
severity: 1,
linterFunction: 'allowedFields',
linterParams: [['destinationType', 'queue', 'topic', 'maxMsgLength', 'bindingVersion']],
marker: 'key',
};

export default allowedFieldsLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const bindingVersionTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_BINDING_VERSION_TYPE,
source: 'apilint',
message: "'bindingVersion' value must be a string",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['string'],
marker: 'value',
target: 'bindingVersion',
data: {},
};

export default bindingVersionTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const destinationTypeEqualsLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_DESTINATION_TYPE_EQUALS,
source: 'apilint',
message: "'destinationType' must be one of allowed values",
severity: 1,
linterFunction: 'apilintValueOrArray',
linterParams: [['queue', 'topic']],
marker: 'value',
target: 'destinationType',
data: {},
};

export default destinationTypeEqualsLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import allowedFieldsLint from './allowed-fields';
import destinationTypeEqualsLint from './destination-type--equals';
import queueTypeLint from './queue--type';
import queueRequiredLint from './queue--required';
import topicTypeLint from './topic--type';
import topicRequiredLint from './topic--required';
import maxMsgLengthTypeLint from './max-msg-length--type';
import bindingVersionTypeLint from './binding-version--type';

const lints = [
destinationTypeEqualsLint,
queueTypeLint,
queueRequiredLint,
topicTypeLint,
topicRequiredLint,
maxMsgLengthTypeLint,
bindingVersionTypeLint,
allowedFieldsLint,
];

export default lints;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const maxMsgLengthTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_MAX_MSG_LENGTH_TYPE,
source: 'apilint',
message: "'maxMsgLength' value must be a positive integer (zero included)",
severity: 1,
linterFunction: 'apilintNumber',
linterParams: [true, true, true],
marker: 'value',
target: 'maxMsgLength',
data: {},
};

export default maxMsgLengthTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const queueRequiredLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_QUEUE_REQUIRED,
source: 'apilint',
message: "should always have a 'queue'",
severity: 1,
linterFunction: 'hasRequiredField',
linterParams: ['queue'],
marker: 'key',
conditions: [
{
targets: [{ path: 'destinationType' }],
function: 'apilintContainsValue',
params: ['queue'],
},
],
data: {
quickFix: [
{
message: "add 'queue' field",
action: 'addChild',
snippetYaml: 'queue: \n ',
snippetJson: '"queue": {},\n ',
},
],
},
};

export default queueRequiredLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const queueTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_QUEUE_TYPE,
source: 'apilint',
message: "'queue' value must be an object",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['object'],
marker: 'value',
target: 'queue',
data: {},
};

export default queueTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const topicRequiredLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_TOPIC_REQUIRED,
source: 'apilint',
message: "should always have a 'topic'",
severity: 1,
linterFunction: 'hasRequiredField',
linterParams: ['topic'],
marker: 'key',
conditions: [
{
targets: [{ path: 'destinationType' }],
function: 'apilintContainsValue',
params: ['topic'],
},
],
data: {
quickFix: [
{
message: "add 'topic' field",
action: 'addChild',
snippetYaml: 'topic: \n ',
snippetJson: '"topic": {},\n ',
},
],
},
};

export default topicRequiredLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApilintCodes from '../../../../../codes';
import { LinterMeta } from '../../../../../../apidom-language-types';

const topicTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_CHANNEL_BINDING_FIELD_TOPIC_TYPE,
source: 'apilint',
message: "'topic' value must be an object",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['object'],
marker: 'value',
target: 'topic',
data: {},
};

export default topicTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import lint from './lint';
import completion from './completion';
import documentation from './documentation';
import { FormatMeta } from '../../../../../apidom-language-types';

const meta: FormatMeta = {
lint,
completion,
documentation,
};

export default meta;
2 changes: 2 additions & 0 deletions packages/apidom-ls/src/config/asyncapi/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import httpMessageBindingMeta from './bindings/http/message-binding/meta';
import httpOperationBindingMeta from './bindings/http/operation-binding/meta';
import httpServerBindingMeta from './bindings/http/server-binding/meta';
// IBM MQ
import ibmmqChannelBindingMeta from './bindings/ibmmq/channel-binding/meta';
import ibmmqMessageBindingMeta from './bindings/ibmmq/message-binding/meta';
import ibmmqServerBindingMeta from './bindings/ibmmq/server-binding/meta';
// JMS
Expand Down Expand Up @@ -196,6 +197,7 @@ export default {
httpOperationBinding: httpOperationBindingMeta,
httpServerBinding: httpServerBindingMeta,
// IMB MQ
ibmmqChannelBinding: ibmmqChannelBindingMeta,
ibmmqMessageBinding: ibmmqMessageBindingMeta,
ibmmqServerBinding: ibmmqServerBindingMeta,
// JMS
Expand Down
Loading

0 comments on commit 1591cfe

Please sign in to comment.