diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce5ff2..a4a450f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,12 @@ All notable changes to [@camunda/linting](https://github.com/camunda/linting) ar ___Note:__ Yet to be released changes appear here._ +## 3.23.0 + +* `FEAT`: support execution listeners ([#111](https://github.com/camunda/linting/pull/111)) * `FIX`: improve `no-loop` performance ([bpmnlint-plugin-camunda-compat#165](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/165)) -* `DEPS`: update to `bpmnlint-plugin-camunda-compat@2.21.1` +* `DEPS`: update to `bpmnlint-plugin-camunda-compat@2.22.0` +* `DEPS`: update to `zeebe-bpmn-moddle@1.4.0` ## 3.22.0 diff --git a/lib/compiled-config.js b/lib/compiled-config.js index bd3d2c4..766624b 100644 --- a/lib/compiled-config.js +++ b/lib/compiled-config.js @@ -33,12 +33,14 @@ const rules = { "camunda-compat/called-element": "error", "camunda-compat/collapsed-subprocess": "error", "camunda-compat/connector-properties": "warn", + "camunda-compat/duplicate-execution-listeners": "error", "camunda-compat/duplicate-task-headers": "error", "camunda-compat/error-reference": "error", "camunda-compat/escalation-boundary-event-attached-to-ref": "error", "camunda-compat/escalation-reference": "error", "camunda-compat/event-based-gateway-target": "error", "camunda-compat/executable-process": "error", + "camunda-compat/execution-listener": "error", "camunda-compat/feel": "error", "camunda-compat/history-time-to-live": "info", "camunda-compat/implementation": "error", @@ -47,6 +49,7 @@ const rules = { "camunda-compat/loop-characteristics": "error", "camunda-compat/message-reference": "error", "camunda-compat/no-candidate-users": "error", + "camunda-compat/no-execution-listeners": "error", "camunda-compat/no-expression": "error", "camunda-compat/no-loop": "error", "camunda-compat/no-multiple-none-start-events": "error", @@ -97,134 +100,146 @@ import rule_3 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/connector cache['bpmnlint-plugin-camunda-compat/connector-properties'] = rule_3; -import rule_4 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/duplicate-task-headers'; +import rule_4 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/duplicate-execution-listeners'; -cache['bpmnlint-plugin-camunda-compat/duplicate-task-headers'] = rule_4; +cache['bpmnlint-plugin-camunda-compat/duplicate-execution-listeners'] = rule_4; -import rule_5 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/error-reference'; +import rule_5 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/duplicate-task-headers'; -cache['bpmnlint-plugin-camunda-compat/error-reference'] = rule_5; +cache['bpmnlint-plugin-camunda-compat/duplicate-task-headers'] = rule_5; -import rule_6 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/escalation-boundary-event-attached-to-ref'; +import rule_6 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/error-reference'; -cache['bpmnlint-plugin-camunda-compat/escalation-boundary-event-attached-to-ref'] = rule_6; +cache['bpmnlint-plugin-camunda-compat/error-reference'] = rule_6; -import rule_7 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/escalation-reference'; +import rule_7 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/escalation-boundary-event-attached-to-ref'; -cache['bpmnlint-plugin-camunda-compat/escalation-reference'] = rule_7; +cache['bpmnlint-plugin-camunda-compat/escalation-boundary-event-attached-to-ref'] = rule_7; -import rule_8 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/event-based-gateway-target'; +import rule_8 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/escalation-reference'; -cache['bpmnlint-plugin-camunda-compat/event-based-gateway-target'] = rule_8; +cache['bpmnlint-plugin-camunda-compat/escalation-reference'] = rule_8; -import rule_9 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/executable-process'; +import rule_9 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/event-based-gateway-target'; -cache['bpmnlint-plugin-camunda-compat/executable-process'] = rule_9; +cache['bpmnlint-plugin-camunda-compat/event-based-gateway-target'] = rule_9; -import rule_10 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/feel'; +import rule_10 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/executable-process'; -cache['bpmnlint-plugin-camunda-compat/feel'] = rule_10; +cache['bpmnlint-plugin-camunda-compat/executable-process'] = rule_10; -import rule_11 from 'bpmnlint-plugin-camunda-compat/rules/camunda-platform/history-time-to-live'; +import rule_11 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/execution-listener'; -cache['bpmnlint-plugin-camunda-compat/history-time-to-live'] = rule_11; +cache['bpmnlint-plugin-camunda-compat/execution-listener'] = rule_11; -import rule_12 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/implementation'; +import rule_12 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/feel'; -cache['bpmnlint-plugin-camunda-compat/implementation'] = rule_12; +cache['bpmnlint-plugin-camunda-compat/feel'] = rule_12; -import rule_13 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/inclusive-gateway'; +import rule_13 from 'bpmnlint-plugin-camunda-compat/rules/camunda-platform/history-time-to-live'; -cache['bpmnlint-plugin-camunda-compat/inclusive-gateway'] = rule_13; +cache['bpmnlint-plugin-camunda-compat/history-time-to-live'] = rule_13; -import rule_14 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/link-event'; +import rule_14 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/implementation'; -cache['bpmnlint-plugin-camunda-compat/link-event'] = rule_14; +cache['bpmnlint-plugin-camunda-compat/implementation'] = rule_14; -import rule_15 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/loop-characteristics'; +import rule_15 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/inclusive-gateway'; -cache['bpmnlint-plugin-camunda-compat/loop-characteristics'] = rule_15; +cache['bpmnlint-plugin-camunda-compat/inclusive-gateway'] = rule_15; -import rule_16 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/message-reference'; +import rule_16 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/link-event'; -cache['bpmnlint-plugin-camunda-compat/message-reference'] = rule_16; +cache['bpmnlint-plugin-camunda-compat/link-event'] = rule_16; -import rule_17 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-candidate-users'; +import rule_17 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/loop-characteristics'; -cache['bpmnlint-plugin-camunda-compat/no-candidate-users'] = rule_17; +cache['bpmnlint-plugin-camunda-compat/loop-characteristics'] = rule_17; -import rule_18 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-expression'; +import rule_18 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/message-reference'; -cache['bpmnlint-plugin-camunda-compat/no-expression'] = rule_18; +cache['bpmnlint-plugin-camunda-compat/message-reference'] = rule_18; -import rule_19 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-loop'; +import rule_19 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-candidate-users'; -cache['bpmnlint-plugin-camunda-compat/no-loop'] = rule_19; +cache['bpmnlint-plugin-camunda-compat/no-candidate-users'] = rule_19; -import rule_20 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-multiple-none-start-events'; +import rule_20 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-execution-listeners'; -cache['bpmnlint-plugin-camunda-compat/no-multiple-none-start-events'] = rule_20; +cache['bpmnlint-plugin-camunda-compat/no-execution-listeners'] = rule_20; -import rule_21 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-propagate-all-parent-variables'; +import rule_21 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-expression'; -cache['bpmnlint-plugin-camunda-compat/no-propagate-all-parent-variables'] = rule_21; +cache['bpmnlint-plugin-camunda-compat/no-expression'] = rule_21; -import rule_22 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-signal-event-sub-process'; +import rule_22 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-loop'; -cache['bpmnlint-plugin-camunda-compat/no-signal-event-sub-process'] = rule_22; +cache['bpmnlint-plugin-camunda-compat/no-loop'] = rule_22; -import rule_23 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-task-schedule'; +import rule_23 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-multiple-none-start-events'; -cache['bpmnlint-plugin-camunda-compat/no-task-schedule'] = rule_23; +cache['bpmnlint-plugin-camunda-compat/no-multiple-none-start-events'] = rule_23; -import rule_24 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-template'; +import rule_24 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-propagate-all-parent-variables'; -cache['bpmnlint-plugin-camunda-compat/no-template'] = rule_24; +cache['bpmnlint-plugin-camunda-compat/no-propagate-all-parent-variables'] = rule_24; -import rule_25 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-zeebe-properties'; +import rule_25 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-signal-event-sub-process'; -cache['bpmnlint-plugin-camunda-compat/no-zeebe-properties'] = rule_25; +cache['bpmnlint-plugin-camunda-compat/no-signal-event-sub-process'] = rule_25; -import rule_26 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-zeebe-user-task'; +import rule_26 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-task-schedule'; -cache['bpmnlint-plugin-camunda-compat/no-zeebe-user-task'] = rule_26; +cache['bpmnlint-plugin-camunda-compat/no-task-schedule'] = rule_26; -import rule_27 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/secrets'; +import rule_27 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-template'; -cache['bpmnlint-plugin-camunda-compat/secrets'] = rule_27; +cache['bpmnlint-plugin-camunda-compat/no-template'] = rule_27; -import rule_28 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/sequence-flow-condition'; +import rule_28 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-zeebe-properties'; -cache['bpmnlint-plugin-camunda-compat/sequence-flow-condition'] = rule_28; +cache['bpmnlint-plugin-camunda-compat/no-zeebe-properties'] = rule_28; -import rule_29 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/signal-reference'; +import rule_29 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-zeebe-user-task'; -cache['bpmnlint-plugin-camunda-compat/signal-reference'] = rule_29; +cache['bpmnlint-plugin-camunda-compat/no-zeebe-user-task'] = rule_29; -import rule_30 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/start-event-form'; +import rule_30 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/secrets'; -cache['bpmnlint-plugin-camunda-compat/start-event-form'] = rule_30; +cache['bpmnlint-plugin-camunda-compat/secrets'] = rule_30; -import rule_31 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/subscription'; +import rule_31 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/sequence-flow-condition'; -cache['bpmnlint-plugin-camunda-compat/subscription'] = rule_31; +cache['bpmnlint-plugin-camunda-compat/sequence-flow-condition'] = rule_31; -import rule_32 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/task-schedule'; +import rule_32 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/signal-reference'; -cache['bpmnlint-plugin-camunda-compat/task-schedule'] = rule_32; +cache['bpmnlint-plugin-camunda-compat/signal-reference'] = rule_32; -import rule_33 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/timer'; +import rule_33 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/start-event-form'; -cache['bpmnlint-plugin-camunda-compat/timer'] = rule_33; +cache['bpmnlint-plugin-camunda-compat/start-event-form'] = rule_33; -import rule_34 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-definition'; +import rule_34 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/subscription'; -cache['bpmnlint-plugin-camunda-compat/user-task-definition'] = rule_34; +cache['bpmnlint-plugin-camunda-compat/subscription'] = rule_34; -import rule_35 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'; +import rule_35 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/task-schedule'; -cache['bpmnlint-plugin-camunda-compat/user-task-form'] = rule_35; +cache['bpmnlint-plugin-camunda-compat/task-schedule'] = rule_35; -import rule_36 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/wait-for-completion'; +import rule_36 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/timer'; -cache['bpmnlint-plugin-camunda-compat/wait-for-completion'] = rule_36; \ No newline at end of file +cache['bpmnlint-plugin-camunda-compat/timer'] = rule_36; + +import rule_37 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-definition'; + +cache['bpmnlint-plugin-camunda-compat/user-task-definition'] = rule_37; + +import rule_38 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'; + +cache['bpmnlint-plugin-camunda-compat/user-task-form'] = rule_38; + +import rule_39 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/wait-for-completion'; + +cache['bpmnlint-plugin-camunda-compat/wait-for-completion'] = rule_39; \ No newline at end of file diff --git a/lib/utils/error-messages.js b/lib/utils/error-messages.js index 85d013a..8244092 100644 --- a/lib/utils/error-messages.js +++ b/lib/utils/error-messages.js @@ -121,6 +121,10 @@ export function getErrorMessage(report, executionPlatform, executionPlatformVers return getPropertyValueDuplicatedErrorMessage(report); } + if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) { + return getPropertyValuesDuplicatedErrorMessage(report); + } + if (type == ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED) { return getPropertyValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler); } @@ -228,6 +232,33 @@ function getPropertyValueDuplicatedErrorMessage(report) { return message; } +function getPropertyValuesDuplicatedErrorMessage(report) { + const { + data, + message + } = report; + + const { + node, + parentNode, + duplicatedProperties, + properties + } = data; + + const { + eventType, + type + } = duplicatedProperties; + + const typeString = getTypeString(parentNode || node); + + if (is(node, 'zeebe:ExecutionListeners') && every(properties, property => is(property, 'zeebe:ExecutionListener'))) { + return `${ getIndefiniteArticle(typeString) } <${ typeString }> with two or more with the same (${ eventType }) and (${ type }) is not supported`; + } + + return message; +} + function getPropertyValueRequiredErrorMessage(report, executionPlatform, executionPlatformVersion) { const { data, @@ -297,6 +328,10 @@ function getExtensionElementNotAllowedErrorMessage(report, executionPlatform, ex return getSupportedMessage('A with ', executionPlatform, executionPlatformVersion, allowedVersion); } + if (is(extensionElement, 'zeebe:ExecutionListeners')) { + return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with `, executionPlatform, executionPlatformVersion, allowedVersion); + } + return message; } @@ -485,6 +520,10 @@ function getPropertyRequiredErrorMessage(report, executionPlatform, executionPla return `${ getIndefiniteArticle(typeString) } <${ typeString }> with must have a defined `; } + if (is(node, 'zeebe:ExecutionListener') && requiredProperty === 'type') { + return 'An must have a defined '; + } + if (requiredProperty === 'errorRef') { if (parentNode && is(parentNode, 'bpmn:CatchEvent')) { diff --git a/lib/utils/properties-panel.js b/lib/utils/properties-panel.js index 44da82b..e019321 100644 --- a/lib/utils/properties-panel.js +++ b/lib/utils/properties-panel.js @@ -316,6 +316,22 @@ export function getEntryIds(report) { return [ 'waitForCompletion' ]; } + if (isPropertyError(data, 'type', 'zeebe:ExecutionListener')) { + const index = path[ path.length - 2 ]; + + return [ `${id}-executionListener-${index}-listenerType` ]; + } + + if (isPropertyValuesDuplicatedError(data, 'zeebe:ExecutionListeners')) { + const { properties, propertiesName } = data; + + return properties.map(property => { + const index = data.node.get(propertiesName).indexOf(property); + + return `${ id }-executionListener-${ index }-listenerType`; + }); + } + return []; } @@ -528,6 +544,14 @@ export function getErrorMessage(id, report) { if (id === 'waitForCompletion') { return 'Must wait for completion.'; } + + if (/^.+-executionListener-[0-9]+-listenerType$/.test(id)) { + if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) { + return 'Must be unique.'; + } else { + return 'Must be defined.'; + } + } } function isExtensionElementNotAllowedError(data, extensionElement, type) { @@ -580,6 +604,11 @@ function isPropertyValueDuplicatedError(data, propertiesName, duplicatedProperty && (!type || is(data.node, type)); } +function isPropertyValuesDuplicatedError(data, type) { + return data.type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED + && (!type || is(data.node, type)); +} + function isExpressionRequiredError(data, propertyName, type) { return data.type === ERROR_TYPES.EXPRESSION_REQUIRED && data.property === propertyName diff --git a/package-lock.json b/package-lock.json index d1dc8ae..d065e85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@bpmn-io/diagram-js-ui": "^0.2.3", "bpmn-moddle": "^9.0.1", "bpmnlint": "^10.3.0", - "bpmnlint-plugin-camunda-compat": "^2.21.1", + "bpmnlint-plugin-camunda-compat": "^2.22.0", "bpmnlint-utils": "^1.0.2", "camunda-bpmn-moddle": "^7.0.1", "clsx": "^2.0.0", @@ -20,13 +20,13 @@ "min-dom": "^5.1.1", "modeler-moddle": "^0.2.0", "semver-compare": "^1.0.0", - "zeebe-bpmn-moddle": "^1.1.0" + "zeebe-bpmn-moddle": "^1.4.0" }, "devDependencies": { "bpmn-js": "^17.9.0", "bpmn-js-element-templates": "^1.16.0", - "bpmn-js-properties-panel": "^5.18.0", - "camunda-bpmn-js-behaviors": "^1.3.0", + "bpmn-js-properties-panel": "^5.20.0", + "camunda-bpmn-js-behaviors": "^1.5.0", "chai": "^4.4.1", "cross-env": "^7.0.3", "eslint": "^8.57.0", @@ -1482,10 +1482,11 @@ } }, "node_modules/bpmn-js-properties-panel": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-5.18.0.tgz", - "integrity": "sha512-5+BD4E/nG0z8kVd3Rr4DTrSNz6jw7Brc6dnvhsOY0El5TJTo1BKh+71QZPwfbeEnE0Byykoax9gB9Dn/1m/13Q==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-5.20.0.tgz", + "integrity": "sha512-0hj1OdOwEmO7alqG8k33aRgtWrXGqHgCe2Gc1IkvEqdzNNIy0vyIujoHwnmsCar/5g3l8k4ef+AiHfm4+pBTjQ==", "dev": true, + "license": "MIT", "dependencies": { "@bpmn-io/extract-process-variables": "^0.8.0", "array-move": "^4.0.0", @@ -1626,9 +1627,10 @@ } }, "node_modules/bpmnlint-plugin-camunda-compat": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/bpmnlint-plugin-camunda-compat/-/bpmnlint-plugin-camunda-compat-2.21.1.tgz", - "integrity": "sha512-BLaG1V5JqmmPTyRsd8YE28SMeUQg3v1f472lKQNcVyZ5WPHeBtqX7HTAG81VJkSJQ1E2c6kS7L/xpoa7AA6+wQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/bpmnlint-plugin-camunda-compat/-/bpmnlint-plugin-camunda-compat-2.22.0.tgz", + "integrity": "sha512-AMk8AzKiprFFtKlbKYdvQocP0M+TVmdC1xPI5s9aE0wQ9F6lEye8lkviWgX82F3xODSCk3ixW4Y4usa9Vml3nw==", + "license": "MIT", "dependencies": { "@bpmn-io/feel-lint": "^1.2.0", "@bpmn-io/moddle-utils": "^0.2.1", @@ -1826,10 +1828,11 @@ } }, "node_modules/camunda-bpmn-js-behaviors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-1.3.0.tgz", - "integrity": "sha512-Nz+Fa5B6SVUq6d+Mb0UOP0GZI6a+NrMwUXKeyA5LSXjVEKxwso500PGwbzW7HGgFfqT40Fv8i/ukvI0adTBPyA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-1.5.0.tgz", + "integrity": "sha512-LHExkeC+ZallNMirN9pcm3y43ifUS5465mFIRsTUlitU1apgGS/L52NS0tsPXXQvCgNdEMk2bjs/kwiHhBLdSw==", "dev": true, + "license": "MIT", "dependencies": { "ids": "^1.0.0", "min-dash": "^4.0.0" @@ -6620,9 +6623,10 @@ } }, "node_modules/zeebe-bpmn-moddle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-1.1.0.tgz", - "integrity": "sha512-ES/UZFO0VmKvAzL4+cD3VcQpKvlmgLtnFKTyiv0DdDcxNrdQg1rI0OmUdrKMiybAbtAgPDkVXZCusE3kkXwEyQ==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-1.4.0.tgz", + "integrity": "sha512-XSm0fMHPjQ5cmEGxga02du9arxb5NKH5ve7VQ0LFSes4wGcrZ/oJjaR3NlBqH6xTTD3g+Mcbh45+yesydPUQPg==", + "license": "MIT" }, "node_modules/zod": { "version": "3.23.8", @@ -7888,9 +7892,9 @@ } }, "bpmn-js-properties-panel": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-5.18.0.tgz", - "integrity": "sha512-5+BD4E/nG0z8kVd3Rr4DTrSNz6jw7Brc6dnvhsOY0El5TJTo1BKh+71QZPwfbeEnE0Byykoax9gB9Dn/1m/13Q==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-5.20.0.tgz", + "integrity": "sha512-0hj1OdOwEmO7alqG8k33aRgtWrXGqHgCe2Gc1IkvEqdzNNIy0vyIujoHwnmsCar/5g3l8k4ef+AiHfm4+pBTjQ==", "dev": true, "requires": { "@bpmn-io/extract-process-variables": "^0.8.0", @@ -7982,9 +7986,9 @@ } }, "bpmnlint-plugin-camunda-compat": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/bpmnlint-plugin-camunda-compat/-/bpmnlint-plugin-camunda-compat-2.21.1.tgz", - "integrity": "sha512-BLaG1V5JqmmPTyRsd8YE28SMeUQg3v1f472lKQNcVyZ5WPHeBtqX7HTAG81VJkSJQ1E2c6kS7L/xpoa7AA6+wQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/bpmnlint-plugin-camunda-compat/-/bpmnlint-plugin-camunda-compat-2.22.0.tgz", + "integrity": "sha512-AMk8AzKiprFFtKlbKYdvQocP0M+TVmdC1xPI5s9aE0wQ9F6lEye8lkviWgX82F3xODSCk3ixW4Y4usa9Vml3nw==", "requires": { "@bpmn-io/feel-lint": "^1.2.0", "@bpmn-io/moddle-utils": "^0.2.1", @@ -8086,9 +8090,9 @@ "dev": true }, "camunda-bpmn-js-behaviors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-1.3.0.tgz", - "integrity": "sha512-Nz+Fa5B6SVUq6d+Mb0UOP0GZI6a+NrMwUXKeyA5LSXjVEKxwso500PGwbzW7HGgFfqT40Fv8i/ukvI0adTBPyA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-1.5.0.tgz", + "integrity": "sha512-LHExkeC+ZallNMirN9pcm3y43ifUS5465mFIRsTUlitU1apgGS/L52NS0tsPXXQvCgNdEMk2bjs/kwiHhBLdSw==", "dev": true, "requires": { "ids": "^1.0.0", @@ -11630,9 +11634,9 @@ "dev": true }, "zeebe-bpmn-moddle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-1.1.0.tgz", - "integrity": "sha512-ES/UZFO0VmKvAzL4+cD3VcQpKvlmgLtnFKTyiv0DdDcxNrdQg1rI0OmUdrKMiybAbtAgPDkVXZCusE3kkXwEyQ==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-1.4.0.tgz", + "integrity": "sha512-XSm0fMHPjQ5cmEGxga02du9arxb5NKH5ve7VQ0LFSes4wGcrZ/oJjaR3NlBqH6xTTD3g+Mcbh45+yesydPUQPg==" }, "zod": { "version": "3.23.8", diff --git a/package.json b/package.json index b0e4fa1..58f7c53 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@bpmn-io/diagram-js-ui": "^0.2.3", "bpmn-moddle": "^9.0.1", "bpmnlint": "^10.3.0", - "bpmnlint-plugin-camunda-compat": "^2.21.1", + "bpmnlint-plugin-camunda-compat": "^2.22.0", "bpmnlint-utils": "^1.0.2", "camunda-bpmn-moddle": "^7.0.1", "clsx": "^2.0.0", @@ -40,13 +40,13 @@ "min-dom": "^5.1.1", "modeler-moddle": "^0.2.0", "semver-compare": "^1.0.0", - "zeebe-bpmn-moddle": "^1.1.0" + "zeebe-bpmn-moddle": "^1.4.0" }, "devDependencies": { "bpmn-js": "^17.9.0", "bpmn-js-element-templates": "^1.16.0", - "bpmn-js-properties-panel": "^5.18.0", - "camunda-bpmn-js-behaviors": "^1.3.0", + "bpmn-js-properties-panel": "^5.20.0", + "camunda-bpmn-js-behaviors": "^1.5.0", "chai": "^4.4.1", "cross-env": "^7.0.3", "eslint": "^8.57.0", diff --git a/test/spec/utils/error-messages.spec.js b/test/spec/utils/error-messages.spec.js index 9cdf050..f033aeb 100644 --- a/test/spec/utils/error-messages.spec.js +++ b/test/spec/utils/error-messages.spec.js @@ -450,6 +450,30 @@ describe('utils/error-messages', function() { expect(errorMessage).to.equal('A with is only supported by Camunda 8.3 or newer'); }); + + it('should adjust (zeebe:ExecutionListeners)', async function() { + + // given + const executionPlatformVersion = '8.2'; + + const node = createElement('bpmn:ServiceTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:ExecutionListeners') + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-execution-listeners'); + + const report = await getLintError(node, rule, { version: executionPlatformVersion }); + + // when + const errorMessage = getErrorMessage(report, 'Camunda Cloud', executionPlatformVersion); + + // then + expect(errorMessage).to.equal('A with is only supported by Camunda 8.6 or newer'); + }); }); @@ -1530,6 +1554,33 @@ describe('utils/error-messages', function() { expect(errorMessage).to.equal('A must have a defined '); }); + + it('should adjust (execution listener type)', async function() { + + // given + const node = createElement('bpmn:ServiceTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:ExecutionListeners', { + listeners: [ + createElement('zeebe:ExecutionListener', { eventType: 'start', type: '' }), + ] + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/execution-listener'); + + const report = await getLintError(node, rule); + + // when + const errorMessage = getErrorMessage(report); + + // then + expect(errorMessage).to.equal('An must have a defined '); + }); + }); @@ -1733,6 +1784,35 @@ describe('utils/error-messages', function() { }); + + it('should adjust (two execution listeners with same event type and type)', async function() { + + // given + const node = createElement('bpmn:ServiceTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:ExecutionListeners', { + listeners: [ + createElement('zeebe:ExecutionListener', { eventType: 'start', type: 'foo' }), + createElement('zeebe:ExecutionListener', { eventType: 'start', type: 'foo' }) + ] + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/duplicate-execution-listeners'); + + const report = await getLintError(node, rule); + + // when + const errorMessage = getErrorMessage(report); + + // then + expect(errorMessage).to.equal('A with two or more with the same (start) and (foo) is not supported'); + + }); + }); diff --git a/test/spec/utils/properties-panel.spec.js b/test/spec/utils/properties-panel.spec.js index e163654..f674f9a 100644 --- a/test/spec/utils/properties-panel.spec.js +++ b/test/spec/utils/properties-panel.spec.js @@ -1934,6 +1934,84 @@ describe('utils/properties-panel', function() { expectErrorMessage(entryIds[ 0 ], 'Must wait for completion.', report); }); + + + describe('execution listener', async function() { + + it('should mark type as required', async function() { + + // given + const node = createElement('bpmn:ServiceTask', { + id: 'ServiceTask_1', + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:ExecutionListeners', { + listeners: [ + createElement('zeebe:ExecutionListener', { + eventType: 'start' + }) + ] + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/execution-listener'); + + const report = await getLintError(node, rule); + + // when + const entryIds = getEntryIds(report); + + // then + expect(entryIds).to.eql([ 'ServiceTask_1-executionListener-0-listenerType' ]); + + expectErrorMessage(entryIds[ 0 ], 'Must be defined.', report); + }); + + + it('duplicated', async function() { + + // given + const node = createElement('bpmn:ServiceTask', { + id: 'ServiceTask_1', + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:ExecutionListeners', { + listeners: [ + createElement('zeebe:ExecutionListener', { + eventType: 'start', + type: 'foo' + }), + createElement('zeebe:ExecutionListener', { + eventType: 'start', + type: 'foo' + }) + ] + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/duplicate-execution-listeners'); + + const reports = await getLintErrors(node, rule); + + // when + reports.forEach(report => { + const entryIds = getEntryIds(report); + + // then + expect(entryIds).to.eql([ + 'ServiceTask_1-executionListener-0-listenerType', + 'ServiceTask_1-executionListener-1-listenerType' + ]); + + expectErrorMessage(entryIds[ 0 ], 'Must be unique.', report); + }); + }); + + }); });