Skip to content

Commit

Permalink
feat(apidom-ls): add AsyncAPI IBM MQ Server 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 664bc7b commit 5d2bae1
Show file tree
Hide file tree
Showing 16 changed files with 337 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { LinterMeta } from '../../../../../../apidom-language-types';
const expiryTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_MESSAGE_BINDING_FIELD_EXPIRY_TYPE,
source: 'apilint',
message: "'expiry' value must be a string",
message: "'expiry' value must be a positive integer (zero included)",
severity: 1,
linterFunction: 'apilintNumber',
linterParams: [true, true, true],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import {
ApidomCompletionItem,
CompletionFormat,
CompletionType,
} from '../../../../../apidom-language-types';

const completion: ApidomCompletionItem[] = [
{
label: 'groupId',
insertText: 'groupId',
kind: 14,
format: CompletionFormat.QUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value:
'Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group.',
},
},
{
label: 'ccdtQueueManagerName',
insertText: 'ccdtQueueManagerName',
kind: 14,
format: CompletionFormat.QUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value: 'The name of the IBM MQ queue manager to bind to in the CCDT file.',
},
},
{
label: 'cipherSpec',
insertText: 'cipherSpec',
kind: 14,
format: CompletionFormat.QUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value:
'The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.dev.doc/q113220_.html) in the IBM MQ Knowledge Center.',
},
},
{
label: 'multiEndpointServer',
insertText: 'multiEndpointServer',
kind: 14,
format: CompletionFormat.UNQUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value:
'If `multiEndpointServer` is `true` then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint (`multiEndpointServer` = `false`) may be required.',
},
},
{
label: 'heartBeatInterval',
insertText: 'heartBeatInterval',
kind: 14,
format: CompletionFormat.UNQUOTED,
type: CompletionType.PROPERTY,
insertTextFormat: 2,
documentation: {
kind: 'markdown',
value:
'The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of `1` means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q108450_.html) 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: 'multiEndpointServer',
label: 'false',
insertText: 'false',
kind: 12,
format: CompletionFormat.UNQUOTED,
type: CompletionType.VALUE,
insertTextFormat: 2,
},
{
target: 'multiEndpointServer',
label: 'true',
insertText: 'true',
kind: 12,
format: CompletionFormat.UNQUOTED,
type: CompletionType.VALUE,
insertTextFormat: 2,
},
{
target: 'heartBeatInterval',
label: '1',
insertText: '1',
kind: 12,
format: CompletionFormat.UNQUOTED,
type: CompletionType.VALUE,
insertTextFormat: 2,
},
];

export default completion;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const documentation = [
{
target: 'groupId',
docs: 'Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group.',
},
{
target: 'ccdtQueueManagerName',
docs: 'The name of the IBM MQ queue manager to bind to in the CCDT file.',
},
{
target: 'cipherSpec',
docs: 'The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.dev.doc/q113220_.html) in the IBM MQ Knowledge Center.',
},
{
target: 'multiEndpointServer',
docs: 'If `multiEndpointServer` is `true` then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint (`multiEndpointServer` = `false`) may be required.',
},
{
target: 'heartBeatInterval',
docs: 'The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of `1` means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q108450_.html) in the IBM MQ Knowledge Center.',
},
{
target: 'bindingVersion',
docs: 'The version of this binding.',
},
{
docs: "#### [Server Binding Object](https://github.com/asyncapi/bindings/blob/master/ibmmq/README.md#server-binding-object)\n\nThis object contains server connection information about the IBM MQ server, referred to as an IBM MQ queue manager. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.\n\n##### Fixed Fields\n\n\nField Name | Type | Description | Applicability \\[default\\] | Constraints\n---|:---:|---|:---|:---\n`groupId` | string | Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group. | OPTIONAL | MUST NOT be specified for URI Scheme `http://` or `file://`\n`ccdtQueueManagerName` | string | The name of the IBM MQ queue manager to bind to in the CCDT file. | OPTIONAL [`*`] | MUST NOT be specified for URI Scheme `ibmmq://`\n`cipherSpec` | string | The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.dev.doc/q113220_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`ANY`] | MUST NOT be specified for protocol `ibmmq` or URI Scheme `file://` or `http://`\n`multiEndpointServer` | boolean | If `multiEndpointServer` is `true` then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint (`multiEndpointServer` = `false`) may be required. | OPTIONAL [`false`] | MUST NOT be specified for URI Scheme `file://` or `http://`\n`heartBeatInterval` | integer | The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of `1` means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q108450_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`300`] | MUST be `0-999999`\n`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | -\n\nThis object MUST contain only the properties defined above.\n\n##### Example for multiple endpoints defined in the AsyncAPI configuration\n\n\n\\\nYAML\n```yaml\nservers:\n production1:\n url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN\n protocol: ibmmq-secure\n description: Production Instance 1\n bindings:\n ibmmq:\n groupId: PRODCLSTR1\n cipherSpec: ANY_TLS12_OR_HIGHER\n bindingVersion: 0.1.0\n production2:\n url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN\n protocol: ibmmq-secure\n description: Production Instance 2\n bindings:\n ibmmq:\n groupId: PRODCLSTR1\n bindingVersion: 0.1.0\n```\n\n##### Example using combined strategy\n\n```yaml\nservers:\n production:\n url: 'http://my-ccdt-json-file'\n protocol: ibmmq-secure\n description: Production MQ Instance\n bindings:\n ibmmq:\n ccdtQueueManagerName: qm1\n test:\n url: ibmmq://qmgrtest:1414/qm2/DEV.APP.SVRCONN\n protocol: ibmmq-secure\n description: Test MQ Instance\n bindings:\n ibmmq:\n cipherSpec: ANY_TLS12_OR_HIGHER\n bindingVersion: 0.1.0\n```",
},
];
export default documentation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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: [
[
'groupId',
'ccdtQueueManagerName',
'cipherSpec',
'multiEndpointServer',
'heartBeatInterval',
'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_SERVER_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 ccdtQueueManagerNameTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_CCDT_QUEUE_MANAGER_NAME_TYPE,
source: 'apilint',
message: "'ccdtQueueManagerName' value must be a string",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['string'],
marker: 'value',
target: 'ccdtQueueManagerName',
data: {},
};

export default ccdtQueueManagerNameTypeLint;
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 cipherSpecTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_CIPHER_SPEC_TYPE,
source: 'apilint',
message: "'cipherSpec' value must be a string",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['string'],
marker: 'value',
target: 'cipherSpec',
data: {},
};

