Compare commits

..

9 Commits

Author SHA1 Message Date
Michel Rögl-Brunner
7079c236ab chore: bump deps and overrides (next >=16.1.5, hono >=4.11.7, lodash >=4.17.23) 2026-01-29 14:27:56 +01:00
Michel Rögl-Brunner
b5c6beafff Fix #362: auto-detect race, VM shell path, UI hints
- Defer resolve in autoDetectLXCContainers (pct/qm list) so stdout is complete
- Pass containerType when opening shell; use qm terminal for VMs, pct enter for LXC
- Add UI hint for VM shell (serial console, Ctrl+O, serial port requirement)
- Rename auto-detect to Containers & VMs and update help text

Fixes #362
2026-01-29 14:12:49 +01:00
Michel Roegl-Brunner
a34566651a Merge pull request #475 from community-scripts/fix/438
Fix PBS certificate validation (Fixes #438)
2026-01-29 13:57:51 +01:00
Michel Rögl-Brunner
4628e67e5c Fix PBS certificate validation: pass PBS_FINGERPRINT, optional fingerprint for trusted CA
- Pass stored pbs_fingerprint as PBS_FINGERPRINT in login, snapshot list, and restore
- Allow empty fingerprint so trusted-CA PBS works without entering one
- Make fingerprint field optional in PBSCredentialsModal with updated helper text

Fixes #438
2026-01-29 13:55:53 +01:00
Michel Roegl-Brunner
578fa28461 Merge pull request #474 from community-scripts/fix/404
fix: allow domain names for APT Cacher in container creation UI
2026-01-29 13:42:31 +01:00
Michel Rögl-Brunner
9e6154b0de fix: allow domain names for APT Cacher in container creation UI
- Add validateHostname and validateAptCacherAddress (IPv4 or hostname)
- Use new validator for var_apt_cacher_ip; error message: Invalid IPv4 or hostname
- Label: APT Cacher host or IP; placeholder shows IP or hostname example

Fixes #404
2026-01-29 13:40:19 +01:00
Michel Roegl-Brunner
d29f71a92f Merge pull request #473 from community-scripts/fix/365
fix: detect app slug from LXC /usr/bin/update for port lookup
2026-01-29 13:28:36 +01:00
Michel Rögl-Brunner
aea14cda7e fix: detect app slug from LXC /usr/bin/update for port lookup
Resolve interface_port from community-scripts update file when hostname
differs from JSON slug (e.g. lxcpeanut vs peanut). Primary: slug parsed
from pct exec ... cat /usr/bin/update; fallback: hostname/suffix match.

Fixes #365
2026-01-29 13:26:29 +01:00
Michel Roegl-Brunner
4893ccda6e Merge pull request #472 from community-scripts/feat/406
feat: private/custom git repos - GitHub, GitLab, Bitbucket, custom
2026-01-29 13:11:54 +01:00
9 changed files with 359 additions and 231 deletions

391
package-lock.json generated
View File

@@ -33,7 +33,7 @@
"dotenv": "^17.2.3",
"jsonwebtoken": "^9.0.3",
"lucide-react": "^0.562.0",
"next": "^16.1.3",
"next": ">=16.1.5",
"node-cron": "^4.2.1",
"node-pty": "^1.1.0",
"react": "^19.2.3",
@@ -68,6 +68,7 @@
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.3",
"jsdom": "^27.4.0",
"next": ">=16.1.5",
"postcss": "^8.5.6",
"prettier": "^3.8.0",
"prettier-plugin-tailwindcss": "^0.7.2",
@@ -641,34 +642,34 @@
}
},
"node_modules/@electric-sql/pglite": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.2.tgz",
"integrity": "sha512-zfWWa+V2ViDCY/cmUfRqeWY1yLto+EpxjXnZzenB1TyxsTiXaTWeZFIZw6mac52BsuQm0RjCnisjBtdBaXOI6w==",
"version": "0.3.15",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz",
"integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true
},
"node_modules/@electric-sql/pglite-socket": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.6.tgz",
"integrity": "sha512-6RjmgzphIHIBA4NrMGJsjNWK4pu+bCWJlEWlwcxFTVY3WT86dFpKwbZaGWZV6C5Rd7sCk1Z0CI76QEfukLAUXw==",
"version": "0.0.20",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz",
"integrity": "sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==",
"devOptional": true,
"license": "Apache-2.0",
"bin": {
"pglite-server": "dist/scripts/server.js"
},
"peerDependencies": {
"@electric-sql/pglite": "0.3.2"
"@electric-sql/pglite": "0.3.15"
}
},
"node_modules/@electric-sql/pglite-tools": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.7.tgz",
"integrity": "sha512-9dAccClqxx4cZB+Ar9B+FZ5WgxDc/Xvl9DPrTWv+dYTf0YNubLzi4wHHRGRGhrJv15XwnyKcGOZAP1VXSneSUg==",
"version": "0.2.20",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz",
"integrity": "sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==",
"devOptional": true,
"license": "Apache-2.0",
"peerDependencies": {
"@electric-sql/pglite": "0.3.2"
"@electric-sql/pglite": "0.3.15"
}
},
"node_modules/@emnapi/core": {
@@ -687,6 +688,7 @@
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
"integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1347,9 +1349,9 @@
"license": "MIT"
},
"node_modules/@hono/node-server": {
"version": "1.19.6",
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.6.tgz",
"integrity": "sha512-Shz/KjlIeAhfiuE93NDKVdZ7HdBVLQAfdbaXEaoAVO3ic9ibRSLGIQGkcBbFyuLr+7/1D5ZCINM8B+6IvXeMtw==",
"version": "1.19.9",
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
"integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==",
"devOptional": true,
"license": "MIT",
"engines": {
@@ -1415,6 +1417,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
@@ -1428,6 +1431,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1450,6 +1454,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1472,6 +1477,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1488,6 +1494,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1504,6 +1511,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1520,6 +1528,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1536,6 +1545,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1552,6 +1562,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1568,6 +1579,7 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1584,6 +1596,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1600,6 +1613,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1616,6 +1630,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1632,6 +1647,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1654,6 +1670,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1676,6 +1693,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1698,6 +1716,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1720,6 +1739,7 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1742,6 +1762,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1764,6 +1785,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1786,6 +1808,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1808,6 +1831,7 @@
"cpu": [
"wasm32"
],
"dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
@@ -1827,6 +1851,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1846,6 +1871,7 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1865,6 +1891,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1928,9 +1955,9 @@
}
},
"node_modules/@mrleebo/prisma-ast": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.12.1.tgz",
"integrity": "sha512-JwqeCQ1U3fvccttHZq7Tk0m/TMC6WcFAQZdukypW3AzlJYKYTGNVd1ANU2GuhKnv4UQuOFj3oAl0LLG/gxFN1w==",
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz",
"integrity": "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@@ -1955,9 +1982,10 @@
}
},
"node_modules/@next/env": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz",
"integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
@@ -1971,12 +1999,13 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz",
"integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1987,12 +2016,13 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz",
"integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2003,12 +2033,13 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz",
"integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2019,12 +2050,13 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz",
"integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2035,12 +2067,13 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz",
"integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2051,12 +2084,13 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz",
"integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2067,12 +2101,13 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz",
"integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2083,12 +2118,13 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"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==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz",
"integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2194,9 +2230,9 @@
"license": "Apache-2.0"
},
"node_modules/@prisma/config": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.2.0.tgz",
"integrity": "sha512-qmvSnfQ6l/srBW1S7RZGfjTQhc44Yl3ldvU6y3pgmuLM+83SBDs6UQVgMtQuMRe9J3gGqB0RF8wER6RlXEr6jQ==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.3.0.tgz",
"integrity": "sha512-QyMV67+eXF7uMtKxTEeQqNu/Be7iH+3iDZOQZW5ttfbSwBamCSdwPszA0dum+Wx27I7anYTPLmRmMORKViSW1A==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
@@ -2255,38 +2291,31 @@
"license": "Apache-2.0"
},
"node_modules/@prisma/dev": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.17.0.tgz",
"integrity": "sha512-6sGebe5jxX+FEsQTpjHLzvOGPn6ypFQprcs3jcuIWv1Xp/5v6P/rjfdvAwTkP2iF6pDx2tCd8vGLNWcsWzImTA==",
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.20.0.tgz",
"integrity": "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==",
"devOptional": true,
"license": "ISC",
"dependencies": {
"@electric-sql/pglite": "0.3.2",
"@electric-sql/pglite-socket": "0.0.6",
"@electric-sql/pglite-tools": "0.2.7",
"@hono/node-server": "1.19.6",
"@mrleebo/prisma-ast": "0.12.1",
"@prisma/get-platform": "6.8.2",
"@prisma/query-plan-executor": "6.18.0",
"@electric-sql/pglite": "0.3.15",
"@electric-sql/pglite-socket": "0.0.20",
"@electric-sql/pglite-tools": "0.2.20",
"@hono/node-server": "1.19.9",
"@mrleebo/prisma-ast": "0.13.1",
"@prisma/get-platform": "7.2.0",
"@prisma/query-plan-executor": "7.2.0",
"foreground-child": "3.3.1",
"get-port-please": "3.1.2",
"hono": "4.10.6",
"get-port-please": "3.2.0",
"hono": "4.11.4",
"http-status-codes": "2.3.0",
"pathe": "2.0.3",
"proper-lockfile": "4.1.2",
"remeda": "2.21.3",
"std-env": "3.9.0",
"remeda": "2.33.4",
"std-env": "3.10.0",
"valibot": "1.2.0",
"zeptomatch": "2.0.2"
"zeptomatch": "2.1.0"
}
},
"node_modules/@prisma/dev/node_modules/std-env": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz",
"integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
"devOptional": true,
"license": "MIT"
},
"node_modules/@prisma/driver-adapter-utils": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.2.0.tgz",
@@ -2297,49 +2326,73 @@
}
},
"node_modules/@prisma/engines": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.2.0.tgz",
"integrity": "sha512-HUeOI/SvCDsHrR9QZn24cxxZcujOjcS3w1oW/XVhnSATAli5SRMOfp/WkG3TtT5rCxDA4xOnlJkW7xkho4nURA==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.3.0.tgz",
"integrity": "sha512-cWRQoPDXPtR6stOWuWFZf9pHdQ/o8/QNWn0m0zByxf5Kd946Q875XdEJ52pEsX88vOiXUmjuPG3euw82mwQNMg==",
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.2.0",
"@prisma/engines-version": "7.2.0-4.0c8ef2ce45c83248ab3df073180d5eda9e8be7a3",
"@prisma/fetch-engine": "7.2.0",
"@prisma/get-platform": "7.2.0"
"@prisma/debug": "7.3.0",
"@prisma/engines-version": "7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735",
"@prisma/fetch-engine": "7.3.0",
"@prisma/get-platform": "7.3.0"
}
},
"node_modules/@prisma/engines-version": {
"version": "7.2.0-4.0c8ef2ce45c83248ab3df073180d5eda9e8be7a3",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.2.0-4.0c8ef2ce45c83248ab3df073180d5eda9e8be7a3.tgz",
"integrity": "sha512-KezsjCZDsbjNR7SzIiVlUsn9PnLePI7r5uxABlwL+xoerurZTfgQVbIjvjF2sVr3Uc0ZcsnREw3F84HvbggGdA==",
"version": "7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735.tgz",
"integrity": "sha512-IH2va2ouUHihyiTTRW889LjKAl1CusZOvFfZxCDNpjSENt7g2ndFsK0vdIw/72v7+jCN6YgkHmdAP/BI7SDgyg==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/engines/node_modules/@prisma/debug": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.3.0.tgz",
"integrity": "sha512-yh/tHhraCzYkffsI1/3a7SHX8tpgbJu1NPnuxS4rEpJdWAUDHUH25F1EDo6PPzirpyLNkgPPZdhojQK804BGtg==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/engines/node_modules/@prisma/get-platform": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz",
"integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.3.0.tgz",
"integrity": "sha512-N7c6m4/I0Q6JYmWKP2RCD/sM9eWiyCPY98g5c0uEktObNSZnugW2U/PO+pwL0UaqzxqTXt7gTsYsb0FnMnJNbg==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.2.0"
"@prisma/debug": "7.3.0"
}
},
"node_modules/@prisma/fetch-engine": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.2.0.tgz",
"integrity": "sha512-Z5XZztJ8Ap+wovpjPD2lQKnB8nWFGNouCrglaNFjxIWAGWz0oeHXwUJRiclIoSSXN/ptcs9/behptSk8d0Yy6w==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.3.0.tgz",
"integrity": "sha512-Mm0F84JMqM9Vxk70pzfNpGJ1lE4hYjOeLMu7nOOD1i83nvp8MSAcFYBnHqLvEZiA6onUR+m8iYogtOY4oPO5lQ==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.2.0",
"@prisma/engines-version": "7.2.0-4.0c8ef2ce45c83248ab3df073180d5eda9e8be7a3",
"@prisma/get-platform": "7.2.0"
"@prisma/debug": "7.3.0",
"@prisma/engines-version": "7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735",
"@prisma/get-platform": "7.3.0"
}
},
"node_modules/@prisma/fetch-engine/node_modules/@prisma/debug": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.3.0.tgz",
"integrity": "sha512-yh/tHhraCzYkffsI1/3a7SHX8tpgbJu1NPnuxS4rEpJdWAUDHUH25F1EDo6PPzirpyLNkgPPZdhojQK804BGtg==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.3.0.tgz",
"integrity": "sha512-N7c6m4/I0Q6JYmWKP2RCD/sM9eWiyCPY98g5c0uEktObNSZnugW2U/PO+pwL0UaqzxqTXt7gTsYsb0FnMnJNbg==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.3.0"
}
},
"node_modules/@prisma/get-platform": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz",
"integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==",
@@ -2349,34 +2402,17 @@
"@prisma/debug": "7.2.0"
}
},
"node_modules/@prisma/get-platform": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.8.2.tgz",
"integrity": "sha512-vXSxyUgX3vm1Q70QwzwkjeYfRryIvKno1SXbIqwSptKwqKzskINnDUcx85oX+ys6ooN2ATGSD0xN2UTfg6Zcow==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "6.8.2"
}
},
"node_modules/@prisma/get-platform/node_modules/@prisma/debug": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.8.2.tgz",
"integrity": "sha512-4muBSSUwJJ9BYth5N8tqts8JtiLT8QI/RSAzEogwEfpbYGFo9mYsInsVo8dqXdPO2+Rm5OG5q0qWDDE3nyUbVg==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/query-plan-executor": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-6.18.0.tgz",
"integrity": "sha512-jZ8cfzFgL0jReE1R10gT8JLHtQxjWYLiQ//wHmVYZ2rVkFHoh0DT8IXsxcKcFlfKN7ak7k6j0XMNn2xVNyr5cA==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz",
"integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/studio-core": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.9.0.tgz",
"integrity": "sha512-xA2zoR/ADu/NCSQuriBKTh6Ps4XjU0bErkEcgMfnSGh346K1VI7iWKnoq1l2DoxUqiddPHIEWwtxJ6xCHG6W7g==",
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.13.1.tgz",
"integrity": "sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==",
"devOptional": true,
"license": "Apache-2.0",
"peerDependencies": {
@@ -3305,6 +3341,7 @@
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
@@ -5279,6 +5316,7 @@
"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==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
@@ -5489,6 +5527,7 @@
"version": "1.0.30001757",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
"integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -5645,6 +5684,7 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
"dev": true,
"license": "MIT"
},
"node_modules/clsx": {
@@ -7324,9 +7364,9 @@
}
},
"node_modules/get-port-please": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz",
"integrity": "sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz",
"integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==",
"devOptional": true,
"license": "MIT"
},
@@ -7467,6 +7507,12 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/graphmatch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.0.tgz",
"integrity": "sha512-0E62MaTW5rPZVRLyIJZG/YejmdA/Xr1QydHEw3Vt+qOKkMIOE8WDLc9ZX2bmAjtJFZcId4lEdrdmASsEy7D1QA==",
"devOptional": true
},
"node_modules/has-bigints": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
@@ -7661,9 +7707,9 @@
"license": "CC0-1.0"
},
"node_modules/hono": {
"version": "4.10.6",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.10.6.tgz",
"integrity": "sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==",
"version": "4.11.7",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
"integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
"devOptional": true,
"license": "MIT",
"peer": true,
@@ -8925,9 +8971,9 @@
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"devOptional": true,
"license": "MIT"
},
@@ -10167,6 +10213,7 @@
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true,
"funding": [
{
"type": "github",
@@ -10211,12 +10258,13 @@
"license": "MIT"
},
"node_modules/next": {
"version": "16.1.3",
"resolved": "https://registry.npmjs.org/next/-/next-16.1.3.tgz",
"integrity": "sha512-gthG3TRD+E3/mA0uDQb9lqBmx1zVosq5kIwxNN6+MRNd085GzD+9VXMPUs+GGZCbZ+GDZdODUq4Pm7CTXK6ipw==",
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz",
"integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@next/env": "16.1.3",
"@next/env": "16.1.6",
"@swc/helpers": "0.5.15",
"baseline-browser-mapping": "^2.8.3",
"caniuse-lite": "^1.0.30001579",
@@ -10230,14 +10278,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
"@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",
"@next/swc-darwin-arm64": "16.1.6",
"@next/swc-darwin-x64": "16.1.6",
"@next/swc-linux-arm64-gnu": "16.1.6",
"@next/swc-linux-arm64-musl": "16.1.6",
"@next/swc-linux-x64-gnu": "16.1.6",
"@next/swc-linux-x64-musl": "16.1.6",
"@next/swc-win32-arm64-msvc": "16.1.6",
"@next/swc-win32-x64-msvc": "16.1.6",
"sharp": "^0.34.4"
},
"peerDependencies": {
@@ -10267,6 +10315,7 @@
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -10355,25 +10404,30 @@
"license": "MIT"
},
"node_modules/nypm": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz",
"integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==",
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.4.tgz",
"integrity": "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"citty": "^0.1.6",
"consola": "^3.4.2",
"citty": "^0.2.0",
"pathe": "^2.0.3",
"pkg-types": "^2.3.0",
"tinyexec": "^1.0.1"
"tinyexec": "^1.0.2"
},
"bin": {
"nypm": "dist/cli.mjs"
},
"engines": {
"node": "^14.16.0 || >=16.10.0"
"node": ">=18"
}
},
"node_modules/nypm/node_modules/citty": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/citty/-/citty-0.2.0.tgz",
"integrity": "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA==",
"devOptional": true,
"license": "MIT"
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -10688,6 +10742,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
@@ -10942,18 +10997,18 @@
}
},
"node_modules/prisma": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-7.2.0.tgz",
"integrity": "sha512-jSdHWgWOgFF24+nRyyNRVBIgGDQEsMEF8KPHvhBBg3jWyR9fUAK0Nq9ThUmiGlNgq2FA7vSk/ZoCvefod+a8qg==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-7.3.0.tgz",
"integrity": "sha512-ApYSOLHfMN8WftJA+vL6XwAPOh/aZ0BgUyyKPwUFgjARmG6EBI9LzDPf6SWULQMSAxydV9qn5gLj037nPNlg2w==",
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@prisma/config": "7.2.0",
"@prisma/dev": "0.17.0",
"@prisma/engines": "7.2.0",
"@prisma/studio-core": "0.9.0",
"@prisma/config": "7.3.0",
"@prisma/dev": "0.20.0",
"@prisma/engines": "7.3.0",
"@prisma/studio-core": "0.13.1",
"mysql2": "3.15.3",
"postgres": "3.4.7"
},
@@ -11464,13 +11519,13 @@
}
},
"node_modules/remeda": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/remeda/-/remeda-2.21.3.tgz",
"integrity": "sha512-XXrZdLA10oEOQhLLzEJEiFFSKi21REGAkHdImIb4rt/XXy8ORGXh5HCcpUOsElfPNDb+X6TA/+wkh+p2KffYmg==",
"version": "2.33.4",
"resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz",
"integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"type-fest": "^4.39.1"
"funding": {
"url": "https://github.com/sponsors/remeda"
}
},
"node_modules/require-from-string": {
@@ -11787,6 +11842,7 @@
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"optional": true,
@@ -11832,6 +11888,7 @@
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
"license": "ISC",
"optional": true,
"bin": {
@@ -12024,6 +12081,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -12067,7 +12125,7 @@
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
"integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/stop-iteration-iterator": {
@@ -12305,6 +12363,7 @@
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
"integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"client-only": "0.0.1"
@@ -13167,19 +13226,6 @@
"node": ">= 0.8.0"
}
},
"node_modules/type-fest": {
"version": "4.41.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
"devOptional": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
@@ -14021,13 +14067,14 @@
}
},
"node_modules/zeptomatch": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.0.2.tgz",
"integrity": "sha512-H33jtSKf8Ijtb5BW6wua3G5DhnFjbFML36eFu+VdOoVY4HD9e7ggjqdM6639B+L87rjnR6Y+XeRzBXZdy52B/g==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz",
"integrity": "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"grammex": "^3.1.10"
"grammex": "^3.1.11",
"graphmatch": "^1.1.0"
}
},
"node_modules/zod": {

View File

@@ -49,7 +49,7 @@
"dotenv": "^17.2.3",
"jsonwebtoken": "^9.0.3",
"lucide-react": "^0.562.0",
"next": "^16.1.3",
"next": ">=16.1.5",
"node-cron": "^4.2.1",
"node-pty": "^1.1.0",
"react": "^19.2.3",
@@ -66,6 +66,7 @@
"zod": "^4.3.5"
},
"devDependencies": {
"next": ">=16.1.5",
"@tailwindcss/postcss": "^4.1.18",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1",
@@ -102,6 +103,8 @@
"node": ">=24.0.0"
},
"overrides": {
"prismjs": "^1.30.0"
"prismjs": "^1.30.0",
"hono": ">=4.11.7",
"lodash": ">=4.17.23"
}
}

