This is an automated email from the ASF dual-hosted git repository. mgubaidullin pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
commit dde1dd3bf679452d115a3ee9033cd69e7bc3e9c5 Author: Marat Gubaidullin <[email protected]> AuthorDate: Mon Aug 24 12:47:09 2026 -0400 vscode cleanup --- karavan-vscode/.eslintrc.json | 31 ------------ karavan-vscode/.vscodeignore | 32 ++++++++++-- karavan-vscode/eslint.config.mjs | 73 ++++++++++++++++++++++++++++ karavan-vscode/package.json | 67 +++++++++++++------------ karavan-vscode/src/extension.ts | 16 +++--- karavan-vscode/tsconfig.json | 11 +++-- karavan-vscode/webpack.config.js | 35 ++++++++----- karavan-vscode/webview/acquireVsCodeApi.d.ts | 12 ++++- karavan-vscode/webview/vscode.ts | 15 ++++-- 9 files changed, 197 insertions(+), 95 deletions(-) diff --git a/karavan-vscode/.eslintrc.json b/karavan-vscode/.eslintrc.json deleted file mode 100644 index d541ada7..00000000 --- a/karavan-vscode/.eslintrc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "node": true - }, - "extends": [ -// "eslint:recommended", -// "plugin:react/recommended", -// "plugin:@typescript-eslint/recommended", -// "plugin:prettier/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 12, - "sourceType": "module" - }, - "settings": { - "react": { - "version": "detect" - } - }, - "ignorePatterns": ["out", "dist", "**/*.d.ts"], - "plugins": ["react", "@typescript-eslint"], - "rules": { - "@typescript-eslint/explicit-module-boundary-types": "off" - } -} diff --git a/karavan-vscode/.vscodeignore b/karavan-vscode/.vscodeignore index f94e7243..093fe431 100644 --- a/karavan-vscode/.vscodeignore +++ b/karavan-vscode/.vscodeignore @@ -1,15 +1,39 @@ +# --- Dev-only tooling and configuration ------------------------------------- .vscode/** .vscode-test/** -out/** -node_modules/** -src/** +.vscode-test-web/** +.idea/** +.DS_Store .gitignore .yarnrc +.prettierignore +.task.md +.task_report.md +AGENT.md vsc-extension-quickstart.md +webpack.config.js +eslint.config.mjs +package-lock.json **/tsconfig.json **/.eslintrc.json -**/*.map +*.vsix + +# --- Sources (everything ships pre-bundled in dist/) ------------------------ +out/** +src/** +webview/** +node_modules/** **/*.ts +**/*.tsx +**/*.map + +# --- Build artifacts that are not needed at runtime ------------------------- +# prerender.js is an SSR helper used at build time only. dist/prerender.js dist/*.prerender.js dist/*.prerender.js.* +# CopyPlugin duplicates metadata/ into dist/ for the prerender build; the +# extension host reads it from <extensionPath>/metadata, so the copy is dead weight. +dist/metadata/** +# Emitted only because MiniCssExtractPlugin runs in the node-target configs; unused at runtime. +dist/ignore.css diff --git a/karavan-vscode/eslint.config.mjs b/karavan-vscode/eslint.config.mjs new file mode 100644 index 00000000..9ca3fd2d --- /dev/null +++ b/karavan-vscode/eslint.config.mjs @@ -0,0 +1,73 @@ +/* + * 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 js from "@eslint/js"; +import globals from "globals"; +import tsParser from "@typescript-eslint/parser"; +import tsPlugin from "@typescript-eslint/eslint-plugin"; +import reactPlugin from "eslint-plugin-react"; + +export default [ + { + ignores: [ + "out/**", + "dist/**", + "node_modules/**", + "**/*.d.ts", + // Vendored copy of karavan-core - maintained upstream, not linted here. + "webview/karavan-core/**", + ], + }, + js.configs.recommended, + { + files: ["**/*.ts", "**/*.tsx"], + languageOptions: { + parser: tsParser, + ecmaVersion: 2022, + sourceType: "module", + parserOptions: { ecmaFeatures: { jsx: true } }, + globals: { ...globals.browser, ...globals.node }, + }, + plugins: { + "@typescript-eslint": tsPlugin, + react: reactPlugin, + }, + settings: { react: { version: "detect" } }, + rules: { + // TypeScript already reports these; the base rules produce false positives on TS syntax. + "no-undef": "off", + "no-unused-vars": "off", + "no-redeclare": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", + { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, + ], + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-explicit-any": "warn", + "react/jsx-key": "warn", + "react/jsx-uses-react": "error", + "react/jsx-uses-vars": "error", + }, + }, + { + files: ["**/*.js", "**/*.cjs"], + languageOptions: { + ecmaVersion: 2022, + sourceType: "commonjs", + globals: { ...globals.node }, + }, + }, +]; diff --git a/karavan-vscode/package.json b/karavan-vscode/package.json index 36c6e068..d6d0cec4 100644 --- a/karavan-vscode/package.json +++ b/karavan-vscode/package.json @@ -39,22 +39,7 @@ "Camel Yaml", "JBang" ], - "activationEvents": [ - "onCommand:karavan.create-yaml", - "onCommand:karavan.create-kamelet", - "onCommand:karavan.create-application", - "onCommand:karavan.deploy", - "onCommand:karavan.open", - "onCommand:karavan.open-file", - "onCommand:karavan.run-project-jbang", - "onCommand:karavan.run-project-runtime", - "onCommand:karavan.jbang-export", - "onCommand:karavan.generate-rest", - "onCommand:karavan.download-image", - "onCommand:karavan.openKnowledgebase", - "onCommand:karavan.reportIssue", - "onView:integrations" - ], + "activationEvents": [], "main": "./dist/extension.js", "browser": "./dist/extension.js", "contributes": { @@ -501,7 +486,25 @@ } ], "menus": { - "explorer/context": [ + "commandPalette": [ + { + "command": "karavan.open", + "when": "false" + }, + { + "command": "karavan.open-file", + "when": "false" + }, + { + "command": "karavan.download-image", + "when": "false" + }, + { + "command": "karavan.generate-rest", + "when": "false" + } + ], + "explorer/context": [ { "command": "karavan.create-yaml", "when": "explorerResourceIsFolder || explorerResourceIsRoot", @@ -514,7 +517,7 @@ }, { "command": "karavan.topology", - "when": "explorerResourceIsFolder || explorerResourceIsRoot || resourceFilename =~ /.camel.yaml$/", + "when": "explorerResourceIsFolder || explorerResourceIsRoot || resourceFilename =~ /\\.camel\\.yaml$/", "group": "karavan@1" }, { @@ -524,7 +527,7 @@ }, { "command": "karavan.open", - "when": "resourceFilename =~ /.camel.yaml$/ || resourceFilename =~ /.kamelet.yaml$/", + "when": "resourceFilename =~ /\\.camel\\.yaml$/ || resourceFilename =~ /\\.kamelet\\.yaml$/", "group": "karavan@4" }, { @@ -556,17 +559,17 @@ "editor/title": [ { "command": "karavan.open", - "when": "resourceFilename =~ /.camel.yaml$/ || resourceFilename =~ /.kamelet.yaml$/", + "when": "resourceFilename =~ /\\.camel\\.yaml$/ || resourceFilename =~ /\\.kamelet\\.yaml$/", "group": "navigation@1" }, { "command": "karavan.run-project-jbang", - "when": "resourceFilename =~ /.camel.yaml$/ || karavan:loaded", + "when": "resourceFilename =~ /\\.camel\\.yaml$/ || karavan:loaded", "group": "navigation@4" }, { "command": "karavan.run-project-runtime", - "when": "resourceFilename =~ /.camel.yaml$/ || karavan:loaded", + "when": "resourceFilename =~ /\\.camel\\.yaml$/ || karavan:loaded", "group": "navigation@5" }, { @@ -661,16 +664,18 @@ ] }, "scripts": { - "vscode:prepublish": "npm run && npm run package", - "compile": "npm run && cross-env NODE_ENV=development node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress --stats-error-details", - "watch": "npm run && cross-env NODE_ENV=development node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress --watch", - "package": "npm run && cross-env NODE_ENV=production node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress", + "vscode:prepublish": "npm run clean && npm run package", + "clean": "node -e \"require('fs').rmSync('dist', {recursive: true, force: true})\"", + "compile": "cross-env NODE_ENV=development node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress --stats-error-details", + "watch": "cross-env NODE_ENV=development node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress --watch", + "package": "cross-env NODE_ENV=production node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress", "webpack": "cross-env NODE_ENV=development node --max-old-space-size=8192 ./node_modules/webpack/bin/webpack.js --progress", - "test-compile": "tsc -p ./", - "test-watch": "tsc -watch -p ./", - "pretest": "npm run && npm run test-compile && npm run lint", - "lint": "eslint src webview --ext .ts,.tsx", - "lint:fix": "eslint --fix src webview --ext .ts,.tsx", + "typecheck": "tsc -p . --noEmit", + "test-compile": "tsc -p . --noEmit", + "test-watch": "tsc -p . --noEmit --watch", + "pretest": "npm run test-compile && npm run lint", + "lint": "eslint src webview", + "lint:fix": "eslint --fix src webview", "test": "node ./out/test/runTest.js", "open-in-browser": "vscode-test-web --extensionDevelopmentPath=. ../karavan-demo/hello-world/" }, diff --git a/karavan-vscode/src/extension.ts b/karavan-vscode/src/extension.ts index 3a8a8e94..af60c384 100644 --- a/karavan-vscode/src/extension.ts +++ b/karavan-vscode/src/extension.ts @@ -24,7 +24,6 @@ import * as jbang from "./jbang"; import * as utils from "./utils"; import * as exec from "./exec"; import { TopologyView } from './topologyView'; -import vscode from "webview/vscode"; const KARAVAN_LOADED = "karavan:loaded"; @@ -37,16 +36,16 @@ export function activate(context: ExtensionContext) { const designer = new DesignerView(context, rootPath); const integrationView = new IntegrationView(designer, rootPath); - window.registerTreeDataProvider('integrations', integrationView); - commands.registerCommand('integrations.refresh', () => integrationView.refresh()); + context.subscriptions.push(window.registerTreeDataProvider('integrations', integrationView)); + context.subscriptions.push(commands.registerCommand('integrations.refresh', () => integrationView.refresh())); const openapiView = new OpenApiView(designer, rootPath); - window.registerTreeDataProvider('openapi', openapiView); - commands.registerCommand('openapi.refresh', () => openapiView.refresh()); + context.subscriptions.push(window.registerTreeDataProvider('openapi', openapiView)); + context.subscriptions.push(commands.registerCommand('openapi.refresh', () => openapiView.refresh())); const helpView = new HelpView(context); - window.registerTreeDataProvider('help', helpView); - commands.registerCommand('karavan.openKnowledgebase', () => helpView.openKaravanWebView("knowledgebase")); + context.subscriptions.push(window.registerTreeDataProvider('help', helpView)); + context.subscriptions.push(commands.registerCommand('karavan.openKnowledgebase', () => helpView.openKaravanWebView("knowledgebase"))); const topologyView = new TopologyView(context); const topologyCommand = commands.registerCommand("karavan.topology", (...args: any[]) => { @@ -168,9 +167,10 @@ export function activate(context: ExtensionContext) { context.subscriptions.push(downloadImageCommand); // Create issue command - commands.registerCommand('karavan.reportIssue', () => { + const reportIssue = commands.registerCommand('karavan.reportIssue', () => { env.openExternal(Uri.parse('https://github.com/apache/camel-karavan/issues/new?title=[VS+Code]New+report&template=issue_template.md')); }); + context.subscriptions.push(reportIssue); } /** diff --git a/karavan-vscode/tsconfig.json b/karavan-vscode/tsconfig.json index 133f9d21..2d15d985 100644 --- a/karavan-vscode/tsconfig.json +++ b/karavan-vscode/tsconfig.json @@ -38,10 +38,11 @@ "skipLibCheck": true }, "include": [ - "**/*.ts", - "**/*.tsx", - "**/*.jsx", - "**/*.js" + "src/**/*.ts", + "webview/**/*.ts", + "webview/**/*.tsx", + "webview/**/*.jsx", + "webview/**/*.js" ], - "exclude": ["node_modules", ".vscode-test"] + "exclude": ["node_modules", "dist", "out", ".vscode-test", "webpack.config.js"] } diff --git a/karavan-vscode/webpack.config.js b/karavan-vscode/webpack.config.js index 4d6d30c9..6e750b37 100644 --- a/karavan-vscode/webpack.config.js +++ b/karavan-vscode/webpack.config.js @@ -13,16 +13,29 @@ const imageInlineSizeLimit = parseInt( process.env.IMAGE_INLINE_SIZE_LIMIT || "10000" ); -const baseConfig = (webpackEnv) => { - const isEnvDevelopment = webpackEnv === "development"; - const isEnvProduction = webpackEnv === "production"; +// Webpack invokes an exported config function with (env, argv), where `env` holds the +// `--env` flags - not NODE_ENV. Read the mode from NODE_ENV (set by the npm scripts) and +// fall back to `argv.mode` / production so `mode` is never left unset. +const resolveMode = (webpackEnv, argv) => + process.env.NODE_ENV === "development" || argv?.mode === "development" + ? "development" + : "production"; + +const baseConfig = (webpackEnv, argv) => { + const mode = resolveMode(webpackEnv, argv); + const isEnvDevelopment = mode === "development"; + const isEnvProduction = mode === "production"; return { - mode: isEnvProduction ? "production" : isEnvDevelopment && "development", + mode, bail: isEnvProduction, devtool: isEnvProduction ? "source-map" - : isEnvDevelopment && "eval-cheap-module-source-map", + : "eval-cheap-module-source-map", + cache: { + type: "filesystem", + buildDependencies: { config: [__filename] }, + }, resolve: { plugins: [new TsconfigPathsPlugin({ configFile: "./tsconfig.json" })], fallback: { @@ -94,9 +107,9 @@ const baseConfig = (webpackEnv) => { }; }; -const extensionConfig = (webpackEnv) => { +const extensionConfig = (webpackEnv, argv) => { return { - ...baseConfig(webpackEnv), + ...baseConfig(webpackEnv, argv), target: "node", entry: "./src/extension.ts", output: { @@ -108,9 +121,9 @@ const extensionConfig = (webpackEnv) => { }; }; -const webviewConfig = (webpackEnv) => { +const webviewConfig = (webpackEnv, argv) => { return { - ...baseConfig(webpackEnv), + ...baseConfig(webpackEnv, argv), entry: "./webview/index.tsx", output: { path: path.resolve(__dirname, "dist"), @@ -126,9 +139,9 @@ const webviewConfig = (webpackEnv) => { }; }; -const prerenderConfig = (webpackEnv) => { +const prerenderConfig = (webpackEnv, argv) => { return { - ...baseConfig(webpackEnv), + ...baseConfig(webpackEnv, argv), target: "node", entry: "./webview/prerender.tsx", output: { diff --git a/karavan-vscode/webview/acquireVsCodeApi.d.ts b/karavan-vscode/webview/acquireVsCodeApi.d.ts index bbfd1238..7c5c6345 100644 --- a/karavan-vscode/webview/acquireVsCodeApi.d.ts +++ b/karavan-vscode/webview/acquireVsCodeApi.d.ts @@ -13,4 +13,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -declare var acquireVsCodeApi: any; +/** + * The API object injected into every VS Code webview. + * See https://code.visualstudio.com/api/extension-guides/webview + */ +interface VsCodeApi { + postMessage(message: unknown): void; + getState<T = unknown>(): T | undefined; + setState<T>(state: T): T; +} + +declare function acquireVsCodeApi(): VsCodeApi; diff --git a/karavan-vscode/webview/vscode.ts b/karavan-vscode/webview/vscode.ts index 2ab70a0b..c0a91a1c 100644 --- a/karavan-vscode/webview/vscode.ts +++ b/karavan-vscode/webview/vscode.ts @@ -14,9 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -let vscode; -if (typeof acquireVsCodeApi !== "undefined") { - vscode = acquireVsCodeApi(); -} +// `acquireVsCodeApi` only exists inside a VS Code webview. The prerender build runs the +// same components under Node, so fall back to a no-op implementation instead of exporting +// `undefined` (which every caller would otherwise have to null-check). +const noopVsCodeApi: VsCodeApi = { + postMessage: () => undefined, + getState: () => undefined, + setState: (state) => state, +}; + +const vscode: VsCodeApi = + typeof acquireVsCodeApi !== "undefined" ? acquireVsCodeApi() : noopVsCodeApi; export default vscode;