export default cipherSpecTypeLint;
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 groupIdTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_GROUP_ID_TYPE,
source: 'apilint',
message: "'groupId' value must be a string",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['string'],
marker: 'value',
target: 'groupId',
data: {},
};

export default groupIdTypeLint;
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 heartBeatIntervalMaximumLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_HEART_BEAT_INTERVAL_MAXIMUM,
source: 'apilint',
message: "'heartBeatInterval' value must be less then 999999",
severity: 1,
linterFunction: 'apilintMaximum',
linterParams: [999999],
marker: 'value',
target: 'heartBeatInterval',
data: {},
};

export default heartBeatIntervalMaximumLint;
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 heartBeatIntervalTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_MESSAGE_BINDING_FIELD_EXPIRY_TYPE,
source: 'apilint',
message: "'heartBeatInterval' value must be a positive integer (zero included)",
severity: 1,
linterFunction: 'apilintNumber',
linterParams: [true, true, true],
marker: 'value',
target: 'heartBeatInterval',
data: {},
};

export default heartBeatIntervalTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import allowedFieldsLint from './allowed-fields';
import groupIdTypeLint from './group-id--type';
import ccdtQueueManagerNameTypeLint from './ccdt-queue-manager-name--type';
import cipherSpecTypeLint from './cipher-spec--type.ts';
import multiEndpointServerTypeLint from './multi-endpoint-server--type';
import heartBeatIntervalTypeLint from './heart-beat-internal--type';
import heartBeatIntervalMaximumLint from './heart-beat-internal--maximum';
import bindingVersionTypeLint from './binding-version--type';

const lints = [
groupIdTypeLint,
ccdtQueueManagerNameTypeLint,
cipherSpecTypeLint,
multiEndpointServerTypeLint,
heartBeatIntervalTypeLint,
heartBeatIntervalMaximumLint,
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 multiEndpointServerTypeLint: LinterMeta = {
code: ApilintCodes.ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_MULTI_ENDPOINT_SERVER_TYPE,
source: 'apilint',
message: "'multiEndpointServer' value must be a boolean",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['boolean'],
marker: 'value',
target: 'multiEndpointServer',
data: {},
};

export default multiEndpointServerTypeLint;
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 @@ -58,6 +58,7 @@ import httpOperationBindingMeta from './bindings/http/operation-binding/meta';
import httpServerBindingMeta from './bindings/http/server-binding/meta';
// IBM MQ
import ibmmqMessageBindingMeta from './bindings/ibmmq/message-binding/meta';
import ibmmqServerBindingMeta from './bindings/ibmmq/server-binding/meta';
// JMS
import jmsChannelBindingMeta from './bindings/jms/channel-binding/meta';
import jmsMessageBindingMeta from './bindings/jms/message-binding/meta';
Expand Down Expand Up @@ -196,6 +197,7 @@ export default {
httpServerBinding: httpServerBindingMeta,
// IMB MQ
ibmmqMessageBinding: ibmmqMessageBindingMeta,
ibmmqServerBinding: ibmmqServerBindingMeta,
// JMS
jmsChannelBinding: jmsChannelBindingMeta,
jmsMessageBinding: jmsMessageBindingMeta,
Expand Down
9 changes: 9 additions & 0 deletions packages/apidom-ls/src/config/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,15 @@ enum ApilintCodes {
ASYNCAPI2_IBMMQ_MESSAGE_BINDING_FIELD_EXPIRY_TYPE = 920400,
ASYNCAPI2_IBMMQ_MESSAGE_BINDING_FIELD_BINDING_VERSION_TYPE = 920500,

ASYNCAPI2_IBMMQ_SERVER_BINDING = 930000,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_GROUP_ID_TYPE = 930100,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_CCDT_QUEUE_MANAGER_NAME_TYPE = 930200,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_CIPHER_SPEC_TYPE = 930300,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_MULTI_ENDPOINT_SERVER_TYPE = 930400,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_HEART_BEAT_INTERVAL_TYPE = 930500,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_HEART_BEAT_INTERVAL_MAXIMUM,
ASYNCAPI2_IBMMQ_SERVER_BINDING_FIELD_BINDING_VERSION_TYPE = 930600,

OPENAPI2 = 3000000,

OPENAPI2_CONTACT = 3010000,
Expand Down
14 changes: 14 additions & 0 deletions packages/apidom-ls/src/services/validation/linter-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,20 @@ export const standardLinterfunctions: FunctionItem[] = [
return true;
},
},
{
functionName: 'apilintMaximum',
function: (element: Element, maximum: number): boolean => {
if (element) {
if (!isNumber(element)) {
return false;
}

return element.toValue() <= maximum;
}

return true;
},
},
{
functionName: 'apilintValidURI',
function: (element: Element): boolean => {
Expand Down

0 comments on commit 5d2bae1

Please sign in to comment.