diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..a55c274 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + "@typescript-eslint/naming-convention": "warn", + "@typescript-eslint/semi": "warn", + "curly": "warn", + "eqeqeq": "warn", + "no-throw-literal": "warn", + "semi": "off" + }, + "ignorePatterns": ["out", "dist", "**/*.d.ts"] + } \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ac2d86e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,23 @@ +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/out +/build +/dist + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..cbe73bf --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "quoteProps": "consistent", + "jsxSingleQuote": false, + "trailingComma": "es5", + "bracketSpacing": true, + "jsxBracketSameLine": true, + "arrowParens": "always" +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index acf1aa2..ce7160a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,18 +4,14 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 { "version": "0.2.0", - "configurations": [{ - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], - "preLaunchTask":"npm: dev" - } + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/out/**/*.js"], + "preLaunchTask": "${defaultBuildTask}" + } ] -} + } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 554aba6..822f489 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,18 +2,19 @@ // for the documentation about the tasks.json format { "version": "2.0.0", - "tasks": [{ + "tasks": [ + { "type": "npm", - "script": "dev", + "script": "compile", "problemMatcher": "$tsc-watch", "isBackground": true, "presentation": { - "reveal": "never" + "reveal": "never" }, "group": { - "kind": "build", - "isDefault": true + "kind": "build", + "isDefault": true } - } + } ] -} \ No newline at end of file + } \ No newline at end of file diff --git a/.vscodeignore b/.vscodeignore index cb54238..6a35be4 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,6 +1,19 @@ -# dist -src -out -node_modules -.vscode +# src +# out +# node_modules +# .vscode + +.vscode/** +.vscode-test/** +# out/** +node_modules/** +src/** +esbuild.js +.gitignore +.yarnrc +vsc-extension-quickstart.md +**/tsconfig.json +**/.eslintrc.json +**/*.map +**/*.ts diff --git a/esbuild.js b/esbuild.js index 896f9c6..b6b7b7f 100644 --- a/esbuild.js +++ b/esbuild.js @@ -1,54 +1,116 @@ -const esbuild = require('esbuild'); +const { build } = require("esbuild"); +const { copy } = require("esbuild-plugin-copy"); +//@ts-check +/** @typedef {import('esbuild').BuildOptions} BuildOptions **/ -const production = process.argv.includes('--production'); -const watch = process.argv.includes('--watch'); +/** @type BuildOptions */ +const baseConfig = { + bundle: true, + minify: process.env.NODE_ENV === "production", + sourcemap: process.env.NODE_ENV !== "production", +}; -async function main() { - const ctx = await esbuild.context({ - entryPoints: ['src/extension.ts'], - bundle: true, - format: 'cjs', - minify: production, - sourcemap: !production, - sourcesContent: false, - platform: 'node', - outfile: 'dist/extension.js', - external: ['vscode'], - logLevel: 'silent', - plugins: [ - /* add to the end of plugins array */ - esbuildProblemMatcherPlugin - ] - }); - if (watch) { - await ctx.watch(); - } else { - await ctx.rebuild(); - await ctx.dispose(); - } -} +// Config for extension source code (to be run in a Node-based context) +/** @type BuildOptions */ +const extensionConfig = { + ...baseConfig, + platform: "node", + mainFields: ["module", "main"], + format: "cjs", + entryPoints: ["./src/extension.ts"], + outfile: "./out/extension.js", + loader:{ + ".node":"copy" + }, + external: ["vscode"], + plugins:[ + copy({ + resolveFrom:"cwd", + assets:{ + from:["./node_modules/ssh2/lib/**/*"], + to:["./out/lib"] + } + }) + ] +}; -/** - * @type {import('esbuild').Plugin} - */ -const esbuildProblemMatcherPlugin = { - name: 'esbuild-problem-matcher', +// Config for webview source code (to be run in a web-based context) +/** @type BuildOptions */ +const webviewConfig = { + ...baseConfig, + target: "es2020", + format: "esm", + entryPoints: ["./src/webview/main.ts"], + outfile: "./out/webview.js", + loader:{ + ".png":"copy" + }, + plugins: [ + // Copy webview css files to `out` directory unaltered + copy({ + verbose:false, + resolveFrom: "cwd", + assets: { + from: ["./src/webview/*.css"], + to: ["./out"], + }, + }), + copy({ + verbose:false, + resolveFrom: "cwd", + assets: { + from: ["./resources/images/explorer-bar.png"], + to: ["./out"], + }, + }), + ], +}; - setup(build) { - build.onStart(() => { - console.log('[watch] build started'); - }); - build.onEnd(result => { - result.errors.forEach(({ text, location }) => { - console.error(`✘ [ERROR] ${text}`); - console.error(` ${location.file}:${location.line}:${location.column}:`); - }); - console.log('[watch] build finished'); - }); - } +// This watch config adheres to the conventions of the esbuild-problem-matchers +// extension (https://github.com/connor4312/esbuild-problem-matchers#esbuild-via-js) +/** @type BuildOptions */ +const watchConfig = { + watch: { + onRebuild(error, result) { + console.log("[watch] build started"); + if (error) { + error.errors.forEach((error) => + console.error( + `> ${error.location.file}:${error.location.line}:${error.location.column}: error: ${error.text}` + ) + ); + } else { + console.log("[watch] build finished"); + } + }, + }, }; -main().catch(e => { - console.error(e); - process.exit(1); -}); +// Build script +(async () => { + const args = process.argv.slice(2); + try { + if (args.includes("--gatch")) { + // Build and watch extension and webview code + console.log("[watch] build started"); + await build({ + ...extensionConfig, + ...watchConfig, + }); + await build({ + ...webviewConfig, + ...watchConfig, + }); + console.log("[watch] build finished"); + } else { + // Build extension and webview code + const loader = {".node":"copy"} + await build({...extensionConfig}); + await build({...webviewConfig}); + console.log("build complete"); + } + } catch (err) { + process.stderr.write(err.stderr); + process.exit(1); + } +})(); \ No newline at end of file diff --git a/esbuild.js-orig b/esbuild.js-orig new file mode 100644 index 0000000..896f9c6 --- /dev/null +++ b/esbuild.js-orig @@ -0,0 +1,54 @@ +const esbuild = require('esbuild'); + +const production = process.argv.includes('--production'); +const watch = process.argv.includes('--watch'); + +async function main() { + const ctx = await esbuild.context({ + entryPoints: ['src/extension.ts'], + bundle: true, + format: 'cjs', + minify: production, + sourcemap: !production, + sourcesContent: false, + platform: 'node', + outfile: 'dist/extension.js', + external: ['vscode'], + logLevel: 'silent', + plugins: [ + /* add to the end of plugins array */ + esbuildProblemMatcherPlugin + ] + }); + if (watch) { + await ctx.watch(); + } else { + await ctx.rebuild(); + await ctx.dispose(); + } +} + +/** + * @type {import('esbuild').Plugin} + */ +const esbuildProblemMatcherPlugin = { + name: 'esbuild-problem-matcher', + + setup(build) { + build.onStart(() => { + console.log('[watch] build started'); + }); + build.onEnd(result => { + result.errors.forEach(({ text, location }) => { + console.error(`✘ [ERROR] ${text}`); + console.error(` ${location.file}:${location.line}:${location.column}:`); + }); + console.log('[watch] build finished'); + }); + } +}; + +main().catch(e => { + console.error(e); + process.exit(1); +}); diff --git a/eslint.config.mjs b/eslint.config.mjs-orig similarity index 100% rename from eslint.config.mjs rename to eslint.config.mjs-orig diff --git a/package-lock.json b/package-lock.json index 6ec0b25..dd303fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,37 @@ { "name": "sharedlock", - "version": "0.3.6", + "version": "0.3.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sharedlock", - "version": "0.3.6", + "version": "0.3.13", "dependencies": { + "@vscode/webview-ui-toolkit": "^1.4.0", "glob": "^11.0.0", "ioredis": "^5.4.1", "micromatch": "^4.0.8", + "ssh-tunneling": "^1.1.23", + "ssh2": "^1.16.0", "vscode-ext-codicons": "^1.6.0" }, "devDependencies": { "@eslint/js": "^9.13.0", "@stylistic/eslint-plugin": "^2.9.0", + "@types/glob": "^8.1.0", "@types/micromatch": "^4.0.9", "@types/node": "^20", + "@types/ssh2": "^1.15.1", "@types/vscode": "^1.73.0", - "esbuild": "^0.24.0", + "@types/vscode-webview": "^1.57.5", + "@typescript-eslint/eslint-plugin": "^8.13.0", + "@typescript-eslint/parser": "^8.13.0", + "esbuild": "^0.16.17", + "esbuild-plugin-copy": "^2.1.1", "eslint": "^9.13.0", "eslint-config-vscode-ext": "^1.1.0", + "prettier": "^3.3.3", "rimraf": "^6.0.1", "terser-webpack-plugin": "^5.3.10", "typescript": "^5.6.2", @@ -43,27 +53,10 @@ "node": ">=10.0.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", "cpu": [ "arm" ], @@ -74,13 +67,13 @@ "android" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", "cpu": [ "arm64" ], @@ -91,13 +84,13 @@ "android" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", "cpu": [ "x64" ], @@ -108,13 +101,13 @@ "android" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", - "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", "cpu": [ "arm64" ], @@ -125,13 +118,13 @@ "darwin" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", "cpu": [ "x64" ], @@ -142,13 +135,13 @@ "darwin" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", "cpu": [ "arm64" ], @@ -159,13 +152,13 @@ "freebsd" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", "cpu": [ "x64" ], @@ -176,13 +169,13 @@ "freebsd" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", "cpu": [ "arm" ], @@ -193,13 +186,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", "cpu": [ "arm64" ], @@ -210,13 +203,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", "cpu": [ "ia32" ], @@ -227,13 +220,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", "cpu": [ "loong64" ], @@ -244,13 +237,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", "cpu": [ "mips64el" ], @@ -261,13 +254,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", "cpu": [ "ppc64" ], @@ -278,13 +271,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", "cpu": [ "riscv64" ], @@ -295,13 +288,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", "cpu": [ "s390x" ], @@ -312,13 +305,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", "cpu": [ "x64" ], @@ -329,13 +322,13 @@ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", "cpu": [ "x64" ], @@ -346,30 +339,13 @@ "netbsd" ], "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", "cpu": [ "x64" ], @@ -380,13 +356,13 @@ "openbsd" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", "cpu": [ "x64" ], @@ -397,13 +373,13 @@ "sunos" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", "cpu": [ "arm64" ], @@ -414,13 +390,13 @@ "win32" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", "cpu": [ "ia32" ], @@ -431,13 +407,13 @@ "win32" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", "cpu": [ "x64" ], @@ -448,7 +424,7 @@ "win32" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@eslint-community/eslint-utils": { @@ -698,6 +674,52 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@microsoft/fast-element": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.14.0.tgz", + "integrity": "sha512-zXvuSOzvsu8zDTy9eby8ix8VqLop2rwKRgp++ZN2kTCsoB3+QJVoaGD2T/Cyso2ViZQFXNpiNCVKfnmxBvmWkQ==", + "license": "MIT" + }, + "node_modules/@microsoft/fast-foundation": { + "version": "2.50.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.50.0.tgz", + "integrity": "sha512-8mFYG88Xea1jZf2TI9Lm/jzZ6RWR8x29r24mGuLojNYqIR2Bl8+hnswoV6laApKdCbGMPKnsAL/O68Q0sRxeVg==", + "license": "MIT", + "dependencies": { + "@microsoft/fast-element": "^1.14.0", + "@microsoft/fast-web-utilities": "^5.4.1", + "tabbable": "^5.2.0", + "tslib": "^1.13.0" + } + }, + "node_modules/@microsoft/fast-foundation/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@microsoft/fast-react-wrapper": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.3.25.tgz", + "integrity": "sha512-jKzmk2xJV93RL/jEFXEZgBvXlKIY4N4kXy3qrjmBfFpqNi3VjY+oUTWyMnHRMC5EUhIFxD+Y1VD4u9uIPX3jQw==", + "license": "MIT", + "dependencies": { + "@microsoft/fast-element": "^1.14.0", + "@microsoft/fast-foundation": "^2.50.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@microsoft/fast-web-utilities": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", + "license": "MIT", + "dependencies": { + "exenv-es6": "^1.1.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -799,6 +821,17 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -815,6 +848,13 @@ "@types/braces": "*" } }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.17.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.0.tgz", @@ -824,23 +864,58 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/ssh2": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.1.tgz", + "integrity": "sha512-ZIbEqKAsi5gj35y4P4vkJYly642wIbY6PqoN0xiyQGshKUGXR9WQjF/iF9mXBQ8uBKy3ezfsCkcoHKhd0BzuDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.64", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.64.tgz", + "integrity": "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ssh2/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/vscode": { "version": "1.94.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.94.0.tgz", "integrity": "sha512-UyQOIUT0pb14XSqJskYnRwD2aG0QrPVefIfrW1djR+/J4KeFQ0i1+hjZoaAmeNf3Z2jleK+R2hv+EboG/m8ruw==", "dev": true }, + "node_modules/@types/vscode-webview": { + "version": "1.57.5", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.5.tgz", + "integrity": "sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -863,17 +938,15 @@ } } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "debug": "^4.3.4" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -881,25 +954,14 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" - }, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -908,15 +970,20 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { @@ -932,33 +999,38 @@ } } }, - "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/types": "8.13.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -966,27 +1038,37 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -997,16 +1079,18 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "node_modules/@typescript-eslint/parser": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1017,16 +1101,22 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1036,35 +1126,437 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true, - "license": "MIT" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.13.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.13.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", + "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", + "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vscode/webview-ui-toolkit": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.4.0.tgz", + "integrity": "sha512-modXVHQkZLsxgmd5yoP3ptRC/G8NBDD+ob+ngPiWNQdlrH6H1xR/qgOBD85bfU3BhOB5sZzFWBwwhp9/SfoHww==", + "license": "MIT", + "dependencies": { + "@microsoft/fast-element": "^1.12.0", + "@microsoft/fast-foundation": "^2.49.4", + "@microsoft/fast-react-wrapper": "^0.3.22", + "tslib": "^2.6.2" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", @@ -1344,17 +1836,72 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1416,6 +1963,15 @@ "dev": true, "license": "MIT" }, + "node_modules/buildcheck": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", + "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1462,6 +2018,44 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -1532,6 +2126,20 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/cpu-features": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.19.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1576,6 +2184,19 @@ "node": ">=0.10" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1630,9 +2251,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1640,33 +2261,47 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=18" + "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, + "node_modules/esbuild-plugin-copy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/esbuild-plugin-copy/-/esbuild-plugin-copy-2.1.1.tgz", + "integrity": "sha512-Bk66jpevTcV8KMFzZI1P7MZKZ+uDcrZm2G2egZ2jNIvVnivDpodZI+/KnpL3Jnap0PBdIHU7HwFGB8r+vV5CVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "fs-extra": "^10.0.1", + "globby": "^11.0.3" + }, + "peerDependencies": { + "esbuild": ">= 0.14.0" } }, "node_modules/escalade": { @@ -1860,6 +2495,12 @@ "node": ">=0.8.x" } }, + "node_modules/exenv-es6": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2009,6 +2650,36 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2097,6 +2768,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2220,6 +2912,32 @@ "url": "https://opencollective.com/ioredis" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -2348,6 +3066,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT", + "peer": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2360,6 +3085,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2385,6 +3116,19 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2460,6 +3204,19 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "11.0.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", @@ -2547,6 +3304,13 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/nan": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "license": "MIT", + "optional": true + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2567,6 +3331,16 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2682,6 +3456,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2778,6 +3562,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2817,6 +3617,32 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -2975,6 +3801,12 @@ ], "license": "MIT" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -3060,6 +3892,40 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3081,6 +3947,39 @@ "source-map": "^0.6.0" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, + "node_modules/ssh-tunneling": { + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/ssh-tunneling/-/ssh-tunneling-1.1.23.tgz", + "integrity": "sha512-DETiTNz1VBefhjDzCNkOwqO1ibG80KbuPMK0XPW5Dok3RZ6tQ9uI+z7rZxuhmI5XeJ6XtD7xzJKLPAIEPToveg==", + "license": "ISC", + "dependencies": { + "socks": "^2.6.2", + "ssh2": "^1.10.0" + } + }, + "node_modules/ssh2": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz", + "integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.10", + "nan": "^2.20.0" + } + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -3220,6 +4119,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", + "license": "MIT" + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -3313,6 +4218,18 @@ "typescript": ">=4.2.0" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3361,12 +4278,110 @@ } } }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", + "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/type-utils": "8.11.0", + "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", + "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", + "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/utils": "8.11.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", diff --git a/package.json b/package.json index 3ccbe92..3993bbf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "sharedlock", "displayName": "SharedLock", "description": "Sharing file locks in workspace files via network", - "version": "0.3.13", + "version": "0.4.0", "publisher": "code4bones", "icon": "resources/icons/logo.png", "repository": { @@ -36,12 +36,12 @@ "menus": { "editor/title/context": [ { - "when": "sharedlock.state == 'locked' && sharedlock.isOwner && sharedlock.hasGit", + "when": "sharedlock.state == 'locked' && sharedlock.isOwner && sharedlock.hasGit && sharedlock.connected", "command": "sharedlock.unlock", "group": "sharedlock" }, { - "when": "sharedlock.state != 'locked' && sharedlock.hasGit", + "when": "sharedlock.state != 'locked' && sharedlock.hasGit && sharedlock.connected", "command": "sharedlock.lock", "group": "sharedlock" } @@ -50,19 +50,34 @@ { "command": "sharedlock.wipeLocked", "group": "navigation@0", - "when": "view == sharedlock.locksView && sharedlock.hasGit" + "when": "view == sharedlock.locksView && sharedlock.hasGit && sharedlock.connected" + }, + { + "command": "sharedlock.settings", + "group": "navigation@1", + "when": "view == sharedlock.locksView" + }, + { + "command": "sharedlock.connect", + "group": "navigation@2", + "when": "view == sharedlock.locksView && !sharedlock.connected" + }, + { + "command": "sharedlock.disconnect", + "group": "navigation@2", + "when": "view == sharedlock.locksView && sharedlock.connected" } ], "explorer/context": [ { "command": "sharedlock.lockFolder", "group": "1_modification", - "when": "explorerResourceIsFolder && sharedlock.hasGit" + "when": "explorerResourceIsFolder && sharedlock.hasGit && sharedlock.connected" } ], "view/item/context": [ { - "when": "viewItem == owned && sharedlock.hasGit", + "when": "viewItem == owned && sharedlock.hasGit && sharedlock.connected", "command": "sharedlock.ctxUnlock", "group": "sharedlock" } @@ -82,6 +97,21 @@ "title": "Wipe Owned Files", "icon": "resources/icons/wipe.png" }, + { + "command": "sharedlock.settings", + "title": "Show Settings", + "icon": "resources/icons/settings.png" + }, + { + "command": "sharedlock.connect", + "title": "Connect to team", + "icon": "resources/icons/disconnect40.png" + }, + { + "command": "sharedlock.disconnect", + "title": "Disconnect from team", + "icon": "resources/icons/connect40.png" + }, { "command": "sharedlock.lock", "title": "Lock File" @@ -108,8 +138,7 @@ { "id": "sharedlock.locksView", "name": "SharedLocks", - "type": "tree", - "when": "sharedlock.hasGit" + "type": "tree" } ] }, @@ -142,64 +171,111 @@ } } ], - "configuration": [ - { - "title": "SharedLock", - "type": "object", - "properties": { - "redisHost": { - "title": "Host", - "type": "string", - "default": "127.0.0.1", - "order": 1, - "markdownDescription": "Redis server name or local instance" - }, - "redisPort": { - "type": "integer", - "default": 6379, - "order": 2 - }, - "redisDB": { - "type": "integer", - "default": 1, - "order": 3, - "markdownDescription": "All memebers in project must set the same value" - }, - "redisUsername": { - "type": "string", - "order": 4 - }, - "redisPassword": { - "type": "string", - "order": 5 - } + "configuration": { + "title": "SharedLock Settings", + "properties": { + "sharedlock.common-tunnel": { + "description": "Use SSH Tunnel to redis server", + "type": "boolean", + "default": false + }, + "sharedlock.common-autoconnect":{ + "description": "Auto connect on startup", + "type": "boolean", + "default": false + }, + "sharedlock.common-welcome":{ + "description": "Welcome message / settings", + "type": "boolean", + "default": true + }, + "sharedlock.redis-host": { + "title": "Host", + "type": "string", + "default": "127.0.0.1", + "order": 1, + "markdownDescription": "Redis server name or local instance" + }, + "sharedlock.redis-port": { + "type": "integer", + "default": 6379, + "order": 2 + }, + "sharedlock.redis-db": { + "type": "integer", + "default": 1, + "order": 3, + "markdownDescription": "All memebers in project must set the same value" + }, + "sharedlock.redis-username": { + "type": "string", + "order": 4 + }, + "sharedlock.redis-password": { + "type": "string", + "order": 5 + }, + "sharedlock.ssh-host": { + "type": "string", + "default": "", + "description": "Host" + }, + "sharedlock.ssh-port": { + "type": "integer", + "description": "Port", + "default": 22 + }, + "sharedlock.ssh-username": { + "type": "string", + "description": "Username" + }, + "sharedlock.ssh-password": { + "type": "string", + "description": "Password" + }, + "sharedlock.ssh-privateKey": { + "type": "string", + "description": "Privatekey" + }, + "sharedlock.ssh-remoteRedisPort": { + "type": "number", + "default": 6379, + "description": "Remote Redis Port" + }, + "sharedlock.ssh-localRedisPort": { + "type": "number", + "default": 6379, + "description": "Bind to local port" } } - ] + } }, - "main": "./dist/extension.js", + "main": "./out/extension.js", "scripts": { - "dev": "npm run compile && npm run watch", - "compile": "tsc -p ./", - "lint": "eslint", - "watch": "tsc -watch -p ./", - "prewatch1": "npm run compile", - "build": "node esbuild.js --production", - "prebuild": "rimraf -rf ./dist", - "package": "vsce package", - "prepackage": "npm run build", + "compile": "node ./esbuild.js", + "lint": "eslint src --ext ts", + "watch": "node ./esbuild.js --watch", + "prepackage": "NODE_ENV=production node ./esbuild.js", + "package":"vsce package", "publish": "vsce publish", - "prepublish": "npm run build" + "prepublish": "npm run package" }, "devDependencies": { "@eslint/js": "^9.13.0", "@stylistic/eslint-plugin": "^2.9.0", + "@types/glob": "^8.1.0", "@types/micromatch": "^4.0.9", "@types/node": "^20", + "@types/ssh2": "^1.15.1", "@types/vscode": "^1.73.0", - "esbuild": "^0.24.0", + "@types/vscode-webview": "^1.57.5", + "@typescript-eslint/eslint-plugin": "^8.13.0", + "@typescript-eslint/parser": "^8.13.0", + "esbuild": "^0.16.17", + "esbuild-plugin-copy": "^2.1.1", "eslint": "^9.13.0", "eslint-config-vscode-ext": "^1.1.0", + "prettier": "^3.3.3", "rimraf": "^6.0.1", "terser-webpack-plugin": "^5.3.10", "typescript": "^5.6.2", @@ -208,9 +284,12 @@ "webpack-cli": "^5.1.4" }, "dependencies": { + "@vscode/webview-ui-toolkit": "^1.4.0", "glob": "^11.0.0", "ioredis": "^5.4.1", "micromatch": "^4.0.8", + "ssh-tunneling": "^1.1.23", + "ssh2": "^1.16.0", "vscode-ext-codicons": "^1.6.0" } } diff --git a/resources/icons/connect40.png b/resources/icons/connect40.png new file mode 100644 index 0000000..5c705f6 Binary files /dev/null and b/resources/icons/connect40.png differ diff --git a/resources/icons/connect64.png b/resources/icons/connect64.png new file mode 100644 index 0000000..4b2cd84 Binary files /dev/null and b/resources/icons/connect64.png differ diff --git a/resources/icons/disconnect40.png b/resources/icons/disconnect40.png new file mode 100644 index 0000000..3c3801f Binary files /dev/null and b/resources/icons/disconnect40.png differ diff --git a/resources/icons/disconnect64.png b/resources/icons/disconnect64.png new file mode 100644 index 0000000..aee1fac Binary files /dev/null and b/resources/icons/disconnect64.png differ diff --git a/resources/icons/settings.png b/resources/icons/settings.png new file mode 100644 index 0000000..7a98edf Binary files /dev/null and b/resources/icons/settings.png differ diff --git a/resources/images/explorer-bar.png b/resources/images/explorer-bar.png new file mode 100644 index 0000000..ecb761f Binary files /dev/null and b/resources/images/explorer-bar.png differ diff --git a/resources/images/settings.gif b/resources/images/settings.gif new file mode 100644 index 0000000..910e832 Binary files /dev/null and b/resources/images/settings.gif differ diff --git a/src/commands.ts b/src/commands.ts index 9656c6e..7c4bc35 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -7,6 +7,7 @@ import * as fs from "fs"; import {glob} from "glob"; import mm from "micromatch"; import { logger } from "./logger"; +import { SettingsPanel } from "./settings/SettingsPanel"; export function registerCommands(ctx:vscode.ExtensionContext) { const ctrl = new Controller(ctx); @@ -88,6 +89,11 @@ export function registerCommands(ctx:vscode.ExtensionContext) { }); } + /* + connect / Disconnect + */ + ctx.subscriptions.push(vscode.commands.registerCommand(C.LockCommands.connect,() => ctrl.connect(true))); + ctx.subscriptions.push(vscode.commands.registerCommand(C.LockCommands.disconnect,() => ctrl.connect(false))); /* Status bar toggler @@ -113,6 +119,10 @@ export function registerCommands(ctx:vscode.ExtensionContext) { */ ctx.subscriptions.push(vscode.commands.registerCommand(C.LockCommands.ctxOpen,(args) => ctxOpen(args))); + /* + WebView + */ + ctx.subscriptions.push(vscode.commands.registerCommand(C.LockCommands.settings,() => SettingsPanel.render(ctx))); return ctrl; } diff --git a/src/config/config.ts b/src/config/config.ts new file mode 100644 index 0000000..1ec9f58 --- /dev/null +++ b/src/config/config.ts @@ -0,0 +1,48 @@ + +export interface UpdateState { + id:string; + action:"add" | "remove"; + class:string; +} + +export interface ConnectionSettings { + host:string; + port:number; + username:string; + password:string; +} + +export interface CommonSettings { + tunnel?:boolean; + autoconnect?:boolean; + welcome?:boolean; +} + +export interface RedisSettings extends ConnectionSettings { + db:number; +} + +export interface SSHSettings extends ConnectionSettings { + remoteRedisPort:number; + localRedisPort:number; + privateKey:string; +} + +export interface Settings { + common:CommonSettings; + redis:RedisSettings; + ssh:SSHSettings; +} + + +export const configCommonKeys = ["tunnel","autoconnect","welcome"]; +export const configBaseKeys = ["host","port","username","password"]; +export const configRedisKeys = [...configBaseKeys,"db"] +export const configSshKeys = [...configBaseKeys,"privateKey","remoteRedisPort","localRedisPort"] + +export const configKeys = { + configBaseKeys, + configCommonKeys, + configRedisKeys, + configSshKeys +} diff --git a/src/conts.ts b/src/conts.ts index 0185cb7..5365cad 100644 --- a/src/conts.ts +++ b/src/conts.ts @@ -15,6 +15,9 @@ export enum LockCommands { ctxUnlock = `${name}.ctxUnlock`, ctxOpen = `${name}.ctxOpen`, lockFolder = `${name}.lockFolder`, + settings = `${name}.settings`, + connect = `${name}.connect`, + disconnect = `${name}.disconnect`, } export enum LockState { diff --git a/src/extension.ts b/src/extension.ts index f99de80..3bf1111 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,6 +2,8 @@ import * as vscode from 'vscode'; import { registerCommands } from './commands'; import { LocksView } from './locksView'; import { createLogger } from './logger'; +import { loadConfig, saveConfig } from './utils/getConfig'; +import { LockCommands } from './conts'; export function activate(context: vscode.ExtensionContext) { @@ -13,5 +15,15 @@ export function activate(context: vscode.ExtensionContext) { createLogger(context).appendLine("Starting..."); const ctrl = registerCommands(context); new LocksView(context,ctrl); - ctrl.initialUpdate(); + const cfg = loadConfig(); + if ( cfg.common.welcome ) { + cfg.common.welcome = false; + saveConfig(cfg); + vscode.commands.executeCommand(LockCommands.settings); + } else { + if ( cfg.common.autoconnect ) { + console.log("Autoconnect...") + vscode.commands.executeCommand(LockCommands.connect); + } + } } diff --git a/src/settings/SettingsPanel.ts b/src/settings/SettingsPanel.ts new file mode 100644 index 0000000..b61b04c --- /dev/null +++ b/src/settings/SettingsPanel.ts @@ -0,0 +1,230 @@ +import * as vs from "vscode"; +import { getNonce } from "../utils/getNonce"; +import { getUri } from "../utils/getUri"; +import { loadConfig, saveConfig } from "../utils/getConfig"; +import { testRedis } from "../utils/testRedis"; +import { createTunnel } from "../utils/tunnel"; + +export class SettingsPanel { + public static currentPanel: SettingsPanel | undefined; + private readonly _panel: vs.WebviewPanel; + private _disposables: vs.Disposable[] = []; + private _ctx: vs.ExtensionContext; + + private constructor(panel: vs.WebviewPanel,ctx:vs.ExtensionContext) { + this._panel = panel; + this._ctx = ctx; + this._panel.webview.html = this._getWebviewContent(this._panel.webview,ctx.extensionUri); + this._setWebviewMessageListener(this._panel.webview); + this._panel.onDidDispose(() => this.dispose(), null, this._disposables); + } + + public static render(ctx:vs.ExtensionContext) { + const extensionUri = ctx.extensionUri; + if (SettingsPanel.currentPanel) { + SettingsPanel.currentPanel._panel.reveal(vs.ViewColumn.One); + } else { + const panel = vs.window.createWebviewPanel("settings", "Settings", vs.ViewColumn.One, { + // Empty for now + enableScripts: true, + // Restrict the webview to only load resources from the `out` directory + localResourceRoots: [vs.Uri.joinPath(extensionUri, "out")], + + }); + SettingsPanel.currentPanel = new SettingsPanel(panel,ctx); + } + } + + private _setWebviewMessageListener(webview:vs.Webview) { + webview.onDidReceiveMessage( + (message: any) => { + console.log("MESSAGE FROM WEB",message); + const command = message.command; + + switch (command) { + case "get-config": + webview.postMessage({ + command:"set-config", + payload:loadConfig(), + }); + break; + case "ssh-test": + webview.postMessage({ + command:"update-state", + payload:{ + id:'ssh-ring', + action:'remove', + class:'hidden' + } + }); + saveConfig(message.payload); + createTunnel(message.payload) + .then((server)=>{ + if ( server ) { + vs.window.showInformationMessage(`SSH Connection Successful`); + server?.close() + } + }) + .catch((e)=>{ + vs.window.showErrorMessage(`SSH: ${e}`); + }).finally(()=>{ + webview.postMessage({ + command:"update-state", + payload:{ + id:'ssh-ring', + action:'add', + class:'hidden' + } + }); + }) + break; + case "redis-test": + saveConfig(message.payload); + webview.postMessage({ + command:"update-state", + payload:{ + id:'redis-ring', + action:'remove', + class:'hidden' + } + }); + testRedis(message.payload) + .then((res)=>{ + if ( res ) { + vs.window.showErrorMessage(`Cannot connect ${res}`); + } else { + vs.window.showInformationMessage(`Redis Connection Successful`); + } + webview.postMessage({ + command:"redis-connect", + payload:res, + }); + }) + .finally(()=>{ + webview.postMessage({ + command:"update-state", + payload:{ + id:'redis-ring', + action:'add', + class:'hidden' + } + }); + }) + break; + + case 'toggle-tunnel': + saveConfig(message.payload); + webview.postMessage({ + command:"toggle-tunnel", + payload:message.payload + }); + break; + // Add more switch case statements here as more webview message commands + // are created within the webview context (i.e. inside src/webview/main.ts) + } + }, + undefined, + this._disposables + ); + } + + private _getWebviewContent(webview: vs.Webview, extensionUri: vs.Uri) { + const webviewUri = getUri(webview, extensionUri, ["out", "webview.js"]); + const cssStyle = webview.asWebviewUri(vs.Uri.joinPath(extensionUri, "out", "style.css")) + const imgUrl = webview.asWebviewUri(vs.Uri.joinPath(extensionUri, "out", "explorer-bar.png")) + + const nonce = getNonce(); + + // Tip: Install the es6-string-html VS Code extension to enable code highlighting below + return /*html*/ ` + + + + + + + + SharedLock Settings + + +

SharedLock Settings

+ + Redis + SSH + +
+
+
+ Address + Port + Database +
+
+ Username + Password +
+
+ AutoConnect on startup +

+ Test and Save + Redis Connection +

+
+ +
    +
  • 1. Show that settings screen
  • +
  • 2. Toggle connection
  • +
+
+ +
+
+ +
+ Enable SSH Tunnel +
+ Host + + Port + +
+ Username + Password + Private key + +
+ Remote Redis Port + Bind to local port +
+
+

+ + Test and Save + +

+ +
+
+
+
+
+
+ + + + `; + } + + public dispose() { + SettingsPanel.currentPanel = undefined; + + this._panel.dispose(); + + while (this._disposables.length) { + const disposable = this._disposables.pop(); + if (disposable) { + disposable.dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/storage.ts b/src/storage.ts index 79264e3..08d9a75 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -8,6 +8,7 @@ import { Tag,LockMessage, UIMessage, UIMessageType, UILockRequestMessage, UILock import { logger } from "./logger"; import { existsSync } from "fs"; import { getPathNS } from "./utils"; +import { loadConfig } from "./utils/getConfig"; export class Storage { private sub:Redis; @@ -17,10 +18,12 @@ export class Storage { private ctx:vs.ExtensionContext; private folders:string[]; private _enabled:boolean; + private _connected:boolean; private userChannel:string; _onDidLockChanged:vs.EventEmitter; _onDidEnabledChanged:vs.EventEmitter; + _onDidConnectionChanged:vs.EventEmitter; get onDidLockChanged() { return this._onDidLockChanged.event; @@ -30,6 +33,10 @@ export class Storage { return this._onDidEnabledChanged.event; } + get onDidConnectionChanged() { + return this._onDidConnectionChanged.event; + } + getTag() { const {username} = os.userInfo(); return { @@ -40,33 +47,62 @@ export class Storage { constructor(_ctx:vs.ExtensionContext) { this.ctx = _ctx; - this._onDidLockChanged = new vs.EventEmitter(); this._onDidEnabledChanged = new vs.EventEmitter(); + this._onDidConnectionChanged = new vs.EventEmitter(); - this._enabled = false; - this.folders = JSON.parse(this.ctx.globalState.get("roots")!); - const host = vs.workspace.getConfiguration().get("redisHost") as string; - const port = parseInt(vs.workspace.getConfiguration().get("redisPort")!); - const db = parseInt(vs.workspace.getConfiguration().get("redisDB")!); - const username = vs.workspace.getConfiguration().get("redisUsername") as string; - const password = vs.workspace.getConfiguration().get("resisPassword") as string; - const connectOpts : RedisOptions = { - host,port,db,username,password, - connectionName:"SHLCK", - }; + this.sub = new Redis({lazyConnect:true}); + this.pub = new Redis({lazyConnect:true}); - console.log("Config",connectOpts,this.folders); + this._connected = false; + this._enabled = false; + this.folders = JSON.parse(this.ctx.globalState.get("roots")!); this.tag = this.getTag(); this.userChannel = `${channelUI}.${this.tag.username}`; + this.startup(); + } + + set connected(en:boolean) { + if ( this._connected !== en ) { + this._connected = en; + this.enabled = en; + commands.executeCommand("setContext","sharedlock.connected",en); + } + } + + get connected() { + return this._connected; + } + + connect(en:boolean) { + if ( !en ) { + this._onDidLockChanged.fire([]); + this.sub.disconnect(false); + this.pub.disconnect(false); + this.connected = false; + return; + } + const {redis} = loadConfig(); + const connectOpts : RedisOptions = { + host:redis.host, + port:+redis.port, + db:+redis.db, + maxRetriesPerRequest:5, + username:redis.username, + password:redis.password, + connectionName:"SHLCK", + autoResubscribe:false, + }; this.sub = new Redis(connectOpts); this.pub = new Redis(connectOpts); - this.sub.on("connect",()=>{ - let txt = `[redis]: Connection made to ${host}:${port}/${db} with auth ${username || '-'}/${password ||'-'}`; + console.log("Config",connectOpts,this.folders); + + this.sub.on("ready",()=>{ + let txt = `[redis]: Connection made to ${connectOpts.host}:${connectOpts.port}/${connectOpts.db} with auth ${connectOpts.username || '-'}/${connectOpts.password ||'-'}`; console.log(txt); logger.info(txt); - this.sub.subscribe(channelID,this.userChannel,(err,count) => { + this.sub!.subscribe(channelID,this.userChannel,(err,count) => { if ( err ){ txt = `[redis] Failed to subscribe to channels ${channelID}: ${err.message}`; logger.error(txt); @@ -75,7 +111,12 @@ export class Storage { txt = `[redis] Message bus started on ${channelID}/${this,this.userChannel} ( count ${count})`; logger.info(txt); console.log(txt); - this.startup(); + this.connected = true; + this.informLocksChanges() + .then(()=>{ + console.log("INITIAL SET STATUS !") + this.setTabStatus(); + }) } }); this.sub.on("message",(channel,msg)=>{ @@ -86,16 +127,24 @@ export class Storage { } }); }); + this.sub.on("close",()=>{ + console.log("Connection closed !"); + this.connected = false; + }) this.sub.on("error",(e)=>{ logger.error(`[redis]: ${e.name}:${e.message}`); - this.enabled = false; + this.connected = false; }); + + } + + get ready() { + return this.enabled && this.connected } startup() { - this.enabled = true; vs.window.onDidChangeActiveTextEditor((e)=>{ - if ( !e?.document ) { + if ( !e?.document || !this.ready ) { return; } const ns = this.ns; @@ -112,7 +161,7 @@ export class Storage { this._enabled = hasGit; vs.commands.executeCommand('setContext','sharedlock.hasGit',hasGit) .then(()=>{ - this._onDidEnabledChanged.fire(hasGit); + this._onDidEnabledChanged.fire(hasGit && this.connected); }); } } @@ -208,7 +257,7 @@ export class Storage { return this.keys() .then((keys)=>{ return Promise.all( - keys.map(file => this.getVal(file).then((tag) => ({file,tag,state:this.isMe(tag!) ? LockState.Owned : LockState.Locked}) as LockMessage)) + keys?.map(file => this.getVal(file).then((tag) => ({file,tag,state:this.isMe(tag!) ? LockState.Owned : LockState.Locked}) as LockMessage)) ); }); } @@ -217,7 +266,7 @@ export class Storage { const data = await this.locks; const wiped = data.filter(m => this.isMe(m.tag)); wiped.forEach((m)=>{ - this.pub.del(m.file) + this.pub!.del(m.file) .then(()=>{ this.publish({state:LockState.Unlocked,file:m.file,tag:m.tag}); }); @@ -226,7 +275,7 @@ export class Storage { } async ctxUnlock(msg:LockMessage) { - await this.pub.del(msg.file); + await this.pub?.del(msg.file); this.publish({state:LockState.Unlocked,file:msg.file,tag:msg.tag}); } @@ -243,23 +292,27 @@ export class Storage { } keys() { - return this.pub.keys(`${this.ns}:*`); + if ( this.enabled && this.connected ) { + return this.pub.keys(`${this.ns}:*`); + } else { + return Promise.resolve([]); + } } set(key:string,obj:Tag) { - if ( !this.enabled ) { + if ( !this.enabled && !this.connected ) { return; } const nskey = this.nsKey(key); logger.debug(`Locking file ${nskey}`); - return this.pub.set(nskey,JSON.stringify(obj)); + return this.pub!.set(nskey,JSON.stringify(obj)); } getVal(key:string) { - if (!this.enabled ) { + if (!this.enabled && !this.connected ) { return Promise.resolve(null); } - return this.pub.get(key) + return this.pub!.get(key) .then((res:string | null)=>{ if ( res ) { return JSON.parse(res) as Tag; @@ -269,7 +322,7 @@ export class Storage { } get(key:string) { - return this.pub.get(this.nsKey(key)) + return this.pub!.get(this.nsKey(key)) .then((res:string | null)=>{ if ( res ) { return JSON.parse(res) as Tag; @@ -284,19 +337,19 @@ export class Storage { } const nskey = this.nsKey(key); logger.debug(`Release file ${nskey}`); - return this.pub.del(nskey); + return this.pub!.del(nskey); } exists(key:string) { if (!this.enabled ) { return; } - return this.pub.exists(this.nsKey(key)); + return this.pub!.exists(this.nsKey(key)); } publish(obj:object) { logger.debug(`[redis]: Publish`,obj); - return this.pub.publish(channelID,JSON.stringify(obj)); + return this.pub!.publish(channelID,JSON.stringify(obj)); } isMe(tag:Tag) { @@ -327,11 +380,13 @@ export class Storage { const ns = getPathNS(oneFile,this.folders); const pendings = files.map((file)=>{ const uri = vs.Uri.parse(file); - const root = this.getRoot(uri); + // const root = this.getRoot(uri); + const root = getPathNS(uri.path,this.folders); if ( root ) { - const key = uri!.path.substring(root!.length); + const index = uri.path.indexOf(root) + const key = uri!.path.substring(index); const tkey = `${ns}:${key}`; - return this.pub.exists(tkey) + return this.pub!.exists(tkey) .then((ignore)=>{ if ( !ignore ) { logger.info(`[${ns}] Locked [${key}]`); @@ -384,7 +439,7 @@ export class Storage { } uiPub(tag:Tag,msg:UIMessage) { - return this.pub.publish(`${channelUI}.${tag.username}`,JSON.stringify(msg)); + return this.pub!.publish(`${channelUI}.${tag.username}`,JSON.stringify(msg)); } nsKey(key:string) { @@ -406,18 +461,41 @@ export class Storage { this.enabled = false; return; } - const root = this.getRoot(uri!); + const root = getPathNS(uri.path,this.folders); if ( !root ) { this.enabled = false; return; } - const key = uri!.path.substring(root!.length); - // console.log("F>",uri.path); - // console.log("R>",root); - // console.log("K>",key); + const index = uri.path.indexOf(root) + const key = uri!.path.substring(index); return key; } + get ns() { + + if ( !vs.window.activeTextEditor ) { + this.enabled = false; + return ''; + } + const {uri} = vs.window.activeTextEditor.document; + const found = getPathNS(uri.path,this.folders); + if ( found ) { + this.enabled = true; + return found; + } else { + logger.warn(`No Repository found for: ${uri.path}`); + this.enabled = false; + } + } + + public dispose() { + console.log("Disposed, Extension stopped."); + logger.warn("Extension Unloaded,stopping connections"); + this.pub!.disconnect(false); + this.sub!.disconnect(false); + } + + /* getRoot(file?:vs.Uri) { const levelUp = (dir:string) => { if ( dir === "/" ) { @@ -450,27 +528,13 @@ export class Storage { return null; } const fsPath = file?.path || vs.window.activeTextEditor?.document?.uri?.path; + console.log("GET ROOT FOR",fsPath) const prs = path.parse(fsPath!); const found = levelUp(prs.dir); + console.log("FOUND ROOT",found); return found; } - - get ns() { - - if ( !vs.window.activeTextEditor ) { - this.enabled = false; - return ''; - } - const {uri} = vs.window.activeTextEditor.document; - const found = getPathNS(uri.path,this.folders); - if ( found ) { - this.enabled = true; - return found; - } else { - logger.warn(`No Repository found for: ${uri.path}`); - this.enabled = false; - } - } + */ /* async getGIT(file:vs.Uri) { @@ -508,9 +572,4 @@ export class Storage { } */ - public dispose() { - console.log("Extension stopped."); - this.pub.disconnect(false); - this.sub.disconnect(false); - } } \ No newline at end of file diff --git a/src/ui.ts b/src/ui.ts index dc70b16..5549e06 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -1,9 +1,13 @@ -import {ExtensionContext, StatusBarAlignment,StatusBarItem,window, ThemeColor } from "vscode"; +import {ExtensionContext, StatusBarAlignment,StatusBarItem,window, ThemeColor, commands } from "vscode"; import { codicons } from "vscode-ext-codicons"; import { Storage } from "./storage"; +import { Server } from "net"; import * as C from "./conts"; import { LockMessage } from "./types"; +import { loadConfig } from "./utils/getConfig"; +import { createTunnel } from "./utils/tunnel"; +import { logger } from "./logger"; export class StatusBar { private item:StatusBarItem; @@ -54,13 +58,17 @@ export class StatusBar { export class Controller { private statusBar:StatusBar; private _storage:Storage; + private _server?:Server; constructor(ctx:ExtensionContext) { this._storage = new Storage(ctx); this.statusBar = new StatusBar(ctx); - this.statusBar.update(C.LockState.Unlocked); + // this.statusBar.update(C.LockState.Unlocked); ctx.subscriptions.push(this.statusBar,this.storage); + this._storage.onDidConnectionChanged(connected => { + this.statusBar.enable(connected); + }); this._storage.onDidEnabledChanged((enable)=>{ this.statusBar.enable(enable); }); @@ -95,6 +103,34 @@ export class Controller { this._storage.ctxUnlock(msg); } + connect(en:boolean) { + const cfg = loadConfig(); + if ( !en ) { + console.log("Closing Tunnel !") + this._storage.connect(en); + if ( this._server && cfg.common.tunnel ) + this._server.close(()=>{ + logger.info("Server closed") + }); + + } else { + if ( cfg.common.tunnel ) { + createTunnel(cfg) + .then((server)=>{ + logger.info("[ssh] Tunnel created") + this._server = server; + this._storage.connect(en); + }) + .catch(e=>{ + logger.error(`[ssh] Tunnel failed: ${e}`); + window.showErrorMessage(`SSH: ${e}`); + }) + } else { + this._storage.connect(en); + } + } + } + async initialUpdate() { const locks = await this.storage.locks; if ( !locks.length ) { diff --git a/src/utils/getConfig.ts b/src/utils/getConfig.ts new file mode 100644 index 0000000..960fa4f --- /dev/null +++ b/src/utils/getConfig.ts @@ -0,0 +1,38 @@ +import {ExtensionContext,workspace} from "vscode"; +import { configRedisKeys,configSshKeys,configCommonKeys,Settings } from "../config/config"; + + +export function loadConfig(ctx?:ExtensionContext) { + const redis = configRedisKeys.reduce((agg,k)=>({ + ...agg,[k]:workspace.getConfiguration().get(`sharedlock.redis-${k}`) as string + }),{}) as Settings["redis"]; + + const ssh = configSshKeys.reduce((agg,k)=>({ + ...agg,[k]:workspace.getConfiguration().get(`sharedlock.ssh-${k}`) as string + }),{}) as Settings["ssh"]; + + const common = configCommonKeys.reduce((agg,k)=>({ + ...agg,[k]:workspace.getConfiguration().get(`sharedlock.common-${k}`) as string + }),{}) as Settings["common"]; + + const cfg:Settings = { + redis, + ssh, + common, + } + console.log("Read Config",cfg); + return cfg; +} + +export function saveConfig(cfg:Settings) { + console.log("Write Config",cfg); + Object.entries(cfg.redis).map(([k,v])=>{ + workspace.getConfiguration().update(`sharedlock.redis-${k}`,v,false); + }) + Object.entries(cfg.ssh).map(([k,v])=>{ + workspace.getConfiguration().update(`sharedlock.ssh-${k}`,v,false); + }) + Object.entries(cfg.common).map(([k,v])=>{ + workspace.getConfiguration().update(`sharedlock.common-${k}`,v,false); + }) +} \ No newline at end of file diff --git a/src/utils/getNonce.ts b/src/utils/getNonce.ts new file mode 100644 index 0000000..cae8405 --- /dev/null +++ b/src/utils/getNonce.ts @@ -0,0 +1,16 @@ +/** + * A helper function that returns a unique alphanumeric identifier called a nonce. + * + * @remarks This function is primarily used to help enforce content security + * policies for resources/scripts being executed in a webview context. + * + * @returns A nonce + */ +export function getNonce() { + let text = ""; + const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < 32; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; + } \ No newline at end of file diff --git a/src/utils/getUri.ts b/src/utils/getUri.ts new file mode 100644 index 0000000..7145499 --- /dev/null +++ b/src/utils/getUri.ts @@ -0,0 +1,16 @@ +import { Uri, Webview } from "vscode"; + +/** + * A helper function which will get the webview URI of a given file or resource. + * + * @remarks This URI can be used within a webview's HTML as a link to the + * given file/resource. + * + * @param webview A reference to the extension webview + * @param extensionUri The URI of the directory containing the extension + * @param pathList An array of strings representing the path to a file/resource + * @returns A URI pointing to the file/resource + */ +export function getUri(webview: Webview, extensionUri: Uri, pathList: string[]) { + return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList)); +} diff --git a/src/utils/testRedis.ts b/src/utils/testRedis.ts new file mode 100644 index 0000000..302cf37 --- /dev/null +++ b/src/utils/testRedis.ts @@ -0,0 +1,35 @@ +import Redis, {RedisOptions } from "ioredis"; +import { logger } from "../logger"; +import { Settings } from "../config/config"; +import { createTunnel } from "./tunnel"; + +export async function testRedis(cfg:Settings) { + const {redis} = cfg; + return new Promise((ok,cancel)=>{ + const opts:RedisOptions = { + host:redis.host, + port:+redis.port, + db:+redis.db, + maxRetriesPerRequest:1, + username:redis.username, + password:redis.password, + reconnectOnError:()=>false, + } + createTunnel(cfg) + .then((server)=>{ + const rd = new Redis(opts); + rd.on("error",(err)=>{ + logger.error(`Testing redis connection: ${err.message}`); + rd.disconnect(); + server?.close(); + ok(err.message); + }) + rd.on("ready",()=>{ + logger.info(`Testing redis connection: connected`) + rd.disconnect(); + server?.close(); + ok(false); + }) + }); + }) +} \ No newline at end of file diff --git a/src/utils/tunnel.ts b/src/utils/tunnel.ts new file mode 100644 index 0000000..38a6c25 --- /dev/null +++ b/src/utils/tunnel.ts @@ -0,0 +1,93 @@ +import { Settings } from "../config/config"; +import { existsSync, readFileSync } from "fs"; +import { Client, ConnectConfig } from "ssh2"; +import net from "net"; + +export function createSSH(cfg:Settings) { + const config : ConnectConfig = { + username:cfg.ssh.username, + password:cfg.ssh.password, + host:cfg.ssh.host, + port:cfg.ssh.port, + privateKey:existsSync(cfg.ssh.privateKey) ? readFileSync(cfg.ssh.privateKey) : undefined, + } + const conn = new Client(); + return {conn,config}; +} + +export function createTunnel(cfg:Settings) { + return new Promise((resolve,reject)=>{ + if ( !cfg.common.tunnel ) { + return resolve(undefined); + } + const {conn,config} = createSSH(cfg); + console.log("Connecting...") + conn.on("ready",()=>{ + const server = net.createServer((socket)=>{ + conn.forwardOut("127.0.0.1",cfg.ssh.localRedisPort,"127.0.0.1",cfg.ssh.remoteRedisPort,(err,channel)=>{ + if ( err ) { + console.log("ERROR FORWARD",err); + } else { + console.log("FORWARD ENABLED..."); + socket.pipe(channel).pipe(socket); + } + }); + }) + .on("listening",()=>{ + console.log("SERVER listen") + }) + .on("connection",()=>{ + console.log("SERVER - conneciton"); + }) + .on("error",(e)=>{ + console.log("SERVER - error",e); + reject(e.message) + }) + .on("close",()=>{ + console.log("SERVER - closed"); + conn.destroy() + // conn.end(); + }) + .listen(cfg.ssh.localRedisPort,"127.0.0.1",()=>{ + console.log("SERVER STARTED"); + resolve(server) + }); + }).on("error",(e)=>{ + console.log("SSH ERROR",e) + reject(e.message); + }).on("end",()=>{ + console.log("SSH END") + }).on("close",()=>{ + console.log("SSH CLOSE") + }).on("timeout",()=>{ + console.log("SSH TIMEOUT") + }) + .connect(config); + }) +} +/* +export function testSSH(cfg:Settings) { + return new Promise((resolve,reject)=>{ + const controller = new AbortController() + const {signal} = controller; + const {cmd,args} = tunnelCommand(cfg) + args.push('id') + console.log("Executing",`${cmd} ${args.join(" ")}`) + const ssh = spawn(cmd,args,{ + shell:true, + stdio:['pipe','pipe',process.stdout] + }); + ssh.stdout.on("data",(m)=>{ + console.log(">",m.toString("utf8")); + }) + ssh.on("error",(e)=>{ + console.log("ERROR",e); + reject({code:-1,error:e.message}); + }) + ssh.on("close",(code)=>{ + resolve({code}); + console.log("CLOSED !",code) + }) + }) +} +*/ \ No newline at end of file diff --git a/src/webview/main.ts b/src/webview/main.ts new file mode 100644 index 0000000..9defc82 --- /dev/null +++ b/src/webview/main.ts @@ -0,0 +1,112 @@ +// import { vsCodeCheckbox,vsCodePanelTab, vsCodeTextField,vsCodeButton } from "@vscode/webview-ui-toolkit"; +import { provideVSCodeDesignSystem, Button } from "@vscode/webview-ui-toolkit"; +import * as ui from "@vscode/webview-ui-toolkit"; +import {configKeys, Settings, UpdateState} from "../config/config"; + +provideVSCodeDesignSystem().register( + ui.vsCodeButton(), + ui.vsCodeCheckbox(), + ui.vsCodeTextField(), + ui.vsCodePanels(), + ui.vsCodePanelView(), + ui.vsCodePanelTab(), + ui.vsCodeLink(), + ui.vsCodeTag(), + ui.vsCodeProgressRing() +); + +const vscode = acquireVsCodeApi(); + +window.addEventListener("load", main); + +function main() { + const btnTestRedis = document.getElementById("redis-save") as Button; + btnTestRedis?.addEventListener("click", () => vscode.postMessage({command: "redis-test",payload:getConfig()})); + + const btnTestSSH = document.getElementById("ssh-save") as Button; + btnTestSSH?.addEventListener("click", () => vscode.postMessage({command: "ssh-test",payload:getConfig()})); + + const chkTunnel = document.getElementById("common-tunnel") as ui.Checkbox + chkTunnel?.addEventListener("click", () => vscode.postMessage({command: "toggle-tunnel",payload:getConfig()})); + + setVSCodeMessageListener(); + + vscode.postMessage({command: "get-config"}); +} + +function toggleTunnel(cfg:Settings) { + const viaSSH = document.getElementById("via-ssh") as HTMLSpanElement; + viaSSH.textContent = cfg.common?.tunnel ? ` [ via SSH on ${cfg.ssh.host} ] ` : " "; + + const btnTestSSH = document.getElementById("ssh-save") as Button; + btnTestSSH.textContent = cfg.common.tunnel ? 'Save and Test connection' : 'Save'; +} + +function updateState(state:UpdateState) { + const el = document.getElementById(state.id) as HTMLDivElement; + if ( state.action === "add" ) { + el?.classList.add(state.class) + } else { + el?.classList.remove(state.class) + } +} + +function getConfig() { + const redis = configKeys.configRedisKeys.reduce((agg,k)=>({ + ...agg,[k]:(document.getElementById(`redis-${k}`) as ui.TextField)?.value + }),{}) as Settings["redis"]; + const ssh = configKeys.configSshKeys.reduce((agg,k)=>({ + ...agg,[k]:(document.getElementById(`ssh-${k}`) as ui.TextField)?.value + }),{}) as Settings["ssh"]; + const common = configKeys.configCommonKeys.reduce((agg,k)=>({ + ...agg,[k]:(document.getElementById(`common-${k}`) as ui.Checkbox)?.checked + }),{}) as Settings["common"]; + return { + redis, + common, + ssh, + } +} + +function setConfig(cfg:Settings) { + console.log("setConfig",cfg); + + toggleTunnel(cfg); + + const setValue = (names:string[]) => { + names.forEach(name => Object.entries(cfg[name]).map(([k,v])=>{ + const el = document.getElementById(`${name}-${k}`)!; + switch ( el.id ) { + case "common-tunnel": + case "common-autoconnect": + (el as ui.Checkbox).checked = Boolean(v); + break; + default: + (el as ui.TextField).value = `${v}` + break; + } + })) + } + setValue(["ssh","redis","common"]); +} + +function setVSCodeMessageListener() { + window.addEventListener("message",(event)=>{ + const {command,payload} = event.data; + console.log("GOT MESSAGE",event.data); + switch ( command ) { + case 'set-config': + setConfig(payload); + return; + case 'toggle-tunnel': + toggleTunnel(payload); + return; + case 'redis-connect': + console.log("WOW !"); + break; + case 'update-state': + updateState(payload) + break; + } + }) +} \ No newline at end of file diff --git a/src/webview/style.css b/src/webview/style.css new file mode 100644 index 0000000..43938bd --- /dev/null +++ b/src/webview/style.css @@ -0,0 +1,26 @@ + +.test { + border:2px solid rgb(0, 238, 255); +} + +.cont-col { + display: flex; + flex-direction: column; +} + +.cont-row { + display: flex; + flex-direction: row; +} + +.spacer { + margin-left: 10px; +} + +#redis-test { + margin:10px 0; +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 73372f3..c056650 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,12 +2,12 @@ "compilerOptions": { "module": "commonjs", "target": "es2020", - "lib": ["es2020"], + "lib": ["es2020","DOM"], "outDir": "dist", "sourceMap": true, "strict": true, "rootDir": "src", "esModuleInterop": true }, - "exclude": ["node_modules", ".vscode-test"] + "exclude": ["node_modules", ".vscode-test","src/webview"] }