diff --git a/packages/extended-services-java/package.json b/packages/extended-services-java/package.json index 03ea848c18a..e1840b082ea 100644 --- a/packages/extended-services-java/package.json +++ b/packages/extended-services-java/package.json @@ -1,9 +1,9 @@ { - "private": true, "name": "@kie-tools/extended-services-java", "version": "0.0.0", "description": "", "license": "Apache-2.0", + "keywords": [], "homepage": "https://github.com/apache/incubator-kie-tools", "repository": { "type": "git", diff --git a/packages/extended-services-vscode-extension/.vscode/launch.json b/packages/extended-services-vscode-extension/.vscode/launch.json new file mode 100644 index 00000000000..b93f503669e --- /dev/null +++ b/packages/extended-services-vscode-extension/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceRoot}"], + "preLaunchTask": "npm: watch" + }, + { + "name": "Run Extension (web)", + "type": "extensionHost", + "debugWebWorkerHost": true, + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionDevelopmentKind=web"], + "preLaunchTask": "npm: watch" + } + ] +} diff --git a/packages/extended-services-vscode-extension/.vscode/settings.json b/packages/extended-services-vscode-extension/.vscode/settings.json new file mode 100644 index 00000000000..0d55a3308e5 --- /dev/null +++ b/packages/extended-services-vscode-extension/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.exclude": { + "out": false + }, + "search.exclude": { + "out": true + }, + "typescript.tsc.autoDetect": "off" +} diff --git a/packages/extended-services-vscode-extension/.vscode/tasks.json b/packages/extended-services-vscode-extension/.vscode/tasks.json new file mode 100644 index 00000000000..34edf970fde --- /dev/null +++ b/packages/extended-services-vscode-extension/.vscode/tasks.json @@ -0,0 +1,18 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/packages/extended-services-vscode-extension/LICENSE b/packages/extended-services-vscode-extension/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/packages/extended-services-vscode-extension/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/extended-services-vscode-extension/env/index.js b/packages/extended-services-vscode-extension/env/index.js new file mode 100644 index 00000000000..61bc742bd66 --- /dev/null +++ b/packages/extended-services-vscode-extension/env/index.js @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const { varsWithName, composeEnv } = require("@kie-tools-scripts/build-env"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({}), + get env() { + return {}; + }, +}); diff --git a/packages/extended-services-vscode-extension/icon.png b/packages/extended-services-vscode-extension/icon.png new file mode 100644 index 00000000000..07950c876dd Binary files /dev/null and b/packages/extended-services-vscode-extension/icon.png differ diff --git a/packages/extended-services-vscode-extension/package.json b/packages/extended-services-vscode-extension/package.json new file mode 100644 index 00000000000..7e9bfd6ae72 --- /dev/null +++ b/packages/extended-services-vscode-extension/package.json @@ -0,0 +1,167 @@ +{ + "name": "extended-services-vscode-extension", + "version": "0.0.0", + "description": "Enhance KIE DMN and BPMN editors capabilities", + "license": "Apache-2.0", + "publisher": "kie-group", + "keywords": [], + "homepage": "https://github.com/kiegroup/kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/kiegroup/kie-tools.git" + }, + "bugs": { + "url": "https://github.com/kiegroup/kie-tools/issues" + }, + "browser": "dist/extension/extension-browser.js", + "main": "dist/extension/extension-main.js", + "scripts": { + "build:dev": "pnpm clean && pnpm copy:extended-services-java && webpack --env dev", + "build:prod": "pnpm clean && pnpm copy:extended-services-java && webpack && pnpm pack:prod", + "clean": "rimraf dist && rimraf dist-dev && mkdir dist-dev", + "compile": "webpack", + "copy:extended-services-java": "cp -R ../extended-services-java/dist/extended-services-java ./dist-dev/extended-services-java", + "lint": "run-script-if --bool \"$(build-env linters.run)\" --then \"kie-tools--eslint ./src\"", + "open-in-browser": "vscode-test-web --extensionDevelopmentPath=. .", + "pack:prod": "vsce package --githubBranch main --no-dependencies -o ./dist/extended_services_vscode_extension_$npm_package_version.vsix", + "run:webmode": "pnpm vscode-test-web --browserType=chromium --extensionDevelopmentPath=. --version=stable", + "watch": "webpack" + }, + "dependencies": { + "@kie-tools-core/vscode-extension": "workspace:*", + "@kie-tools/extended-services-java": "workspace:*" + }, + "devDependencies": { + "@kie-tools-core/webpack-base": "workspace:*", + "@kie-tools/eslint": "workspace:*", + "@kie-tools/root-env": "workspace:*", + "@kie-tools/tsconfig": "workspace:*", + "@types/vscode": "1.67.0", + "@vscode/test-web": "^0.0.30", + "@vscode/vsce": "^2.22.0", + "copy-webpack-plugin": "^11.0.0", + "node-fetch": "^3.3.1", + "rimraf": "^3.0.2", + "webpack": "^5.88.2", + "webpack-cli": "^4.10.0", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0" + }, + "engines": { + "vscode": "^1.67.0" + }, + "displayName": "Apache KIE Extended Services", + "categories": [ + "Other" + ], + "contributes": { + "commands": [ + { + "category": "Extended-Services", + "command": "extended-services-vscode-extension.connectExtendedServices", + "title": "Connect Apache KIE Extended-Services", + "when": "extended-services-vscode-extension.connected" + }, + { + "category": "Extended-Services", + "command": "extended-services-vscode-extension.disconnectExtendedServices", + "title": "Disconnect Apache KIE Extended-Services" + } + ], + "configuration": { + "properties": { + "extendedServices.connectionHeartbeatInterval": { + "default": 5, + "description": "Specifies the interval (in seconds) between each connection check.", + "format": "time", + "order": 2, + "type": "integer" + }, + "extendedServices.enableAutorun": { + "default": true, + "description": "Automatically run a local instance of the service.", + "order": 0, + "type": "boolean" + }, + "extendedServices.serviceURL": { + "default": "http://localhost:21345", + "description": "Specifies the service URL.", + "format": "uri", + "order": 1, + "type": "string" + } + }, + "title": "Apache KIE Extended Services" + }, + "icons": { + "extended-services-connected": { + "default": { + "fontCharacter": "\\E000", + "fontPath": "./static/extended-services-font.woff" + }, + "description": "Connected to the Apache KIE Extended-Services" + }, + "extended-services-disconnected": { + "default": { + "fontCharacter": "\\E001", + "fontPath": "./static/extended-services-font.woff" + }, + "description": "Apache KIE Extended-Services are Disconnected" + } + }, + "languages": [ + { + "aliases": [ + "bpmn", + "bpmn2", + "BPMN", + "BPMN2", + "Business Process Model and Notation" + ], + "extensions": [ + ".bpmn", + ".bpmn2", + ".BPMN", + ".BPMN2" + ], + "id": "bpmn" + }, + { + "aliases": [ + "dmn", + "DMN", + "Decision Model and Notation" + ], + "extensions": [ + ".dmn", + ".DMN" + ], + "id": "dmn" + } + ], + "menus": { + "commandPalette": [ + { + "command": "extended-services-vscode-extension.connectExtendedServices", + "when": "!extended-services-vscode-extension.connected" + }, + { + "command": "extended-services-vscode-extension.disconnectExtendedServices", + "when": "extended-services-vscode-extension.connected" + } + ] + } + }, + "activationEvents": [ + "onLanguage:bpmn", + "onLanguage:dmn", + "onCustomEditor:kieKogitoWebviewEditorsBpmn", + "onCustomEditor:kieKogitoWebviewEditorsDmn" + ], + "icon": "icon.png", + "capabilities": { + "untrustedWorkspaces": { + "supported": false + } + } +} \ No newline at end of file diff --git a/packages/extended-services-vscode-extension/src/connection-manager.ts b/packages/extended-services-vscode-extension/src/connection-manager.ts new file mode 100644 index 00000000000..9079db40979 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/connection-manager.ts @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { JITCommands } from "./jit-executor/jit-commands"; +import { PingResponse } from "./jit-executor/responses"; + +export class ConnectionManager { + readonly startConnectionHeartbeatCommandUID: string = "extended-services-vscode-extension.startConnectionHeartbeat"; + readonly stopConnectionHeartbeatCommandUID: string = "extended-services-vscode-extension.stopConnectionHeartbeat"; + + private startConnectionHeartbeatCommand: vscode.Disposable; + private stopConnectionHeartbeatCommand: vscode.Disposable; + + private connectedHandler: ConnectedHandler | null = null; + private disconnectedHandler: DisconnectedHandler | null = null; + + private context: vscode.ExtensionContext; + private lastPingStarted: boolean = false; + + private timeout: NodeJS.Timeout | null = null; + + constructor(context: vscode.ExtensionContext) { + this.context = context; + this.initializeCommands(); + } + + private initializeCommands(): void { + const startConnectionHeartbeatCommandHandler = (serviceURL: URL, connectionHeartbeatInterval: number) => { + this.start(serviceURL, connectionHeartbeatInterval); + }; + + const stopConnectionHeartbeatCommandHandler = () => { + this.stop(); + }; + + this.startConnectionHeartbeatCommand = vscode.commands.registerCommand( + this.startConnectionHeartbeatCommandUID, + startConnectionHeartbeatCommandHandler + ); + this.stopConnectionHeartbeatCommand = vscode.commands.registerCommand( + this.stopConnectionHeartbeatCommandUID, + stopConnectionHeartbeatCommandHandler + ); + + this.context.subscriptions.push(this.startConnectionHeartbeatCommand); + this.context.subscriptions.push(this.stopConnectionHeartbeatCommand); + } + + private async performHeartbeatCheck(serviceURL: URL): Promise { + try { + const pingResponse: PingResponse = await JITCommands.ping(serviceURL); + if (pingResponse.started != this.lastPingStarted) { + if (pingResponse.started) { + this.fireConnectedEvent(); + } else { + this.fireDisconnectedEvent(); + } + this.lastPingStarted = pingResponse.started; + } + } catch (error) { + this.fireDisconnectedEvent(); + this.stopHeartbeatCheck(); + vscode.window.showErrorMessage("Error performing heartbeat check: " + error.message); + } + } + + private stopHeartbeatCheck(): void { + if (this.timeout) { + this.fireDisconnectedEvent(); + clearInterval(this.timeout); + this.lastPingStarted = false; + } + } + + private fireConnectedEvent() { + if (this.connectedHandler) { + this.connectedHandler(); + } + } + + private fireDisconnectedEvent() { + if (this.disconnectedHandler) { + this.disconnectedHandler(); + } + } + + private async start(serviceURL: URL, connectionHeartbeatInterval: number): Promise { + this.performHeartbeatCheck(serviceURL); + this.timeout = setInterval(async () => { + this.performHeartbeatCheck(serviceURL); + }, connectionHeartbeatInterval * 1000); + } + + private stop(): void { + this.stopHeartbeatCheck(); + } + + public subscribeConnected(handler: ConnectedHandler) { + this.connectedHandler = handler; + } + + public subscribeDisconnected(handler: DisconnectedHandler) { + this.disconnectedHandler = handler; + } + + public unsubscribeConnected() { + this.connectedHandler = null; + } + + public unsubscribeDisconnected() { + this.disconnectedHandler = null; + } + + public dispose(): void { + this.stop(); + this.startConnectionHeartbeatCommand.dispose(); + this.stopConnectionHeartbeatCommand.dispose(); + this.unsubscribeConnected(); + this.unsubscribeDisconnected(); + this.timeout = null; + } +} + +interface ConnectedHandler { + (): void; +} + +interface DisconnectedHandler { + (): void; +} diff --git a/packages/extended-services-vscode-extension/src/extension/extension-browser.ts b/packages/extended-services-vscode-extension/src/extension/extension-browser.ts new file mode 100644 index 00000000000..efb8025b562 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/extension/extension-browser.ts @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { Configuration } from "../watchers/configurations/configuration"; +import { ConfigurationWatcher } from "../watchers/configurations/configuration-watcher"; +import { ConnectionManager } from "../connection-manager"; +import { KIEFileWatcher } from "../watchers/kie-files/kie-file-watcher"; +import { ValidationHelper } from "../validation-helper"; + +const connectExtendedServicesCommandUID: string = "extended-services-vscode-extension.connectExtendedServices"; +const disconnectExtendedServicesCommandUID: string = "extended-services-vscode-extension.disconnectExtendedServices"; +const connectedEnablamentUID: string = "extended-services-vscode-extension.connected"; + +let connectExtendedServicesCommand: vscode.Disposable; +let disconnectExtendedServicesCommand: vscode.Disposable; + +let kieFileWatcher: KIEFileWatcher; +let configurationWatcher: ConfigurationWatcher; +let connectionManager: ConnectionManager; +let validationHelper: ValidationHelper; +let statusBarItem: vscode.StatusBarItem; +let userDisconnected: boolean; +let connected: boolean; + +function connectExtendedServices(): void { + userDisconnected = false; + const configuration = Configuration.fetchConfiguration(); + if (configuration) { + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } +} + +function disconnectExtendedServices(): void { + userDisconnected = true; + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration) { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + } +} + +function initializeCommands(context: vscode.ExtensionContext): void { + const connectExtendedServicesCommandHandler = () => { + connectExtendedServices(); + }; + + const disconnectExtendedServicesCommandHandler = () => { + disconnectExtendedServices(); + }; + + connectExtendedServicesCommand = vscode.commands.registerCommand( + connectExtendedServicesCommandUID, + connectExtendedServicesCommandHandler + ); + + disconnectExtendedServicesCommand = vscode.commands.registerCommand( + disconnectExtendedServicesCommandUID, + disconnectExtendedServicesCommandHandler + ); + + context.subscriptions.push(connectExtendedServicesCommand); + context.subscriptions.push(disconnectExtendedServicesCommand); +} + +export function activate(context: vscode.ExtensionContext): void { + vscode.commands.executeCommand("setContext", connectedEnablamentUID, false); + userDisconnected = false; + connected = false; + + statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); + statusBarItem.show(); + context.subscriptions.push(statusBarItem); + + kieFileWatcher = new KIEFileWatcher(); + configurationWatcher = new ConfigurationWatcher(); + connectionManager = new ConnectionManager(context); + validationHelper = new ValidationHelper(context); + + initializeCommands(context); + + configurationWatcher.subscribeSettingsChanged(() => { + if (!userDisconnected && connected) { + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + + if (configuration) { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } + } + }); + + kieFileWatcher.subscribeKIEFilesOpened(() => { + statusBarItem.show(); + if (!userDisconnected) { + const configuration = Configuration.fetchConfiguration(); + if (configuration) { + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } + } + }); + + kieFileWatcher.subscribeKIEFilesChanged(() => { + vscode.commands.executeCommand(validationHelper.clearValidationCommandUID); + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration && connected) { + vscode.commands.executeCommand(validationHelper.validateCommandUID, configuration.serviceURL); + } + }); + + kieFileWatcher.subscribeKIEFilesClosed(() => { + statusBarItem.hide(); + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration) { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + } + }); + + connectionManager.subscribeConnected(() => { + connected = true; + vscode.commands.executeCommand("setContext", connectedEnablamentUID, true); + statusBarItem.text = "$(extended-services-connected)"; + statusBarItem.tooltip = "Apache KIE Extended Services are connected. \n" + "Click to disconnect."; + statusBarItem.command = disconnectExtendedServicesCommandUID; + vscode.commands.executeCommand(validationHelper.clearValidationCommandUID); + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration && connected) { + vscode.commands.executeCommand(validationHelper.validateCommandUID, configuration.serviceURL); + } + }); + + connectionManager.subscribeDisconnected(() => { + connected = false; + vscode.commands.executeCommand("setContext", connectedEnablamentUID, false); + statusBarItem.text = "$(extended-services-disconnected)"; + statusBarItem.tooltip = "Apache KIE Extended Services are not connected. \n" + "Click to connect."; + statusBarItem.command = connectExtendedServicesCommandUID; + vscode.commands.executeCommand(validationHelper.clearValidationCommandUID); + }); +} + +export function deactivate(): void { + connectExtendedServicesCommand.dispose(); + disconnectExtendedServicesCommand.dispose(); + validationHelper.dispose(); + connectionManager.dispose(); + kieFileWatcher.dispose(); + configurationWatcher.dispose(); + statusBarItem.dispose(); +} diff --git a/packages/extended-services-vscode-extension/src/extension/extension-main.ts b/packages/extended-services-vscode-extension/src/extension/extension-main.ts new file mode 100644 index 00000000000..36302f71d1a --- /dev/null +++ b/packages/extended-services-vscode-extension/src/extension/extension-main.ts @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { Configuration } from "../watchers/configurations/configuration"; +import { ConfigurationWatcher } from "../watchers/configurations/configuration-watcher"; +import { ConnectionManager } from "../connection-manager"; +import { KIEFileWatcher } from "../watchers/kie-files/kie-file-watcher"; +import { LocalServiceManager } from "../local-service-manager"; +import { ValidationHelper } from "../validation-helper"; + +const connectExtendedServicesCommandUID: string = "extended-services-vscode-extension.connectExtendedServices"; +const disconnectExtendedServicesCommandUID: string = "extended-services-vscode-extension.disconnectExtendedServices"; +const connectedEnablamentUID: string = "extended-services-vscode-extension.connected"; + +let connectExtendedServicesCommand: vscode.Disposable; +let disconnectExtendedServicesCommand: vscode.Disposable; + +let kieFileWatcher: KIEFileWatcher; +let configurationWatcher: ConfigurationWatcher; +let connectionManager: ConnectionManager; +let localServiceManager: LocalServiceManager; +let validationHelper: ValidationHelper; +let statusBarItem: vscode.StatusBarItem; +let userDisconnected: boolean; +let connected: boolean; + +function connectExtendedServices(): void { + userDisconnected = false; + const configuration = Configuration.fetchConfiguration(); + if (configuration) { + if (configuration.autoRun) { + vscode.commands.executeCommand(localServiceManager.startLocalServiceCommandUID, configuration.serviceURL); + } else { + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } + } +} + +function disconnectExtendedServices(): void { + userDisconnected = true; + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration && configuration.autoRun) { + vscode.commands.executeCommand(localServiceManager.stopLocalServiceCommandUID); + } else { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + } +} + +function initializeCommands(context: vscode.ExtensionContext): void { + const connectExtendedServicesCommandHandler = () => { + connectExtendedServices(); + }; + + const disconnectExtendedServicesCommandHandler = () => { + disconnectExtendedServices(); + }; + + connectExtendedServicesCommand = vscode.commands.registerCommand( + connectExtendedServicesCommandUID, + connectExtendedServicesCommandHandler + ); + + disconnectExtendedServicesCommand = vscode.commands.registerCommand( + disconnectExtendedServicesCommandUID, + disconnectExtendedServicesCommandHandler + ); + + context.subscriptions.push(connectExtendedServicesCommand); + context.subscriptions.push(disconnectExtendedServicesCommand); +} + +export function activate(context: vscode.ExtensionContext): void { + vscode.commands.executeCommand("setContext", connectedEnablamentUID, false); + userDisconnected = false; + connected = false; + + statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); + statusBarItem.show(); + context.subscriptions.push(statusBarItem); + + kieFileWatcher = new KIEFileWatcher(); + configurationWatcher = new ConfigurationWatcher(); + localServiceManager = new LocalServiceManager(context); + connectionManager = new ConnectionManager(context); + validationHelper = new ValidationHelper(context); + + initializeCommands(context); + + configurationWatcher.subscribeSettingsChanged(() => { + if (!userDisconnected && connected) { + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + + if (configuration && configuration.autoRun) { + vscode.commands.executeCommand(localServiceManager.stopLocalServiceCommandUID); + } else { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + } + + if (configuration) { + if (configuration.autoRun) { + vscode.commands.executeCommand(localServiceManager.startLocalServiceCommandUID, configuration.serviceURL); + } else { + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } + } + } + }); + + kieFileWatcher.subscribeKIEFilesOpened(() => { + statusBarItem.show(); + if (!userDisconnected) { + const configuration = Configuration.fetchConfiguration(); + if (configuration) { + if (configuration.autoRun) { + vscode.commands.executeCommand(localServiceManager.startLocalServiceCommandUID, configuration.serviceURL); + } else { + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } + } + } + }); + + kieFileWatcher.subscribeKIEFilesChanged(() => { + vscode.commands.executeCommand(validationHelper.clearValidationCommandUID); + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration && connected) { + vscode.commands.executeCommand(validationHelper.validateCommandUID, configuration.serviceURL); + } + }); + + kieFileWatcher.subscribeKIEFilesClosed(() => { + statusBarItem.hide(); + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration && configuration.autoRun) { + vscode.commands.executeCommand(localServiceManager.stopLocalServiceCommandUID); + } else { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + } + }); + + localServiceManager.subscribeLocalServicesRunning(() => { + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration) { + vscode.commands.executeCommand( + connectionManager.startConnectionHeartbeatCommandUID, + configuration.serviceURL, + configuration.connectionHeartbeatInterval + ); + } + }); + + localServiceManager.subscribeLocalServicesTerminated(() => { + vscode.commands.executeCommand(connectionManager.stopConnectionHeartbeatCommandUID); + }); + + connectionManager.subscribeConnected(() => { + connected = true; + vscode.commands.executeCommand("setContext", connectedEnablamentUID, true); + statusBarItem.text = "$(extended-services-connected)"; + statusBarItem.tooltip = "Apache KIE Extended Services are connected. \n" + "Click to disconnect."; + statusBarItem.command = disconnectExtendedServicesCommandUID; + vscode.commands.executeCommand(validationHelper.clearValidationCommandUID); + const configuration: Configuration | undefined = Configuration.fetchConfiguration(); + if (configuration && connected) { + vscode.commands.executeCommand(validationHelper.validateCommandUID, configuration.serviceURL); + } + }); + + connectionManager.subscribeDisconnected(() => { + connected = false; + vscode.commands.executeCommand("setContext", connectedEnablamentUID, false); + statusBarItem.text = "$(extended-services-disconnected)"; + statusBarItem.tooltip = "Apache KIE Extended Services are not connected. \n" + "Click to connect."; + statusBarItem.command = connectExtendedServicesCommandUID; + vscode.commands.executeCommand(validationHelper.clearValidationCommandUID); + }); +} + +export function deactivate(): void { + connectExtendedServicesCommand.dispose(); + disconnectExtendedServicesCommand.dispose(); + validationHelper.dispose(); + localServiceManager.dispose(); + connectionManager.dispose(); + kieFileWatcher.dispose(); + configurationWatcher.dispose(); + statusBarItem.dispose(); +} diff --git a/packages/extended-services-vscode-extension/src/jit-executor/jit-commands.ts b/packages/extended-services-vscode-extension/src/jit-executor/jit-commands.ts new file mode 100644 index 00000000000..2dd69551b58 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/jit-executor/jit-commands.ts @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { + BPMNValidationResponse, + BPMNValidationResponseParser, + DMNValidationResponse, + DMNValidationResponseParser, + PingResponse, +} from "./responses"; +import { KIEValidateBodyPayload, KIEValidateResourcePayload } from "./payloads"; + +export class JITCommands { + public static async ping(serviceURL: URL): Promise { + const url = new URL("/ping", serviceURL); + + try { + const response = await fetch(url.toString()); + const responseData = (await response.json()) as PingResponse; + return responseData; + } catch (error) { + vscode.window.showErrorMessage("Error at JIT-Commands Ping request: ", error.message); + return { + started: false, + version: "undefined", + }; + } + } + + public static async validateBPMN( + serviceURL: URL, + documents: vscode.TextDocument[] + ): Promise { + const url = new URL("/jitbpmn/validate", serviceURL); + + try { + const response = await fetch(url.toString(), { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JITCommands.buildBodyPayload(documents), + }); + + const responseData: string[] = (await response.json()) as string[]; + const validationResponses: BPMNValidationResponse[] = BPMNValidationResponseParser.parse(responseData); + return validationResponses; + } catch (error) { + vscode.window.showErrorMessage("Error at JIT-Commands Validate BPMN request: ", error.message); + throw error; + } + } + + public static async validateDMN(serviceURL: URL, documents: vscode.TextDocument[]): Promise { + const url = new URL("/jitdmn/validate", serviceURL); + + try { + const response = await fetch(url.toString(), { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JITCommands.buildBodyPayload(documents), + }); + + const responseData: any = await response.json(); + const validationResponses: DMNValidationResponse[] = DMNValidationResponseParser.parse(responseData); + return validationResponses; + } catch (error) { + vscode.window.showErrorMessage("Error at JIT-Commands Validate DMN request: ", error.message); + throw error; + } + } + + private static buildBodyPayload(documents: vscode.TextDocument[]): string { + const bodyPayload: KIEValidateBodyPayload = { + mainURI: "VS Code KIE files", + resources: [], + }; + + for (const document of documents) { + const resourcePayload: KIEValidateResourcePayload = { + content: document.getText(), + URI: document.fileName, + }; + bodyPayload.resources.push(resourcePayload); + } + + try { + return JSON.stringify(bodyPayload); + } catch (error) { + vscode.window.showErrorMessage("Error building body payload: ", error.message); + return ""; + } + } +} diff --git a/packages/extended-services-vscode-extension/src/jit-executor/payloads.ts b/packages/extended-services-vscode-extension/src/jit-executor/payloads.ts new file mode 100644 index 00000000000..8b3531bce42 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/jit-executor/payloads.ts @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface KIEValidateBodyPayload { + mainURI: string; + resources: KIEValidateResourcePayload[]; +} + +export interface KIEValidateResourcePayload { + URI: string; + content: string; +} diff --git a/packages/extended-services-vscode-extension/src/jit-executor/responses.ts b/packages/extended-services-vscode-extension/src/jit-executor/responses.ts new file mode 100644 index 00000000000..3414411c413 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/jit-executor/responses.ts @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import * as vscode from "vscode"; + +export interface BPMNValidationResponse { + uri: vscode.Uri; + processID: string; + name: string; + error: string; +} + +export interface DMNValidationResponse { + severity: string; + message: string; + messageType: string; + sourceId: string; + level: string; +} + +export interface PingResponse { + version: string; + started: boolean; +} + +export class BPMNValidationResponseParser { + public static parse(jsonResponse: string[]): BPMNValidationResponse[] { + if (jsonResponse.length > 0) { + return jsonResponse.map((response) => { + const uriMarker = "Uri: "; + const processIdMarker = " - Process id: "; + const nameMarker = " - name : "; + const errorMarker = " - error : "; + + const uriStartIndex = response.indexOf(uriMarker); + const processIdStartIndex = response.indexOf(processIdMarker); + const nameStartIndex = response.indexOf(nameMarker); + const errorStartIndex = response.indexOf(errorMarker); + + const uriEndIndex = response.indexOf(processIdMarker); + const processIdEndIndex = response.indexOf(nameMarker); + const nameEndIndex = response.indexOf(errorMarker); + const errorEndIndex = response.length; + + if (uriStartIndex !== -1 || processIdStartIndex !== -1 || nameStartIndex !== -1 || errorStartIndex !== -1) { + const uri = response.substring(uriStartIndex + uriMarker.length, uriEndIndex).trim(); + const processId = response.substring(processIdStartIndex + processIdMarker.length, processIdEndIndex).trim(); + const name = response.substring(nameStartIndex + nameMarker.length, nameEndIndex).trim(); + const error = response.substring(errorStartIndex + errorMarker.length, errorEndIndex).trim(); + + return { + uri: vscode.Uri.parse(uri), + processID: processId, + name: name, + error: error, + }; + } else { + return { + uri: vscode.Uri.parse(""), + processID: "", + name: "", + error: response, + }; + } + }); + } else { + return []; + } + } +} + +export class DMNValidationResponseParser { + public static parse(json: any): DMNValidationResponse[] { + if (json && !json.details) { + return json as DMNValidationResponse[]; + } else { + return []; + } + } +} diff --git a/packages/extended-services-vscode-extension/src/local-service-manager.ts b/packages/extended-services-vscode-extension/src/local-service-manager.ts new file mode 100644 index 00000000000..83e6a48f048 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/local-service-manager.ts @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as childProcess from "child_process"; +import * as path from "path"; +import * as vscode from "vscode"; + +export class LocalServiceManager { + readonly startLocalServiceCommandUID: string = "extended-services-vscode-extension.startLocalService"; + readonly stopLocalServiceCommandUID: string = "extended-services-vscode-extension.stopLocalService"; + + private readonly relativePath: string = "/dist-dev/extended-services-java"; + private readonly jarFileName: string = "quarkus-run.jar"; + + private localServiceRunningHandler: LocalServiceRunningHandler | null = null; + private localServiceTerminatedHandler: LocalServiceTerminatedHandler | null = null; + + private context: vscode.ExtensionContext; + private startLocalServiceCommand: vscode.Disposable; + private stopLocalServiceCommand: vscode.Disposable; + private serviceProcess: childProcess.ChildProcess | undefined; + + constructor(context: vscode.ExtensionContext) { + this.context = context; + this.initializeCommands(); + } + + private initializeCommands(): void { + const startLocalServiceCommandHandler = (serviceURL: URL) => { + this.start(serviceURL); + }; + + const stopLocalServiceCommandHandler = () => { + this.stop(); + }; + + this.startLocalServiceCommand = vscode.commands.registerCommand( + this.startLocalServiceCommandUID, + startLocalServiceCommandHandler + ); + this.stopLocalServiceCommand = vscode.commands.registerCommand( + this.stopLocalServiceCommandUID, + stopLocalServiceCommandHandler + ); + + this.context.subscriptions.push(this.startLocalServiceCommand); + this.context.subscriptions.push(this.stopLocalServiceCommand); + } + + private fireLocalServicesRunningEvent() { + if (this.localServiceRunningHandler) { + this.localServiceRunningHandler(); + } + } + + private fireLocalServicesTerminatedEvent() { + if (this.localServiceTerminatedHandler) { + this.localServiceTerminatedHandler(); + } + } + + public subscribeLocalServicesRunning(handler: LocalServiceRunningHandler) { + this.localServiceRunningHandler = handler; + } + + public subscribeLocalServicesTerminated(handler: LocalServiceTerminatedHandler) { + this.localServiceTerminatedHandler = handler; + } + + public unsubscribeLocalServicesRunning() { + this.localServiceRunningHandler = null; + } + + public unsubscribeLocalServicesTerminated() { + this.localServiceTerminatedHandler = null; + } + + private runLocalService(serviceURL: URL): void { + const absolutePath = this.context.extensionPath; + const jarFilePath = path.join(absolutePath, this.relativePath, this.jarFileName); + const hostname = serviceURL.hostname; + const port = serviceURL.port; + const command = "java -jar -Dquarkus.http.host=" + hostname + " -Dquarkus.http.port=" + port + " " + jarFilePath; + + const options: childProcess.SpawnOptions = { + shell: true, + stdio: "pipe", + }; + + try { + this.serviceProcess = childProcess.spawn(command, options); + + if (this.serviceProcess.stdout) { + this.serviceProcess.stdout.on("data", (data) => { + const output = data.toString(); + if (output.includes("Listening on: " + serviceURL.origin)) { + this.fireLocalServicesRunningEvent(); + } + }); + } + + if (this.serviceProcess.stderr) { + this.serviceProcess.stderr.on("data", (data) => { + const errorOutput = data.toString(); + vscode.window.showErrorMessage(errorOutput); + }); + } + + this.serviceProcess.on("exit", (code, signal) => { + this.fireLocalServicesTerminatedEvent(); + }); + } catch (error) { + vscode.window.showErrorMessage("Error running local service: " + error.message); + } + } + + private terminateLocalService(): void { + if (this.serviceProcess) { + if (!this.serviceProcess.kill()) { + vscode.window.showErrorMessage("Local service failed to terminate."); + } + this.serviceProcess = undefined; + } + } + + private start(serviceURL: URL): void { + this.runLocalService(serviceURL); + } + + private stop(): void { + this.terminateLocalService(); + } + + public dispose(): void { + this.stop(); + this.startLocalServiceCommand.dispose(); + this.stopLocalServiceCommand.dispose(); + } +} + +interface LocalServiceRunningHandler { + (): void; +} + +interface LocalServiceTerminatedHandler { + (): void; +} diff --git a/packages/extended-services-vscode-extension/src/validation-helper.ts b/packages/extended-services-vscode-extension/src/validation-helper.ts new file mode 100644 index 00000000000..918239b31c3 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/validation-helper.ts @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { BPMNValidationResponse, DMNValidationResponse } from "./jit-executor/responses"; +import { JITCommands } from "./jit-executor/jit-commands"; +import { KIEFileWatcher } from "./watchers/kie-files/kie-file-watcher"; + +export class ValidationHelper { + readonly source = "Apache KIE Extended Services"; + readonly clearValidationCommandUID: string = "extended-services-vscode-extension.clearValidation"; + readonly validateCommandUID: string = "extended-services-vscode-extension.validate"; + + private context: vscode.ExtensionContext; + private clearValidationCommand: vscode.Disposable; + private validateCommand: vscode.Disposable; + private diagnosticCollection; + + constructor(context: vscode.ExtensionContext) { + this.context = context; + this.diagnosticCollection = vscode.languages.createDiagnosticCollection("KIE Files Diagnostics"); + this.initializeCommand(); + } + + private initializeCommand(): void { + const clearValidationCommandHandler = () => { + this.clearValidation(); + }; + + const validateCommandHandler = (serviceURL: URL) => { + this.validate(serviceURL); + }; + + this.clearValidationCommand = vscode.commands.registerCommand( + this.clearValidationCommandUID, + clearValidationCommandHandler + ); + this.validateCommand = vscode.commands.registerCommand(this.validateCommandUID, validateCommandHandler); + + this.context.subscriptions.push(this.validateCommand); + } + + private createBPMNDiagnostics(document: vscode.TextDocument, validationResponses: BPMNValidationResponse[]): void { + const diagnostics: vscode.Diagnostic[] = []; + + for (const validationResponse of validationResponses) { + const diagnostic = new vscode.Diagnostic( + new vscode.Range(0, 0, 0, 0), + validationResponse.error, + vscode.DiagnosticSeverity.Error + ); + diagnostic.source = this.source; + diagnostics.push(diagnostic); + } + + this.diagnosticCollection.set(document.uri, diagnostics); + } + + private createDMNDiagnostics(document: vscode.TextDocument, validationResponses: DMNValidationResponse[]): void { + const diagnostics: vscode.Diagnostic[] = []; + + for (const validationResponse of validationResponses) { + const diagnostic = new vscode.Diagnostic( + new vscode.Range(0, 0, 0, 0), + validationResponse.message, + vscode.DiagnosticSeverity.Error + ); + diagnostic.code = validationResponse.messageType; + diagnostic.source = this.source; + + diagnostics.push(diagnostic); + } + + this.diagnosticCollection.set(document.uri, diagnostics); + } + + private async validateBPMN(serviceURL: URL, documents: vscode.TextDocument[]): Promise { + for (const document of documents) { + try { + const validationResponses: BPMNValidationResponse[] = await JITCommands.validateBPMN(serviceURL, [document]); + this.createBPMNDiagnostics(document, validationResponses); + } catch (error) { + vscode.window.showErrorMessage("Validate BPMN error: " + error.message); + } + } + } + + private async validateDMN(serviceURL: URL, documents: vscode.TextDocument[]): Promise { + for (const document of documents) { + try { + const validationResponses: DMNValidationResponse[] = await JITCommands.validateDMN(serviceURL, [document]); + this.createDMNDiagnostics(document, validationResponses); + } catch (error) { + vscode.window.showErrorMessage("Validate DMN error: " + error.message); + } + } + } + + private async validate(serviceURL: URL): Promise { + const bpmnFiles: vscode.TextDocument[] = await KIEFileWatcher.findOpenBPMNFiles(); + const dmnFiles: vscode.TextDocument[] = await KIEFileWatcher.findOpenDMNFiles(); + + await this.validateBPMN(serviceURL, bpmnFiles); + await this.validateDMN(serviceURL, dmnFiles); + } + + private clearValidation(): void { + this.diagnosticCollection.clear(); + } + + public dispose(): void { + this.validateCommand.dispose(); + this.clearValidationCommand.dispose(); + } +} diff --git a/packages/extended-services-vscode-extension/src/watchers/configurations/configuration-watcher.ts b/packages/extended-services-vscode-extension/src/watchers/configurations/configuration-watcher.ts new file mode 100644 index 00000000000..ad21dea4071 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/watchers/configurations/configuration-watcher.ts @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { Configuration } from "./configuration"; + +export class ConfigurationWatcher { + private configurationChangedHandler: ConfigurationChangedHandler | null = null; + private configurationChangeListener: vscode.Disposable | undefined; + + constructor() { + this.configurationChangeListener = vscode.workspace.onDidChangeConfiguration(this.handleConfigurationChange, this); + } + + private handleConfigurationChange(configurationChange: vscode.ConfigurationChangeEvent) { + const autoRunChanged = configurationChange.affectsConfiguration(Configuration.autoRunConfigurationID); + const changedServiceURLChanged = configurationChange.affectsConfiguration(Configuration.serviceURLConfigurationID); + const changedConnectionHeartbeatIntervalChanged = configurationChange.affectsConfiguration( + Configuration.connectionHeartbeatIntervalConfigurationID + ); + if (autoRunChanged || changedServiceURLChanged || changedConnectionHeartbeatIntervalChanged) { + this.fireConfigurationChangedEvent(); + } + } + + private fireConfigurationChangedEvent() { + if (this.configurationChangedHandler) { + this.configurationChangedHandler(); + } + } + + public subscribeSettingsChanged(handler: ConfigurationChangedHandler) { + this.configurationChangedHandler = handler; + } + + public unsubscribeSettingsChanged() { + this.configurationChangedHandler = null; + } + + public dispose(): void { + if (this.configurationChangeListener) { + this.configurationChangeListener.dispose(); + } + this.unsubscribeSettingsChanged(); + } +} + +interface ConfigurationChangedHandler { + (): void; +} diff --git a/packages/extended-services-vscode-extension/src/watchers/configurations/configuration.ts b/packages/extended-services-vscode-extension/src/watchers/configurations/configuration.ts new file mode 100644 index 00000000000..060fecc879f --- /dev/null +++ b/packages/extended-services-vscode-extension/src/watchers/configurations/configuration.ts @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; + +export class Configuration { + static readonly autoRunConfigurationID: string = "extendedServices.enableAutorun"; + static readonly serviceURLConfigurationID: string = "extendedServices.serviceURL"; + static readonly connectionHeartbeatIntervalConfigurationID: string = "extendedServices.connectionHeartbeatInterval"; + + readonly autoRun: boolean; + readonly serviceURL: URL; + readonly connectionHeartbeatInterval: number; + + constructor(autoRun: boolean, serviceURL: URL, connectionHeartbeatInterval: number) { + this.autoRun = autoRun; + this.serviceURL = serviceURL; + this.connectionHeartbeatInterval = connectionHeartbeatInterval; + } + + private static fetchAutoRun(): boolean | undefined { + const autoRunConfig = vscode.workspace.getConfiguration().get(Configuration.autoRunConfigurationID); + if (autoRunConfig !== undefined) { + try { + return autoRunConfig; + } catch (error) { + vscode.window.showErrorMessage("Invalid Auto Run:" + error.message); + return undefined; + } + } else { + vscode.window.showErrorMessage("Auto Run configuration not found"); + return undefined; + } + } + + private static fetchServiceURL(): URL | undefined { + const serviceURLConfig = vscode.workspace.getConfiguration().get(Configuration.serviceURLConfigurationID); + if (serviceURLConfig !== undefined) { + try { + return new URL(serviceURLConfig); + } catch (error) { + vscode.window.showErrorMessage("Invalid service URL:" + error.message); + return undefined; + } + } else { + vscode.window.showErrorMessage("Service URL configuration not found"); + return undefined; + } + } + + private static fetchConnectionHeartbeatInterval(): number | undefined { + const connectionHeartbeatIntervalConfig = vscode.workspace + .getConfiguration() + .get(Configuration.connectionHeartbeatIntervalConfigurationID); + if (connectionHeartbeatIntervalConfig !== undefined) { + try { + return connectionHeartbeatIntervalConfig; + } catch (error) { + vscode.window.showErrorMessage("Invalid Heartbeat Interval: " + error.message); + return undefined; + } + } else { + vscode.window.showErrorMessage("Connection Heartbeat Interval configuration not found"); + return undefined; + } + } + + public static fetchConfiguration(): Configuration | undefined { + const autoRunConfig = Configuration.fetchAutoRun(); + const serviceURLConfig = Configuration.fetchServiceURL(); + const connectionHeartbeatIntervalConfig = Configuration.fetchConnectionHeartbeatInterval(); + if ( + autoRunConfig !== undefined && + serviceURLConfig !== undefined && + connectionHeartbeatIntervalConfig !== undefined + ) { + const configuration: Configuration = { + autoRun: autoRunConfig, + serviceURL: serviceURLConfig, + connectionHeartbeatInterval: connectionHeartbeatIntervalConfig, + }; + return configuration; + } else { + return undefined; + } + } +} diff --git a/packages/extended-services-vscode-extension/src/watchers/kie-files/kie-file-watcher.ts b/packages/extended-services-vscode-extension/src/watchers/kie-files/kie-file-watcher.ts new file mode 100644 index 00000000000..4fa6760ca1c --- /dev/null +++ b/packages/extended-services-vscode-extension/src/watchers/kie-files/kie-file-watcher.ts @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; +import { KIEFile } from "./kie-file"; + +export class KIEFileWatcher { + private kieFilesOpenedEventHandler: KIEFilesOpenedHandler | null; + private kieFilesClosedEventHandler: KIEFilesClosedHandler | null; + private kieFilesChangedEventHandler: KIEFilesChangedHandler | null; + + private tabChangeListener: vscode.Disposable | undefined; + private watchedKIEFiles: KIEFile[]; + + constructor() { + this.watchedKIEFiles = []; + this.tabChangeListener = vscode.window.tabGroups.onDidChangeTabs(this.updateOpenFiles, this); + this.updateOpenFiles(); + } + + private async updateOpenFiles() { + var watchedFilesUpdated = false; + var lastWatchedFilesCount = this.watchedKIEFiles.length; + + const openKIEFiles: vscode.TextDocument[] = await KIEFileWatcher.findOpenKIEFiles(); + + const kieFileToStopWatching: KIEFile[] = this.watchedKIEFiles.filter( + (watchedFile) => !openKIEFiles.some((openFile) => openFile.uri.fsPath === watchedFile.fsPath) + ); + + kieFileToStopWatching.forEach((kieFile) => { + const index = this.watchedKIEFiles.indexOf(kieFile); + this.watchedKIEFiles.splice(index, 1); + watchedFilesUpdated = true; + kieFile.dispose(); + }); + + const kieFilesToStartWatching: vscode.TextDocument[] = openKIEFiles.filter( + (openFile) => !this.watchedKIEFiles.some((watchedFile) => watchedFile.fsPath === openFile.uri.fsPath) + ); + + kieFilesToStartWatching.forEach((openFile) => { + const kieFile = new KIEFile(openFile); + kieFile.subscribeKIEFileChanged(() => { + this.fireKIEFilesChangedEvent(); + }); + this.watchedKIEFiles.push(kieFile); + watchedFilesUpdated = true; + }); + + if (watchedFilesUpdated) { + if (lastWatchedFilesCount == 0 && this.watchedKIEFiles.length > 0) { + this.fireKIEFilesOpenedEvent(); + } + if (lastWatchedFilesCount > 0 && this.watchedKIEFiles.length == 0) { + this.fireKIEFilesClosedEvent(); + } + this.fireKIEFilesChangedEvent(); + } + } + + private fireKIEFilesOpenedEvent() { + if (this.kieFilesOpenedEventHandler) { + this.kieFilesOpenedEventHandler(); + } + } + + private fireKIEFilesClosedEvent() { + if (this.kieFilesClosedEventHandler) { + this.kieFilesClosedEventHandler(); + } + } + + private fireKIEFilesChangedEvent() { + if (this.kieFilesChangedEventHandler) { + this.kieFilesChangedEventHandler(); + } + } + + public subscribeKIEFilesOpened(handler: KIEFilesOpenedHandler) { + this.kieFilesOpenedEventHandler = handler; + } + + public subscribeKIEFilesClosed(handler: KIEFilesClosedHandler) { + this.kieFilesClosedEventHandler = handler; + } + + public subscribeKIEFilesChanged(handler: KIEFilesChangedHandler) { + this.kieFilesChangedEventHandler = handler; + } + + public unsubscribeKIEFilesOpened() { + this.kieFilesClosedEventHandler = null; + } + + public unsubscribeKIEFilesClosed() { + this.kieFilesClosedEventHandler = null; + } + + public unsubscribeKIEFilesChanged() { + this.kieFilesChangedEventHandler = null; + } + + public dispose(): void { + this.tabChangeListener?.dispose(); + this.unsubscribeKIEFilesOpened(); + this.unsubscribeKIEFilesClosed(); + this.unsubscribeKIEFilesChanged(); + } + + private static async findOpenFiles(documentSelectors: vscode.DocumentSelector): Promise { + const tabGroups = vscode.window.tabGroups.all; + + const foundDocuments: vscode.TextDocument[] = []; + for (const tabGroup of tabGroups) { + for (const tab of tabGroup.tabs) { + if (tab.input instanceof vscode.TabInputCustom || tab.input instanceof vscode.TabInputText) { + const textDocument: vscode.TextDocument = await vscode.workspace.openTextDocument(tab.input.uri); + if (vscode.languages.match(documentSelectors, textDocument) > 0) { + foundDocuments.push(textDocument); + } + } + } + } + + return foundDocuments; + } + + public static async findOpenBPMNFiles(): Promise { + const bpmnDocumentFilter: vscode.DocumentSelector = { + language: "bpmn", + scheme: "file", + }; + + return KIEFileWatcher.findOpenFiles(bpmnDocumentFilter); + } + + public static async findOpenDMNFiles(): Promise { + const dmnDocumentFilter: vscode.DocumentSelector = { + language: "dmn", + scheme: "file", + }; + + return KIEFileWatcher.findOpenFiles(dmnDocumentFilter); + } + + public static async findOpenKIEFiles(): Promise { + const bpmnFiles = await KIEFileWatcher.findOpenBPMNFiles(); + const dmnFiles = await KIEFileWatcher.findOpenDMNFiles(); + + const openKieFiles: vscode.TextDocument[] = [...bpmnFiles, ...dmnFiles]; + + return openKieFiles; + } +} + +interface KIEFilesOpenedHandler { + (): void; +} + +interface KIEFilesClosedHandler { + (): void; +} + +interface KIEFilesChangedHandler { + (): void; +} diff --git a/packages/extended-services-vscode-extension/src/watchers/kie-files/kie-file.ts b/packages/extended-services-vscode-extension/src/watchers/kie-files/kie-file.ts new file mode 100644 index 00000000000..93f38178a76 --- /dev/null +++ b/packages/extended-services-vscode-extension/src/watchers/kie-files/kie-file.ts @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as vscode from "vscode"; + +export class KIEFile { + public readonly fsPath: string; + + private kieFileChangedEventHandler: KIEFileChangedHandler | null; + private fileWatcher: vscode.FileSystemWatcher; + + constructor(textDocument: vscode.TextDocument) { + this.fsPath = textDocument.uri.fsPath; + this.fileWatcher = vscode.workspace.createFileSystemWatcher(this.fsPath); + this.fileWatcher.onDidChange(this.fireKIEFileChangedEvent, this); + } + + public subscribeKIEFileChanged(handler: KIEFileChangedHandler) { + this.kieFileChangedEventHandler = handler; + } + + private fireKIEFileChangedEvent() { + if (this.kieFileChangedEventHandler) { + this.kieFileChangedEventHandler(); + } + } + + public unsubscribeKIEFileChanged() { + this.kieFileChangedEventHandler = null; + } + + public dispose() { + this.unsubscribeKIEFileChanged(); + this.fileWatcher.dispose(); + } +} + +interface KIEFileChangedHandler { + (): void; +} diff --git a/packages/extended-services-vscode-extension/static/extended-services-connected.svg b/packages/extended-services-vscode-extension/static/extended-services-connected.svg new file mode 100644 index 00000000000..606a4b36675 --- /dev/null +++ b/packages/extended-services-vscode-extension/static/extended-services-connected.svg @@ -0,0 +1,6 @@ + + + diff --git a/packages/extended-services-vscode-extension/static/extended-services-disconnected.svg b/packages/extended-services-vscode-extension/static/extended-services-disconnected.svg new file mode 100644 index 00000000000..6ccaf9225db --- /dev/null +++ b/packages/extended-services-vscode-extension/static/extended-services-disconnected.svg @@ -0,0 +1,6 @@ + + + diff --git a/packages/extended-services-vscode-extension/static/extended-services-font.woff b/packages/extended-services-vscode-extension/static/extended-services-font.woff new file mode 100644 index 00000000000..0a2894792e4 Binary files /dev/null and b/packages/extended-services-vscode-extension/static/extended-services-font.woff differ diff --git a/packages/extended-services-vscode-extension/tsconfig.json b/packages/extended-services-vscode-extension/tsconfig.json new file mode 100644 index 00000000000..3609d3e6a64 --- /dev/null +++ b/packages/extended-services-vscode-extension/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@kie-tools/tsconfig/tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "declaration": false, + "declarationMap": false + }, + "include": ["src"] +} diff --git a/packages/extended-services-vscode-extension/webpack.config.js b/packages/extended-services-vscode-extension/webpack.config.js new file mode 100644 index 00000000000..3d9f05537b0 --- /dev/null +++ b/packages/extended-services-vscode-extension/webpack.config.js @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const { merge } = require("webpack-merge"); +const common = require("@kie-tools-core/webpack-base/webpack.common.config"); + +const commonConfig = (env) => + merge(common(env), { + output: { + library: "ExtendedServices", + libraryTarget: "umd", + umdNamedDefine: true, + globalObject: "this", + }, + externals: { + vscode: "commonjs vscode", + }, + plugins: [], + }); + +module.exports = async (env) => [ + merge(commonConfig(env), { + target: "node", + entry: { + "extension/extension-main": "./src/extension/extension-main.ts", + }, + }), + merge(commonConfig(env), { + target: "web", + entry: { + "extension/extension-browser": "./src/extension/extension-browser.ts", + }, + }), +]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5f21896cf6..e53e046674c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4235,6 +4235,58 @@ importers: specifier: ^1.1.6 version: 1.1.6 + packages/extended-services-vscode-extension: + dependencies: + "@kie-tools-core/vscode-extension": + specifier: workspace:* + version: link:../vscode-extension + "@kie-tools/extended-services-java": + specifier: workspace:* + version: link:../extended-services-java + devDependencies: + "@kie-tools-core/webpack-base": + specifier: workspace:* + version: link:../webpack-base + "@kie-tools/eslint": + specifier: workspace:* + version: link:../eslint + "@kie-tools/root-env": + specifier: workspace:* + version: link:../root-env + "@kie-tools/tsconfig": + specifier: workspace:* + version: link:../tsconfig + "@types/vscode": + specifier: 1.67.0 + version: 1.67.0 + "@vscode/test-web": + specifier: ^0.0.30 + version: 0.0.30 + "@vscode/vsce": + specifier: ^2.22.0 + version: 2.22.0 + copy-webpack-plugin: + specifier: ^11.0.0 + version: 11.0.0(webpack@5.88.2) + node-fetch: + specifier: ^3.3.1 + version: 3.3.1 + rimraf: + specifier: ^3.0.2 + version: 3.0.2 + webpack: + specifier: ^5.88.2 + version: 5.88.2(webpack-cli@4.10.0) + webpack-cli: + specifier: ^4.10.0 + version: 4.10.0(webpack-dev-server@4.15.1)(webpack@5.88.2) + webpack-dev-server: + specifier: ^4.15.1 + version: 4.15.1(webpack-cli@4.10.0)(webpack@5.88.2) + webpack-merge: + specifier: ^5.9.0 + version: 5.9.0 + packages/feel-input-component: dependencies: "@kie-tools-core/i18n": @@ -9582,7 +9634,7 @@ importers: version: 5.88.2(webpack-cli@4.10.0) webpack-dev-server: specifier: ^4.15.1 - version: 4.15.1(webpack@5.88.2) + version: 4.15.1(webpack-cli@4.10.0)(webpack@5.88.2) webpack-merge: specifier: ^5.9.0 version: 5.9.0 @@ -19123,6 +19175,7 @@ packages: resolution: { integrity: sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw== } engines: { node: ">= 8.0.0" } + deprecated: "**IMPORTANT 10x+ PERFORMANCE UPGRADE**: Please upgrade to v12.0.1+ as we have fixed an issue with debuglog causing 10x slower router benchmark performance, see https://github.com/koajs/router/pull/173" dependencies: debug: 4.3.4(supports-color@8.1.1) http-errors: 1.8.1 @@ -26986,7 +27039,7 @@ packages: engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } dependencies: bytes: 3.1.2 - content-type: 1.0.4 + content-type: 1.0.5 debug: 2.6.9 depd: 2.0.0 destroy: 1.2.0 @@ -28337,7 +28390,6 @@ packages: resolution: { integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== } engines: { node: ">= 0.6" } - dev: true /convert-source-map@1.7.0: resolution: @@ -35976,7 +36028,7 @@ packages: accepts: 1.3.8 cache-content-type: 1.0.1 content-disposition: 0.5.4 - content-type: 1.0.4 + content-type: 1.0.5 cookies: 0.8.0 debug: 4.3.4(supports-color@8.1.1) delegates: 1.0.0 @@ -36844,6 +36896,7 @@ packages: resolution: { integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== } engines: { node: ">=10" } + requiresBuild: true /mimic-response@4.0.0: resolution: @@ -41344,7 +41397,7 @@ packages: { integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== } hasBin: true dependencies: - is-core-module: 2.12.0 + is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -45349,58 +45402,6 @@ packages: - utf-8-validate dev: true - /webpack-dev-server@4.15.1(webpack@5.88.2): - resolution: - { integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA== } - engines: { node: ">= 12.13.0" } - hasBin: true - peerDependencies: - webpack: ^4.37.0 || ^5.0.0 - webpack-cli: "*" - peerDependenciesMeta: - webpack: - optional: true - webpack-cli: - optional: true - dependencies: - "@types/bonjour": 3.5.10 - "@types/connect-history-api-fallback": 1.3.5 - "@types/express": 4.17.17 - "@types/serve-index": 1.9.1 - "@types/serve-static": 1.13.10 - "@types/sockjs": 0.3.33 - "@types/ws": 8.5.5 - ansi-html-community: 0.0.8 - bonjour-service: 1.1.1 - chokidar: 3.5.3 - colorette: 2.0.20 - compression: 1.7.4 - connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 - express: 4.18.2 - graceful-fs: 4.2.11 - html-entities: 2.3.2 - http-proxy-middleware: 2.0.6(@types/express@4.17.17) - ipaddr.js: 2.0.1 - launch-editor: 2.6.0 - open: 8.4.0 - p-retry: 4.6.1 - rimraf: 3.0.2 - schema-utils: 4.0.0 - selfsigned: 2.1.1 - serve-index: 1.9.1 - sockjs: 0.3.24 - spdy: 4.0.2 - webpack: 5.88.2(webpack-cli@4.10.0) - webpack-dev-middleware: 5.3.3(webpack@5.88.2) - ws: 8.14.2 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - dev: true - /webpack-hot-middleware@2.25.4: resolution: { integrity: sha512-IRmTspuHM06aZh98OhBJtqLpeWFM8FXJS5UYpKYxCJzyFoyWj1w6VGFfomZU7OPA55dMLrQK0pRT1eQ3PACr4w== } diff --git a/repo/graph.dot b/repo/graph.dot index 30d6dff5996..9507110ab26 100644 --- a/repo/graph.dot +++ b/repo/graph.dot @@ -97,7 +97,8 @@ digraph G { "@kie-tools-core/keyboard-shortcuts" [ color = "purple", fontcolor = "purple", style = "rounded" ]; "@kie-tools-core/envelope-bus" [ color = "purple", fontcolor = "purple", style = "rounded" ]; "@kie-tools/extended-services" [ color = "black", fontcolor = "black", style = "dashed, rounded" ]; - "@kie-tools/extended-services-java" [ color = "black", fontcolor = "black", style = "dashed, rounded" ]; + "@kie-tools/extended-services-java" [ color = "blue", fontcolor = "blue", style = "rounded" ]; + "extended-services-vscode-extension" [ color = "blue", fontcolor = "blue", style = "rounded" ]; "@kie-tools-core/monaco-editor" [ color = "purple", fontcolor = "purple", style = "rounded" ]; "@kie-tools/form" [ color = "blue", fontcolor = "blue", style = "rounded" ]; "@kie-tools/form-generation-tool" [ color = "blue", fontcolor = "blue", style = "rounded" ]; @@ -310,8 +311,11 @@ digraph G { "@kie-tools-core/envelope-bus" -> "@kie-tools/tsconfig" [ style = "dashed", color = "purple" ]; "@kie-tools/extended-services" -> "@kie-tools/root-env" [ style = "dashed", color = "black" ]; "@kie-tools/extended-services-api" -> "@kie-tools-core/notifications" [ style = "solid", color = "blue" ]; - "@kie-tools/extended-services-java" -> "@kie-tools/maven-config-setup-helper" [ style = "dashed", color = "black" ]; - "@kie-tools/extended-services-java" -> "@kie-tools/root-env" [ style = "dashed", color = "black" ]; + "@kie-tools/extended-services-java" -> "@kie-tools/maven-config-setup-helper" [ style = "dashed", color = "blue" ]; + "@kie-tools/extended-services-java" -> "@kie-tools/root-env" [ style = "dashed", color = "blue" ]; + "extended-services-vscode-extension" -> "@kie-tools-core/vscode-extension" [ style = "solid", color = "blue" ]; + "extended-services-vscode-extension" -> "@kie-tools/extended-services-java" [ style = "solid", color = "blue" ]; + "extended-services-vscode-extension" -> "@kie-tools-core/webpack-base" [ style = "dashed", color = "blue" ]; "@kie-tools/feel-input-component" -> "@kie-tools-core/monaco-editor" [ style = "solid", color = "blue" ]; "@kie-tools/feel-input-component" -> "@kie-tools-core/patternfly-base" [ style = "solid", color = "blue" ]; "@kie-tools/feel-input-component" -> "@kie-tools/dmn-language-service" [ style = "solid", color = "blue" ]; diff --git a/repo/graph.json b/repo/graph.json index 3440aac19f1..85f28b5c4f3 100644 --- a/repo/graph.json +++ b/repo/graph.json @@ -109,6 +109,7 @@ { "id": "dmn-vscode-extension" }, { "id": "@kie-tools/extended-services" }, { "id": "@kie-tools/extended-services-java" }, + { "id": "extended-services-vscode-extension" }, { "id": "@kie-tools/form-generation-tool" }, { "id": "@kie-tools/uniforms-bootstrap4-codegen" }, { "id": "@kie-tools/uniforms-patternfly-codegen" }, @@ -684,6 +685,9 @@ { "source": "@kie-tools/extended-services", "target": "@kie-tools/root-env", "weight": 1 }, { "source": "@kie-tools/extended-services-java", "target": "@kie-tools/maven-config-setup-helper", "weight": 1 }, { "source": "@kie-tools/extended-services-java", "target": "@kie-tools/root-env", "weight": 1 }, + { "source": "extended-services-vscode-extension", "target": "@kie-tools-core/vscode-extension", "weight": 1 }, + { "source": "extended-services-vscode-extension", "target": "@kie-tools/extended-services-java", "weight": 1 }, + { "source": "extended-services-vscode-extension", "target": "@kie-tools-core/webpack-base", "weight": 1 }, { "source": "@kie-tools/form-generation-tool", "target": "@kie-tools/uniforms-bootstrap4-codegen", "weight": 1 }, { "source": "@kie-tools/form-generation-tool", "target": "@kie-tools/uniforms-patternfly-codegen", "weight": 1 }, { "source": "@kie-tools/uniforms-bootstrap4-codegen", "target": "@kie-tools-core/webpack-base", "weight": 1 }, @@ -1056,6 +1060,7 @@ ["@kie-tools/extended-services", "packages/extended-services"], ["@kie-tools/extended-services-api", "packages/extended-services-api"], ["@kie-tools/extended-services-java", "packages/extended-services-java"], + ["extended-services-vscode-extension", "packages/extended-services-vscode-extension"], ["@kie-tools/feel-input-component", "packages/feel-input-component"], ["@kie-tools/form", "packages/form"], ["@kie-tools/form-dmn", "packages/form-dmn"],