View File

@@ -312,7 +312,7 @@ class ScriptExecutionHandler {
} else if (isUpdate && containerId) {
await this.startUpdateExecution(ws, containerId, executionId, mode, server, backupStorage);
} else if (isShell && containerId) {
await this.startShellExecution(ws, containerId, executionId, mode, server);
await this.startShellExecution(ws, containerId, executionId, mode, server, containerType);
} else {
await this.startScriptExecution(ws, scriptPath, executionId, mode, server, envVars);
}
@@ -1474,21 +1474,21 @@ class ScriptExecutionHandler {
* @param {string} executionId
* @param {string} mode
* @param {ServerInfo|null} server
* @param {'lxc'|'vm'} [containerType='lxc']
*/
async startShellExecution(ws, containerId, executionId, mode = 'local', server = null) {
async startShellExecution(ws, containerId, executionId, mode = 'local', server = null, containerType = 'lxc') {
try {
// Send start message
const typeLabel = containerType === 'vm' ? 'VM' : 'container';
this.sendMessage(ws, {
type: 'start',
data: `Starting shell session for container ${containerId}...`,
data: `Starting shell session for ${typeLabel} ${containerId}...`,
timestamp: Date.now()
});
if (mode === 'ssh' && server) {
await this.startSSHShellExecution(ws, containerId, executionId, server);
await this.startSSHShellExecution(ws, containerId, executionId, server, containerType);
} else {
await this.startLocalShellExecution(ws, containerId, executionId);
await this.startLocalShellExecution(ws, containerId, executionId, containerType);
}
} catch (error) {
@@ -1505,12 +1505,12 @@ class ScriptExecutionHandler {
* @param {ExtendedWebSocket} ws
* @param {string} containerId
* @param {string} executionId
* @param {'lxc'|'vm'} [containerType='lxc']
*/
async startLocalShellExecution(ws, containerId, executionId) {
async startLocalShellExecution(ws, containerId, executionId, containerType = 'lxc') {
const { spawn } = await import('node-pty');
// Create a shell process that will run pct enter
const childProcess = spawn('bash', ['-c', `pct enter ${containerId}`], {
const shellCommand = containerType === 'vm' ? `qm terminal ${containerId}` : `pct enter ${containerId}`;
const childProcess = spawn('bash', ['-c', shellCommand], {
name: 'xterm-color',
cols: 80,
rows: 24,
@@ -1553,14 +1553,15 @@ class ScriptExecutionHandler {
* @param {string} containerId
* @param {string} executionId
* @param {ServerInfo} server
* @param {'lxc'|'vm'} [containerType='lxc']
*/
async startSSHShellExecution(ws, containerId, executionId, server) {
async startSSHShellExecution(ws, containerId, executionId, server, containerType = 'lxc') {
const sshService = getSSHExecutionService();
const shellCommand = containerType === 'vm' ? `qm terminal ${containerId}` : `pct enter ${containerId}`;
try {
const execution = await sshService.executeCommand(
server,
`pct enter ${containerId}`,
shellCommand,
/** @param {string} data */
(data) => {
this.sendMessage(ws, {

View File

@@ -199,6 +199,17 @@ export function ConfigurationModal({
return !isNaN(num) && num > 0;
};
const validateHostname = (hostname: string): boolean => {
if (!hostname || hostname.length > 253) return false;
const label = /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/;
const labels = hostname.split('.');
return labels.length >= 1 && labels.every(l => l.length >= 1 && l.length <= 63 && label.test(l));
};
const validateAptCacherAddress = (value: string): boolean => {
return validateIPv4(value) || validateHostname(value);
};
const validateForm = (): boolean => {
const newErrors: Record<string, string> = {};
@@ -216,8 +227,8 @@ export function ConfigurationModal({
if (advancedVars.var_ns && !validateIPv4(advancedVars.var_ns as string)) {
newErrors.var_ns = 'Invalid IPv4 address';
}
if (advancedVars.var_apt_cacher_ip && !validateIPv4(advancedVars.var_apt_cacher_ip as string)) {
newErrors.var_apt_cacher_ip = 'Invalid IPv4 address';
if (advancedVars.var_apt_cacher_ip && !validateAptCacherAddress(advancedVars.var_apt_cacher_ip as string)) {
newErrors.var_apt_cacher_ip = 'Invalid IPv4 address or hostname';
}
// Validate IPv4 CIDR if network mode is static
const netValue = advancedVars.var_net;
@@ -904,13 +915,13 @@ export function ConfigurationModal({
</div>
<div>
<label className="block text-sm font-medium text-foreground mb-2">
APT Cacher IP
APT Cacher host or IP
</label>
<Input
type="text"
value={typeof advancedVars.var_apt_cacher_ip === 'boolean' ? '' : String(advancedVars.var_apt_cacher_ip ?? '')}
onChange={(e) => updateAdvancedVar('var_apt_cacher_ip', e.target.value)}
placeholder="192.168.1.10"
placeholder="192.168.1.10 or apt-cacher.internal"
className={errors.var_apt_cacher_ip ? 'border-destructive' : ''}
/>
{errors.var_apt_cacher_ip && (

View File

@@ -80,6 +80,7 @@ export function InstalledScriptsTab() {
id: number;
containerId: string;
server?: any;
containerType?: 'lxc' | 'vm';
} | null>(null);
const [showBackupPrompt, setShowBackupPrompt] = useState(false);
const [showStorageSelection, setShowStorageSelection] = useState(false);
@@ -1167,6 +1168,7 @@ export function InstalledScriptsTab() {
id: script.id,
containerId: script.container_id,
server: server,
containerType: script.is_vm ? 'vm' : 'lxc',
});
};
@@ -1452,6 +1454,13 @@ export function InstalledScriptsTab() {
{/* Shell Terminal */}
{openingShell && (
<div className="mb-8" data-terminal="shell">
{openingShell.containerType === 'vm' && (
<p className="text-muted-foreground mb-2 text-sm">
VM shell uses the Proxmox serial console. The VM must have a
serial port configured (e.g. <code className="bg-muted rounded px-1">qm set {openingShell.containerId} -serial0 socket</code>).
Detach with <kbd className="bg-muted rounded px-1">Ctrl+O</kbd>.
</p>
)}
<Terminal
scriptPath={`shell-${openingShell.containerId}`}
onClose={handleCloseShellTerminal}
@@ -1459,6 +1468,7 @@ export function InstalledScriptsTab() {
server={openingShell.server}
isShell={true}
containerId={openingShell.containerId}
containerType={openingShell.containerType}
/>
</div>
)}
@@ -1538,7 +1548,7 @@ export function InstalledScriptsTab() {
>
{showAutoDetectForm
? "Cancel Auto-Detect"
: '🔍 Auto-Detect LXC Containers (Must contain a tag with "community-script")'}
: '🔍 Auto-Detect Containers & VMs (tag: community-script)'}
</Button>
<Button
onClick={() => {
@@ -1764,12 +1774,11 @@ export function InstalledScriptsTab() {
</div>
)}
{/* Auto-Detect LXC Containers Form */}
{/* Auto-Detect Containers & VMs Form */}
{showAutoDetectForm && (
<div className="bg-card border-border mb-6 rounded-lg border p-4 shadow-sm sm:p-6">
<h3 className="text-foreground mb-4 text-lg font-semibold sm:mb-6">
Auto-Detect LXC Containers (Must contain a tag with
&quot;community-script&quot;)
Auto-Detect Containers &amp; VMs (tag: community-script)
</h3>
<div className="space-y-4 sm:space-y-6">
<div className="bg-muted/30 border-muted rounded-lg border p-4">
@@ -1795,12 +1804,12 @@ export function InstalledScriptsTab() {
<p>This feature will:</p>
<ul className="mt-1 list-inside list-disc space-y-1">
<li>Connect to the selected server via SSH</li>
<li>Scan all LXC config files in /etc/pve/lxc/</li>
<li>Scan LXC configs in /etc/pve/lxc/ and VM configs in /etc/pve/qemu-server/</li>
<li>
Find containers with &quot;community-script&quot; in
Find containers and VMs with &quot;community-script&quot; in
their tags
</li>
<li>Extract the container ID and hostname</li>
<li>Extract the container/VM ID and hostname or name</li>
<li>Add them as installed script entries</li>
</ul>
</div>
@@ -2302,6 +2311,11 @@ export function InstalledScriptsTab() {
"stopped"
}
className="text-muted-foreground hover:text-foreground hover:bg-muted/20 focus:bg-muted/20"
title={
script.is_vm
? "VM serial console (requires serial port; detach with Ctrl+O)"
: undefined
}
>
Shell
</DropdownMenuItem>

View File

@@ -270,22 +270,21 @@ export function PBSCredentialsModal({
htmlFor="pbs-fingerprint"
className="text-foreground mb-1 block text-sm font-medium"
>
Fingerprint <span className="text-error">*</span>
Fingerprint
</label>
<input
type="text"
id="pbs-fingerprint"
value={pbsFingerprint}
onChange={(e) => setPbsFingerprint(e.target.value)}
required
disabled={isLoading}
className="bg-card text-foreground placeholder-muted-foreground focus:ring-ring focus:border-ring border-border w-full rounded-md border px-3 py-2 shadow-sm focus:ring-2 focus:outline-none"
placeholder="e.g., 7b:e5:87:38:5e:16:05:d1:12:22:7f:73:d2:e2:d0:cf:8c:cb:28:e2:74:0c:78:91:1a:71:74:2e:79:20:5a:02"
/>
<p className="text-muted-foreground mt-1 text-xs">
Server fingerprint for auto-acceptance. You can find this on
your PBS dashboard by clicking the &quot;Show Fingerprint&quot;
button.
Leave empty if PBS uses a trusted CA (e.g. Let&apos;s Encrypt).
For self-signed certificates, enter the server fingerprint from
the PBS dashboard (&quot;Show Fingerprint&quot;).
</p>
</div>

View File

@@ -1060,7 +1060,7 @@ export const installedScriptsRouter = createTRPCRouter({
reject(new Error(`pct list failed: ${error}`));
},
(_exitCode: number) => {
resolve();
setImmediate(() => resolve());
}
);
});
@@ -1079,7 +1079,7 @@ export const installedScriptsRouter = createTRPCRouter({
reject(new Error(`qm list failed: ${error}`));
},
(_exitCode: number) => {
resolve();
setImmediate(() => resolve());
}
);
});
@@ -2068,32 +2068,72 @@ export const installedScriptsRouter = createTRPCRouter({
};
}
// Get the script's interface_port from metadata (prioritize metadata over existing database values)
let detectedPort = 80; // Default fallback
// Resolve app slug from /usr/bin/update (community-scripts) when available; else from hostname/suffix.
let slugFromUpdate: string | null = null;
try {
const updateCommand = `pct exec ${scriptData.container_id} -- cat /usr/bin/update 2>/dev/null`;
let updateOutput = '';
await new Promise<void>((resolve) => {
void sshExecutionService.executeCommand(
server as Server,
updateCommand,
(data: string) => { updateOutput += data; },
() => {},
() => resolve()
);
});
const ctSlugMatch = /ct\/([a-zA-Z0-9_.-]+)\.sh/.exec(updateOutput);
if (ctSlugMatch?.[1]) {
slugFromUpdate = ctSlugMatch[1].trim().toLowerCase();
console.log('🔍 Slug from /usr/bin/update:', slugFromUpdate);
}
} catch {
// Container may not be from community-scripts; use hostname fallback
}
// Get the script's interface_port from metadata. Primary: slug from /usr/bin/update; fallback: hostname/suffix.
let detectedPort = 80; // Default fallback
try {
// Import localScriptsService to get script metadata
const { localScriptsService } = await import('~/server/services/localScripts');
// Get all scripts and find the one matching our script name
const allScripts = await localScriptsService.getAllScripts();
// Extract script slug from script_name (remove .sh extension)
const scriptSlug = scriptData.script_name.replace(/\.sh$/, '');
console.log('🔍 Looking for script with slug:', scriptSlug);
const scriptMetadata = allScripts.find(script => script.slug === scriptSlug);
const nameFromHostname = scriptData.script_name.replace(/\.sh$/, '').toLowerCase();
// Primary: slug from /usr/bin/update (community-scripts)
let scriptMetadata =
slugFromUpdate != null
? allScripts.find((s) => s.slug === slugFromUpdate)
: undefined;
if (scriptMetadata) {
console.log('🔍 Using slug from /usr/bin/update for metadata:', scriptMetadata.slug);
}
// Fallback: exact hostname then hostname ends with slug (longest wins)
if (!scriptMetadata) {
scriptMetadata = allScripts.find((script) => script.slug === nameFromHostname);
if (!scriptMetadata) {
const suffixMatches = allScripts.filter((script) => nameFromHostname.endsWith(script.slug));
scriptMetadata =
suffixMatches.length > 0
? suffixMatches.reduce((a, b) => (a.slug.length >= b.slug.length ? a : b))
: undefined;
if (scriptMetadata) {
console.log('🔍 Matched metadata by slug suffix in hostname:', scriptMetadata.slug);
}
}
}
if (scriptMetadata?.interface_port) {
detectedPort = scriptMetadata.interface_port;
console.log('📋 Found interface_port in metadata:', detectedPort);
} else {
console.log('📋 No interface_port found in metadata, using default port 80');
detectedPort = 80; // Default to port 80 if no metadata port found
detectedPort = 80;
}
} catch (error) {
console.log('⚠️ Error getting script metadata, using default port 80:', error);
detectedPort = 80; // Default to port 80 if metadata lookup fails
detectedPort = 80;
}
console.log('🎯 Final detected port:', detectedPort);

View File

@@ -327,13 +327,16 @@ class BackupService {
// PBS supports PBS_PASSWORD and PBS_REPOSITORY environment variables for non-interactive login
const repository = `root@pam@${pbsIp}:${pbsDatastore}`;
// Escape password for shell safety (single quotes)
// Escape password and fingerprint for shell safety (single quotes)
const escapedPassword = credential.pbs_password.replace(/'/g, "'\\''");
// Use PBS_PASSWORD environment variable for non-interactive authentication
// Auto-accept fingerprint by piping "y" to stdin
// PBS will use PBS_PASSWORD env var if available, avoiding interactive prompt
const fullCommand = `echo "y" | PBS_PASSWORD='${escapedPassword}' PBS_REPOSITORY='${repository}' timeout 10 proxmox-backup-client login --repository ${repository} 2>&1`;
const fingerprint = credential.pbs_fingerprint?.trim() ?? '';
const escapedFingerprint = fingerprint ? fingerprint.replace(/'/g, "'\\''") : '';
const envParts = [`PBS_PASSWORD='${escapedPassword}'`, `PBS_REPOSITORY='${repository}'`];
if (escapedFingerprint) {
envParts.push(`PBS_FINGERPRINT='${escapedFingerprint}'`);
}
const envStr = envParts.join(' ');
const fullCommand = `${envStr} timeout 10 proxmox-backup-client login --repository ${repository} 2>&1`;
console.log(`[BackupService] Logging into PBS: ${repository}`);
@@ -419,9 +422,12 @@ class BackupService {
// Build full repository string: root@pam@<IP>:<DATASTORE>
const repository = `root@pam@${pbsIp}:${pbsDatastore}`;
const fingerprint = credential.pbs_fingerprint?.trim() ?? '';
const escapedFingerprint = fingerprint ? fingerprint.replace(/'/g, "'\\''") : '';
const snapshotEnvParts = escapedFingerprint ? [`PBS_FINGERPRINT='${escapedFingerprint}'`] : [];
const snapshotEnvStr = snapshotEnvParts.length ? snapshotEnvParts.join(' ') + ' ' : '';
// Use correct command: snapshot list ct/<CT_ID> --repository <full_repo_string>
const command = `timeout 30 proxmox-backup-client snapshot list ct/${ctId} --repository ${repository} 2>&1 || echo "PBS_ERROR"`;
const command = `${snapshotEnvStr}timeout 30 proxmox-backup-client snapshot list ct/${ctId} --repository ${repository} 2>&1 || echo "PBS_ERROR"`;
let output = '';
console.log(`[BackupService] Discovering PBS backups for CT ${ctId} on repository ${repository}`);

View File

@@ -250,9 +250,16 @@ class RestoreService {
const targetFolder = `/var/lib/vz/dump/vzdump-lxc-${ctId}-${snapshotNameForPath}`;
const targetTar = `${targetFolder}.tar`;
// Use PBS_PASSWORD env var and add timeout for long downloads
// Use PBS_PASSWORD env var and add timeout for long downloads; PBS_FINGERPRINT when set for cert validation
const escapedPassword = credential.pbs_password.replace(/'/g, "'\\''");
const restoreCommand = `PBS_PASSWORD='${escapedPassword}' PBS_REPOSITORY='${repository}' timeout 300 proxmox-backup-client restore "${snapshotPath}" root.pxar "${targetFolder}" --repository '${repository}' 2>&1`;
const fingerprint = credential.pbs_fingerprint?.trim() ?? '';
const escapedFingerprint = fingerprint ? fingerprint.replace(/'/g, "'\\''") : '';
const restoreEnvParts = [`PBS_PASSWORD='${escapedPassword}'`, `PBS_REPOSITORY='${repository}'`];
if (escapedFingerprint) {
restoreEnvParts.push(`PBS_FINGERPRINT='${escapedFingerprint}'`);
}
const restoreEnvStr = restoreEnvParts.join(' ');
const restoreCommand = `${restoreEnvStr} timeout 300 proxmox-backup-client restore "${snapshotPath}" root.pxar "${targetFolder}" --repository '${repository}' 2>&1`;
let output = '';
let exitCode = 0;