Compare commits

..

61 Commits

Author SHA1 Message Date
CanbiZ
a6e53dea01 Remove redundant cleanup steps from update scripts
Eliminated unnecessary 'Cleaning up' messages and duplicate cleanup commands from multiple service update scripts. Cleanup actions (such as removing backup files and temporary artifacts) are now performed directly without extra messaging, streamlining the update process and reducing log verbosity.
2025-11-22 14:35:05 +01:00
CanbiZ
e4b2e051bf fixes bug in setup_php 2025-11-22 13:23:40 +01:00
CanbiZ
e05a351712 Update tools.func 2025-11-22 13:20:18 +01:00
CanbiZ
053e5ab128 Merge branch 'main' of https://github.com/community-scripts/ProxmoxVE 2025-11-22 13:13:25 +01:00
CanbiZ
1f6a141341 Refactor PHP setup for stricter version enforcement
Reworks the PHP installation logic to always remove conflicting PHP versions before pinning and repository setup, ensuring only the desired version is present. Simplifies module installation by letting apt-get handle missing modules and improves error handling for individual package installations. Removes pre-checks and warnings for unavailable modules, streamlining the process and reducing complexity.
2025-11-22 13:08:30 +01:00
community-scripts-pr-app[bot]
b47d4747d6 Update versions.json (#9352)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-22 13:04:34 +01:00
CanbiZ
27bd55364c Improve PHP setup: enforce version pinning and cleanup
Enhances the PHP setup function to enforce APT pinning for PHP versions during updates and installations, ensuring correct version selection. Adds logic to remove conflicting PHP versions, improves module availability checks, and provides clearer messaging for installed and missing modules.
2025-11-22 13:02:53 +01:00
CanbiZ
8ad68e7c97 core: improve setup_php robustness and version validation
Enhances the setup_php function to enforce explicit PHP version pinning during installation, adds checks for available versions and missing modules, and improves error handling. The script now verifies the installed PHP version matches the requested version and provides fallback installation logic if version-constrained installs fail.
2025-11-22 12:52:47 +01:00
community-scripts-pr-app[bot]
088186712a Update CHANGELOG.md (#9348)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-22 08:10:53 +00:00
Bram
6dd0195912 Refactor /data page (#9343) 2025-11-22 09:10:29 +01:00
community-scripts-pr-app[bot]
afa385d225 Update CHANGELOG.md (#9345)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-22 00:12:30 +00:00
community-scripts-pr-app[bot]
f43efc1431 Update versions.json (#9344)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-22 01:12:09 +01:00
community-scripts-pr-app[bot]
06d8e5354a Update CHANGELOG.md (#9338)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 14:34:47 +00:00
community-scripts-pr-app[bot]
60fc5573aa Update CHANGELOG.md (#9337)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 14:34:11 +00:00
CanbiZ
29ee6cdff3 plex: prevent [] syntax issue (#9318) 2025-11-21 15:34:04 +01:00
community-scripts-pr-app[bot]
bda9286043 Update CHANGELOG.md (#9336)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 14:33:50 +00:00
Tobias
4389a43670 fix: karakeep strip "v" from release version (#9324)
* fix: karakeep strip "v" from release version

* fix: strip v from release for karakeep version

* Fix MODULE_VERSION and SERVER_VERSION formatting

* formatting
2025-11-21 15:33:44 +01:00
Chris
43877a8b17 NetVisor: fix grep in update (#9334) 2025-11-21 15:33:24 +01:00
CanbiZ
ff6cb3b87e Fix rustup update to avoid interactive prompts
Redirects stdin from /dev/null when running 'rustup update' to prevent any interactive prompts that may block automated scripts.
2025-11-21 15:22:01 +01:00
community-scripts-pr-app[bot]
4b0fb547e9 Update CHANGELOG.md (#9333)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 13:33:37 +00:00
Chris
e2c6020c64 pin correct version (#9332) 2025-11-21 14:33:09 +01:00
community-scripts-pr-app[bot]
33f4482012 Update versions.json (#9330)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 13:05:51 +01:00
community-scripts-pr-app[bot]
9b375bccab Update CHANGELOG.md (#9327)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 07:54:10 +00:00
CanbiZ
3f2f29d352 Refactor IPv6 disable logic and add 'disable' option (#9326)
Replaces previous IPv6 disabling method with a dedicated 'disable' option, storing sysctl settings in /etc/sysctl.d/99-disable-ipv6.conf. Updates build and install scripts to clarify the difference between 'none' (no assignment) and 'disable' (fully disables IPv6), adds user warnings, and disables IPv6 listeners in nginx if present.
2025-11-21 08:53:46 +01:00
しぐれ
636b0d3afd fix: update website URL in filebrowser.json (#9322) 2025-11-21 07:25:12 +01:00
community-scripts-pr-app[bot]
36acad3b25 Update CHANGELOG.md (#9321)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 00:13:22 +00:00
community-scripts-pr-app[bot]
00060740d9 Update versions.json (#9320)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-21 01:12:53 +01:00
community-scripts-pr-app[bot]
4a5f7ab855 Update CHANGELOG.md (#9313)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 17:29:48 +00:00
Chris
dd8bb6f42b Immich v2.3.1: OpenVINO tuning, OCR fixes, Maintenance mode, workflows/plugin framework (#9310)
* Add env var for OpenVINO floating point precision setting

* v2.3.1 - Maintenance mode, workflow/plugin framework
2025-11-20 18:08:25 +01:00
CanbiZ
9879cb4b69 Remove package-lock.json copy in install script
Removed the copy of package-lock.json from the installation script.
2025-11-20 16:13:25 +01:00
CanbiZ
264a29980c documenso: test turbo prune 2025-11-20 16:04:24 +01:00
community-scripts-pr-app[bot]
3af525882a Update versions.json (#9305)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 13:07:30 +01:00
community-scripts-pr-app[bot]
17bb0af069 Update CHANGELOG.md (#9304)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 12:02:56 +00:00
Tobias
3850960eca kasm: add: update (#9253) 2025-11-20 13:02:30 +01:00
community-scripts-pr-app[bot]
323ca24625 Update CHANGELOG.md (#9303)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 12:02:06 +00:00
CanbiZ
6fc20ae5c2 Omada - AVX-only support (#9295) 2025-11-20 13:01:41 +01:00
community-scripts-pr-app[bot]
318574fcd1 Update CHANGELOG.md (#9302)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 12:01:26 +00:00
CanbiZ
fe3dab0ee1 tools/pve: expand PVE support to 9.0–9.1 (post-install & netdata) (#9298) 2025-11-20 13:01:01 +01:00
community-scripts-pr-app[bot]
b314ba4bf1 Update CHANGELOG.md (#9300)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 11:43:18 +00:00
CanbiZ
0153f4bd40 core: change 'uv cache clear' to 'uv cache clean' (#9299) 2025-11-20 12:42:57 +01:00
CanbiZ
3b7de3da6b searxng updatable -> false 2025-11-20 11:09:58 +01:00
dependabot[bot]
7ea03832ec build(deps): bump golang.org/x/crypto (#9292)
Bumps the go_modules group with 1 update in the /api directory: [golang.org/x/crypto](https://github.com/golang/crypto).


Updates `golang.org/x/crypto` from 0.35.0 to 0.45.0
- [Commits](https://github.com/golang/crypto/compare/v0.35.0...v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.45.0
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-20 09:39:07 +01:00
community-scripts-pr-app[bot]
e849fd0ffe Update CHANGELOG.md (#9291)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 00:13:22 +00:00
community-scripts-pr-app[bot]
a11bb982e4 Update versions.json (#9290)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-20 01:12:57 +01:00
community-scripts-pr-app[bot]
2ff85e7aeb Update CHANGELOG.md (#9287)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 18:13:44 +00:00
Chris
2d5c3f9f6d HotFix: Fix NetVisor env var (#9286)
- It was incorrect in the docs
2025-11-19 19:13:16 +01:00
community-scripts-pr-app[bot]
ff00e90746 Update CHANGELOG.md (#9283)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 16:36:54 +00:00
CanbiZ
acb1c4efbd PVE 9.1 version support (#9280) 2025-11-19 17:36:29 +01:00
community-scripts-pr-app[bot]
26444515d4 Update CHANGELOG.md (#9279)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 15:28:12 +00:00
CanbiZ
5b39f2931e force disable IPv6 if IPV6_METHOD = none (#9277)
* Enhance IPv6 disabling logic in install script

Updated verb_ip6 to check both IPV6_METHOD and DISABLEIPV6 variables. Added disabling for all, default, and loopback interfaces, improved messaging, and redirected sysctl output to /dev/null for cleaner logs.

* Improve IPv6 disabling logic in install scripts

Updated both alpine-install.func and install.func to enhance IPv6 disabling by checking IPV6_METHOD and adding more sysctl settings. Also improved messaging and removed suppression of sysctl output in install.func.
2025-11-19 16:27:42 +01:00
community-scripts-pr-app[bot]
73490605c5 Update CHANGELOG.md (#9275)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 13:46:48 +00:00
Chris
abc0f261fa Jotty: reduce RAM requirement (#9272) 2025-11-19 14:46:23 +01:00
Sven Schneider
18f474c4e7 fix: Update Passbolt credential path in JSON file (#9267) 2025-11-19 14:46:01 +01:00
community-scripts-pr-app[bot]
c7342399f3 Update versions.json (#9271)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 13:06:11 +01:00
community-scripts-pr-app[bot]
988ad7e624 Update CHANGELOG.md (#9266)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 09:39:52 +01:00
Chris
e3164f6ea5 NetVisor: v0.10.0 fixes (#9255) 2025-11-19 09:36:55 +01:00
community-scripts-pr-app[bot]
783db6630a Update CHANGELOG.md (#9265)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 08:36:46 +00:00
Slaviša Arežina
e5db2c6eb9 Nginx Proxy Manager: Pin version to v2.13.4 (#9259)
* Update Nginx Proxy Manager release version

* Update nginxproxymanager.sh

---------

Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com>
2025-11-19 09:36:20 +01:00
community-scripts-pr-app[bot]
29d0d98fa2 Update CHANGELOG.md (#9262)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 00:13:36 +00:00
community-scripts-pr-app[bot]
f3af0f6c34 Update versions.json (#9261)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-19 01:13:13 +01:00
CanbiZ
ae8c3002ab add clean_install for npm 2025-11-18 14:23:03 +01:00
95 changed files with 1939 additions and 1300 deletions

View File

@@ -10,6 +10,66 @@
> [!CAUTION] > [!CAUTION]
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes. Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
## 2025-11-22
### 🌐 Website
- #### ✨ New Features
- Refactor /data page [@BramSuurdje](https://github.com/BramSuurdje) ([#9343](https://github.com/community-scripts/ProxmoxVE/pull/9343))
## 2025-11-21
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- plex: prevent [] syntax issue [@MickLesk](https://github.com/MickLesk) ([#9318](https://github.com/community-scripts/ProxmoxVE/pull/9318))
- fix: karakeep strip "v" from release version [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9324](https://github.com/community-scripts/ProxmoxVE/pull/9324))
- NetVisor: fix grep in update [@vhsdream](https://github.com/vhsdream) ([#9334](https://github.com/community-scripts/ProxmoxVE/pull/9334))
- Immich: pin correct version [@vhsdream](https://github.com/vhsdream) ([#9332](https://github.com/community-scripts/ProxmoxVE/pull/9332))
- #### 🔧 Refactor
- Refactor IPv6 disable logic and add 'disable' option [@MickLesk](https://github.com/MickLesk) ([#9326](https://github.com/community-scripts/ProxmoxVE/pull/9326))
## 2025-11-20
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- core: change 'uv cache clear' to 'uv cache clean' [@MickLesk](https://github.com/MickLesk) ([#9299](https://github.com/community-scripts/ProxmoxVE/pull/9299))
- #### ✨ New Features
- Immich v2.3.1: OpenVINO tuning, OCR fixes, Maintenance mode, workflows/plugin framework [@vhsdream](https://github.com/vhsdream) ([#9310](https://github.com/community-scripts/ProxmoxVE/pull/9310))
- kasm: add: update [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9253](https://github.com/community-scripts/ProxmoxVE/pull/9253))
- tools/pve: expand PVE support to 9.09.1 (post-install & netdata) [@MickLesk](https://github.com/MickLesk) ([#9298](https://github.com/community-scripts/ProxmoxVE/pull/9298))
- #### 💥 Breaking Changes
- Omada - AVX-only support [@MickLesk](https://github.com/MickLesk) ([#9295](https://github.com/community-scripts/ProxmoxVE/pull/9295))
## 2025-11-19
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- HotFix: Fix NetVisor env var [@vhsdream](https://github.com/vhsdream) ([#9286](https://github.com/community-scripts/ProxmoxVE/pull/9286))
- Jotty: reduce RAM requirement [@vhsdream](https://github.com/vhsdream) ([#9272](https://github.com/community-scripts/ProxmoxVE/pull/9272))
- Nginx Proxy Manager: Pin version to v2.13.4 [@tremor021](https://github.com/tremor021) ([#9259](https://github.com/community-scripts/ProxmoxVE/pull/9259))
- #### ✨ New Features
- PVE 9.1 version support [@MickLesk](https://github.com/MickLesk) ([#9280](https://github.com/community-scripts/ProxmoxVE/pull/9280))
- force disable IPv6 if IPV6_METHOD = none [@MickLesk](https://github.com/MickLesk) ([#9277](https://github.com/community-scripts/ProxmoxVE/pull/9277))
- #### 💥 Breaking Changes
- NetVisor: v0.10.0 fixes [@vhsdream](https://github.com/vhsdream) ([#9255](https://github.com/community-scripts/ProxmoxVE/pull/9255))
## 2025-11-18 ## 2025-11-18
### 🚀 Updated Scripts ### 🚀 Updated Scripts

View File

@@ -1,6 +1,6 @@
module proxmox-api module proxmox-api
go 1.23.2 go 1.24.0
require ( require (
github.com/gorilla/mux v1.8.1 github.com/gorilla/mux v1.8.1
@@ -17,7 +17,7 @@ require (
github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
golang.org/x/crypto v0.35.0 // indirect golang.org/x/crypto v0.45.0 // indirect
golang.org/x/sync v0.11.0 // indirect golang.org/x/sync v0.18.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.31.0 // indirect
) )

View File

@@ -27,16 +27,16 @@ go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793Sqyh
go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -48,8 +48,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

View File

@@ -57,15 +57,6 @@ function update_script() {
$STD composer install --no-dev --prefer-dist $STD composer install --no-dev --prefer-dist
php artisan 2fauth:install php artisan 2fauth:install
$STD systemctl restart nginx $STD systemctl restart nginx
msg_info "Cleaning Up"
if dpkg -l | grep -q 'php8.2'; then
$STD apt remove --purge -y php8.2*
fi
$STD apt -y autoremove
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -62,6 +62,7 @@ function update_script() {
cd /opt/adventurelog/frontend || exit cd /opt/adventurelog/frontend || exit
$STD pnpm i $STD pnpm i
$STD pnpm build $STD pnpm build
rm -rf /opt/adventurelog-backup
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Services" msg_info "Starting Services"
@@ -69,10 +70,6 @@ function update_script() {
systemctl start adventurelog-backend systemctl start adventurelog-backend
systemctl start adventurelog-frontend systemctl start adventurelog-frontend
msg_ok "Services Started" msg_ok "Services Started"
msg_info "Cleaning Up"
rm -rf /opt/adventurelog-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -38,15 +38,13 @@ function update_script() {
curl -fsSL -o tika-server-standard-${RELEASE}.jar "https://dlcdn.apache.org/tika/${RELEASE}/tika-server-standard-${RELEASE}.jar" curl -fsSL -o tika-server-standard-${RELEASE}.jar "https://dlcdn.apache.org/tika/${RELEASE}/tika-server-standard-${RELEASE}.jar"
mv --force tika-server-standard.jar tika-server-standard-prev-version.jar mv --force tika-server-standard.jar tika-server-standard-prev-version.jar
mv tika-server-standard-${RELEASE}.jar tika-server-standard.jar mv tika-server-standard-${RELEASE}.jar tika-server-standard.jar
rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to v${RELEASE}" msg_ok "Updated ${APP} to v${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start apache-tika systemctl start apache-tika
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -31,15 +31,11 @@ function update_script() {
fi fi
if check_for_gh_release "authelia" "authelia/authelia"; then if check_for_gh_release "authelia" "authelia/authelia"; then
$STD apt-get update $STD apt update
$STD apt-get -y upgrade $STD apt -y upgrade
fetch_and_deploy_gh_release "authelia" "authelia/authelia" "binary" fetch_and_deploy_gh_release "authelia" "authelia/authelia" "binary"
msg_info "Cleaning Up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -39,16 +39,13 @@ function update_script() {
curl -fsSL "https://github.com/garethgeorge/backrest/releases/download/v${RELEASE}/backrest_Linux_x86_64.tar.gz" -o "$temp_file" curl -fsSL "https://github.com/garethgeorge/backrest/releases/download/v${RELEASE}/backrest_Linux_x86_64.tar.gz" -o "$temp_file"
tar xzf $temp_file -C /opt/backrest/bin tar xzf $temp_file -C /opt/backrest/bin
chmod +x /opt/backrest/bin/backrest chmod +x /opt/backrest/bin/backrest
rm -f "$temp_file"
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to ${RELEASE}" msg_ok "Updated ${APP} to ${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start backrest systemctl start backrest
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -f "$temp_file"
msg_ok "Cleaned up"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -47,15 +47,12 @@ function update_script() {
chmod -R 755 /opt/baikal/ chmod -R 755 /opt/baikal/
cd /opt/baikal cd /opt/baikal
$STD composer install $STD composer install
rm -rf /opt/baikal-backup
msg_ok "Configured Baikal" msg_ok "Configured Baikal"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start apache2 systemctl start apache2
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/baikal-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -54,15 +54,12 @@ function update_script() {
$STD php artisan route:cache $STD php artisan route:cache
$STD php artisan event:cache $STD php artisan event:cache
chown -R www-data:www-data /opt/bar-assistant chown -R www-data:www-data /opt/bar-assistant
rm -rf /opt/bar-assistant-backup
msg_ok "Updated Bar-Assistant" msg_ok "Updated Bar-Assistant"
msg_info "Starting nginx" msg_info "Starting nginx"
systemctl start nginx systemctl start nginx
msg_ok "Started nginx" msg_ok "Started nginx"
msg_info "Cleaning up"
rm -rf /opt/bar-assistant-backup
msg_ok "Cleaned"
fi fi
if check_for_gh_release "vue-salt-rim" "karlomikus/vue-salt-rim"; then if check_for_gh_release "vue-salt-rim" "karlomikus/vue-salt-rim"; then
@@ -81,15 +78,12 @@ function update_script() {
cd /opt/vue-salt-rim cd /opt/vue-salt-rim
$STD npm install $STD npm install
$STD npm run build $STD npm run build
rm -rf /opt/vue-salt-rim-backup
msg_ok "Updated Vue Salt Rim" msg_ok "Updated Vue Salt Rim"
msg_info "Starting nginx" msg_info "Starting nginx"
systemctl start nginx systemctl start nginx
msg_ok "Started nginx" msg_ok "Started nginx"
msg_info "Cleaning up"
rm -rf /opt/vue-salt-rim-backup
msg_ok "Cleaned"
fi fi
if check_for_gh_release "meilisearch" "meilisearch/meilisearch"; then if check_for_gh_release "meilisearch" "meilisearch/meilisearch"; then

View File

@@ -57,15 +57,12 @@ function update_script() {
chmod -R 755 /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage chmod -R 755 /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage
chmod -R 775 /opt/bookstack/storage /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads chmod -R 775 /opt/bookstack/storage /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads
chmod -R 640 /opt/bookstack/.env chmod -R 640 /opt/bookstack/.env
rm -rf /opt/bookstack-backup
msg_ok "Configured BookStack" msg_ok "Configured BookStack"
msg_info "Starting Apache2" msg_info "Starting Apache2"
systemctl start apache2 systemctl start apache2
msg_ok "Started Apache2" msg_ok "Started Apache2"
msg_info "Cleaning Up"
rm -rf /opt/bookstack-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -109,6 +109,7 @@ function update_script() {
fi fi
$STD uv run python manage.py migrate --noinput $STD uv run python manage.py migrate --noinput
$STD uv run python manage.py collectstatic --noinput $STD uv run python manage.py collectstatic --noinput
rm -f /tmp/dispatcharr_db_*.sql
msg_ok "Migrations Complete" msg_ok "Migrations Complete"
msg_info "Starting Services" msg_info "Starting Services"
@@ -117,10 +118,6 @@ function update_script() {
systemctl start dispatcharr-celerybeat systemctl start dispatcharr-celerybeat
systemctl start dispatcharr-daphne systemctl start dispatcharr-daphne
msg_ok "Started Services" msg_ok "Started Services"
msg_info "Cleaning up"
rm -f /tmp/dispatcharr_db_*.sql
msg_ok "Cleanup completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -76,11 +76,6 @@ function update_script() {
portainer/agent portainer/agent
msg_ok "Updated Portainer Agent" msg_ok "Updated Portainer Agent"
fi fi
msg_info "Cleaning up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleanup complete"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
exit exit
} }

View File

@@ -50,16 +50,13 @@ function update_script() {
$STD turbo run build --filter=@documenso/remix $STD turbo run build --filter=@documenso/remix
$STD npm run prisma:migrate-deploy $STD npm run prisma:migrate-deploy
$STD turbo daemon stop $STD turbo daemon stop
rm -rf /opt/v${RELEASE}.zip
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start documenso systemctl start documenso
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/v${RELEASE}.zip
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -47,16 +47,13 @@ function update_script() {
msg_info "Installing EMQX" msg_info "Installing EMQX"
$STD apt-get install -y "$DEB_FILE" $STD apt-get install -y "$DEB_FILE"
rm -f "$DEB_FILE"
echo "$RELEASE" >~/.emqx
msg_ok "Installed EMQX v${RELEASE}" msg_ok "Installed EMQX v${RELEASE}"
msg_info "Starting EMQX" msg_info "Starting EMQX"
systemctl start emqx systemctl start emqx
echo "$RELEASE" >~/.emqx
msg_ok "Started EMQX" msg_ok "Started EMQX"
msg_info "Cleaning Up"
rm -f "$DEB_FILE"
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. EMQX is already at v${RELEASE}" msg_ok "No update required. EMQX is already at v${RELEASE}"

View File

@@ -48,16 +48,13 @@ function update_script() {
temp_file=$(mktemp) temp_file=$(mktemp)
curl -fsSL https://fileflows.com/downloads/zip -o "$temp_file" curl -fsSL https://fileflows.com/downloads/zip -o "$temp_file"
$STD unzip -o -d /opt/fileflows "$temp_file" $STD unzip -o -d /opt/fileflows "$temp_file"
rm -rf "$temp_file"
rm -rf "$backup_filename"
msg_ok "Updated $APP to latest version" msg_ok "Updated $APP to latest version"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start fileflows systemctl start fileflows
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf "$temp_file"
rm -rf "$backup_filename"
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at latest version" msg_ok "No update required. ${APP} is already at latest version"

View File

@@ -56,10 +56,6 @@ function update_script() {
msg_info "Starting Service" msg_info "Starting Service"
systemctl start ghostfolio systemctl start ghostfolio
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
$STD npm cache clean --force
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -61,6 +61,15 @@ EOF
msg_ok "Installed libmimalloc3" msg_ok "Installed libmimalloc3"
fi fi
if [[ ! -f /etc/apt/sources.list.d/mise.list ]]; then
msg_info "Installing Mise"
curl -fSs https://mise.jdx.dev/gpg-key.pub | tee /etc/apt/keyrings/mise-archive-keyring.pub 1>/dev/null
echo "deb [signed-by=/etc/apt/keyrings/mise-archive-keyring.pub arch=amd64] https://mise.jdx.dev/deb stable main" | tee /etc/apt/sources.list.d/mise.list
$STD apt update
$STD apt install -y mise
msg_ok "Installed Mise"
fi
STAGING_DIR=/opt/staging STAGING_DIR=/opt/staging
BASE_DIR=${STAGING_DIR}/base-images BASE_DIR=${STAGING_DIR}/base-images
SOURCE_DIR=${STAGING_DIR}/image-source SOURCE_DIR=${STAGING_DIR}/image-source
@@ -93,7 +102,7 @@ EOF
msg_ok "Image-processing libraries up to date" msg_ok "Image-processing libraries up to date"
fi fi
RELEASE="2.2.3" RELEASE="2.3.1"
if check_for_gh_release "immich" "immich-app/immich" "${RELEASE}"; then if check_for_gh_release "immich" "immich-app/immich" "${RELEASE}"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop immich-web systemctl stop immich-web
@@ -121,6 +130,7 @@ EOF
UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)" UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)"
SRC_DIR="${INSTALL_DIR}/source" SRC_DIR="${INSTALL_DIR}/source"
APP_DIR="${INSTALL_DIR}/app" APP_DIR="${INSTALL_DIR}/app"
PLUGIN_DIR="${APP_DIR}/corePlugin"
ML_DIR="${APP_DIR}/machine-learning" ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata" GEO_DIR="${INSTALL_DIR}/geodata"
@@ -145,9 +155,7 @@ EOF
rm -rf "${APP_DIR:?}"/* rm -rf "${APP_DIR:?}"/*
) )
rm -rf "$SRC_DIR" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v${RELEASE}" "$SRC_DIR"
fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v${RELEASE}" "$SRC_DIR"
msg_info "Updating ${APP} web and microservices" msg_info "Updating ${APP} web and microservices"
cd "$SRC_DIR"/server cd "$SRC_DIR"/server
@@ -180,7 +188,18 @@ EOF
$STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli $STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli
cd "$APP_DIR" cd "$APP_DIR"
mv "$INSTALL_DIR"/start.sh "$APP_DIR"/bin mv "$INSTALL_DIR"/start.sh "$APP_DIR"/bin
msg_ok "Updated ${APP} web and microservices"
# plugins
cd "$SRC_DIR"
$STD mise trust --ignore ./mise.toml
$STD mise trust ./plugins/mise.toml
cd plugins
$STD mise install
$STD mise run build
mkdir -p "$PLUGIN_DIR"
cp -r ./dist "$PLUGIN_DIR"/dist
cp ./manifest.json "$PLUGIN_DIR"
msg_ok "Updated ${APP} server, web, cli and plugins"
cd "$SRC_DIR"/machine-learning cd "$SRC_DIR"/machine-learning
mkdir -p "$ML_DIR" && chown -R immich:immich "$ML_DIR" mkdir -p "$ML_DIR" && chown -R immich:immich "$ML_DIR"

View File

@@ -38,11 +38,6 @@ function update_script() {
$STD apt-get update $STD apt-get update
$STD apt-get -y upgrade $STD apt-get -y upgrade
msg_ok "Updating Packages" msg_ok "Updating Packages"
msg_info "Cleaning up"
apt-get -y autoremove
apt-get -y autoclean
msg_ok "Cleaning up"
fi fi
cd /opt/jellyseerr cd /opt/jellyseerr

View File

@@ -8,7 +8,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
APP="jotty" APP="jotty"
var_tags="${var_tags:-tasks;notes}" var_tags="${var_tags:-tasks;notes}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}" var_ram="${var_ram:-3072}"
var_disk="${var_disk:-6}" var_disk="${var_disk:-6}"
var_os="${var_os:-debian}" var_os="${var_os:-debian}"
var_version="${var_version:-13}" var_version="${var_version:-13}"

View File

@@ -82,7 +82,7 @@ function update_script() {
cd /opt/karakeep/packages/db cd /opt/karakeep/packages/db
$STD pnpm migrate $STD pnpm migrate
$STD pnpm store prune $STD pnpm store prune
sed -i "s/^SERVER_VERSION=.*$/SERVER_VERSION=${CHECK_UPDATE_RELEASE}/" /etc/karakeep/karakeep.env sed -i "s/^SERVER_VERSION=.*$/SERVER_VERSION=${CHECK_UPDATE_RELEASE#v}/" /etc/karakeep/karakeep.env
msg_ok "Updated Karakeep" msg_ok "Updated Karakeep"
msg_info "Starting Services" msg_info "Starting Services"

View File

@@ -49,15 +49,12 @@ function update_script() {
cp -a keycloak.old/conf/. keycloak/conf/ cp -a keycloak.old/conf/. keycloak/conf/
cp -a keycloak.old/providers/. keycloak/providers/ 2>/dev/null || true cp -a keycloak.old/providers/. keycloak/providers/ 2>/dev/null || true
cp -a keycloak.old/themes/. keycloak/themes/ 2>/dev/null || true cp -a keycloak.old/themes/. keycloak/themes/ 2>/dev/null || true
rm -rf keycloak.old
msg_ok "Updated Keycloak" msg_ok "Updated Keycloak"
msg_info "Restarting Service" msg_info "Restarting Service"
systemctl restart keycloak systemctl restart keycloak
msg_ok "Restarted Service" msg_ok "Restarted Service"
msg_info "Cleaning up"
rm -rf keycloak.old
msg_ok "Cleanup complete"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -50,15 +50,12 @@ function update_script() {
$STD yarn install $STD yarn install
$STD yarn build $STD yarn build
chown -R www-data:www-data /opt/koillection/public/uploads chown -R www-data:www-data /opt/koillection/public/uploads
rm -r /opt/koillection-backup
msg_ok "Updated Koillection" msg_ok "Updated Koillection"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start apache2 systemctl start apache2
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -r /opt/koillection-backup
msg_ok "Cleaned"
msg_ok "Updated Successfully!" msg_ok "Updated Successfully!"
fi fi
exit exit

View File

@@ -52,17 +52,14 @@ function update_script() {
$STD yarn web:build $STD yarn web:build
$STD yarn prisma:deploy $STD yarn prisma:deploy
[ -d /opt/data.bak ] && mv /opt/data.bak /opt/linkwarden/data [ -d /opt/data.bak ] && mv /opt/data.bak /opt/linkwarden/data
rm -rf ~/.cargo/registry ~/.cargo/git ~/.cargo/.package-cache ~/.rustup
rm -rf /root/.cache/yarn
rm -rf /opt/linkwarden/.next/cache
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start linkwarden systemctl start linkwarden
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf ~/.cargo/registry ~/.cargo/git ~/.cargo/.package-cache ~/.rustup
rm -rf /root/.cache/yarn
rm -rf /opt/linkwarden/.next/cache
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -42,15 +42,12 @@ function update_script() {
mv /opt/listmonk-backup/config.toml /opt/listmonk/config.toml mv /opt/listmonk-backup/config.toml /opt/listmonk/config.toml
mv /opt/listmonk-backup/uploads /opt/listmonk/uploads mv /opt/listmonk-backup/uploads /opt/listmonk/uploads
$STD /opt/listmonk/listmonk --upgrade --yes --config /opt/listmonk/config.toml $STD /opt/listmonk/listmonk --upgrade --yes --config /opt/listmonk/config.toml
rm -rf /opt/listmonk-backup/
msg_ok "Configured listmonk" msg_ok "Configured listmonk"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start listmonk systemctl start listmonk
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/listmonk-backup/
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -53,15 +53,12 @@ function update_script() {
msg_info "Configuring LubeLogger" msg_info "Configuring LubeLogger"
chmod 700 /opt/lubelogger/CarCareTracker chmod 700 /opt/lubelogger/CarCareTracker
cp -rf /tmp/lubeloggerData/* /opt/lubelogger/ cp -rf /tmp/lubeloggerData/* /opt/lubelogger/
rm -rf /tmp/lubeloggerData
msg_ok "Configured LubeLogger" msg_ok "Configured LubeLogger"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start lubelogger systemctl start lubelogger
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /tmp/lubeloggerData
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -38,15 +38,9 @@ function update_script() {
curl -fsSL -o "$DEB_FILE" "$DEB_URL" curl -fsSL -o "$DEB_FILE" "$DEB_URL"
$STD apt install "$DEB_FILE" -y $STD apt install "$DEB_FILE" -y
systemctl restart lyrion systemctl restart lyrion
$STD rm -f "$DEB_FILE"
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to ${RELEASE}" msg_ok "Updated $APP to ${RELEASE}"
msg_info "Cleaning up"
$STD rm -f "$DEB_FILE"
$STD apt -y autoremove
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "$APP is already up to date (${RELEASE})" msg_ok "$APP is already up to date (${RELEASE})"

View File

@@ -55,17 +55,13 @@ function update_script() {
mv /usr/local/bin/minio /usr/local/bin/minio_bak mv /usr/local/bin/minio /usr/local/bin/minio_bak
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/minio" -o /usr/local/bin/minio curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/minio" -o /usr/local/bin/minio
chmod +x /usr/local/bin/minio chmod +x /usr/local/bin/minio
rm -f /usr/local/bin/minio_bak
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start minio systemctl start minio
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -f /usr/local/bin/minio_bak
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -52,15 +52,12 @@ function update_script() {
$STD php artisan monica:update --force $STD php artisan monica:update --force
chown -R www-data:www-data /opt/monica chown -R www-data:www-data /opt/monica
chmod -R 775 /opt/monica/storage chmod -R 775 /opt/monica/storage
rm -r /opt/monica-backup
msg_ok "Configured monica" msg_ok "Configured monica"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start apache2 systemctl start apache2
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -r /opt/monica-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -57,17 +57,14 @@ function update_script() {
fi fi
$STD /opt/netbox/upgrade.sh $STD /opt/netbox/upgrade.sh
rm -r "/opt/v${RELEASE}.zip"
rm -r /opt/netbox-backup
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}" msg_ok "Updated $APP to v${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start netbox netbox-rq systemctl start netbox netbox-rq
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -r "/opt/v${RELEASE}.zip"
rm -r /opt/netbox-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -35,7 +35,7 @@ function update_script() {
msg_ok "Stopped services" msg_ok "Stopped services"
msg_info "Backing up configurations" msg_info "Backing up configurations"
cp /opt/netvisor/.env /opt/netvisor.env cp /opt/netvisor/.env /opt/netvisor.env.bak
msg_ok "Backed up configurations" msg_ok "Backed up configurations"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netvisor" "mayanayza/netvisor" "tarball" "latest" "/opt/netvisor" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netvisor" "mayanayza/netvisor" "tarball" "latest" "/opt/netvisor"
@@ -49,10 +49,16 @@ function update_script() {
TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')" TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
mv /opt/netvisor.env /opt/netvisor/.env cp /opt/netvisor.env.bak /opt/netvisor/.env
LOCAL_IP="$(hostname -I | awk '{print $1}')"
if ! grep -q "PUBLIC_URL" /opt/netvisor/.env; then
sed -i "\|_PATH=|a\NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/netvisor/.env
fi
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/netvisor/.env
msg_info "Creating frontend UI" msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=60072 export PUBLIC_SERVER_PORT=""
cd /opt/netvisor/ui cd /opt/netvisor/ui
$STD npm ci --no-fund --no-audit $STD npm ci --no-fund --no-audit
$STD npm run build $STD npm run build
@@ -64,10 +70,16 @@ function update_script() {
mv ./target/release/server /usr/bin/netvisor-server mv ./target/release/server /usr/bin/netvisor-server
msg_ok "Built Netvisor-server" msg_ok "Built Netvisor-server"
msg_info "Building Netvisor-daemon (amd64 version)" msg_info "Building Netvisor-daemon"
$STD cargo build --release --bin daemon $STD cargo build --release --bin daemon
cp ./target/release/daemon /usr/bin/netvisor-daemon cp ./target/release/daemon /usr/bin/netvisor-daemon
msg_ok "Built Netvisor-daemon (amd64 version)" msg_ok "Built Netvisor-daemon"
sed -i -e 's|-target|-url|' \
-e 's| --server-port |:|' \
/etc/systemd/system/netvisor-daemon.service
sed -i '/^ \"server_target.*$/d' /root/.config/daemon/config.json
systemctl daemon-reload
msg_info "Starting services" msg_info "Starting services"
systemctl start netvisor-server netvisor-daemon systemctl start netvisor-server netvisor-daemon

View File

@@ -41,15 +41,12 @@ function update_script() {
cd /opt cd /opt
curl -fsSL "https://nextpvr.com/nextpvr-helper.deb" -o $(basename "https://nextpvr.com/nextpvr-helper.deb") curl -fsSL "https://nextpvr.com/nextpvr-helper.deb" -o $(basename "https://nextpvr.com/nextpvr-helper.deb")
$STD dpkg -i nextpvr-helper.deb $STD dpkg -i nextpvr-helper.deb
rm -rf /opt/nextpvr-helper.deb
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start nextpvr-server systemctl start nextpvr-server
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/nextpvr-helper.deb
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
exit exit
} }

View File

@@ -49,11 +49,12 @@ function update_script() {
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | #RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
grep "tag_name" | #grep "tag_name" |
awk '{print substr($2, 3, length($2)-4) }') #awk '{print substr($2, 3, length($2)-4) }')
fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" RELEASE="2.13.4"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" "tarball" "v${RELEASE}" "/opt/nginxproxymanager"
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop openresty systemctl stop openresty

View File

@@ -42,17 +42,13 @@ function update_script() {
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
export DEBCONF_NOWARNINGS=yes export DEBCONF_NOWARNINGS=yes
$STD dpkg -i nxwitness-server-$RELEASE-linux_x64.deb $STD dpkg -i nxwitness-server-$RELEASE-linux_x64.deb
rm -f /tmp/nxwitness-server-$RELEASE-linux_x64.deb
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start networkoptix-root-tool networkoptix-mediaserver systemctl start networkoptix-root-tool networkoptix-mediaserver
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -f /tmp/nxwitness-server-$RELEASE-linux_x64.deb
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -50,17 +50,13 @@ function update_script() {
msg_info "Updating ${APP} to ${LATEST_VERSION}" msg_info "Updating ${APP} to ${LATEST_VERSION}"
curl -fsSL https://nightly.odoo.com/${RELEASE}/nightly/deb/odoo_${RELEASE}.latest_all.deb -o /opt/odoo.deb curl -fsSL https://nightly.odoo.com/${RELEASE}/nightly/deb/odoo_${RELEASE}.latest_all.deb -o /opt/odoo.deb
$STD apt install -y /opt/odoo.deb $STD apt install -y /opt/odoo.deb
rm -f /opt/odoo.deb
echo "$LATEST_VERSION" >/opt/${APP}_version.txt echo "$LATEST_VERSION" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to ${LATEST_VERSION}" msg_ok "Updated ${APP} to ${LATEST_VERSION}"
msg_info "Starting ${APP} service" msg_info "Starting Service"
systemctl start odoo systemctl start odoo
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -f /opt/odoo.deb
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${LATEST_VERSION}" msg_ok "No update required. ${APP} is already at ${LATEST_VERSION}"

View File

@@ -43,16 +43,13 @@ function update_script() {
mkdir -p /usr/local/lib/ollama mkdir -p /usr/local/lib/ollama
tar -xzf "${TMP_TAR}" -C /usr/local/lib/ollama tar -xzf "${TMP_TAR}" -C /usr/local/lib/ollama
ln -sf /usr/local/lib/ollama/bin/ollama /usr/local/bin/ollama ln -sf /usr/local/lib/ollama/bin/ollama /usr/local/bin/ollama
rm -f "${TMP_TAR}"
echo "${RELEASE}" >/opt/Ollama_version.txt echo "${RELEASE}" >/opt/Ollama_version.txt
msg_ok "Updated Ollama to ${RELEASE}" msg_ok "Updated Ollama to ${RELEASE}"
msg_info "Starting Services" msg_info "Starting Services"
systemctl start ollama systemctl start ollama
msg_ok "Started Services" msg_ok "Started Services"
msg_info "Cleaning Up"
rm -f "${TMP_TAR}"
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. Ollama is already at ${RELEASE}" msg_ok "No update required. Ollama is already at ${RELEASE}"

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-3072}" var_ram="${var_ram:-3072}"
var_disk="${var_disk:-8}" var_disk="${var_disk:-8}"
var_os="${var_os:-debian}" var_os="${var_os:-debian}"
var_version="${var_version:-13}" var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}" var_unprivileged="${var_unprivileged:-1}"
header_info "$APP" header_info "$APP"
@@ -32,19 +32,11 @@ function update_script() {
if lscpu | grep -q 'avx'; then if lscpu | grep -q 'avx'; then
MONGO_VERSION="8.0" setup_mongodb MONGO_VERSION="8.0" setup_mongodb
else else
msg_warn "No AVX detected: Using older MongoDB 4.4" msg_error "No AVX detected (CPU-Flag)! We have discontinued support for this. You are welcome to try it manually with a Debian LXC, but due to the many issues with Omada, we currently only support AVX CPUs."
MONGO_VERSION="4.4" setup_mongodb exit 10
fi fi
msg_info "Checking if right Azul Zulu Java is installed" JAVA_VERSION="21" setup_java
java_version=$(java -version 2>&1 | awk -F[\"_] '/version/ {print $2}')
if [[ "$java_version" =~ ^1\.8\.* ]]; then
$STD apt remove --purge -y zulu8-jdk
$STD apt -y install zulu21-jre-headless
msg_ok "Updated Azul Zulu Java to 21"
else
msg_ok "Azul Zulu Java 21 already installed"
fi
msg_info "Updating Omada Controller" msg_info "Updating Omada Controller"
OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/omada-controller/" | OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/omada-controller/" |

View File

@@ -39,17 +39,14 @@ function update_script() {
tar -xzf onedev-latest.tar.gz tar -xzf onedev-latest.tar.gz
$STD /opt/onedev-latest/bin/upgrade.sh /opt/onedev $STD /opt/onedev-latest/bin/upgrade.sh /opt/onedev
RELEASE=$(cat /opt/onedev/release.properties | grep "version" | cut -d'=' -f2) RELEASE=$(cat /opt/onedev/release.properties | grep "version" | cut -d'=' -f2)
rm -rf /opt/onedev-latest
rm -rf /opt/onedev-latest.tar.gz
echo "${RELEASE}" >"/opt/${APP}_version.txt" echo "${RELEASE}" >"/opt/${APP}_version.txt"
msg_ok "Updated ${APP} to v${RELEASE}" msg_ok "Updated ${APP} to v${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start onedev systemctl start onedev
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/onedev-latest
rm -rf /opt/onedev-latest.tar.gz
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}." msg_ok "No update required. ${APP} is already at v${RELEASE}."

View File

@@ -65,17 +65,14 @@ EOF
$STD pip install --no-cache-dir -r requirements.txt $STD pip install --no-cache-dir -r requirements.txt
mkdir -p data/chromadb mkdir -p data/chromadb
$STD npm install $STD npm install
rm -rf /opt/v${RELEASE}.zip
rm -rf /opt/paperless-ai_bak
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}" msg_ok "Updated $APP to v${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start paperless-ai systemctl start paperless-ai
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/v${RELEASE}.zip
rm -rf /opt/paperless-ai_bak
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -47,16 +47,13 @@ function update_script() {
export CC=musl-gcc export CC=musl-gcc
CGO_ENABLED=1 go build -tags musl -o /dev/null github.com/mattn/go-sqlite3 CGO_ENABLED=1 go build -tags musl -o /dev/null github.com/mattn/go-sqlite3
CGO_ENABLED=1 go build -tags musl -o paperless-gpt . CGO_ENABLED=1 go build -tags musl -o paperless-gpt .
rm -f $temp_file
echo "${RELEASE}" >"/opt/paperless-gpt_version.txt" echo "${RELEASE}" >"/opt/paperless-gpt_version.txt"
msg_ok "Updated Paperless-GPT to ${RELEASE}" msg_ok "Updated Paperless-GPT to ${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start paperless-gpt systemctl start paperless-gpt
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -f $temp_file
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -52,17 +52,14 @@ function update_script() {
$STD php bin/console cache:clear $STD php bin/console cache:clear
$STD php bin/console doctrine:migrations:migrate -n $STD php bin/console doctrine:migrations:migrate -n
chown -R www-data:www-data /opt/partdb chown -R www-data:www-data /opt/partdb
rm -r "/opt/v${RELEASE}.zip"
rm -r /opt/partdb-backup
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}" msg_ok "Updated $APP to v${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start apache2 systemctl start apache2
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -r "/opt/v${RELEASE}.zip"
rm -r /opt/partdb-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -67,6 +67,7 @@ function update_script() {
$STD php artisan migrate --seed --force $STD php artisan migrate --seed --force
chown -R www-data:www-data /opt/pelican-panel chown -R www-data:www-data /opt/pelican-panel
chmod -R 755 /opt/pelican-panel/storage /opt/pelican-panel/bootstrap/cache/ chmod -R 755 /opt/pelican-panel/storage /opt/pelican-panel/bootstrap/cache/
rm -rf "/opt/pelican-panel/panel.tar.gz"
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}" msg_ok "Updated $APP to v${RELEASE}"
@@ -74,10 +75,6 @@ function update_script() {
$STD php artisan queue:restart $STD php artisan queue:restart
$STD php artisan up $STD php artisan up
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf "/opt/pelican-panel/panel.tar.gz"
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -23,7 +23,8 @@ function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] && [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] \
&& [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi

View File

@@ -70,6 +70,7 @@ EOF
$STD php artisan migrate --seed --force --no-interaction $STD php artisan migrate --seed --force --no-interaction
chown -R www-data:www-data /opt/pterodactyl-panel/* chown -R www-data:www-data /opt/pterodactyl-panel/*
chmod -R 755 /opt/pterodactyl-panel/storage /opt/pterodactyl-panel/bootstrap/cache/ chmod -R 755 /opt/pterodactyl-panel/storage /opt/pterodactyl-panel/bootstrap/cache/
rm -rf "/opt/pterodactyl-panel/panel.tar.gz"
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}" msg_ok "Updated $APP to v${RELEASE}"
@@ -77,10 +78,6 @@ EOF
$STD php artisan queue:restart $STD php artisan queue:restart
$STD php artisan up $STD php artisan up
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf "/opt/pterodactyl-panel/panel.tar.gz"
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -43,14 +43,11 @@ function update_script() {
$STD apt remove --purge -y dotnet-sdk-8.0 $STD apt remove --purge -y dotnet-sdk-8.0
$STD apt install -y dotnet-sdk-9.0 $STD apt install -y dotnet-sdk-9.0
fi fi
rm -rf /opt/rdtc-backup
msg_info "Starting Service" msg_info "Starting Service"
systemctl start rdtc systemctl start rdtc
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/rdtc-backup
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -54,6 +54,7 @@ function update_script() {
cd /tmp cd /tmp
curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio.deb -o minio.deb curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio.deb -o minio.deb
$STD dpkg -i minio.deb $STD dpkg -i minio.deb
rm -f /tmp/minio.deb
msg_ok "Updated Minio" msg_ok "Updated Minio"
msg_info "Updating Browserless (Patience)" msg_info "Updating Browserless (Patience)"
@@ -75,16 +76,12 @@ function update_script() {
$STD npm run build:function $STD npm run build:function
$STD npm prune production $STD npm prune production
mv /opt/browserless.env /opt/browserless/.env mv /opt/browserless.env /opt/browserless/.env
rm -f "$brwsr_tmp"
msg_ok "Updated Browserless" msg_ok "Updated Browserless"
msg_info "Restarting services" msg_info "Restarting services"
systemctl start minio Reactive-Resume browserless systemctl start minio Reactive-Resume browserless
msg_ok "Restarted services" msg_ok "Restarted services"
msg_info "Cleaning Up"
rm -f /tmp/minio.deb
rm -f "$brwsr_tmp"
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -41,15 +41,12 @@ function update_script() {
$STD npm install $STD npm install
cp -f /opt/index.html /opt/revealjs cp -f /opt/index.html /opt/revealjs
sed -i '25s/localhost/0.0.0.0/g' /opt/revealjs/gulpfile.js sed -i '25s/localhost/0.0.0.0/g' /opt/revealjs/gulpfile.js
rm -f /opt/index.html
msg_ok "Updated $APP" msg_ok "Updated $APP"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start revealjs systemctl start revealjs
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -f /opt/index.html
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -61,15 +61,12 @@ function update_script() {
$STD pip install -r requirements.txt $STD pip install -r requirements.txt
mv /opt/config.ini.bak /opt/soularr/config.ini mv /opt/config.ini.bak /opt/soularr/config.ini
mv /opt/run.sh.bak /opt/soularr/run.sh mv /opt/run.sh.bak /opt/soularr/run.sh
rm -rf /tmp/main.zip
msg_ok "Updated soularr" msg_ok "Updated soularr"
msg_info "Starting soularr timer" msg_info "Starting soularr timer"
systemctl start soularr.timer systemctl start soularr.timer
msg_ok "Started soularr timer" msg_ok "Started soularr timer"
msg_info "Cleaning Up"
rm -rf /tmp/main.zip
msg_ok "Cleanup Completed"
exit exit
} }

View File

@@ -43,17 +43,13 @@ function update_script() {
cd spoolman cd spoolman
$STD pip3 install -r requirements.txt $STD pip3 install -r requirements.txt
curl -fsSL "https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example" -o ".env" curl -fsSL "https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example" -o ".env"
rm -rf /opt/spoolman.zip
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to ${RELEASE}" msg_ok "Updated ${APP} to ${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start spoolman systemctl start spoolman
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/spoolman.zip
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -64,16 +64,13 @@ EOF
cd /opt/tandoor cd /opt/tandoor
$STD /opt/tandoor/.venv/bin/python manage.py migrate $STD /opt/tandoor/.venv/bin/python manage.py migrate
$STD /opt/tandoor/.venv/bin/python manage.py collectstatic --no-input $STD /opt/tandoor/.venv/bin/python manage.py collectstatic --no-input
rm -rf /opt/tandoor.bak
msg_ok "Updated Trandoor" msg_ok "Updated Trandoor"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start tandoor systemctl start tandoor
systemctl reload nginx systemctl reload nginx
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/tandoor.bak
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -45,16 +45,13 @@ function update_script() {
export NODE_OPTIONS=--openssl-legacy-provider export NODE_OPTIONS=--openssl-legacy-provider
$STD npm i $STD npm i
$STD yarn build $STD yarn build
rm -r "/opt/v${RELEASE}.tar.gz"
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated TasmoCompiler" msg_ok "Updated TasmoCompiler"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start tasmocompiler systemctl start tasmocompiler
msg_ok "Started Service" msg_ok "Started Service"
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_info "Cleaning up"
rm -r "/opt/v${RELEASE}.tar.gz"
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -37,11 +37,8 @@ function update_script() {
$STD unzip Tdarr_Updater.zip $STD unzip Tdarr_Updater.zip
chmod +x Tdarr_Updater chmod +x Tdarr_Updater
$STD ./Tdarr_Updater $STD ./Tdarr_Updater
msg_ok "Updated Tdarr"
msg_info "Cleaning up"
rm -rf /opt/tdarr/Tdarr_Updater.zip rm -rf /opt/tdarr/Tdarr_Updater.zip
msg_ok "Cleaned up" msg_ok "Updated Tdarr"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
exit exit
} }

View File

@@ -38,11 +38,8 @@ function update_script() {
msg_info "Updating Technitium DNS" msg_info "Updating Technitium DNS"
curl -fsSL "https://download.technitium.com/dns/DnsServerPortable.tar.gz" -o /opt/DnsServerPortable.tar.gz curl -fsSL "https://download.technitium.com/dns/DnsServerPortable.tar.gz" -o /opt/DnsServerPortable.tar.gz
$STD tar zxvf /opt/DnsServerPortable.tar.gz -C /opt/technitium/dns/ $STD tar zxvf /opt/DnsServerPortable.tar.gz -C /opt/technitium/dns/
msg_ok "Updated Technitium DNS"
msg_info "Cleaning up"
rm -f /opt/DnsServerPortable.tar.gz rm -f /opt/DnsServerPortable.tar.gz
msg_ok "Cleaned up" msg_ok "Updated Technitium DNS"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. Technitium DNS is already at v${RELEASE}." msg_ok "No update required. Technitium DNS is already at v${RELEASE}."

View File

@@ -41,15 +41,12 @@ function update_script() {
msg_info "Restoring data" msg_info "Restoring data"
cp -R /opt/teddycloud_bak/certs /opt/teddycloud_bak/config /opt/teddycloud_bak/data /opt/teddycloud cp -R /opt/teddycloud_bak/certs /opt/teddycloud_bak/config /opt/teddycloud_bak/data /opt/teddycloud
rm -rf /opt/teddycloud_bak
msg_ok "Data restored" msg_ok "Data restored"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start teddycloud systemctl start teddycloud
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/teddycloud_bak
msg_ok "Cleaned up"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -43,7 +43,7 @@ function update_script() {
fetch_and_deploy_gh_release "tianji" "msgbyte/tianji" fetch_and_deploy_gh_release "tianji" "msgbyte/tianji"
msg_info "Updating ${APP}" msg_info "Updating Tianji"
cd /opt/tianji cd /opt/tianji
export NODE_OPTIONS="--max_old_space_size=4096" export NODE_OPTIONS="--max_old_space_size=4096"
$STD pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile $STD pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile
@@ -55,7 +55,11 @@ function update_script() {
mv /opt/.env /opt/tianji/src/server/.env mv /opt/.env /opt/tianji/src/server/.env
cd src/server cd src/server
$STD pnpm db:migrate:apply $STD pnpm db:migrate:apply
msg_ok "Updated ${APP}" rm -rf /opt/tianji_bak
rm -rf /opt/tianji/src/client
rm -rf /opt/tianji/website
rm -rf /opt/tianji/reporter
msg_ok "Updated Tianji"
msg_info "Updating AppRise" msg_info "Updating AppRise"
$STD uv pip install apprise cryptography --system $STD uv pip install apprise cryptography --system
@@ -64,13 +68,6 @@ function update_script() {
msg_info "Starting Service" msg_info "Starting Service"
systemctl start tianji systemctl start tianji
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/tianji_bak
rm -rf /opt/tianji/src/client
rm -rf /opt/tianji/website
rm -rf /opt/tianji/reporter
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -50,18 +50,12 @@ function update_script() {
mv /opt/traccar.xml /opt/traccar/conf mv /opt/traccar.xml /opt/traccar/conf
[[ -d /opt/data ]] && mv /opt/data /opt/traccar [[ -d /opt/data ]] && mv /opt/data /opt/traccar
[[ -d /opt/media ]] && mv /opt/media /opt/traccar [[ -d /opt/media ]] && mv /opt/media /opt/traccar
[ -f README.txt ] || [ -f traccar.run ] && rm -f README.txt traccar.run
msg_ok "Data restored" msg_ok "Data restored"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start traccar systemctl start traccar
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
[ -f README.txt ] || [ -f traccar.run ] && rm -f README.txt traccar.run
$STD apt -y autoremove
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleaned up"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -55,14 +55,8 @@ function update_script() {
msg_info "Restoring Database" msg_info "Restoring Database"
mkdir -p "$(dirname "${DB_RESTORE_PATH}")" mkdir -p "$(dirname "${DB_RESTORE_PATH}")"
cp -r /opt/trilium_backup/$(basename "${DB_PATH}") "${DB_RESTORE_PATH}" cp -r /opt/trilium_backup/$(basename "${DB_PATH}") "${DB_RESTORE_PATH}"
msg_ok "Restored Database"
msg_info "Cleaning up"
rm -rf /opt/trilium_backup rm -rf /opt/trilium_backup
$STD apt -y autoremove msg_ok "Restored Database"
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleaned"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start trilium systemctl start trilium

View File

@@ -43,12 +43,6 @@ function update_script() {
msg_info "Starting Service" msg_info "Starting Service"
systemctl start uhf-server systemctl start uhf-server
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
$STD apt -y autoremove
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -57,11 +57,8 @@ function update_script() {
else else
cp target/release/vaultwarden /opt/vaultwarden/bin/ cp target/release/vaultwarden /opt/vaultwarden/bin/
fi fi
msg_ok "Updated VaultWarden"
msg_info "Cleaning up"
cd ~ && rm -rf vaultwarden cd ~ && rm -rf vaultwarden
msg_ok "Cleaned" msg_ok "Updated VaultWarden"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start vaultwarden systemctl start vaultwarden
@@ -77,11 +74,8 @@ function update_script() {
msg_info "Updating Web-Vault to $WVRELEASE" msg_info "Updating Web-Vault to $WVRELEASE"
$STD curl -fsSLO https://github.com/dani-garcia/bw_web_builds/releases/download/"$WVRELEASE"/bw_web_"$WVRELEASE".tar.gz $STD curl -fsSLO https://github.com/dani-garcia/bw_web_builds/releases/download/"$WVRELEASE"/bw_web_"$WVRELEASE".tar.gz
$STD tar -zxf bw_web_"$WVRELEASE".tar.gz -C /opt/vaultwarden/ $STD tar -zxf bw_web_"$WVRELEASE".tar.gz -C /opt/vaultwarden/
msg_ok "Updated Web-Vault"
msg_info "Cleaning up"
rm bw_web_"$WVRELEASE".tar.gz rm bw_web_"$WVRELEASE".tar.gz
msg_ok "Cleaned" msg_ok "Updated Web-Vault"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start vaultwarden systemctl start vaultwarden

View File

@@ -39,16 +39,13 @@ function update_script() {
curl -fsSL "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb" -o $(basename "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb") curl -fsSL "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb" -o $(basename "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb")
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
$STD dpkg -i vikunja-"$RELEASE"-amd64.deb $STD dpkg -i vikunja-"$RELEASE"-amd64.deb
rm -rf /opt/vikunja-"$RELEASE"-amd64.deb
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start vikunja systemctl start vikunja
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/vikunja-"$RELEASE"-amd64.deb
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at ${RELEASE}" msg_ok "No update required. ${APP} is already at ${RELEASE}"

View File

@@ -73,16 +73,13 @@ EOF
cp -f wastebin* /opt/wastebin/ cp -f wastebin* /opt/wastebin/
chmod +x /opt/wastebin/wastebin chmod +x /opt/wastebin/wastebin
chmod +x /opt/wastebin/wastebin-ctl chmod +x /opt/wastebin/wastebin-ctl
rm -f "$temp_file"
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated Wastebin" msg_ok "Updated Wastebin"
msg_info "Starting Wastebin" msg_info "Starting Wastebin"
systemctl start wastebin systemctl start wastebin
msg_ok "Started Wastebin" msg_ok "Started Wastebin"
msg_info "Cleaning Up"
rm -f "$temp_file"
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -37,10 +37,7 @@ function update_script() {
fetch_and_deploy_gh_release "watchyourlan" "aceberg/WatchYourLAN" "binary" fetch_and_deploy_gh_release "watchyourlan" "aceberg/WatchYourLAN" "binary"
cp -R config.yaml /data/config.yaml cp -R config.yaml /data/config.yaml
sed -i 's|/etc/watchyourlan/config.yaml|/data/config.yaml|' /lib/systemd/system/watchyourlan.service sed -i 's|/etc/watchyourlan/config.yaml|/data/config.yaml|' /lib/systemd/system/watchyourlan.service
msg_info "Cleaning up"
rm ~/config.yaml rm ~/config.yaml
msg_ok "Cleaned up"
msg_info "Starting service" msg_info "Starting service"
systemctl enable -q --now watchyourlan systemctl enable -q --now watchyourlan

View File

@@ -45,16 +45,13 @@ function update_script() {
$STD python3 manage.py collectstatic --no-input $STD python3 manage.py collectstatic --no-input
$STD yarn install $STD yarn install
$STD yarn build:css:sass $STD yarn build:css:sass
rm -rf "$temp_file"
echo "${RELEASE}" >/opt/${APP}_version.txt echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}" msg_ok "Updated $APP to v${RELEASE}"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start wger systemctl start wger
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf "$temp_file"
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
else else
msg_ok "No update required. ${APP} is already at v${RELEASE}" msg_ok "No update required. ${APP} is already at v${RELEASE}"

View File

@@ -54,15 +54,12 @@ function update_script() {
msg_info "Restoring Data" msg_info "Restoring Data"
cp -R /opt/wikijs-backup/* /opt/wikijs cp -R /opt/wikijs-backup/* /opt/wikijs
$SQLITE_INSTALL && $STD npm rebuild sqlite3 $SQLITE_INSTALL && $STD npm rebuild sqlite3
rm -rf /opt/wikijs-backup
msg_ok "Restored Data" msg_ok "Restored Data"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start wikijs systemctl start wikijs
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf /opt/wikijs-backup
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -56,15 +56,12 @@ function update_script() {
if ! grep -q 'frozen' /opt/wizarr/start.sh; then if ! grep -q 'frozen' /opt/wizarr/start.sh; then
sed -i 's/run/& --frozen/' /opt/wizarr/start.sh sed -i 's/run/& --frozen/' /opt/wizarr/start.sh
fi fi
rm -rf "$BACKUP_FILE"
msg_ok "Updated Wizarr" msg_ok "Updated Wizarr"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start wizarr systemctl start wizarr
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning Up"
rm -rf "$BACKUP_FILE"
msg_ok "Cleanup Completed"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

View File

@@ -59,6 +59,7 @@ function update_script() {
xargs -I{} echo "https://repo.zabbix.com/zabbix/{}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb")" \ xargs -I{} echo "https://repo.zabbix.com/zabbix/{}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb")" \
-o /tmp/zabbix-release_latest+debian13_all.deb -o /tmp/zabbix-release_latest+debian13_all.deb
$STD dpkg -i zabbix-release_latest+debian13_all.deb $STD dpkg -i zabbix-release_latest+debian13_all.deb
rm -rf /tmp/zabbix-release_latest+debian13_all.deb
$STD apt update $STD apt update
$STD apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php php8.4-pgsql $STD apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php php8.4-pgsql
@@ -88,13 +89,6 @@ function update_script() {
systemctl start "$AGENT_SERVICE" systemctl start "$AGENT_SERVICE"
systemctl restart apache2 systemctl restart apache2
msg_ok "Started Services" msg_ok "Started Services"
msg_info "Cleaning Up"
rm -rf /tmp/zabbix-release_latest+debian13_all.deb
$STD apt -y autoremove
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleaned"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
exit exit
} }

View File

@@ -50,15 +50,12 @@ function update_script() {
grep -q "^packageImportMethod" ./pnpm-workspace.yaml || echo "packageImportMethod: hardlink" >>./pnpm-workspace.yaml grep -q "^packageImportMethod" ./pnpm-workspace.yaml || echo "packageImportMethod: hardlink" >>./pnpm-workspace.yaml
$STD pnpm install --frozen-lockfile $STD pnpm install --frozen-lockfile
$STD pnpm build $STD pnpm build
rm -rf /opt/z2m_backup
msg_ok "Updated Zigbee2MQTT" msg_ok "Updated Zigbee2MQTT"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start zigbee2mqtt systemctl start zigbee2mqtt
msg_ok "Started Service" msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf /opt/z2m_backup
msg_ok "Cleaned up"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
exit exit

100
frontend/bun.lock generated
View File

@@ -11,6 +11,7 @@
"@radix-ui/react-label": "^2.1.2", "@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-navigation-menu": "^1.2.5", "@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.1.6", "@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-slot": "^1.1.2",
@@ -26,7 +27,7 @@
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"framer-motion": "^11.18.2", "framer-motion": "^11.18.2",
"fuse.js": "^7.1.0", "fuse.js": "^7.1.0",
"lucide-react": "^0.542.0", "lucide-react": "^0.554.0",
"mini-svg-data-uri": "^1.4.4", "mini-svg-data-uri": "^1.4.4",
"motion": "^12.23.12", "motion": "^12.23.12",
"next": "15.5.2", "next": "15.5.2",
@@ -43,6 +44,7 @@
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-simple-typewriter": "^5.0.1", "react-simple-typewriter": "^5.0.1",
"react-use-measure": "^2.1.7", "react-use-measure": "^2.1.7",
"recharts": "2.15.4",
"sharp": "^0.33.5", "sharp": "^0.33.5",
"simple-icons": "^13.21.0", "simple-icons": "^13.21.0",
"sonner": "^1.7.4", "sonner": "^1.7.4",
@@ -417,6 +419,8 @@
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="], "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="],
"@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.5", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA=="], "@radix-ui/react-select": ["@radix-ui/react-select@2.2.5", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA=="],
"@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="], "@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
@@ -515,6 +519,24 @@
"@types/babel__traverse": ["@types/babel__traverse@7.20.7", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng=="], "@types/babel__traverse": ["@types/babel__traverse@7.20.7", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng=="],
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
"@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
"@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="],
"@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
"@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
"@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
"@types/d3-shape": ["@types/d3-shape@3.1.7", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg=="],
"@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
"@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
@@ -765,6 +787,28 @@
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
"d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
"d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
"d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="],
"d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
"d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
"d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
"d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
"d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
"d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
"d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
"damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="], "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
"data-urls": ["data-urls@5.0.0", "", { "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" } }, "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg=="], "data-urls": ["data-urls@5.0.0", "", { "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" } }, "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg=="],
@@ -783,6 +827,8 @@
"decimal.js": ["decimal.js@10.5.0", "", {}, "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw=="], "decimal.js": ["decimal.js@10.5.0", "", {}, "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw=="],
"decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
"decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="],
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
@@ -807,6 +853,8 @@
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
"dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
@@ -939,12 +987,16 @@
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
"eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
"exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="],
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="],
"fast-equals": ["fast-equals@5.3.3", "", {}, "sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw=="],
"fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="], "fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="],
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
@@ -1059,6 +1111,8 @@
"internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
"internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
"is-alphabetical": ["is-alphabetical@1.0.4", "", {}, "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="], "is-alphabetical": ["is-alphabetical@1.0.4", "", {}, "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="],
"is-alphanumerical": ["is-alphanumerical@1.0.4", "", { "dependencies": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" } }, "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A=="], "is-alphanumerical": ["is-alphanumerical@1.0.4", "", { "dependencies": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" } }, "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A=="],
@@ -1191,7 +1245,7 @@
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"lucide-react": ["lucide-react@0.542.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw=="], "lucide-react": ["lucide-react@0.554.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-St+z29uthEJVx0Is7ellNkgTEhaeSoA42I7JjOCBCrc5X6LYMGSv0P/2uS5HDLTExP5tpiqRD2PyUEOS6s9UXA=="],
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
@@ -1455,7 +1509,7 @@
"react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="], "react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="],
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
"react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
@@ -1465,16 +1519,24 @@
"react-simple-typewriter": ["react-simple-typewriter@5.0.1", "", { "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-vA5HkABwJKL/DJ4RshSlY/igdr+FiVY4MLsSQYJX6FZG/f1/VwN4y1i3mPXRyfaswrvI8xii1kOVe1dYtO2Row=="], "react-simple-typewriter": ["react-simple-typewriter@5.0.1", "", { "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-vA5HkABwJKL/DJ4RshSlY/igdr+FiVY4MLsSQYJX6FZG/f1/VwN4y1i3mPXRyfaswrvI8xii1kOVe1dYtO2Row=="],
"react-smooth": ["react-smooth@4.0.4", "", { "dependencies": { "fast-equals": "^5.0.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q=="],
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
"react-syntax-highlighter": ["react-syntax-highlighter@15.6.1", "", { "dependencies": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", "highlightjs-vue": "^1.0.0", "lowlight": "^1.17.0", "prismjs": "^1.27.0", "refractor": "^3.6.0" }, "peerDependencies": { "react": ">= 0.14.0" } }, "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg=="], "react-syntax-highlighter": ["react-syntax-highlighter@15.6.1", "", { "dependencies": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", "highlightjs-vue": "^1.0.0", "lowlight": "^1.17.0", "prismjs": "^1.27.0", "refractor": "^3.6.0" }, "peerDependencies": { "react": ">= 0.14.0" } }, "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg=="],
"react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
"react-use-measure": ["react-use-measure@2.1.7", "", { "peerDependencies": { "react": ">=16.13", "react-dom": ">=16.13" } }, "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg=="], "react-use-measure": ["react-use-measure@2.1.7", "", { "peerDependencies": { "react": ">=16.13", "react-dom": ">=16.13" } }, "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg=="],
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
"recharts": ["recharts@2.15.4", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.4", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw=="],
"recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="],
"refa": ["refa@0.12.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0" } }, "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g=="], "refa": ["refa@0.12.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0" } }, "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g=="],
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
@@ -1625,6 +1687,8 @@
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
"tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
@@ -1693,6 +1757,8 @@
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="],
"vite": ["vite@7.1.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx"], "bin": "bin/vite.js" }, "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ=="], "vite": ["vite@7.1.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx"], "bin": "bin/vite.js" }, "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ=="],
"vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" } }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="], "vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" } }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="],
@@ -1757,18 +1823,18 @@
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@eslint/config-array/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
"@eslint/eslintrc/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "@eslint/eslintrc/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"@eslint/eslintrc/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="], "@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="],
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
"@radix-ui/react-scroll-area/@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
"@radix-ui/react-scroll-area/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
"@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], "@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
@@ -1797,24 +1863,18 @@
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-plugin-import/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"eslint-plugin-jsdoc/@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.52.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.34.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing=="], "eslint-plugin-jsdoc/@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.52.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.34.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing=="],
"eslint-plugin-jsonc/synckit": ["synckit@0.11.8", "", { "dependencies": { "@pkgr/core": "^0.2.4" } }, "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A=="], "eslint-plugin-jsonc/synckit": ["synckit@0.11.8", "", { "dependencies": { "@pkgr/core": "^0.2.4" } }, "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A=="],
"eslint-plugin-jsx-a11y/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"eslint-plugin-n/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], "eslint-plugin-n/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="],
"eslint-plugin-n/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "eslint-plugin-n/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"eslint-plugin-n/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "eslint-plugin-n/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"eslint-plugin-react/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="],
"eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
@@ -1851,6 +1911,8 @@
"path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
"readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"refractor/prismjs": ["prismjs@1.27.0", "", {}, "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA=="], "refractor/prismjs": ["prismjs@1.27.0", "", {}, "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA=="],
@@ -1873,8 +1935,6 @@
"tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": "lib/cli.js" }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], "tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": "lib/cli.js" }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
"w3c-xmlserializer/xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
"wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
@@ -1883,24 +1943,14 @@
"yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"eslint-plugin-import/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"eslint-plugin-jsonc/synckit/@pkgr/core": ["@pkgr/core@0.2.7", "", {}, "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg=="], "eslint-plugin-jsonc/synckit/@pkgr/core": ["@pkgr/core@0.2.7", "", {}, "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg=="],
"eslint-plugin-jsx-a11y/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"eslint-plugin-unicorn/@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="], "eslint-plugin-unicorn/@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="],
"glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],

4
frontend/package.json generated
View File

@@ -23,6 +23,7 @@
"@radix-ui/react-label": "^2.1.2", "@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-navigation-menu": "^1.2.5", "@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.1.6", "@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-slot": "^1.1.2",
@@ -38,7 +39,7 @@
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"framer-motion": "^11.18.2", "framer-motion": "^11.18.2",
"fuse.js": "^7.1.0", "fuse.js": "^7.1.0",
"lucide-react": "^0.542.0", "lucide-react": "^0.554.0",
"mini-svg-data-uri": "^1.4.4", "mini-svg-data-uri": "^1.4.4",
"motion": "^12.23.12", "motion": "^12.23.12",
"next": "15.5.2", "next": "15.5.2",
@@ -55,6 +56,7 @@
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-simple-typewriter": "^5.0.1", "react-simple-typewriter": "^5.0.1",
"react-use-measure": "^2.1.7", "react-use-measure": "^2.1.7",
"recharts": "2.15.4",
"sharp": "^0.33.5", "sharp": "^0.33.5",
"simple-icons": "^13.21.0", "simple-icons": "^13.21.0",
"sonner": "^1.7.4", "sonner": "^1.7.4",

View File

@@ -11,7 +11,7 @@
"privileged": false, "privileged": false,
"interface_port": 8080, "interface_port": 8080,
"documentation": null, "documentation": null,
"website": "https://filebrowser.org/features", "website": "https://filebrowser.org/index.html#features",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/file-browser.webp", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/file-browser.webp",
"config_path": "", "config_path": "",
"description": "File Browser offers a user-friendly web interface for managing files within a designated directory. It allows you to perform various actions such as uploading, deleting, previewing, renaming, and editing files.", "description": "File Browser offers a user-friendly web interface for managing files within a designated directory. It allows you to perform various actions such as uploading, deleting, previewing, renaming, and editing files.",

View File

@@ -20,7 +20,7 @@
"script": "ct/jotty.sh", "script": "ct/jotty.sh",
"resources": { "resources": {
"cpu": 2, "cpu": 2,
"ram": 4096, "ram": 3072,
"hdd": 6, "hdd": 6,
"os": "debian", "os": "debian",
"version": "13" "version": "13"

View File

@@ -35,6 +35,10 @@
{ {
"text": "The integrated daemon config is located at `/root/.config/daemon/config.json`", "text": "The integrated daemon config is located at `/root/.config/daemon/config.json`",
"type": "info" "type": "info"
},
{
"text": "When using a reverse proxy, edit `/opt/netvisor/ui/build/_app/env.js`: add 443 to `PUBLIC_SERVER_PORT` and remove 'default' from `PUBLIC_SERVER_HOSTNAME`.",
"type": "info"
} }
] ]
} }

View File

@@ -23,7 +23,7 @@
"ram": 3072, "ram": 3072,
"hdd": 8, "hdd": 8,
"os": "debian", "os": "debian",
"version": "13" "version": "12"
} }
} }
], ],

View File

@@ -33,7 +33,7 @@
}, },
"notes": [ "notes": [
{ {
"text": "Type `cat ~/.Passbolt.creds` to see MariaDB database credentials. You will need those to setup Passbolt.", "text": "Type `cat ~/passbolt.creds` to see MariaDB database credentials. You will need those to setup Passbolt.",
"type": "info" "type": "info"
}, },
{ {

View File

@@ -6,7 +6,7 @@
], ],
"date_created": "2025-08-26", "date_created": "2025-08-26",
"type": "ct", "type": "ct",
"updateable": true, "updateable": false,
"privileged": false, "privileged": false,
"interface_port": 8888, "interface_port": 8888,
"documentation": "https://docs.searxng.org/", "documentation": "https://docs.searxng.org/",

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,67 @@
"use client"; "use client";
import React, { useEffect, useState } from "react"; import {
import "react-datepicker/dist/react-datepicker.css"; ArrowUpDown,
Box,
CheckCircle2,
ChevronLeft,
ChevronRight,
List,
Loader2,
Trophy,
XCircle,
} from "lucide-react";
import {
Bar,
BarChart,
CartesianGrid,
Cell,
LabelList,
XAxis,
} from "recharts";
import React, { useEffect, useMemo, useState } from "react";
import ApplicationChart from "../../components/application-chart"; import type { ChartConfig } from "@/components/ui/chart";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart";
import { formattedBadge } from "@/components/command-menu";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
type DataModel = { type DataModel = {
id: number; id: number;
@@ -30,42 +88,76 @@ type SummaryData = {
nsapp_count: Record<string, number>; nsapp_count: Record<string, number>;
}; };
const DataFetcher: React.FC = () => { // Chart colors optimized for both light and dark modes
// Medium-toned colors that are visible and not too flashy in both themes
const CHART_COLORS = [
"#5B8DEF", // blue - medium tone
"#4ECDC4", // teal - medium tone
"#FF8C42", // orange - medium tone
"#A78BFA", // purple - medium tone
"#F472B6", // pink - medium tone
"#38BDF8", // cyan - medium tone
"#4ADE80", // green - medium tone
"#FBBF24", // yellow - medium tone
"#818CF8", // indigo - medium tone
"#FB7185", // rose - medium tone
"#2DD4BF", // turquoise - medium tone
"#C084FC", // violet - medium tone
"#60A5FA", // sky blue - medium tone
"#84CC16", // lime - medium tone
"#F59E0B", // amber - medium tone
"#A855F7", // purple - medium tone
"#10B981", // emerald - medium tone
"#EAB308", // gold - medium tone
"#3B82F6", // royal blue - medium tone
"#EF4444", // red - medium tone
];
const chartConfigApps = {
count: {
label: "Installations",
color: "hsl(var(--chart-1))",
},
} satisfies ChartConfig;
export default function DataPage() {
const [data, setData] = useState<DataModel[]>([]); const [data, setData] = useState<DataModel[]>([]);
const [summary, setSummary] = useState<SummaryData | null>(null); const [summary, setSummary] = useState<SummaryData | null>(null);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(25); const [itemsPerPage, setItemsPerPage] = useState(25);
const [sortConfig, setSortConfig] = useState<{ key: string; direction: "ascending" | "descending" } | null>(null); const [sortConfig, setSortConfig] = useState<{
key: string;
direction: "ascending" | "descending";
} | null>(null);
const nf = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }); const nf = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 });
useEffect(() => { useEffect(() => {
const fetchSummary = async () => { const fetchData = async () => {
try {
const response = await fetch("https://api.htl-braunau.at/data/summary");
if (!response.ok)
throw new Error(`Failed to fetch summary: ${response.statusText}`);
const result: SummaryData = await response.json();
setSummary(result);
}
catch (err) {
setError((err as Error).message);
}
};
fetchSummary();
}, []);
useEffect(() => {
const fetchPaginatedData = async () => {
setLoading(true); setLoading(true);
try { try {
const response = await fetch(`https://api.htl-braunau.at/data/paginated?page=${currentPage}&limit=${itemsPerPage === 0 ? "" : itemsPerPage}`); const [summaryRes, dataRes] = await Promise.all([
if (!response.ok) fetch("https://api.htl-braunau.at/data/summary"),
throw new Error(`Failed to fetch data: ${response.statusText}`); fetch(
const result: DataModel[] = await response.json(); `https://api.htl-braunau.at/data/paginated?page=${currentPage}&limit=${itemsPerPage === 0 ? "" : itemsPerPage
setData(result); }`,
),
]);
if (!summaryRes.ok) {
throw new Error(`Failed to fetch summary: ${summaryRes.statusText}`);
}
if (!dataRes.ok) {
throw new Error(`Failed to fetch data: ${dataRes.statusText}`);
}
const summaryData: SummaryData = await summaryRes.json();
const pageData: DataModel[] = await dataRes.json();
setSummary(summaryData);
setData(pageData);
} }
catch (err) { catch (err) {
setError((err as Error).message); setError((err as Error).message);
@@ -75,13 +167,13 @@ const DataFetcher: React.FC = () => {
} }
}; };
fetchPaginatedData(); fetchData();
}, [currentPage, itemsPerPage]); }, [currentPage, itemsPerPage]);
const sortedData = React.useMemo(() => { const sortedData = useMemo(() => {
if (!sortConfig) if (!sortConfig)
return data; return data;
const sorted = [...data].sort((a, b) => { return [...data].sort((a, b) => {
if (a[sortConfig.key] < b[sortConfig.key]) { if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === "ascending" ? -1 : 1; return sortConfig.direction === "ascending" ? -1 : 1;
} }
@@ -90,23 +182,15 @@ const DataFetcher: React.FC = () => {
} }
return 0; return 0;
}); });
return sorted;
}, [data, sortConfig]); }, [data, sortConfig]);
if (loading)
return <p>Loading...</p>;
if (error) {
return (
<p>
Error:
{error}
</p>
);
}
const requestSort = (key: string) => { const requestSort = (key: string) => {
let direction: "ascending" | "descending" = "ascending"; let direction: "ascending" | "descending" = "ascending";
if (sortConfig && sortConfig.key === key && sortConfig.direction === "ascending") { if (
sortConfig
&& sortConfig.key === key
&& sortConfig.direction === "ascending"
) {
direction = "descending"; direction = "descending";
} }
setSortConfig({ key, direction }); setSortConfig({ key, direction });
@@ -114,135 +198,447 @@ const DataFetcher: React.FC = () => {
const formatDate = (dateString: string): string => { const formatDate = (dateString: string): string => {
const date = new Date(dateString); const date = new Date(dateString);
const year = date.getFullYear(); return new Intl.DateTimeFormat("en-US", {
const month = date.getMonth() + 1; dateStyle: "medium",
const day = date.getDate(); timeStyle: "short",
const hours = String(date.getHours()).padStart(2, "0"); }).format(date);
const minutes = String(date.getMinutes()).padStart(2, "0");
const timezoneOffset = dateString.slice(-6);
return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`;
}; };
const getTypeBadge = (type: string) => {
if (type === "lxc")
return formattedBadge("ct");
if (type === "vm")
return formattedBadge("vm");
return null;
};
// Stats calculations
const successCount = summary?.status_count.done ?? 0;
const failureCount = summary?.status_count.failed ?? 0;
const totalCount = summary?.total_entries ?? 0;
const successRate = totalCount > 0 ? (successCount / totalCount) * 100 : 0;
const allApps = useMemo(() => {
if (!summary?.nsapp_count)
return [];
return Object.entries(summary.nsapp_count).sort(([, a], [, b]) => b - a);
}, [summary]);
const topApps = useMemo(() => {
return allApps.slice(0, 15);
}, [allApps]);
const mostPopularApp = topApps[0];
// Chart Data
const appsChartData = topApps.map(([name, count], index) => ({
app: name,
count,
fill: CHART_COLORS[index % CHART_COLORS.length],
}));
if (error) {
return ( return (
<div className="p-6 mt-20"> <div className="p-6 text-center text-red-500">
<h1 className="text-2xl font-bold mb-4 text-center">Created LXCs</h1> <p>
<ApplicationChart data={summary} /> Error loading data:
<p className="text-lg font-bold mt-4"> </p> {error}
<div className="mb-4 flex justify-between items-center">
<p className="text-lg font-bold">
{nf.format(
summary?.total_entries ?? 0,
)}
{" "}
results found
</p>
<p className="text-lg font">
Status Legend: 🔄 installing
{" "}
{nf.format(summary?.status_count.installing ?? 0)}
{" "}
| completed
{" "}
{nf.format(summary?.status_count.done ?? 0)}
{" "}
| failed
{" "}
{nf.format(summary?.status_count.failed ?? 0)}
{" "}
| unknown
</p> </p>
</div> </div>
<div className="overflow-x-auto"> );
<div className="overflow-y-auto lg:overflow-y-visible"> }
<table className="min-w-full table-auto border-collapse">
<thead> return (
<tr> <div className="mb-3">
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("status")}>Status</th> <div className="mt-20 flex sm:px-4 xl:px-0">
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("type")}>Type</th> <div className="mx-4 w-full sm:mx-0 space-y-8">
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("nsapp")}>Application</th> {/* Header */}
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("os_type")}>OS</th> <div>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("os_version")}>OS Version</th> <h1 className="text-3xl font-bold tracking-tight">Analytics</h1>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("disk_size")}>Disk Size</th> <p className="text-muted-foreground">
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("core_count")}>Core Count</th> Overview of container installations and system statistics.
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("ram_size")}>RAM Size</th> </p>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("method")}>Method</th> </div>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("pve_version")}>PVE Version</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("error")}>Error Message</th> {/* Widgets */}
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("created_at")}>Created At</th> <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
</tr> <Card>
</thead> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<tbody> <CardTitle className="text-sm font-medium">Total Created</CardTitle>
{sortedData.map((item, index) => ( <Box className="h-4 w-4 text-muted-foreground" />
<tr key={index}> </CardHeader>
<td className="px-4 py-2 border-b"> <CardContent>
<div className="text-2xl font-bold">{nf.format(totalCount)}</div>
<p className="text-xs text-muted-foreground">
Total LXC/VM entries found
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Success Rate</CardTitle>
<CheckCircle2 className="h-4 w-4 text-green-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{successRate.toFixed(1)}
%
</div>
<p className="text-xs text-muted-foreground">
{nf.format(successCount)}
{" "}
successful installations
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Failures</CardTitle>
<XCircle className="h-4 w-4 text-red-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{nf.format(failureCount)}</div>
<p className="text-xs text-muted-foreground">
Installations encountered errors
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Most Popular</CardTitle>
<Trophy className="h-4 w-4 text-yellow-500" />
</CardHeader>
<CardContent>
<div className="truncate text-2xl font-bold">
{mostPopularApp ? mostPopularApp[0] : "N/A"}
</div>
<p className="text-xs text-muted-foreground">
{mostPopularApp ? nf.format(mostPopularApp[1]) : 0}
{" "}
installations
</p>
</CardContent>
</Card>
</div>
{/* Graphs */}
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<div className="space-y-1.5">
<CardTitle>Top Applications</CardTitle>
<CardDescription>
The most frequently installed applications.
</CardDescription>
</div>
<Dialog>
<DialogTrigger asChild>
<Button variant="outline" size="sm" className="ml-auto">
<List className="mr-2 h-4 w-4" />
View All
</Button>
</DialogTrigger>
<DialogContent className="max-h-[80vh] sm:max-w-md">
<DialogHeader>
<DialogTitle>Application Statistics</DialogTitle>
<DialogDescription>
Installation counts for all
{" "}
{allApps.length}
{" "}
applications.
</DialogDescription>
</DialogHeader>
<ScrollArea className="h-[60vh] w-full rounded-md border p-4">
<div className="space-y-4">
{allApps.map(([name, count], index) => (
<div
key={name}
className="flex items-center justify-between text-sm"
>
<div className="flex items-center gap-2">
<span className="w-8 font-mono text-muted-foreground">
{index + 1}
.
</span>
<span className="font-medium">{name}</span>
</div>
<span className="font-mono">{nf.format(count)}</span>
</div>
))}
</div>
</ScrollArea>
</DialogContent>
</Dialog>
</CardHeader>
<CardContent className="pl-2">
<div className="h-[300px] w-full">
{loading
? (
<div className="flex h-full w-full items-center justify-center">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
)
: (
<ChartContainer config={chartConfigApps} className="h-full w-full">
<BarChart
accessibilityLayer
data={appsChartData}
margin={{
top: 20,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="app"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={value => (value.length > 8 ? `${value.slice(0, 8)}...` : value)}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent nameKey="app" />}
/>
<Bar dataKey="count" radius={8}>
{appsChartData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.fill} />
))}
<LabelList
position="top"
offset={12}
className="fill-foreground"
fontSize={12}
/>
</Bar>
</BarChart>
</ChartContainer>
)}
</div>
</CardContent>
</Card>
{/* Data Table */}
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<div>
<CardTitle>Installation Log</CardTitle>
<CardDescription>
Detailed records of all container creation attempts.
</CardDescription>
</div>
<div className="flex items-center gap-2">
<Select
value={String(itemsPerPage)}
onValueChange={val => setItemsPerPage(Number(val))}
>
<SelectTrigger className="w-[80px]">
<SelectValue placeholder="Limit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="10">10</SelectItem>
<SelectItem value="25">25</SelectItem>
<SelectItem value="50">50</SelectItem>
<SelectItem value="100">100</SelectItem>
</SelectContent>
</Select>
</div>
</CardHeader>
<CardContent>
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead
className="w-[100px] cursor-pointer"
onClick={() => requestSort("status")}
>
Status
{sortConfig?.key === "status" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="cursor-pointer"
onClick={() => requestSort("type")}
>
Type
{sortConfig?.key === "type" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="cursor-pointer"
onClick={() => requestSort("nsapp")}
>
Application
{sortConfig?.key === "nsapp" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="hidden cursor-pointer md:table-cell"
onClick={() => requestSort("os_type")}
>
OS
{sortConfig?.key === "os_type" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="hidden cursor-pointer md:table-cell"
onClick={() => requestSort("disk_size")}
>
Disk Size
{sortConfig?.key === "disk_size" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="hidden cursor-pointer lg:table-cell"
onClick={() => requestSort("core_count")}
>
Core Count
{sortConfig?.key === "core_count" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="hidden cursor-pointer lg:table-cell"
onClick={() => requestSort("ram_size")}
>
RAM Size
{sortConfig?.key === "ram_size" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
<TableHead
className="cursor-pointer text-right"
onClick={() => requestSort("created_at")}
>
Created At
{sortConfig?.key === "created_at" && (
<ArrowUpDown className="ml-2 inline h-4 w-4" />
)}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{loading
? (
<TableRow>
<TableCell colSpan={8} className="h-24 text-center">
<div className="flex items-center justify-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
{" "}
Loading data...
</div>
</TableCell>
</TableRow>
)
: sortedData.length > 0
? (
sortedData.map((item, idx) => (
<TableRow key={`${item.id}-${idx}`}>
<TableCell>
{item.status === "done" {item.status === "done"
? ( ? (
"✔️" <Badge className="text-green-500/75 border-green-500/75">
Success
</Badge>
) )
: item.status === "failed" : item.status === "failed"
? ( ? (
"❌" <Badge className="text-red-500/75 border-red-500/75">
Failed
</Badge>
) )
: item.status === "installing" : item.status === "installing"
? ( ? (
"🔄" <Badge className="text-blue-500/75 border-blue-500/75">
Installing
</Badge>
) )
: ( : (
item.status <Badge variant="outline">
{item.status}
</Badge>
)} )}
</td> </TableCell>
<td className="px-4 py-2 border-b"> <TableCell>
{item.type === "lxc" {getTypeBadge(item.type) || (
? ( <Badge variant="outline">
"📦" {item.type}
) </Badge>
: item.type === "vm" )}
? ( </TableCell>
"🖥️" <TableCell className="font-medium">
{item.nsapp}
</TableCell>
<TableCell className="hidden md:table-cell">
{item.os_type}
{" "}
{item.os_version}
</TableCell>
<TableCell className="hidden md:table-cell">
{item.disk_size}
MB
</TableCell>
<TableCell className="hidden lg:table-cell">
{item.core_count}
</TableCell>
<TableCell className="hidden lg:table-cell">
{item.ram_size}
MB
</TableCell>
<TableCell className="text-right">
{formatDate(item.created_at)}
</TableCell>
</TableRow>
))
) )
: ( : (
item.type <TableRow>
<TableCell colSpan={8} className="h-24 text-center">
No results found.
</TableCell>
</TableRow>
)} )}
</td> </TableBody>
<td className="px-4 py-2 border-b">{item.nsapp}</td> </Table>
<td className="px-4 py-2 border-b">{item.os_type}</td>
<td className="px-4 py-2 border-b">{item.os_version}</td>
<td className="px-4 py-2 border-b">{item.disk_size}</td>
<td className="px-4 py-2 border-b">{item.core_count}</td>
<td className="px-4 py-2 border-b">{item.ram_size}</td>
<td className="px-4 py-2 border-b">{item.method}</td>
<td className="px-4 py-2 border-b">{item.pve_version}</td>
<td className="px-4 py-2 border-b">{item.error}</td>
<td className="px-4 py-2 border-b">{formatDate(item.created_at)}</td>
</tr>
))}
</tbody>
</table>
</div> </div>
</div>
<div className="mt-4 flex justify-between items-center"> <div className="flex items-center justify-end space-x-2 py-4">
<button onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))} disabled={currentPage === 1} className="p-2 border">Previous</button> <Button
<span> variant="outline"
Page size="sm"
{currentPage} onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
</span> disabled={currentPage === 1 || loading}
<button onClick={() => setCurrentPage(prev => prev + 1)} className="p-2 border">Next</button>
<select
value={itemsPerPage}
onChange={e => setItemsPerPage(Number(e.target.value))}
className="p-2 border"
> >
<option value={10}>10</option> <ChevronLeft className="mr-2 h-4 w-4" />
<option value={20}>20</option> Previous
<option value={50}>50</option> </Button>
<option value={100}>100</option> <div className="text-sm text-muted-foreground">
<option value={250}>250</option> Page
<option value={500}>500</option> {" "}
<option value={5000}>5000</option> {currentPage}
</select> </div>
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(prev => prev + 1)}
disabled={loading || sortedData.length < itemsPerPage}
>
Next
<ChevronRight className="ml-2 h-4 w-4" />
</Button>
</div>
</CardContent>
</Card>
</div>
</div> </div>
</div> </div>
); );
}; }
export default DataFetcher;

View File

@@ -1,199 +0,0 @@
"use client";
import { ArcElement, Chart as ChartJS, Tooltip as ChartTooltip, Legend } from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { BarChart3, PieChart } from "lucide-react";
import React, { useState } from "react";
import { Pie } from "react-chartjs-2";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
ChartJS.register(ArcElement, ChartTooltip, Legend, ChartDataLabels);
type SummaryData = {
nsapp_count: Record<string, number>;
};
type ApplicationChartProps = {
data: SummaryData | null;
};
const ITEMS_PER_PAGE = 20;
const CHART_COLORS = [
"#ff6384",
"#36a2eb",
"#ffce56",
"#4bc0c0",
"#9966ff",
"#ff9f40",
"#4dc9f6",
"#f67019",
"#537bc4",
"#acc236",
"#166a8f",
"#00a950",
"#58595b",
"#8549ba",
];
export default function ApplicationChart({ data }: ApplicationChartProps) {
const [isChartOpen, setIsChartOpen] = useState(false);
const [isTableOpen, setIsTableOpen] = useState(false);
const [chartStartIndex, setChartStartIndex] = useState(0);
const [tableLimit, setTableLimit] = useState(ITEMS_PER_PAGE);
if (!data)
return null;
const sortedApps = Object.entries(data.nsapp_count)
.sort(([, a], [, b]) => b - a);
const chartApps = sortedApps.slice(
chartStartIndex,
chartStartIndex + ITEMS_PER_PAGE,
);
const chartData = {
labels: chartApps.map(([name]) => name),
datasets: [
{
data: chartApps.map(([, count]) => count),
backgroundColor: CHART_COLORS,
},
],
};
const chartOptions = {
plugins: {
legend: { display: false },
datalabels: {
color: "white",
font: { weight: "bold" as const },
formatter: (value: number, context: any) => {
const label = context.chart.data.labels?.[context.dataIndex];
return `${label}\n(${value})`;
},
},
},
responsive: true,
maintainAspectRatio: false,
};
return (
<div className="mt-6 flex justify-center gap-4">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
onClick={() => setIsChartOpen(true)}
>
<PieChart className="h-5 w-5" />
</Button>
</TooltipTrigger>
<TooltipContent>Open Chart View</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
onClick={() => setIsTableOpen(true)}
>
<BarChart3 className="h-5 w-5" />
</Button>
</TooltipTrigger>
<TooltipContent>Open Table View</TooltipContent>
</Tooltip>
</TooltipProvider>
<Dialog open={isChartOpen} onOpenChange={setIsChartOpen}>
<DialogContent className="max-w-3xl">
<DialogHeader>
<DialogTitle>Applications Distribution</DialogTitle>
</DialogHeader>
<div className="h-[60vh] w-full">
<Pie data={chartData} options={chartOptions} />
</div>
<div className="flex justify-center gap-4">
<Button
variant="outline"
onClick={() => setChartStartIndex(Math.max(0, chartStartIndex - ITEMS_PER_PAGE))}
disabled={chartStartIndex === 0}
>
Previous
{" "}
{ITEMS_PER_PAGE}
</Button>
<Button
variant="outline"
onClick={() => setChartStartIndex(chartStartIndex + ITEMS_PER_PAGE)}
disabled={chartStartIndex + ITEMS_PER_PAGE >= sortedApps.length}
>
Next
{" "}
{ITEMS_PER_PAGE}
</Button>
</div>
</DialogContent>
</Dialog>
<Dialog open={isTableOpen} onOpenChange={setIsTableOpen}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Applications Count</DialogTitle>
</DialogHeader>
<div className="max-h-[60vh] overflow-y-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Application</TableHead>
<TableHead className="text-right">Count</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{sortedApps.slice(0, tableLimit).map(([name, count]) => (
<TableRow key={name}>
<TableCell>{name}</TableCell>
<TableCell className="text-right">{count}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
{tableLimit < sortedApps.length && (
<Button
variant="outline"
className="w-full"
onClick={() => setTableLimit(prev => prev + ITEMS_PER_PAGE)}
>
Load More
</Button>
)}
</DialogContent>
</Dialog>
</div>
);
}

View File

@@ -0,0 +1,369 @@
"use client"
import * as React from "react"
import * as RechartsPrimitive from "recharts"
import { cn } from "@/lib/utils"
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const
export type ChartConfig = {
[k in string]: {
label?: React.ReactNode
icon?: React.ComponentType
} & (
| { color?: string; theme?: never }
| { color?: never; theme: Record<keyof typeof THEMES, string> }
)
}
type ChartContextProps = {
config: ChartConfig
}
const ChartContext = React.createContext<ChartContextProps | null>(null)
function useChart() {
const context = React.useContext(ChartContext)
if (!context) {
throw new Error("useChart must be used within a <ChartContainer />")
}
return context
}
const ChartContainer = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & {
config: ChartConfig
children: React.ComponentProps<
typeof RechartsPrimitive.ResponsiveContainer
>["children"]
}
>(({ id, className, children, config, ...props }, ref) => {
const uniqueId = React.useId()
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
return (
<ChartContext.Provider value={{ config }}>
<div
data-chart={chartId}
ref={ref}
className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
className
)}
{...props}
>
<ChartStyle id={chartId} config={config} />
<RechartsPrimitive.ResponsiveContainer>
{children}
</RechartsPrimitive.ResponsiveContainer>
</div>
</ChartContext.Provider>
)
})
ChartContainer.displayName = "Chart"
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter(
([, config]) => config.theme || config.color
)
if (!colorConfig.length) {
return null
}
return (
<style
dangerouslySetInnerHTML={{
__html: Object.entries(THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color
return color ? ` --color-${key}: ${color};` : null
})
.join("\n")}
}
`
)
.join("\n"),
}}
/>
)
}
const ChartTooltip = RechartsPrimitive.Tooltip
const ChartTooltipContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
React.ComponentProps<"div"> & {
hideLabel?: boolean
hideIndicator?: boolean
indicator?: "line" | "dot" | "dashed"
nameKey?: string
labelKey?: string
}
>(
(
{
active,
payload,
className,
indicator = "dot",
hideLabel = false,
hideIndicator = false,
label,
labelFormatter,
labelClassName,
formatter,
color,
nameKey,
labelKey,
},
ref
) => {
const { config } = useChart()
const tooltipLabel = React.useMemo(() => {
if (hideLabel || !payload?.length) {
return null
}
const [item] = payload
const key = `${labelKey || item?.dataKey || item?.name || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const value =
!labelKey && typeof label === "string"
? config[label as keyof typeof config]?.label || label
: itemConfig?.label
if (labelFormatter) {
return (
<div className={cn("font-medium", labelClassName)}>
{labelFormatter(value, payload)}
</div>
)
}
if (!value) {
return null
}
return <div className={cn("font-medium", labelClassName)}>{value}</div>
}, [
label,
labelFormatter,
payload,
hideLabel,
labelClassName,
config,
labelKey,
])
if (!active || !payload?.length) {
return null
}
const nestLabel = payload.length === 1 && indicator !== "dot"
return (
<div
ref={ref}
className={cn(
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
className
)}
>
{!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5">
{payload
.filter((item) => item.type !== "none")
.map((item, index) => {
const key = `${nameKey || item.name || item.dataKey || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const indicatorColor = color || item.payload.fill || item.color
return (
<div
key={item.dataKey}
className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
indicator === "dot" && "items-center"
)}
>
{formatter && item?.value !== undefined && item.name ? (
formatter(item.value, item.name, item, index, item.payload)
) : (
<>
{itemConfig?.icon ? (
<itemConfig.icon />
) : (
!hideIndicator && (
<div
className={cn(
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
{
"h-2.5 w-2.5": indicator === "dot",
"w-1": indicator === "line",
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
"my-0.5": nestLabel && indicator === "dashed",
}
)}
style={
{
"--color-bg": indicatorColor,
"--color-border": indicatorColor,
} as React.CSSProperties
}
/>
)
)}
<div
className={cn(
"flex flex-1 justify-between leading-none",
nestLabel ? "items-end" : "items-center"
)}
>
<div className="grid gap-1.5">
{nestLabel ? tooltipLabel : null}
<span className="text-muted-foreground">
{itemConfig?.label || item.name}
</span>
</div>
{item.value && (
<span className="font-mono font-medium tabular-nums text-foreground">
{item.value.toLocaleString()}
</span>
)}
</div>
</>
)}
</div>
)
})}
</div>
</div>
)
}
)
ChartTooltipContent.displayName = "ChartTooltip"
const ChartLegend = RechartsPrimitive.Legend
const ChartLegendContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean
nameKey?: string
}
>(
(
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
ref
) => {
const { config } = useChart()
if (!payload?.length) {
return null
}
return (
<div
ref={ref}
className={cn(
"flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3",
className
)}
>
{payload
.filter((item) => item.type !== "none")
.map((item) => {
const key = `${nameKey || item.dataKey || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
return (
<div
key={item.value}
className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
)}
>
{itemConfig?.icon && !hideIcon ? (
<itemConfig.icon />
) : (
<div
className="h-2 w-2 shrink-0 rounded-[2px]"
style={{
backgroundColor: item.color,
}}
/>
)}
{itemConfig?.label}
</div>
)
})}
</div>
)
}
)
ChartLegendContent.displayName = "ChartLegend"
// Helper to extract item config from a payload.
function getPayloadConfigFromPayload(
config: ChartConfig,
payload: unknown,
key: string
) {
if (typeof payload !== "object" || payload === null) {
return undefined
}
const payloadPayload =
"payload" in payload &&
typeof payload.payload === "object" &&
payload.payload !== null
? payload.payload
: undefined
let configLabelKey: string = key
if (
key in payload &&
typeof payload[key as keyof typeof payload] === "string"
) {
configLabelKey = payload[key as keyof typeof payload] as string
} else if (
payloadPayload &&
key in payloadPayload &&
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
) {
configLabelKey = payloadPayload[
key as keyof typeof payloadPayload
] as string
}
return configLabelKey in config
? config[configLabelKey]
: config[key as keyof typeof config]
}
export {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegend,
ChartLegendContent,
ChartStyle,
}

View File

@@ -0,0 +1,48 @@
"use client"
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
import { cn } from "@/lib/utils"
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
export { ScrollArea, ScrollBar }

View File

@@ -71,7 +71,11 @@ export TURBO_CACHE=1
export NEXT_TELEMETRY_DISABLED=1 export NEXT_TELEMETRY_DISABLED=1
export CYPRESS_INSTALL_BINARY=0 export CYPRESS_INSTALL_BINARY=0
export NODE_OPTIONS="--max-old-space-size=4096" export NODE_OPTIONS="--max-old-space-size=4096"
$STD turbo prune --scope=@documenso/remix --docker
cd out
cp -r json/* .
$STD npm ci $STD npm ci
cp -r full/* .
$STD turbo run build --filter=@documenso/remix $STD turbo run build --filter=@documenso/remix
$STD npm run prisma:migrate-deploy $STD npm run prisma:migrate-deploy
echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"

View File

@@ -84,6 +84,13 @@ if [[ "$CTTYPE" == "0" && -d /dev/dri ]]; then
fi fi
msg_ok "Dependencies Installed" msg_ok "Dependencies Installed"
msg_info "Installing Mise"
curl -fSs https://mise.jdx.dev/gpg-key.pub | tee /etc/apt/keyrings/mise-archive-keyring.pub 1>/dev/null
echo "deb [signed-by=/etc/apt/keyrings/mise-archive-keyring.pub arch=amd64] https://mise.jdx.dev/deb stable main" | tee /etc/apt/sources.list.d/mise.list
$STD apt update
$STD apt install -y mise
msg_ok "Installed Mise"
read -r -p "${TAB3}Install OpenVINO dependencies for Intel HW-accelerated machine-learning? y/N " prompt read -r -p "${TAB3}Install OpenVINO dependencies for Intel HW-accelerated machine-learning? y/N " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing OpenVINO dependencies" msg_info "Installing OpenVINO dependencies"
@@ -277,12 +284,13 @@ INSTALL_DIR="/opt/${APPLICATION}"
UPLOAD_DIR="${INSTALL_DIR}/upload" UPLOAD_DIR="${INSTALL_DIR}/upload"
SRC_DIR="${INSTALL_DIR}/source" SRC_DIR="${INSTALL_DIR}/source"
APP_DIR="${INSTALL_DIR}/app" APP_DIR="${INSTALL_DIR}/app"
PLUGIN_DIR="${APP_DIR}/corePlugin"
ML_DIR="${APP_DIR}/machine-learning" ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata" GEO_DIR="${INSTALL_DIR}/geodata"
mkdir -p "$INSTALL_DIR" mkdir -p "$INSTALL_DIR"
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache} mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v2.2.3" "$SRC_DIR" fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v2.3.1" "$SRC_DIR"
msg_info "Installing ${APPLICATION} (patience)" msg_info "Installing ${APPLICATION} (patience)"
@@ -314,7 +322,18 @@ cp LICENSE "$APP_DIR"
$STD pnpm --filter @immich/sdk --filter @immich/cli --frozen-lockfile install $STD pnpm --filter @immich/sdk --filter @immich/cli --frozen-lockfile install
$STD pnpm --filter @immich/sdk --filter @immich/cli build $STD pnpm --filter @immich/sdk --filter @immich/cli build
$STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli $STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli
msg_ok "Installed Immich Server and Web Components"
# plugins
cd "$SRC_DIR"
$STD mise trust --ignore ./mise.toml
$STD mise trust ./plugins/mise.toml
cd plugins
$STD mise install
$STD mise run build
mkdir -p "$PLUGIN_DIR"
cp -r ./dist "$PLUGIN_DIR"/dist
cp ./manifest.json "$PLUGIN_DIR"
msg_ok "Installed Immich Server, Web and Plugin Components"
cd "$SRC_DIR"/machine-learning cd "$SRC_DIR"/machine-learning
$STD useradd -U -s /usr/sbin/nologin -r -M -d "$INSTALL_DIR" immich $STD useradd -U -s /usr/sbin/nologin -r -M -d "$INSTALL_DIR" immich
@@ -378,6 +397,10 @@ DB_VECTOR_EXTENSION=vectorchord
REDIS_HOSTNAME=127.0.0.1 REDIS_HOSTNAME=127.0.0.1
IMMICH_MACHINE_LEARNING_URL=http://127.0.0.1:3003 IMMICH_MACHINE_LEARNING_URL=http://127.0.0.1:3003
MACHINE_LEARNING_CACHE_FOLDER=${INSTALL_DIR}/cache MACHINE_LEARNING_CACHE_FOLDER=${INSTALL_DIR}/cache
## - For OpenVINO only - uncomment below to increase
## - inference speed while reducing accuracy
## - Default is FP32
# MACHINE_LEARNING_OPENVINO_PRECISION=FP16
IMMICH_MEDIA_LOCATION=${UPLOAD_DIR} IMMICH_MEDIA_LOCATION=${UPLOAD_DIR}
EOF EOF

View File

@@ -64,7 +64,7 @@ export DATA_DIR=/opt/karakeep_data
karakeep_SECRET=$(openssl rand -base64 36 | cut -c1-24) karakeep_SECRET=$(openssl rand -base64 36 | cut -c1-24)
mkdir -p /etc/karakeep mkdir -p /etc/karakeep
cat <<EOF >/etc/karakeep/karakeep.env cat <<EOF >/etc/karakeep/karakeep.env
SERVER_VERSION="$(cat ~/.karakeep)" SERVER_VERSION="$(sed 's/^v//' ~/.karakeep)"
NEXTAUTH_SECRET="$karakeep_SECRET" NEXTAUTH_SECRET="$karakeep_SECRET"
NEXTAUTH_URL="http://localhost:3000" NEXTAUTH_URL="http://localhost:3000"
DATA_DIR=${DATA_DIR} DATA_DIR=${DATA_DIR}

View File

@@ -31,7 +31,7 @@ RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
msg_info "Creating frontend UI" msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=60072 export PUBLIC_SERVER_PORT=""
cd /opt/netvisor/ui cd /opt/netvisor/ui
$STD npm ci --no-fund --no-audit $STD npm ci --no-fund --no-audit
$STD npm run build $STD npm run build
@@ -49,20 +49,18 @@ cp ./target/release/daemon /usr/bin/netvisor-daemon
msg_ok "Built Netvisor-daemon" msg_ok "Built Netvisor-daemon"
msg_info "Configuring server & daemon for first-run" msg_info "Configuring server & daemon for first-run"
LOCAL_IP="$(hostname -I | awk '{print $1}')"
cat <<EOF >/opt/netvisor/.env cat <<EOF >/opt/netvisor/.env
### - UI
PUBLIC_SERVER_HOSTNAME=default
PUBLIC_SERVER_PORT=60072
### - SERVER ### - SERVER
NETVISOR_DATABASE_URL=postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME NETVISOR_DATABASE_URL=postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME
NETVISOR_WEB_EXTERNAL_PATH="/opt/netvisor/ui/build" NETVISOR_WEB_EXTERNAL_PATH="/opt/netvisor/ui/build"
NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072
NETVISOR_SERVER_PORT=60072 NETVISOR_SERVER_PORT=60072
NETVISOR_LOG_LEVEL=info NETVISOR_LOG_LEVEL=info
NETVISOR_INTEGRATED_DAEMON_URL=http://127.0.0.1:60073 NETVISOR_INTEGRATED_DAEMON_URL=http://127.0.0.1:60073
## - uncomment to disable signups ## - uncomment to disable signups
# NETVISOR_DISABLE_REGISTRATION=true # NETVISOR_DISABLE_REGISTRATION=true
## - uncomment when behind reverse proxy ## - uncomment when using TLS
# NETVISOR_USE_SECURE_SESSION_COOKIES=true # NETVISOR_USE_SECURE_SESSION_COOKIES=true
### - OIDC (optional) ### - OIDC (optional)
@@ -74,8 +72,14 @@ NETVISOR_INTEGRATED_DAEMON_URL=http://127.0.0.1:60073
## - Callback URL for reference ## - Callback URL for reference
# http://your-netvisor-domain:60072/api/auth/oidc/callback # http://your-netvisor-domain:60072/api/auth/oidc/callback
### - SMTP (password reset and notifications - optional)
# NETVISOR_SMTP_RELAY=smtp.gmail.com:587
# NETVISOR_SMTP_USERNAME=your-email@gmail.com
# NETVISOR_SMTP_PASSWORD=your-app-password
# NETVISOR_SMTP_EMAIL=netvisor@yourdomain.tld
### - INTEGRATED DAEMON ### - INTEGRATED DAEMON
NETVISOR_SERVER_TARGET=127.0.0.1 NETVISOR_SERVER_URL=http://127.0.0.1:60072
NETVISOR_BIND_ADDRESS=0.0.0.0 NETVISOR_BIND_ADDRESS=0.0.0.0
NETVISOR_NAME="netvisor-daemon" NETVISOR_NAME="netvisor-daemon"
NETVISOR_HEARTBEAT_INTERVAL=30 NETVISOR_HEARTBEAT_INTERVAL=30
@@ -112,7 +116,7 @@ After=network.target netvisor-server.service
[Service] [Service]
Type=simple Type=simple
EnvironmentFile=/opt/netvisor/.env EnvironmentFile=/opt/netvisor/.env
ExecStart=/usr/bin/netvisor-daemon --server-target http://127.0.0.1 --server-port 60072 --network-id ${NETWORK_ID} --daemon-api-key ${API_KEY} ExecStart=/usr/bin/netvisor-daemon --server-url http://127.0.0.1:60072 --network-id ${NETWORK_ID} --daemon-api-key ${API_KEY}
Restart=always Restart=always
RestartSec=10 RestartSec=10
StandardOutput=journal StandardOutput=journal

View File

@@ -54,11 +54,12 @@ msg_ok "Installed Openresty"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | # RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
grep "tag_name" | # grep "tag_name" |
awk '{print substr($2, 3, length($2)-4) }') # awk '{print substr($2, 3, length($2)-4) }')
RELEASE="2.13.4"
fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" "tarball" "v2.13.4"
msg_info "Setting up Environment" msg_info "Setting up Environment"
ln -sf /usr/bin/python3 /usr/bin/python ln -sf /usr/bin/python3 /usr/bin/python

View File

@@ -17,24 +17,15 @@ msg_info "Installing Dependencies"
$STD apt install -y jsvc $STD apt install -y jsvc
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
msg_info "Checking CPU Features" JAVA_VERSION="21" setup_java
if lscpu | grep -q 'avx'; then if lscpu | grep -q 'avx'; then
MONGODB_VERSION="8.0"
msg_ok "AVX detected: Using MongoDB 8.0"
MONGO_VERSION="8.0" setup_mongodb MONGO_VERSION="8.0" setup_mongodb
else else
MONGO_VERSION="4.4" setup_mongodb msg_error "No AVX detected (CPU-Flag)! We have discontinued support for this. You are welcome to try it manually with a Debian LXC, but due to the many issues with Omada, we currently only support AVX CPUs."
exit 10
fi fi
msg_info "Installing Azul Zulu Java"
curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xB1998361219BD9C9" -o "/etc/apt/trusted.gpg.d/zulu-repo.asc"
curl -fsSL "https://cdn.azul.com/zulu/bin/zulu-repo_1.0.0-3_all.deb" -o zulu-repo.deb
$STD dpkg -i zulu-repo.deb
$STD apt update
$STD apt -y install zulu21-jre-headless
msg_ok "Installed Azul Zulu Java"
if ! dpkg -l | grep -q 'libssl1.1'; then if ! dpkg -l | grep -q 'libssl1.1'; then
msg_info "Installing libssl (if needed)" msg_info "Installing libssl (if needed)"
curl -fsSL "https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.1w-0+deb11u4_amd64.deb" -o "/tmp/libssl.deb" curl -fsSL "https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.1w-0+deb11u4_amd64.deb" -o "/tmp/libssl.deb"
@@ -50,14 +41,9 @@ OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/o
OMADA_PKG=$(basename "$OMADA_URL") OMADA_PKG=$(basename "$OMADA_URL")
curl -fsSL "$OMADA_URL" -o "$OMADA_PKG" curl -fsSL "$OMADA_URL" -o "$OMADA_PKG"
$STD dpkg -i "$OMADA_PKG" $STD dpkg -i "$OMADA_PKG"
rm -rf "$OMADA_PKG"
msg_ok "Installed Omada Controller" msg_ok "Installed Omada Controller"
motd_ssh motd_ssh
customize customize
cleanup_lxc
msg_info "Cleaning up"
rm -rf "$OMADA_PKG" zulu-repo.deb
$STD apt -y autoremove
$STD apt -y autoclean
$STD apt -y clean
msg_ok "Cleaned"

View File

@@ -17,7 +17,7 @@ msg_info "Installing Dependencies"
$STD apt install -y fping $STD apt install -y fping
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
PHP_VERSION="8.3" PHP_APACHE="YES" PHP_FPM="YES" PHP_MODULE="mysql,gmp,snmp,ldap,apcu" setup_php PHP_VERSION="8.3" PHP_APACHE="YES" PHP_FPM="YES" PHP_MODULE="pdo,pdo-mysql,gmp,snmp,ldap,apcu" setup_php
msg_info "Installing PHP-PEAR" msg_info "Installing PHP-PEAR"
$STD apt install -y \ $STD apt install -y \

View File

@@ -13,10 +13,19 @@ load_functions
verb_ip6() { verb_ip6() {
set_std_mode # Set STD mode based on VERBOSE set_std_mode # Set STD mode based on VERBOSE
if [ "$DISABLEIPV6" == "yes" ]; then if [ "$IPV6_METHOD" == "disable" ]; then
msg_info "Disabling IPv6 (this may affect some services)"
$STD sysctl -w net.ipv6.conf.all.disable_ipv6=1 $STD sysctl -w net.ipv6.conf.all.disable_ipv6=1
echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf $STD sysctl -w net.ipv6.conf.default.disable_ipv6=1
$STD sysctl -w net.ipv6.conf.lo.disable_ipv6=1
mkdir -p /etc/sysctl.d
$STD tee /etc/sysctl.d/99-disable-ipv6.conf >/dev/null <<EOF
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
$STD rc-update add sysctl default $STD rc-update add sysctl default
msg_ok "Disabled IPv6"
fi fi
} }

View File

@@ -65,7 +65,7 @@ root_check() {
} }
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported. # This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
# Supported: Proxmox VE 8.0.x 8.9.x and 9.0 (NOT 9.1+) # Supported: Proxmox VE 8.0.x 8.9.x, 9.0 and 9.1
pve_check() { pve_check() {
local PVE_VER local PVE_VER
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')" PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
@@ -81,12 +81,12 @@ pve_check() {
return 0 return 0
fi fi
# Check for Proxmox VE 9.x: allow ONLY 9.0 # Check for Proxmox VE 9.x: allow 9.0 and 9.1
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}" local MINOR="${BASH_REMATCH[1]}"
if ((MINOR != 0)); then if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported." msg_error "This version of Proxmox VE is not supported."
msg_error "Supported: Proxmox VE version 9.0" msg_error "Supported: Proxmox VE version 9.0 9.1"
exit 1 exit 1
fi fi
return 0 return 0
@@ -94,7 +94,7 @@ pve_check() {
# All other unsupported versions # All other unsupported versions
msg_error "This version of Proxmox VE is not supported." msg_error "This version of Proxmox VE is not supported."
msg_error "Supported versions: Proxmox VE 8.0 8.x or 9.0" msg_error "Supported versions: Proxmox VE 8.0 8.x or 9.0 9.1"
exit 1 exit 1
} }
@@ -627,11 +627,12 @@ advanced_settings() {
# IPv6 Address Management selection # IPv6 Address Management selection
while true; do while true; do
IPV6_METHOD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --menu \ IPV6_METHOD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --menu \
"Select IPv6 Address Management Type:" 15 58 4 \ "Select IPv6 Address Management Type:" 16 70 5 \
"auto" "SLAAC/AUTO (recommended, default)" \ "auto" "SLAAC/AUTO (recommended) - Dynamic IPv6 from network" \
"dhcp" "DHCPv6" \ "dhcp" "DHCPv6 - DHCP-assigned IPv6 address" \
"static" "Static (manual entry)" \ "static" "Static - Manual IPv6 address configuration" \
"none" "Disabled" \ "none" "None - No IPv6 assignment (most containers)" \
"disable" "Fully Disabled - (breaks some services)" \
--default-item "auto" 3>&1 1>&2 2>&3) --default-item "auto" 3>&1 1>&2 2>&3)
[ $? -ne 0 ] && exit_script [ $? -ne 0 ] && exit_script
@@ -680,7 +681,15 @@ advanced_settings() {
break break
;; ;;
none) none)
echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}Disabled${CL}" echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}None${CL}"
IPV6_ADDR="none"
IPV6_GATE=""
break
;;
disable)
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox \
"⚠️ WARNING - FULLY DISABLE IPv6:\n\nThis will completely disable IPv6 inside the container via sysctl.\n\nSide Effects:\n • Services requiring IPv6 will fail\n • Localhost IPv6 (::1) will not work\n • Some applications may not start\n\nOnly use if you have a specific reason to completely disable IPv6.\n\nFor most use cases, select 'None' instead." 14 70
echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}Fully Disabled (IPv6 disabled via sysctl)${CL}"
IPV6_ADDR="none" IPV6_ADDR="none"
IPV6_GATE="" IPV6_GATE=""
break break

View File

@@ -393,7 +393,7 @@ cleanup_lxc() {
# Python pip # Python pip
if command -v pip &>/dev/null; then $STD pip cache purge || true; fi if command -v pip &>/dev/null; then $STD pip cache purge || true; fi
# Python uv # Python uv
if command -v uv &>/dev/null; then $STD uv cache clear || true; fi if command -v uv &>/dev/null; then $STD uv cache clean || true; fi
# Node.js npm # Node.js npm
if command -v npm &>/dev/null; then $STD npm cache clean --force || true; fi if command -v npm &>/dev/null; then $STD npm cache clean --force || true; fi
# Node.js yarn # Node.js yarn

View File

@@ -200,7 +200,6 @@ if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
fi fi
# This checks for the presence of valid Container Storage and Template Storage locations # This checks for the presence of valid Container Storage and Template Storage locations
msg_info "Validating storage"
if ! check_storage_support "rootdir"; then if ! check_storage_support "rootdir"; then
msg_error "No valid storage found for 'rootdir' [Container]" msg_error "No valid storage found for 'rootdir' [Container]"
exit 1 exit 1
@@ -210,7 +209,6 @@ if ! check_storage_support "vztmpl"; then
exit 1 exit 1
fi fi
#msg_info "Checking template storage"
while true; do while true; do
if select_storage template; then if select_storage template; then
TEMPLATE_STORAGE="$STORAGE_RESULT" TEMPLATE_STORAGE="$STORAGE_RESULT"

View File

@@ -15,9 +15,17 @@ load_functions
verb_ip6() { verb_ip6() {
set_std_mode # Set STD mode based on VERBOSE set_std_mode # Set STD mode based on VERBOSE
if [ "$DISABLEIPV6" == "yes" ]; then if [ "$IPV6_METHOD" == "disable" ]; then
echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf msg_info "Disabling IPv6 (this may affect some services)"
$STD sysctl -p mkdir -p /etc/sysctl.d
$STD tee /etc/sysctl.d/99-disable-ipv6.conf >/dev/null <<EOF
# Disable IPv6 (set by community-scripts)
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
$STD sysctl -p /etc/sysctl.d/99-disable-ipv6.conf
msg_ok "Disabled IPv6"
fi fi
} }

View File

@@ -3628,59 +3628,57 @@ function setup_php() {
local CURRENT_PHP="" local CURRENT_PHP=""
CURRENT_PHP=$(is_tool_installed "php" 2>/dev/null) || true CURRENT_PHP=$(is_tool_installed "php" 2>/dev/null) || true
# Scenario 1: Already at target version - just update packages # CRITICAL: If wrong version is installed, remove it FIRST before any pinning
if [[ -n "$CURRENT_PHP" && "$CURRENT_PHP" == "$PHP_VERSION" ]]; then
msg_info "Update PHP $PHP_VERSION"
# Ensure Sury repo is available
if [[ ! -f /etc/apt/sources.list.d/php.sources ]]; then
manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || {
msg_error "Failed to setup PHP repository"
return 1
}
fi
ensure_apt_working || return 1
# Perform upgrade with retry logic (non-fatal if fails)
upgrade_packages_with_retry "php${PHP_VERSION}" || true
cache_installed_version "php" "$PHP_VERSION"
msg_ok "Update PHP $PHP_VERSION"
else
# Scenario 2: Different version installed - clean upgrade
if [[ -n "$CURRENT_PHP" && "$CURRENT_PHP" != "$PHP_VERSION" ]]; then if [[ -n "$CURRENT_PHP" && "$CURRENT_PHP" != "$PHP_VERSION" ]]; then
msg_info "Upgrade PHP from $CURRENT_PHP to $PHP_VERSION" msg_info "Removing conflicting PHP ${CURRENT_PHP} (need ${PHP_VERSION})"
# Stop and disable ALL PHP-FPM versions
stop_all_services "php.*-fpm" stop_all_services "php.*-fpm"
remove_old_tool_version "php" $STD apt-get purge -y "php*" 2>/dev/null || true
else $STD apt-get autoremove -y 2>/dev/null || true
msg_info "Setup PHP $PHP_VERSION"
fi fi
# Prepare repository (cleanup + validation) # NOW create pinning for the desired version
mkdir -p /etc/apt/preferences.d
cat <<EOF >/etc/apt/preferences.d/php-pin
Package: php${PHP_VERSION}*
Pin: version ${PHP_VERSION}.*
Pin-Priority: 1001
Package: php[0-9].*
Pin: release o=packages.sury.org-php
Pin-Priority: -1
EOF
# Setup repository
prepare_repository_setup "php" "deb.sury.org-php" || { prepare_repository_setup "php" "deb.sury.org-php" || {
msg_error "Failed to prepare PHP repository" msg_error "Failed to prepare PHP repository"
return 1 return 1
} }
# Setup Sury repository
manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || { manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || {
msg_error "Failed to setup PHP repository" msg_error "Failed to setup PHP repository"
return 1 return 1
} }
ensure_apt_working || return 1 ensure_apt_working || return 1
$STD apt-get update
# Get available PHP version from repository
local AVAILABLE_PHP_VERSION=""
AVAILABLE_PHP_VERSION=$(apt-cache show "php${PHP_VERSION}" 2>/dev/null | grep -m1 "^Version:" | awk '{print $2}' | cut -d- -f1) || true
if [[ -z "$AVAILABLE_PHP_VERSION" ]]; then
msg_error "PHP ${PHP_VERSION} not found in configured repositories"
return 1
fi fi
# Build module list # Build module list - without version pinning (preferences.d handles it)
local MODULE_LIST="php${PHP_VERSION}" local MODULE_LIST="php${PHP_VERSION}"
IFS=',' read -ra MODULES <<<"$COMBINED_MODULES" IFS=',' read -ra MODULES <<<"$COMBINED_MODULES"
for mod in "${MODULES[@]}"; do for mod in "${MODULES[@]}"; do
if apt-cache show "php${PHP_VERSION}-${mod}" >/dev/null 2>&1; then
MODULE_LIST+=" php${PHP_VERSION}-${mod}" MODULE_LIST+=" php${PHP_VERSION}-${mod}"
fi
done done
if [[ "$PHP_FPM" == "YES" ]]; then if [[ "$PHP_FPM" == "YES" ]]; then
MODULE_LIST+=" php${PHP_VERSION}-fpm" MODULE_LIST+=" php${PHP_VERSION}-fpm"
fi fi
@@ -3688,18 +3686,52 @@ function setup_php() {
# install apache2 with PHP support if requested # install apache2 with PHP support if requested
if [[ "$PHP_APACHE" == "YES" ]]; then if [[ "$PHP_APACHE" == "YES" ]]; then
if ! dpkg -l 2>/dev/null | grep -q "libapache2-mod-php${PHP_VERSION}"; then if ! dpkg -l 2>/dev/null | grep -q "libapache2-mod-php${PHP_VERSION}"; then
install_packages_with_retry "apache2" "libapache2-mod-php${PHP_VERSION}" || { msg_info "Installing Apache with PHP ${PHP_VERSION} module"
msg_error "Failed to install Apache with PHP module" install_packages_with_retry "apache2" || {
msg_error "Failed to install Apache"
return 1 return 1
} }
install_packages_with_retry "libapache2-mod-php${PHP_VERSION}" || {
msg_warn "Failed to install libapache2-mod-php${PHP_VERSION}, continuing without Apache module"
}
fi fi
fi fi
# Install PHP packages with retry logic # Install PHP packages (pinning via preferences.d ensures correct version)
install_packages_with_retry $MODULE_LIST || { msg_info "Installing PHP ${PHP_VERSION} packages"
msg_error "Failed to install PHP packages" if ! install_packages_with_retry $MODULE_LIST; then
msg_warn "Failed to install PHP packages, attempting individual installation"
# Install main package first (critical)
install_packages_with_retry "php${PHP_VERSION}" || {
msg_error "Failed to install php${PHP_VERSION}"
return 1 return 1
} }
# Try to install Apache module individually if requested
if [[ "$PHP_APACHE" == "YES" ]]; then
install_packages_with_retry "libapache2-mod-php${PHP_VERSION}" || {
msg_warn "Could not install libapache2-mod-php${PHP_VERSION}"
}
fi
# Try to install modules individually - skip those that don't exist
for pkg in "${MODULES[@]}"; do
if apt-cache search "^php${PHP_VERSION}-${pkg}\$" 2>/dev/null | grep -q "^php${PHP_VERSION}-${pkg}"; then
install_packages_with_retry "php${PHP_VERSION}-${pkg}" || {
msg_warn "Could not install php${PHP_VERSION}-${pkg}"
}
fi
done
if [[ "$PHP_FPM" == "YES" ]]; then
if apt-cache search "^php${PHP_VERSION}-fpm\$" 2>/dev/null | grep -q "^php${PHP_VERSION}-fpm"; then
install_packages_with_retry "php${PHP_VERSION}-fpm" || {
msg_warn "Could not install php${PHP_VERSION}-fpm"
}
fi
fi
fi
cache_installed_version "php" "$PHP_VERSION" cache_installed_version "php" "$PHP_VERSION"
# Patch all relevant php.ini files # Patch all relevant php.ini files
@@ -3735,7 +3767,24 @@ function setup_php() {
fi fi
fi fi
msg_ok "Setup PHP $PHP_VERSION" # Verify PHP installation - critical check
if ! command -v php >/dev/null 2>&1; then
msg_error "PHP installation verification failed - php command not found"
return 1
fi
local INSTALLED_VERSION=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
# Critical: if major.minor doesn't match, fail and cleanup
if [[ "$INSTALLED_VERSION" != "$PHP_VERSION" ]]; then
msg_error "PHP version mismatch: requested ${PHP_VERSION} but got ${INSTALLED_VERSION}"
msg_error "This indicates a critical package installation issue"
# Don't cache wrong version
return 1
fi
cache_installed_version "php" "$INSTALLED_VERSION"
msg_ok "Setup PHP ${INSTALLED_VERSION}"
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -4439,7 +4488,7 @@ function setup_rust() {
} }
# Update to latest patch version # Update to latest patch version
$STD rustup update "$RUST_TOOLCHAIN" || true $STD rustup update "$RUST_TOOLCHAIN" </dev/null || true
# Ensure PATH is updated for current shell session # Ensure PATH is updated for current shell session
export PATH="$CARGO_BIN:$PATH" export PATH="$CARGO_BIN:$PATH"

View File

@@ -42,7 +42,7 @@ function msg_ok() {
function msg_error() { echo -e "${RD}$1${CL}"; } function msg_error() { echo -e "${RD}$1${CL}"; }
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported. # This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
# Supported: Proxmox VE 8.0.x 8.9.x and 9.0 (NOT 9.1+) # Supported: Proxmox VE 8.0.x 8.9.x and 9.09.1.x
pve_check() { pve_check() {
local PVE_VER local PVE_VER
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')" PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
@@ -58,12 +58,12 @@ pve_check() {
return 0 return 0
fi fi
# Check for Proxmox VE 9.x: allow ONLY 9.0 # Check for Proxmox VE 9.x: allow 9.09.1.x
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}" local MINOR="${BASH_REMATCH[1]}"
if ((MINOR != 0)); then if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported." msg_error "This version of Proxmox VE is not yet supported."
msg_error "Supported: Proxmox VE version 9.0" msg_error "Supported: Proxmox VE version 9.09.1.x"
exit 1 exit 1
fi fi
return 0 return 0
@@ -71,7 +71,7 @@ pve_check() {
# All other unsupported versions # All other unsupported versions
msg_error "This version of Proxmox VE is not supported." msg_error "This version of Proxmox VE is not supported."
msg_error "Supported versions: Proxmox VE 8.0 8.x or 9.0" msg_error "Supported versions: Proxmox VE 8.0 8.9 or 9.09.1.x"
exit 1 exit 1
} }

View File

@@ -88,14 +88,14 @@ main() {
fi fi
start_routines_8 start_routines_8
elif [[ "$PVE_MAJOR" == "9" ]]; then elif [[ "$PVE_MAJOR" == "9" ]]; then
if ((PVE_MINOR != 0)); then if ((PVE_MINOR < 0 || PVE_MINOR > 1)); then
msg_error "Only Proxmox 9.0 is currently supported" msg_error "Only Proxmox 9.0-9.1.x is currently supported"
exit 1 exit 1
fi fi
start_routines_9 start_routines_9
else else
msg_error "Unsupported Proxmox VE major version: $PVE_MAJOR" msg_error "Unsupported Proxmox VE major version: $PVE_MAJOR"
echo -e "Supported: 8.08.9.x and 9.0" echo -e "Supported: 8.08.9.x and 9.09.1.x"
exit 1 exit 1
fi fi
} }