From ab7e46cbc03783f9884e7be31e7d8b293db8ded4 Mon Sep 17 00:00:00 2001 From: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com> Date: Fri, 3 Oct 2025 13:56:21 +0200 Subject: [PATCH] fix: resolve npm audit vulnerabilities in prismjs dependency (#37) * Cleanup: Remove unused components and update configuration - Remove RepoStatusButton component (unused) - Remove git.ts library file (unused) - Update ExecutionModeModal with improvements - Update page.tsx with enhancements - Update env.js configuration - Update scripts router with improvements - Update .env.example with new variables * fix: resolve npm audit vulnerabilities in prismjs dependency - Add overrides to force prismjs@^1.30.0 across all dependencies - Update refractor to latest version (5.0.0) - Resolves 3 moderate severity vulnerabilities in prismjs DOM Clobbering - All npm audit vulnerabilities now resolved (0 vulnerabilities found) --- .env.example | 1 - package-lock.json | 406 ++++++++++++++------- package.json | 17 +- src/app/_components/ExecutionModeModal.tsx | 43 +-- src/app/_components/RepoStatusButton.tsx | 185 ---------- src/app/page.tsx | 16 +- src/env.js | 4 +- src/server/api/routers/scripts.ts | 23 +- src/server/lib/git.ts | 258 ------------- 9 files changed, 304 insertions(+), 649 deletions(-) delete mode 100644 src/app/_components/RepoStatusButton.tsx delete mode 100644 src/server/lib/git.ts diff --git a/.env.example b/.env.example index 77c4ffd..175f439 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,6 @@ # When adding additional environment variables, the schema in "/src/env.js" # should be updated accordingly. -ORIGINAL_REPO_URL="https://github.com/michelroegl-brunner/PVEScriptslocal" REPO_URL="https://github.com/community-scripts/ProxmoxVE" REPO_BRANCH="main" SCRIPTS_DIRECTORY="scripts" diff --git a/package-lock.json b/package-lock.json index bd58e26..c8ca24e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@trpc/server": "^11.0.0", "@types/react-syntax-highlighter": "^15.5.13", "@types/ws": "^8.18.1", - "@xterm/addon-attach": "^0.11.0", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/xterm": "^5.5.0", @@ -25,12 +24,11 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-syntax-highlighter": "^15.6.6", + "refractor": "^5.0.0", "server-only": "^0.0.1", - "simple-git": "^3.28.0", "strip-ansi": "^7.1.2", "superjson": "^2.2.1", "ws": "^8.18.3", - "xterm": "^5.3.0", "zod": "^3.24.2" }, "devDependencies": { @@ -1706,21 +1704,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -2856,12 +2839,12 @@ "license": "MIT" }, "node_modules/@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "license": "MIT", "dependencies": { - "@types/unist": "^2" + "@types/unist": "*" } }, "node_modules/@types/json-schema": { @@ -2887,6 +2870,12 @@ "undici-types": "~7.10.0" } }, + "node_modules/@types/prismjs": { + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz", + "integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.1.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", @@ -2916,9 +2905,9 @@ } }, "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, "node_modules/@types/ws": { @@ -3692,15 +3681,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@xterm/addon-attach": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-attach/-/addon-attach-0.11.0.tgz", - "integrity": "sha512-JboCN0QAY6ZLY/SSB/Zl2cQ5zW1Eh4X3fH7BnuR1NB7xGRhzbqU2Npmpiw/3zFlxDaU88vtKzok44JKi2L2V2Q==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } - }, "node_modules/@xterm/addon-fit": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", @@ -4324,9 +4304,9 @@ } }, "node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "license": "MIT", "funding": { "type": "github", @@ -4334,9 +4314,9 @@ } }, "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "license": "MIT", "funding": { "type": "github", @@ -4344,9 +4324,9 @@ } }, "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "license": "MIT", "funding": { "type": "github", @@ -4425,9 +4405,9 @@ } }, "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "license": "MIT", "funding": { "type": "github", @@ -4584,6 +4564,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4604,6 +4585,19 @@ "dev": true, "license": "MIT" }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -6039,26 +6033,29 @@ } }, "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", "license": "MIT", "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" }, "funding": { "type": "opencollective", @@ -6236,9 +6233,9 @@ } }, "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "license": "MIT", "funding": { "type": "github", @@ -6246,13 +6243,13 @@ } }, "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "license": "MIT", "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" }, "funding": { "type": "github", @@ -6425,9 +6422,9 @@ } }, "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "license": "MIT", "funding": { "type": "github", @@ -6503,9 +6500,9 @@ } }, "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "license": "MIT", "funding": { "type": "github", @@ -7513,6 +7510,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/nan": { @@ -7917,23 +7915,30 @@ } }, "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "license": "MIT", "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/parse5": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", @@ -8271,13 +8276,10 @@ "license": "MIT" }, "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -8404,6 +8406,188 @@ "react": ">= 0.14.0" } }, + "node_modules/react-syntax-highlighter/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/react-syntax-highlighter/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/react-syntax-highlighter/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-syntax-highlighter/node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-syntax-highlighter/node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "license": "MIT", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/refractor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "license": "MIT", + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.27.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react-syntax-highlighter/node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -8456,29 +8640,21 @@ } }, "node_modules/refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-5.0.0.tgz", + "integrity": "sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==", "license": "MIT", "dependencies": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" + "@types/hast": "^3.0.0", + "@types/prismjs": "^1.0.0", + "hastscript": "^9.0.0", + "parse-entities": "^4.0.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/refractor/node_modules/prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -9010,21 +9186,6 @@ "simple-concat": "^1.0.0" } }, - "node_modules/simple-git": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.28.0.tgz", - "integrity": "sha512-Rs/vQRwsn1ILH1oBUy8NucJlXmnnLeLCfcvbSehkPzbv3wwoFWIdtfd6Ndo6ZPhlPsCZ60CPI4rxurnwAa+a2w==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -9060,9 +9221,9 @@ } }, "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", "funding": { "type": "github", @@ -10567,13 +10728,6 @@ "node": ">=0.4" } }, - "node_modules/xterm": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz", - "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==", - "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", - "license": "MIT" - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index b22a14b..01096c1 100644 --- a/package.json +++ b/package.json @@ -29,23 +29,21 @@ "@trpc/server": "^11.0.0", "@types/react-syntax-highlighter": "^15.5.13", "@types/ws": "^8.18.1", - "@xterm/addon-attach": "^0.11.0", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/xterm": "^5.5.0", + "better-sqlite3": "^9.6.0", "next": "^15.5.3", "node-pty": "^1.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-syntax-highlighter": "^15.6.6", + "refractor": "^5.0.0", "server-only": "^0.0.1", - "simple-git": "^3.28.0", "strip-ansi": "^7.1.2", "superjson": "^2.2.1", "ws": "^8.18.3", - "xterm": "^5.3.0", - "zod": "^3.24.2", - "better-sqlite3": "^9.6.0" + "zod": "^3.24.2" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", @@ -53,6 +51,7 @@ "@testing-library/jest-dom": "^6.8.0", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", + "@types/better-sqlite3": "^7.6.8", "@types/node": "^24.3.1", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", @@ -68,11 +67,13 @@ "tailwindcss": "^4.0.15", "typescript": "^5.8.2", "typescript-eslint": "^8.27.0", - "vitest": "^3.2.4", - "@types/better-sqlite3": "^7.6.8" + "vitest": "^3.2.4" }, "ct3aMetadata": { "initVersion": "7.39.3" }, - "packageManager": "npm@10.9.3" + "packageManager": "npm@10.9.3", + "overrides": { + "prismjs": "^1.30.0" + } } diff --git a/src/app/_components/ExecutionModeModal.tsx b/src/app/_components/ExecutionModeModal.tsx index ea62553..a3af4bc 100644 --- a/src/app/_components/ExecutionModeModal.tsx +++ b/src/app/_components/ExecutionModeModal.tsx @@ -79,11 +79,9 @@ export function ExecutionModeModal({ isOpen, onClose, onExecute, scriptName }: E

- How would you like to execute "{scriptName}"? + Where would you like to execute "{scriptName}"?

-

- Choose between local execution or running the script on a remote server via SSH. -

+
{error && ( @@ -103,42 +101,7 @@ export function ExecutionModeModal({ isOpen, onClose, onExecute, scriptName }: E {/* Execution Mode Selection */}
- {/* Local Execution */} -
handleModeChange('local')} - > -
- handleModeChange('local')} - className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300" - /> - -
-
+ {/* SSH Execution */}
(null); - const [updateSteps, setUpdateSteps] = useState([]); - const [showSteps, setShowSteps] = useState(false); - - // Query repository status - const { data: repoStatus, refetch: refetchStatus } = api.scripts.getRepoStatus.useQuery(); - - // Full update mutation - const fullUpdateMutation = api.scripts.fullUpdateRepo.useMutation({ - onSuccess: (data) => { - setIsUpdating(false); - setUpdateMessage(data.message); - setUpdateSteps(data.steps); - setShowSteps(true); - - if (data.success) { - // Refetch status after successful update - setTimeout(() => { - void refetchStatus(); - }, 1000); - - // Clear message after 5 seconds for success - setTimeout(() => { - setUpdateMessage(null); - setShowSteps(false); - }, 5000); - } else { - // Clear message after 10 seconds for errors - setTimeout(() => { - setUpdateMessage(null); - setShowSteps(false); - }, 10000); - } - }, - onError: (error) => { - setIsUpdating(false); - setUpdateMessage(`Error: ${error.message}`); - setUpdateSteps([`❌ ${error.message}`]); - setShowSteps(true); - setTimeout(() => { - setUpdateMessage(null); - setShowSteps(false); - }, 10000); - }, - }); - - const handleFullUpdate = async () => { - setIsUpdating(true); - setUpdateMessage(null); - setUpdateSteps([]); - setShowSteps(false); - fullUpdateMutation.mutate(); - }; - - const getStatusColor = () => { - if (!repoStatus?.isRepo) return 'text-gray-500'; - if (repoStatus.isBehind) return 'text-orange-500'; - return 'text-green-500'; - }; - - const getStatusIcon = () => { - if (!repoStatus?.isRepo) return '❓'; - if (repoStatus.isBehind) return '⚠️'; - return '✅'; - }; - - const getStatusText = () => { - if (!repoStatus?.isRepo) return 'Not a git repository'; - if (repoStatus.isBehind) return 'Updates available'; - return 'Up to date'; - }; - - return ( -
- {/* Status Display */} -
-
-
- {getStatusIcon()} -
-
- Repository Status: {getStatusText()} -
- {repoStatus?.isRepo && ( -
- Branch: {repoStatus.branch ?? 'unknown'} | - Last commit: {repoStatus.lastCommit ? repoStatus.lastCommit.substring(0, 8) : 'unknown'} -
- )} -
-
-
- -
- {repoStatus?.isBehind && ( - - )} - - -
-
- - {/* Update Message */} - {updateMessage && ( -
-
{updateMessage}
- {showSteps && updateSteps.length > 0 && ( -
- - {showSteps && ( -
- {updateSteps.map((step, index) => ( -
- {step} -
- ))} -
- )} -
- )} -
- )} - - {/* Update Steps (always show when updating) */} - {isUpdating && updateSteps.length > 0 && ( -
-
Update Progress:
-
- {updateSteps.map((step, index) => ( -
- {step} -
- ))} -
-
- )} -
- ); -} diff --git a/src/app/page.tsx b/src/app/page.tsx index 4acc565..6fe0d76 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -33,6 +33,14 @@ export default function Home() {

+ {/* Controls */} +
+
+ + +
+
+ {/* Tab Navigation */}
@@ -61,13 +69,7 @@ export default function Home() {
- {/* Controls */} -
-
- - -
-
+ {/* Running Script Terminal */} {runningScript && ( diff --git a/src/env.js b/src/env.js index 55b0aa7..88dd269 100644 --- a/src/env.js +++ b/src/env.js @@ -13,7 +13,7 @@ export const env = createEnv({ .default("development"), // Repository Configuration REPO_URL: z.string().url().optional(), - ORIGINAL_REPO_URL: z.string().url().optional(), + REPO_BRANCH: z.string().default("main"), SCRIPTS_DIRECTORY: z.string().default("scripts"), JSON_FOLDER: z.string().default("json"), @@ -42,7 +42,7 @@ export const env = createEnv({ NODE_ENV: process.env.NODE_ENV, // Repository Configuration REPO_URL: process.env.REPO_URL, - ORIGINAL_REPO_URL: process.env.ORIGINAL_REPO_URL, + REPO_BRANCH: process.env.REPO_BRANCH, SCRIPTS_DIRECTORY: process.env.SCRIPTS_DIRECTORY, JSON_FOLDER: process.env.JSON_FOLDER, diff --git a/src/server/api/routers/scripts.ts b/src/server/api/routers/scripts.ts index eb01d3b..330e6a8 100644 --- a/src/server/api/routers/scripts.ts +++ b/src/server/api/routers/scripts.ts @@ -1,7 +1,6 @@ import { z } from "zod"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc"; import { scriptManager } from "~/server/lib/scripts"; -import { gitManager } from "~/server/lib/git"; import { githubJsonService } from "~/server/services/githubJsonService"; import { localScriptsService } from "~/server/services/localScripts"; import { scriptDownloaderService } from "~/server/services/scriptDownloader"; @@ -27,27 +26,7 @@ export const scriptsRouter = createTRPCRouter({ }; }), - // Get repository status - getRepoStatus: publicProcedure - .query(async () => { - const status = await gitManager.getStatus(); - return status; - }), - - // Update repository - updateRepo: publicProcedure - .mutation(async () => { - const result = await gitManager.pullUpdates(); - return result; - }), - - // Full update repository (git pull, npm install, build) - fullUpdateRepo: publicProcedure - .mutation(async () => { - const result = await gitManager.fullUpdate(); - return result; - }), - + // Get script content for viewing getScriptContent: publicProcedure .input(z.object({ path: z.string() })) diff --git a/src/server/lib/git.ts b/src/server/lib/git.ts deleted file mode 100644 index ed7acca..0000000 --- a/src/server/lib/git.ts +++ /dev/null @@ -1,258 +0,0 @@ -import { simpleGit, type SimpleGit } from 'simple-git'; -import { env } from '~/env.js'; -import { join } from 'path'; -import { exec } from 'child_process'; -import { promisify } from 'util'; - -const execAsync = promisify(exec); - -export class GitManager { - private git: SimpleGit; - private repoPath: string; - private scriptsDir: string | null = null; - - constructor() { - this.repoPath = process.cwd(); - this.git = simpleGit(this.repoPath); - } - - private initializeConfig() { - this.scriptsDir ??= join(this.repoPath, env.SCRIPTS_DIRECTORY); - } - - /** - * Check if the repository is behind the remote - */ - async isBehindRemote(): Promise { - try { - if (!env.ORIGINAL_REPO_URL) { - return false; // No remote configured - } - - // Fetch latest changes without merging - await this.git.fetch(); - - // Check if local branch is behind remote - const status = await this.git.status(); - const behind = status.behind > 0; - - return behind; - } catch (error) { - console.error('Error checking repo status:', error); - return false; - } - } - - /** - * Pull updates from remote repository - */ - async pullUpdates(): Promise<{ success: boolean; message: string }> { - try { - if (!env.ORIGINAL_REPO_URL) { - return { success: false, message: 'No remote repository configured' }; - } - - // Check if we're in a git repository - const isRepo = await this.git.checkIsRepo(); - if (!isRepo) { - // Clone the repository if it doesn't exist - return await this.cloneRepository(); - } - - // Pull latest changes - const result = await this.git.pull(env.REPO_BRANCH); - - return { - success: true, - message: `Successfully pulled updates. ${result.summary.changes} changes, ${result.summary.insertions} insertions, ${result.summary.deletions} deletions` - }; - } catch (error) { - console.error('Error pulling updates:', error); - return { - success: false, - message: `Failed to pull updates: ${error instanceof Error ? error.message : 'Unknown error'}` - }; - } - } - - /** - * Full update process: git pull, npm install, and restart server - */ - async fullUpdate(): Promise<{ success: boolean; message: string; steps: string[] }> { - const steps: string[] = []; - - try { - if (!env.ORIGINAL_REPO_URL) { - return { - success: false, - message: 'No remote repository configured', - steps: ['❌ No remote repository configured'] - }; - } - - // Step 1: Git pull - steps.push('🔄 Pulling latest changes from repository...'); - const pullResult = await this.pullUpdates(); - if (!pullResult.success) { - return { - success: false, - message: pullResult.message, - steps: [...steps, `❌ ${pullResult.message}`] - }; - } - steps.push(`✅ ${pullResult.message}`); - - // Step 2: npm install - steps.push('📦 Installing/updating dependencies...'); - try { - const { stderr } = await execAsync('npm install', { cwd: this.repoPath }); - if (stderr && !stderr.includes('npm WARN')) { - console.warn('npm install warnings:', stderr); - } - steps.push('✅ Dependencies updated successfully'); - } catch (error) { - const errorMsg = `Failed to install dependencies: ${error instanceof Error ? error.message : 'Unknown error'}`; - steps.push(`❌ ${errorMsg}`); - return { - success: false, - message: errorMsg, - steps - }; - } - - // Step 3: Build the application - steps.push('🔨 Building application...'); - try { - const { stderr } = await execAsync('npm run build', { cwd: this.repoPath }); - if (stderr && !stderr.includes('npm WARN')) { - console.warn('npm build warnings:', stderr); - } - steps.push('✅ Application built successfully'); - } catch (error) { - const errorMsg = `Failed to build application: ${error instanceof Error ? error.message : 'Unknown error'}`; - steps.push(`❌ ${errorMsg}`); - return { - success: false, - message: errorMsg, - steps - }; - } - - // Step 4: Restart server (this will be handled by the process manager) - steps.push('🔄 Server restart required - please restart manually or use a process manager'); - steps.push('✅ Update process completed successfully'); - - return { - success: true, - message: 'Repository updated successfully. Please restart the server to apply changes.', - steps - }; - - } catch (error) { - const errorMsg = `Update failed: ${error instanceof Error ? error.message : 'Unknown error'}`; - steps.push(`❌ ${errorMsg}`); - return { - success: false, - message: errorMsg, - steps - }; - } - } - - /** - * Clone the repository if it doesn't exist - */ - private async cloneRepository(): Promise<{ success: boolean; message: string }> { - try { - if (!env.ORIGINAL_REPO_URL) { - return { success: false, message: 'No repository URL configured' }; - } - - - // Clone the repository - await this.git.clone(env.ORIGINAL_REPO_URL, this.repoPath, [ - '--branch', env.REPO_BRANCH, - '--single-branch', - '--depth', '1' - ]); - - return { - success: true, - message: `Successfully cloned repository from ${env.ORIGINAL_REPO_URL}` - }; - } catch (error) { - console.error('Error cloning repository:', error); - return { - success: false, - message: `Failed to clone repository: ${error instanceof Error ? error.message : 'Unknown error'}` - }; - } - } - - /** - * Initialize repository on startup if needed - */ - async initializeRepository(): Promise { - try { - if (!env.ORIGINAL_REPO_URL) { - return; - } - - const isRepo = await this.git.checkIsRepo(); - if (!isRepo) { - const result = await this.cloneRepository(); - if (result.success) { - } else { - } - } else { - const behind = await this.isBehindRemote(); - if (behind) { - const result = await this.pullUpdates(); - if (result.success) { - } else { - } - } else { - } - } - } catch (error) { - console.error('Error initializing repository:', error); - } - } - - /** - * Get repository status information - */ - async getStatus(): Promise<{ - isRepo: boolean; - isBehind: boolean; - lastCommit?: string; - branch?: string; - }> { - try { - const isRepo = await this.git.checkIsRepo(); - if (!isRepo) { - return { isRepo: false, isBehind: false }; - } - - const isBehind = await this.isBehindRemote(); - const log = await this.git.log({ maxCount: 1 }); - const status = await this.git.status(); - - return { - isRepo: true, - isBehind, - lastCommit: log.latest?.hash ?? undefined, - branch: status.current ?? undefined - }; - } catch (error) { - console.error('Error getting repository status:', error); - return { isRepo: false, isBehind: false }; - } - } -} - -// Export singleton instance -export const gitManager = new GitManager(); - -// Initialize repository on module load -gitManager.initializeRepository().catch(console.error);