Compare commits

..

27 Commits

Author SHA1 Message Date
Michel Rögl-Brunner
944a527972 fix: normalize failed item error type for TypeScript build 2026-01-29 11:22:43 +01:00
Michel Rögl-Brunner
34eade3971 feat: add Update all downloaded scripts button
- Add bulk update button on Downloaded Scripts tab
- Use existing loadMultipleScripts API for all downloaded script slugs
- Confirmation modal before running (may take several minutes)
- Inline result: success/fail counts, hover for failed slugs
- Invalidate getAllDownloadedScripts and getScriptCardsWithCategories on success
2026-01-29 11:17:36 +01:00
Michel Roegl-Brunner
9b77fc7ddb Merge pull request #468 from community-scripts/fix/465
fix: advanced modal SSH key discovery and tags delimiter
2026-01-29 10:27:56 +01:00
Michel Rögl-Brunner
db12ac4219 fix: advanced modal SSH key discovery and tags delimiter
- Allow ; as alternative to , for tags field (normalize on submit)
- Add GET /api/servers/[id]/discover-ssh-keys to find host SSH keys like native advanced mode
- Advanced modal: fetch discovered keys, dropdown to select + manual paste input
- Label/placeholder: Tags (comma or semicolon separated), e.g. tag1; tag2
2026-01-29 10:23:17 +01:00
Michel Roegl-Brunner
f66d1db861 Merge pull request #467 from community-scripts/fix/398
feat(ConfigurationModal): add Container ID (CTID) and DNS Search Domain to advanced install
2026-01-29 10:10:45 +01:00
Michel Rögl-Brunner
886c3e37ff feat(ConfigurationModal): add Container ID (CTID) and DNS Search Domain to advanced install
- Add optional Container ID (CTID) field at top of advanced form (var_ctid)
- Add DNS Search Domain field in Network section (var_searchdomain)
- Validate CTID when set: integer >= 100; empty = use next available ID
- Both fields optional; empty values omitted from env so script uses defaults
2026-01-29 10:05:14 +01:00
root
38deb09aa9 Add ctid option 2026-01-29 10:01:30 +01:00
dependabot[bot]
6d326dce1f build(deps): Bump next from 16.1.2 to 16.1.3 (#453)
Bumps [next](https://github.com/vercel/next.js) from 16.1.2 to 16.1.3.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.1.2...v16.1.3)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 21:19:21 +01:00
dependabot[bot]
6c8e177d3e build(deps-dev): Bump baseline-browser-mapping from 2.9.14 to 2.9.15 (#454)
Bumps [baseline-browser-mapping](https://github.com/web-platform-dx/baseline-browser-mapping) from 2.9.14 to 2.9.15.
- [Release notes](https://github.com/web-platform-dx/baseline-browser-mapping/releases)
- [Commits](https://github.com/web-platform-dx/baseline-browser-mapping/compare/v2.9.14...v2.9.15)

---
updated-dependencies:
- dependency-name: baseline-browser-mapping
  dependency-version: 2.9.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 21:19:11 +01:00
dependabot[bot]
879a548345 build(deps-dev): Bump eslint-config-next from 16.1.2 to 16.1.3 (#455)
Bumps [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) from 16.1.2 to 16.1.3.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v16.1.3/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: eslint-config-next
  dependency-version: 16.1.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 21:19:01 +01:00
dependabot[bot]
64cd81d5ba build(deps): Bump @tanstack/react-query from 5.90.17 to 5.90.18 (#456)
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.90.17 to 5.90.18.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.90.18/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.90.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 21:18:49 +01:00
Michel Roegl-Brunner
61e75949c8 Merge pull request #452 from community-scripts/dependabot/npm_and_yarn/prettier-3.8.0 2026-01-15 21:02:14 +01:00
Michel Roegl-Brunner
a5d24bfad7 Merge pull request #451 from community-scripts/dependabot/npm_and_yarn/eslint-config-next-16.1.2 2026-01-15 21:02:01 +01:00
Michel Roegl-Brunner
04595c0093 Merge pull request #450 from community-scripts/dependabot/npm_and_yarn/next-16.1.2 2026-01-15 21:01:51 +01:00
Michel Roegl-Brunner
06fdb4889d Merge pull request #449 from community-scripts/dependabot/npm_and_yarn/types/node-24.10.9 2026-01-15 21:01:33 +01:00
dependabot[bot]
38d4f9f918 build(deps-dev): Bump prettier from 3.7.4 to 3.8.0
Bumps [prettier](https://github.com/prettier/prettier) from 3.7.4 to 3.8.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.7.4...3.8.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-15 19:57:36 +00:00
dependabot[bot]
63dc7c6983 build(deps-dev): Bump eslint-config-next from 16.1.1 to 16.1.2
Bumps [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) from 16.1.1 to 16.1.2.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v16.1.2/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: eslint-config-next
  dependency-version: 16.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-15 19:57:08 +00:00
dependabot[bot]
d57c6059fc build(deps): Bump next from 16.1.1 to 16.1.2
Bumps [next](https://github.com/vercel/next.js) from 16.1.1 to 16.1.2.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.1.1...v16.1.2)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-15 19:56:46 +00:00
dependabot[bot]
eb152f9fae build(deps-dev): Bump @types/node from 24.10.8 to 24.10.9
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.8 to 24.10.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.10.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-15 19:56:22 +00:00
Michel Roegl-Brunner
1a8e98fec0 Merge pull request #448 from community-scripts/dependabot/npm_and_yarn/tanstack/react-query-5.90.17 2026-01-15 14:24:10 +01:00
Michel Roegl-Brunner
83a1c7ea31 Merge pull request #446 from community-scripts/dependabot/npm_and_yarn/types/node-24.10.8 2026-01-15 14:23:57 +01:00
dependabot[bot]
79c63a7d3d build(deps): Bump @tanstack/react-query from 5.90.16 to 5.90.17
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.90.16 to 5.90.17.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.90.17/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.90.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-14 19:57:01 +00:00
dependabot[bot]
753721eee0 build(deps-dev): Bump @types/node from 24.10.4 to 24.10.8
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.4 to 24.10.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.10.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-13 20:01:03 +00:00
github-actions[bot]
09607296af chore: add VERSION v0.5.5 (#445)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-13 17:03:29 +00:00
CanbiZ (MickLesk)
c88040084a Improve server startup logging and update script fetching (#443)
Adds success and error logging to the Next.js app preparation process in server.js, including guidance for missing production builds. In versionRouter, always fetches the latest update.sh from GitHub before running updates, logging the outcome and falling back to the local script if fetching fails.
2026-01-13 18:03:01 +01:00
CanbiZ (MickLesk)
2573eb7314 github: improve PR template (#444) 2026-01-13 18:02:41 +01:00
github-actions[bot]
414c356446 chore: add VERSION v0.5.4 (#441)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-13 16:05:32 +00:00
11 changed files with 415 additions and 98 deletions

View File

@@ -4,7 +4,7 @@
## 🔗 Related PR / Issue
Link: #
Fixes: #
## ✅ Prerequisites (**X** in brackets)

View File

@@ -1 +1 @@
0.5.4
0.5.5

190
package-lock.json generated
View File

@@ -15,7 +15,7 @@
"@radix-ui/react-slot": "^1.2.4",
"@t3-oss/env-nextjs": "^0.13.10",
"@tailwindcss/typography": "^0.5.19",
"@tanstack/react-query": "^5.90.16",
"@tanstack/react-query": "^5.90.18",
"@trpc/client": "^11.8.1",
"@trpc/react-query": "^11.8.1",
"@trpc/server": "^11.8.1",
@@ -33,7 +33,7 @@
"dotenv": "^17.2.3",
"jsonwebtoken": "^9.0.3",
"lucide-react": "^0.562.0",
"next": "^16.1.1",
"next": "^16.1.3",
"node-cron": "^4.2.1",
"node-pty": "^1.1.0",
"react": "^19.2.3",
@@ -57,19 +57,19 @@
"@types/bcryptjs": "^3.0.0",
"@types/better-sqlite3": "^7.6.13",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.10.4",
"@types/node": "^24.10.9",
"@types/node-cron": "^3.0.11",
"@types/react": "^19.2.8",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2",
"@vitest/coverage-v8": "^4.0.17",
"@vitest/ui": "^4.0.17",
"baseline-browser-mapping": "^2.9.14",
"baseline-browser-mapping": "^2.9.15",
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.1",
"eslint-config-next": "^16.1.3",
"jsdom": "^27.4.0",
"postcss": "^8.5.6",
"prettier": "^3.7.4",
"prettier": "^3.8.0",
"prettier-plugin-tailwindcss": "^0.7.2",
"prisma": "^7.2.0",
"tailwindcss": "^4.1.18",
@@ -195,6 +195,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -310,7 +311,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"devOptional": true,
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -320,7 +321,7 @@
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"devOptional": true,
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -354,7 +355,7 @@
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"devOptional": true,
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.28.5"
@@ -445,7 +446,7 @@
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"devOptional": true,
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -590,6 +591,7 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
},
@@ -633,6 +635,7 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@@ -642,7 +645,8 @@
"resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.2.tgz",
"integrity": "sha512-zfWWa+V2ViDCY/cmUfRqeWY1yLto+EpxjXnZzenB1TyxsTiXaTWeZFIZw6mac52BsuQm0RjCnisjBtdBaXOI6w==",
"devOptional": true,
"license": "Apache-2.0"
"license": "Apache-2.0",
"peer": true
},
"node_modules/@electric-sql/pglite-socket": {
"version": "0.0.6",
@@ -1951,15 +1955,15 @@
}
},
"node_modules/@next/env": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.1.tgz",
"integrity": "sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.3.tgz",
"integrity": "sha512-BLP14oBOvZWXgfdJf9ao+VD8O30uE+x7PaV++QtACLX329WcRSJRO5YJ+Bcvu0Q+c/lei41TjSiFf6pXqnpbQA==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.1.tgz",
"integrity": "sha512-Ovb/6TuLKbE1UiPcg0p39Ke3puyTCIKN9hGbNItmpQsp+WX3qrjO3WaMVSi6JHr9X1NrmthqIguVHodMJbh/dw==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.3.tgz",
"integrity": "sha512-MqBh3ltFAy0AZCRFVdjVjjeV7nEszJDaVIpDAnkQcn8U9ib6OEwkSnuK6xdYxMGPhV/Y4IlY6RbDipPOpLfBqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1967,9 +1971,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.1.tgz",
"integrity": "sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.3.tgz",
"integrity": "sha512-CpOD3lmig6VflihVoGxiR/l5Jkjfi4uLaOR4ziriMv0YMDoF6cclI+p5t2nstM8TmaFiY6PCTBgRWB57/+LiBA==",
"cpu": [
"arm64"
],
@@ -1983,9 +1987,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.1.tgz",
"integrity": "sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.3.tgz",
"integrity": "sha512-aF4us2JXh0zn3hNxvL1Bx3BOuh8Lcw3p3Xnurlvca/iptrDH1BrpObwkw9WZra7L7/0qB9kjlREq3hN/4x4x+Q==",
"cpu": [
"x64"
],
@@ -1999,9 +2003,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.1.tgz",
"integrity": "sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.3.tgz",
"integrity": "sha512-8VRkcpcfBtYvhGgXAF7U3MBx6+G1lACM1XCo1JyaUr4KmAkTNP8Dv2wdMq7BI+jqRBw3zQE7c57+lmp7jCFfKA==",
"cpu": [
"arm64"
],
@@ -2015,9 +2019,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.1.tgz",
"integrity": "sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.3.tgz",
"integrity": "sha512-UbFx69E2UP7MhzogJRMFvV9KdEn4sLGPicClwgqnLht2TEi204B71HuVfps3ymGAh0c44QRAF+ZmvZZhLLmhNg==",
"cpu": [
"arm64"
],
@@ -2031,9 +2035,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.1.tgz",
"integrity": "sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.3.tgz",
"integrity": "sha512-SzGTfTjR5e9T+sZh5zXqG/oeRQufExxBF6MssXS7HPeZFE98JDhCRZXpSyCfWrWrYrzmnw/RVhlP2AxQm+wkRQ==",
"cpu": [
"x64"
],
@@ -2047,9 +2051,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.1.tgz",
"integrity": "sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.3.tgz",
"integrity": "sha512-HlrDpj0v+JBIvQex1mXHq93Mht5qQmfyci+ZNwGClnAQldSfxI6h0Vupte1dSR4ueNv4q7qp5kTnmLOBIQnGow==",
"cpu": [
"x64"
],
@@ -2063,9 +2067,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.1.tgz",
"integrity": "sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.3.tgz",
"integrity": "sha512-3gFCp83/LSduZMSIa+lBREP7+5e7FxpdBoc9QrCdmp+dapmTK9I+SLpY60Z39GDmTXSZA4huGg9WwmYbr6+WRw==",
"cpu": [
"arm64"
],
@@ -2079,9 +2083,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.1.tgz",
"integrity": "sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.3.tgz",
"integrity": "sha512-1SZVfFT8zmMB+Oblrh5OKDvUo5mYQOkX2We6VGzpg7JUVZlqe4DYOFGKYZKTweSx1gbMixyO1jnFT4thU+nNHQ==",
"cpu": [
"x64"
],
@@ -3705,9 +3709,9 @@
}
},
"node_modules/@tanstack/query-core": {
"version": "5.90.16",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.16.tgz",
"integrity": "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww==",
"version": "5.90.18",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.18.tgz",
"integrity": "sha512-rbGx6bHgPNVzutP7BEr+53UPKohpckqlMAad+To9UxTbeaQ+kC/1SDRj+QzkwbQ7qhLT/1IKp34yS6thda6fzA==",
"license": "MIT",
"funding": {
"type": "github",
@@ -3715,12 +3719,13 @@
}
},
"node_modules/@tanstack/react-query": {
"version": "5.90.16",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.16.tgz",
"integrity": "sha512-bpMGOmV4OPmif7TNMteU/Ehf/hoC0Kf98PDc0F4BZkFrEapRMEqI/V6YS0lyzwSV6PQpY1y4xxArUIfBW5LVxQ==",
"version": "5.90.18",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.18.tgz",
"integrity": "sha512-KqNZX0C5IFz4639zR1ilnQ288tQdJrMNLtzmlzyJ14xauBkhtLEy3mPU/V4KiHsr41eL1ILZbDP36TB12lYfCQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@tanstack/query-core": "5.90.16"
"@tanstack/query-core": "5.90.18"
},
"funding": {
"type": "github",
@@ -3828,6 +3833,7 @@
"https://trpc.io/sponsor"
],
"license": "MIT",
"peer": true,
"peerDependencies": {
"@trpc/server": "11.8.1",
"typescript": ">=5.7.2"
@@ -3858,6 +3864,7 @@
"https://trpc.io/sponsor"
],
"license": "MIT",
"peer": true,
"peerDependencies": {
"typescript": ">=5.7.2"
}
@@ -3878,8 +3885,7 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -4039,9 +4045,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.10.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz",
"integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==",
"version": "24.10.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz",
"integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
@@ -4065,6 +4071,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz",
"integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==",
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -4075,6 +4082,7 @@
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"devOptional": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -4148,6 +4156,7 @@
"integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.53.0",
"@typescript-eslint/types": "8.53.0",
@@ -4802,6 +4811,7 @@
"integrity": "sha512-hRDjg6dlDz7JlZAvjbiCdAJ3SDG+NH8tjZe21vjxfvT2ssYAn72SRXMge3dKKABm3bIJ3C+3wdunIdur8PHEAw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/utils": "4.0.17",
"fflate": "^0.8.2",
@@ -4859,6 +4869,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4909,7 +4920,6 @@
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=8"
}
@@ -5266,9 +5276,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.9.14",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz",
"integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==",
"version": "2.9.15",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz",
"integrity": "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==",
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
@@ -5371,6 +5381,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.25",
"caniuse-lite": "^1.0.30001754",
@@ -6096,8 +6107,7 @@
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/dotenv": {
"version": "17.2.3",
@@ -6456,6 +6466,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -6511,13 +6522,13 @@
}
},
"node_modules/eslint-config-next": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.1.tgz",
"integrity": "sha512-55nTpVWm3qeuxoQKLOjQVciKZJUphKrNM0fCcQHAIOGl6VFXgaqeMfv0aKJhs7QtcnlAPhNVqsqRfRjeKBPIUA==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.3.tgz",
"integrity": "sha512-q2Z87VSsoJcv+vgR+Dm8NPRf+rErXcRktuBR5y3umo/j5zLjIWH7rqBCh3X804gUGKbOrqbgsLUkqDE35C93Gw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@next/eslint-plugin-next": "16.1.1",
"@next/eslint-plugin-next": "16.1.3",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.32.0",
@@ -6641,6 +6652,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -7654,6 +7666,7 @@
"integrity": "sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==",
"devOptional": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=16.9.0"
}
@@ -8427,6 +8440,7 @@
"integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@acemir/cssom": "^0.9.28",
"@asamuzakjp/dom-selector": "^6.7.6",
@@ -9051,7 +9065,6 @@
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -10198,12 +10211,12 @@
"license": "MIT"
},
"node_modules/next": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/next/-/next-16.1.1.tgz",
"integrity": "sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==",
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/next/-/next-16.1.3.tgz",
"integrity": "sha512-gthG3TRD+E3/mA0uDQb9lqBmx1zVosq5kIwxNN6+MRNd085GzD+9VXMPUs+GGZCbZ+GDZdODUq4Pm7CTXK6ipw==",
"license": "MIT",
"dependencies": {
"@next/env": "16.1.1",
"@next/env": "16.1.3",
"@swc/helpers": "0.5.15",
"baseline-browser-mapping": "^2.8.3",
"caniuse-lite": "^1.0.30001579",
@@ -10217,14 +10230,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
"@next/swc-darwin-arm64": "16.1.1",
"@next/swc-darwin-x64": "16.1.1",
"@next/swc-linux-arm64-gnu": "16.1.1",
"@next/swc-linux-arm64-musl": "16.1.1",
"@next/swc-linux-x64-gnu": "16.1.1",
"@next/swc-linux-x64-musl": "16.1.1",
"@next/swc-win32-arm64-msvc": "16.1.1",
"@next/swc-win32-x64-msvc": "16.1.1",
"@next/swc-darwin-arm64": "16.1.3",
"@next/swc-darwin-x64": "16.1.3",
"@next/swc-linux-arm64-gnu": "16.1.3",
"@next/swc-linux-arm64-musl": "16.1.3",
"@next/swc-linux-x64-gnu": "16.1.3",
"@next/swc-linux-x64-musl": "16.1.3",
"@next/swc-win32-arm64-msvc": "16.1.3",
"@next/swc-win32-x64-msvc": "16.1.3",
"sharp": "^0.34.4"
},
"peerDependencies": {
@@ -10805,11 +10818,12 @@
}
},
"node_modules/prettier": {
"version": "3.7.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.0.tgz",
"integrity": "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -10905,7 +10919,6 @@
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -10921,7 +10934,6 @@
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10"
},
@@ -10936,6 +10948,7 @@
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@prisma/config": "7.2.0",
"@prisma/dev": "0.17.0",
@@ -11124,6 +11137,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11133,6 +11147,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -11145,8 +11160,7 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/react-markdown": {
"version": "10.1.0",
@@ -12369,7 +12383,8 @@
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/tapable": {
"version": "2.3.0",
@@ -12471,6 +12486,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -13247,6 +13263,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -13522,6 +13539,7 @@
"integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==",
"devOptional": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"typescript": ">=5"
},
@@ -13565,6 +13583,7 @@
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -13658,6 +13677,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -13671,6 +13691,7 @@
"integrity": "sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/expect": "4.0.17",
"@vitest/mocker": "4.0.17",
@@ -14014,6 +14035,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz",
"integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View File

@@ -31,7 +31,7 @@
"@radix-ui/react-slot": "^1.2.4",
"@t3-oss/env-nextjs": "^0.13.10",
"@tailwindcss/typography": "^0.5.19",
"@tanstack/react-query": "^5.90.16",
"@tanstack/react-query": "^5.90.18",
"@trpc/client": "^11.8.1",
"@trpc/react-query": "^11.8.1",
"@trpc/server": "^11.8.1",
@@ -49,7 +49,7 @@
"dotenv": "^17.2.3",
"jsonwebtoken": "^9.0.3",
"lucide-react": "^0.562.0",
"next": "^16.1.1",
"next": "^16.1.3",
"node-cron": "^4.2.1",
"node-pty": "^1.1.0",
"react": "^19.2.3",
@@ -73,19 +73,19 @@
"@types/bcryptjs": "^3.0.0",
"@types/better-sqlite3": "^7.6.13",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.10.4",
"@types/node": "^24.10.9",
"@types/node-cron": "^3.0.11",
"@types/react": "^19.2.8",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2",
"@vitest/coverage-v8": "^4.0.17",
"@vitest/ui": "^4.0.17",
"baseline-browser-mapping": "^2.9.14",
"baseline-browser-mapping": "^2.9.15",
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.1",
"eslint-config-next": "^16.1.3",
"jsdom": "^27.4.0",
"postcss": "^8.5.6",
"prettier": "^3.7.4",
"prettier": "^3.8.0",
"prettier-plugin-tailwindcss": "^0.7.2",
"prisma": "^7.2.0",
"tailwindcss": "^4.1.18",

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
SCRIPT_DIR="$(dirname "$0")"
source "$SCRIPT_DIR/../core/build.func"
# Copyright (c) 2021-2025 tteck
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.debian.org/
@@ -40,5 +40,5 @@ start
build_container
description
msg_ok "Completed Successfully!\n"
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 tteck
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.debian.org/

View File

@@ -1610,6 +1610,7 @@ class ScriptExecutionHandler {
// TerminalHandler removed - not used by current application
app.prepare().then(() => {
console.log('> Next.js app prepared successfully');
const httpServer = createServer(async (req, res) => {
try {
// Be sure to pass `true` as the second argument to `url.parse`.
@@ -1715,4 +1716,9 @@ app.prepare().then(() => {
autoSyncModule.setupGracefulShutdown();
}
});
}).catch((err) => {
console.error('> Failed to start server:', err.message);
console.error('> If you see "Could not find a production build", run: npm run build');
console.error('> Full error:', err);
process.exit(1);
});

View File

@@ -58,6 +58,11 @@ export function ConfigurationModal({
// Advanced mode state
const [advancedVars, setAdvancedVars] = useState<EnvVars>({});
// Discovered SSH keys on the Proxmox host (advanced mode only)
const [discoveredSshKeys, setDiscoveredSshKeys] = useState<string[]>([]);
const [discoveredSshKeysLoading, setDiscoveredSshKeysLoading] = useState(false);
const [discoveredSshKeysError, setDiscoveredSshKeysError] = useState<string | null>(null);
// Validation errors
const [errors, setErrors] = useState<Record<string, string>>({});
@@ -119,6 +124,38 @@ export function ConfigurationModal({
}
}, [actualScript, server, mode, resources, slug]);
// Discover SSH keys on the Proxmox host when advanced mode is open
useEffect(() => {
if (!server?.id || !isOpen || mode !== 'advanced') {
setDiscoveredSshKeys([]);
setDiscoveredSshKeysError(null);
return;
}
let cancelled = false;
setDiscoveredSshKeysLoading(true);
setDiscoveredSshKeysError(null);
fetch(`/api/servers/${server.id}/discover-ssh-keys`)
.then((res) => {
if (!res.ok) throw new Error(res.status === 404 ? 'Server not found' : res.statusText);
return res.json();
})
.then((data: { keys?: string[] }) => {
if (!cancelled && Array.isArray(data.keys)) setDiscoveredSshKeys(data.keys);
})
.catch((err) => {
if (!cancelled) {
setDiscoveredSshKeys([]);
setDiscoveredSshKeysError(err instanceof Error ? err.message : 'Could not detect keys');
}
})
.finally(() => {
if (!cancelled) setDiscoveredSshKeysLoading(false);
});
return () => {
cancelled = true;
};
}, [server?.id, isOpen, mode]);
// Validation functions
const validateIPv4 = (ip: string): boolean => {
if (!ip) return true; // Empty is allowed (auto)
@@ -275,6 +312,16 @@ export function ConfigurationModal({
if ((hasPassword || hasSSHKey) && envVars.var_ssh !== 'no') {
envVars.var_ssh = 'yes';
}
// Normalize var_tags: accept both comma and semicolon, output comma-separated
const rawTags = envVars.var_tags;
if (typeof rawTags === 'string' && rawTags.trim() !== '') {
envVars.var_tags = rawTags
.split(/[,;]/)
.map((s) => s.trim())
.filter(Boolean)
.join(',');
}
}
// Remove empty string values (but keep 0, false, etc.)
@@ -644,13 +691,13 @@ export function ConfigurationModal({
</div>
<div className="col-span-2">
<label className="block text-sm font-medium text-foreground mb-2">
Tags (comma-separated)
Tags (comma or semicolon separated)
</label>
<Input
type="text"
value={typeof advancedVars.var_tags === 'boolean' ? '' : String(advancedVars.var_tags ?? '')}
onChange={(e) => updateAdvancedVar('var_tags', e.target.value)}
placeholder="community-script"
placeholder="e.g. tag1; tag2"
/>
</div>
</div>
@@ -677,11 +724,40 @@ export function ConfigurationModal({
<label className="block text-sm font-medium text-foreground mb-2">
SSH Authorized Key
</label>
{discoveredSshKeysLoading && (
<p className="text-sm text-muted-foreground mb-2">Detecting SSH keys...</p>
)}
{discoveredSshKeysError && !discoveredSshKeysLoading && (
<p className="text-sm text-muted-foreground mb-2">Could not detect keys on host</p>
)}
{discoveredSshKeys.length > 0 && !discoveredSshKeysLoading && (
<div className="mb-2">
<label htmlFor="discover-ssh-key" className="sr-only">Use detected key</label>
<select
id="discover-ssh-key"
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus:ring-2 focus:ring-ring focus:outline-none mb-2"
value=""
onChange={(e) => {
const idx = e.target.value;
if (idx === '') return;
const key = discoveredSshKeys[Number(idx)];
if (key) updateAdvancedVar('var_ssh_authorized_key', key);
}}
>
<option value=""> Select or paste below </option>
{discoveredSshKeys.map((key, i) => (
<option key={i} value={i}>
{key.length > 44 ? `${key.slice(0, 44)}...` : key}
</option>
))}
</select>
</div>
)}
<Input
type="text"
value={typeof advancedVars.var_ssh_authorized_key === 'boolean' ? '' : String(advancedVars.var_ssh_authorized_key ?? '')}
onChange={(e) => updateAdvancedVar('var_ssh_authorized_key', e.target.value)}
placeholder="ssh-rsa AAAA..."
placeholder="Or paste a public key: ssh-rsa AAAA..."
/>
</div>
</div>

View File

@@ -8,7 +8,9 @@ import { ScriptDetailModal } from "./ScriptDetailModal";
import { CategorySidebar } from "./CategorySidebar";
import { FilterBar, type FilterState } from "./FilterBar";
import { ViewToggle } from "./ViewToggle";
import { ConfirmationModal } from "./ConfirmationModal";
import { Button } from "./ui/button";
import { RefreshCw } from "lucide-react";
import type { ScriptCard as ScriptCardType } from "~/types/script";
import type { Server } from "~/types/server";
import { getDefaultFilters, mergeFiltersWithDefaults } from "./filterUtils";
@@ -32,8 +34,15 @@ export function DownloadedScriptsTab({
const [filters, setFilters] = useState<FilterState>(getDefaultFilters());
const [saveFiltersEnabled, setSaveFiltersEnabled] = useState(false);
const [isLoadingFilters, setIsLoadingFilters] = useState(true);
const [updateAllConfirmOpen, setUpdateAllConfirmOpen] = useState(false);
const [updateResult, setUpdateResult] = useState<{
successCount: number;
failCount: number;
failed: { slug: string; error: string }[];
} | null>(null);
const gridRef = useRef<HTMLDivElement>(null);
const utils = api.useUtils();
const {
data: scriptCardsData,
isLoading: githubLoading,
@@ -50,6 +59,30 @@ export function DownloadedScriptsTab({
{ enabled: !!selectedSlug },
);
const loadMultipleScriptsMutation = api.scripts.loadMultipleScripts.useMutation({
onSuccess: (data) => {
void utils.scripts.getAllDownloadedScripts.invalidate();
void utils.scripts.getScriptCardsWithCategories.invalidate();
setUpdateResult({
successCount: data.successful?.length ?? 0,
failCount: data.failed?.length ?? 0,
failed: (data.failed ?? []).map((f) => ({
slug: f.slug,
error: f.error ?? "Unknown error",
})),
});
setTimeout(() => setUpdateResult(null), 8000);
},
onError: (error) => {
setUpdateResult({
successCount: 0,
failCount: 1,
failed: [{ slug: "Request failed", error: error.message }],
});
setTimeout(() => setUpdateResult(null), 8000);
},
});
// Load SAVE_FILTER setting, saved filters, and view mode on component mount
useEffect(() => {
const loadSettings = async () => {
@@ -416,6 +449,21 @@ export function DownloadedScriptsTab({
setSelectedSlug(null);
};
const handleUpdateAllClick = () => {
setUpdateResult(null);
setUpdateAllConfirmOpen(true);
};
const handleUpdateAllConfirm = () => {
setUpdateAllConfirmOpen(false);
const slugs = downloadedScripts
.map((s) => s.slug)
.filter((slug): slug is string => Boolean(slug));
if (slugs.length > 0) {
loadMultipleScriptsMutation.mutate({ slugs });
}
};
if (githubLoading || localLoading) {
return (
<div className="flex items-center justify-center py-12">
@@ -508,6 +556,43 @@ export function DownloadedScriptsTab({
{/* Main Content */}
<div className="order-1 min-w-0 flex-1 lg:order-2" ref={gridRef}>
{/* Update all downloaded scripts */}
<div className="mb-4 flex flex-wrap items-center gap-3">
<Button
onClick={handleUpdateAllClick}
disabled={loadMultipleScriptsMutation.isPending}
variant="secondary"
size="default"
className="flex items-center gap-2"
>
{loadMultipleScriptsMutation.isPending ? (
<>
<RefreshCw className="h-4 w-4 animate-spin" />
<span>Updating...</span>
</>
) : (
<>
<RefreshCw className="h-4 w-4" />
<span>Update all downloaded scripts</span>
</>
)}
</Button>
{updateResult && (
<span className="text-muted-foreground text-sm">
Updated {updateResult.successCount} successfully
{updateResult.failCount > 0
? `, ${updateResult.failCount} failed`
: ""}
.
{updateResult.failCount > 0 && updateResult.failed.length > 0 && (
<span className="ml-1" title={updateResult.failed.map((f) => `${f.slug}: ${f.error}`).join("\n")}>
(hover for details)
</span>
)}
</span>
)}
</div>
{/* Enhanced Filter Bar */}
<FilterBar
filters={filters}
@@ -621,6 +706,17 @@ export function DownloadedScriptsTab({
onClose={handleCloseModal}
onInstallScript={onInstallScript}
/>
<ConfirmationModal
isOpen={updateAllConfirmOpen}
onClose={() => setUpdateAllConfirmOpen(false)}
onConfirm={handleUpdateAllConfirm}
title="Update all downloaded scripts"
message={`Update all ${downloadedScripts.length} downloaded scripts? This may take several minutes.`}
variant="simple"
confirmButtonText="Update all"
cancelButtonText="Cancel"
/>
</div>
</div>
</div>

View File

@@ -0,0 +1,96 @@
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { getDatabase } from '../../../../../server/database-prisma';
import { getSSHExecutionService } from '../../../../../server/ssh-execution-service';
import type { Server } from '~/types/server';
const DISCOVER_TIMEOUT_MS = 10_000;
/** Match lines that look like SSH public keys (same as build.func) */
const SSH_PUBKEY_RE = /^(ssh-(rsa|ed25519)|ecdsa-sha2-nistp256|sk-(ssh-ed25519|ecdsa-sha2-nistp256))\s+/;
/**
* Run a command on the Proxmox host and return buffered stdout.
* Resolves when the process exits or rejects on timeout/spawn error.
*/
function runRemoteCommand(
server: Server,
command: string,
timeoutMs: number
): Promise<{ stdout: string; exitCode: number }> {
const ssh = getSSHExecutionService();
return new Promise((resolve, reject) => {
const chunks: string[] = [];
let settled = false;
const finish = (stdout: string, exitCode: number) => {
if (settled) return;
settled = true;
clearTimeout(timer);
resolve({ stdout, exitCode });
};
const timer = setTimeout(() => {
if (settled) return;
settled = true;
reject(new Error('SSH discover keys timeout'));
}, timeoutMs);
ssh
.executeCommand(
server,
command,
(data: string) => chunks.push(data),
() => {},
(code: number) => finish(chunks.join(''), code)
)
.catch((err) => {
if (!settled) {
settled = true;
clearTimeout(timer);
reject(err);
}
});
});
}
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id: idParam } = await params;
const id = parseInt(idParam);
if (isNaN(id)) {
return NextResponse.json({ error: 'Invalid server ID' }, { status: 400 });
}
const db = getDatabase();
const server = await db.getServerById(id) as Server | null;
if (!server) {
return NextResponse.json({ error: 'Server not found' }, { status: 404 });
}
// Same paths as native build.func ssh_discover_default_files()
const remoteScript = `bash -c 'for f in /root/.ssh/authorized_keys /root/.ssh/authorized_keys2 /root/.ssh/*.pub /etc/ssh/authorized_keys /etc/ssh/authorized_keys.d/* 2>/dev/null; do [ -f "$f" ] && [ -r "$f" ] && grep -E "^(ssh-(rsa|ed25519)|ecdsa-sha2-nistp256|sk-)" "$f" 2>/dev/null; done | sort -u'`;
const { stdout } = await runRemoteCommand(server, remoteScript, DISCOVER_TIMEOUT_MS);
const keys = stdout
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.length > 0 && SSH_PUBKEY_RE.test(line));
return NextResponse.json({ keys });
} catch (error) {
console.error('Error discovering SSH keys:', error);
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : String(error),
},
{ status: 500 }
);
}
}

View File

@@ -238,6 +238,27 @@ export const versionRouter = createTRPCRouter({
// Clear/create the log file
await writeFile(logPath, '', 'utf-8');
// Always fetch the latest update.sh from GitHub before running
// This ensures we always use the newest update script, avoiding
// the "chicken-and-egg" problem where old scripts can't update properly
const updateScriptUrl = 'https://raw.githubusercontent.com/community-scripts/ProxmoxVE-Local/main/update.sh';
try {
const response = await fetch(updateScriptUrl);
if (response.ok) {
const latestScript = await response.text();
await writeFile(updateScriptPath, latestScript, { mode: 0o755 });
// Log that we fetched the latest script
await writeFile(logPath, '[INFO] Fetched latest update.sh from GitHub\n', { flag: 'a' });
} else {
// If fetch fails, log warning but continue with local script
await writeFile(logPath, `[WARNING] Could not fetch latest update.sh (HTTP ${response.status}), using local version\n`, { flag: 'a' });
}
} catch (fetchError) {
// If fetch fails, log warning but continue with local script
const errorMsg = fetchError instanceof Error ? fetchError.message : 'Unknown error';
await writeFile(logPath, `[WARNING] Could not fetch latest update.sh: ${errorMsg}, using local version\n`, { flag: 'a' });
}
// Spawn the update script as a detached process using nohup
// This allows it to run independently and kill the parent Node.js process
// Redirect output to log file