From 69fe180968738c319958d0400efe03f6fb93cdef Mon Sep 17 00:00:00 2001 From: "homarr-update-contributors[bot]" <210161987+homarr-update-contributors[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 13:25:53 +0000 Subject: [PATCH 01/11] chore: update contributors (#5674) Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com> --- static-data/contributors.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static-data/contributors.json b/static-data/contributors.json index 5db83ab61..d6a6b43fa 100644 --- a/static-data/contributors.json +++ b/static-data/contributors.json @@ -1 +1 @@ -[{"login":"ajnart","avatar_url":"https://avatars.githubusercontent.com/u/49837342?v=4"},{"login":"manuel-rw","avatar_url":"https://avatars.githubusercontent.com/u/30572287?v=4"},{"login":"Meierschlumpf","avatar_url":"https://avatars.githubusercontent.com/u/63781622?v=4"},{"login":"SeDemal","avatar_url":"https://avatars.githubusercontent.com/u/26098587?v=4"},{"login":"lammersbjorn","avatar_url":"https://avatars.githubusercontent.com/u/71191962?v=4"},{"login":"LarveyOfficial","avatar_url":"https://avatars.githubusercontent.com/u/39219859?v=4"},{"login":"c00ldude1oo","avatar_url":"https://avatars.githubusercontent.com/u/15677803?v=4"},{"login":"InterN0te","avatar_url":"https://avatars.githubusercontent.com/u/10882916?v=4"},{"login":"Aimsucks","avatar_url":"https://avatars.githubusercontent.com/u/1828486?v=4"},{"login":"JannesV","avatar_url":"https://avatars.githubusercontent.com/u/5984244?v=4"},{"login":"MauriceNino","avatar_url":"https://avatars.githubusercontent.com/u/18658092?v=4"},{"login":"hillaliy","avatar_url":"https://avatars.githubusercontent.com/u/950010?v=4"},{"login":"Skeeww","avatar_url":"https://avatars.githubusercontent.com/u/9639992?v=4"},{"login":"RichyHBM","avatar_url":"https://avatars.githubusercontent.com/u/5472275?v=4"},{"login":"Bonfire","avatar_url":"https://avatars.githubusercontent.com/u/5704760?v=4"},{"login":"wieli99","avatar_url":"https://avatars.githubusercontent.com/u/46794825?v=4"},{"login":"ishaanparlikar","avatar_url":"https://avatars.githubusercontent.com/u/43013132?v=4"},{"login":"Zareix","avatar_url":"https://avatars.githubusercontent.com/u/29818713?v=4"},{"login":"tuggan","avatar_url":"https://avatars.githubusercontent.com/u/4325608?v=4"},{"login":"Spillebulle","avatar_url":"https://avatars.githubusercontent.com/u/46653946?v=4"},{"login":"spkesDE","avatar_url":"https://avatars.githubusercontent.com/u/1682314?v=4"},{"login":"j3lte","avatar_url":"https://avatars.githubusercontent.com/u/2557568?v=4"},{"login":"dslatt","avatar_url":"https://avatars.githubusercontent.com/u/5211001?v=4"},{"login":"Malong11-007","avatar_url":"https://avatars.githubusercontent.com/u/40298510?v=4"},{"login":"StefanB7","avatar_url":"https://avatars.githubusercontent.com/u/22056509?v=4"},{"login":"souravghosh01","avatar_url":"https://avatars.githubusercontent.com/u/37548139?v=4"},{"login":"SR3u","avatar_url":"https://avatars.githubusercontent.com/u/2380522?v=4"},{"login":"Rikpat","avatar_url":"https://avatars.githubusercontent.com/u/33869814?v=4"},{"login":"NormanJS","avatar_url":"https://avatars.githubusercontent.com/u/83409549?v=4"},{"login":"No-Maines-Land","avatar_url":"https://avatars.githubusercontent.com/u/20687725?v=4"},{"login":"stark1tty","avatar_url":"https://avatars.githubusercontent.com/u/69326376?v=4"},{"login":"Momcilo42","avatar_url":"https://avatars.githubusercontent.com/u/10118137?v=4"},{"login":"marius-arch","avatar_url":"https://avatars.githubusercontent.com/u/72494359?v=4"},{"login":"Lumilias","avatar_url":"https://avatars.githubusercontent.com/u/10852161?v=4"},{"login":"Havock94","avatar_url":"https://avatars.githubusercontent.com/u/7635248?v=4"},{"login":"Lollyde","avatar_url":"https://avatars.githubusercontent.com/u/11347524?v=4"},{"login":"krishnamuppaneni","avatar_url":"https://avatars.githubusercontent.com/u/4703366?v=4"},{"login":"devtobi","avatar_url":"https://avatars.githubusercontent.com/u/28538704?v=4"},{"login":"TyxTang","avatar_url":"https://avatars.githubusercontent.com/u/90897955?v=4"},{"login":"alotlikebeans","avatar_url":"https://avatars.githubusercontent.com/u/19630511?v=4"},{"login":"WillyJL","avatar_url":"https://avatars.githubusercontent.com/u/49810075?v=4"},{"login":"anonysoul","avatar_url":"https://avatars.githubusercontent.com/u/105715150?v=4"},{"login":"cospeedster","avatar_url":"https://avatars.githubusercontent.com/u/52749645?v=4"},{"login":"diederbert","avatar_url":"https://avatars.githubusercontent.com/u/162878798?v=4"},{"login":"digdilem","avatar_url":"https://avatars.githubusercontent.com/u/4052275?v=4"},{"login":"dinghino","avatar_url":"https://avatars.githubusercontent.com/u/14729459?v=4"},{"login":"gfomichev","avatar_url":"https://avatars.githubusercontent.com/u/1596146?v=4"},{"login":"gnattu","avatar_url":"https://avatars.githubusercontent.com/u/12995396?v=4"},{"login":"tuxpizza","avatar_url":"https://avatars.githubusercontent.com/u/84710786?v=4"},{"login":"xmarkurion","avatar_url":"https://avatars.githubusercontent.com/u/46654687?v=4"},{"login":"huanga","avatar_url":"https://avatars.githubusercontent.com/u/732970?v=4"},{"login":"taos15","avatar_url":"https://avatars.githubusercontent.com/u/122130728?v=4"},{"login":"arghyadipchak","avatar_url":"https://avatars.githubusercontent.com/u/32430374?v=4"},{"login":"AuthorShin","avatar_url":"https://avatars.githubusercontent.com/u/4959043?v=4"},{"login":"benniblot","avatar_url":"https://avatars.githubusercontent.com/u/47495914?v=4"},{"login":"bebsworthy","avatar_url":"https://avatars.githubusercontent.com/u/5266759?v=4"},{"login":"catrielmuller","avatar_url":"https://avatars.githubusercontent.com/u/2272323?v=4"},{"login":"Vysp3r","avatar_url":"https://avatars.githubusercontent.com/u/62019735?v=4"},{"login":"DR-Blogs","avatar_url":"https://avatars.githubusercontent.com/u/96393186?v=4"},{"login":"singular0","avatar_url":"https://avatars.githubusercontent.com/u/1925883?v=4"},{"login":"diogovalentte","avatar_url":"https://avatars.githubusercontent.com/u/49578155?v=4"},{"login":"codezninja","avatar_url":"https://avatars.githubusercontent.com/u/4400773?v=4"},{"login":"fabricionaweb","avatar_url":"https://avatars.githubusercontent.com/u/15933?v=4"},{"login":"nyok1912","avatar_url":"https://avatars.githubusercontent.com/u/32163949?v=4"},{"login":"bo3bdo","avatar_url":"https://avatars.githubusercontent.com/u/5271380?v=4"},{"login":"hskrtich","avatar_url":"https://avatars.githubusercontent.com/u/1214484?v=4"},{"login":"ishults","avatar_url":"https://avatars.githubusercontent.com/u/7275442?v=4"},{"login":"jelliuk","avatar_url":"https://avatars.githubusercontent.com/u/4790959?v=4"},{"login":"Moohan","avatar_url":"https://avatars.githubusercontent.com/u/5982260?v=4"},{"login":"tesar-tech","avatar_url":"https://avatars.githubusercontent.com/u/33880579?v=4"},{"login":"jbruell","avatar_url":"https://avatars.githubusercontent.com/u/31685172?v=4"},{"login":"JasonLeeB06","avatar_url":"https://avatars.githubusercontent.com/u/82266978?v=4"},{"login":"jeffersonraimon","avatar_url":"https://avatars.githubusercontent.com/u/80064475?v=4"},{"login":"jo-chemla","avatar_url":"https://avatars.githubusercontent.com/u/16822841?v=4"},{"login":"joser93","avatar_url":"https://avatars.githubusercontent.com/u/6912089?v=4"},{"login":"justijndepover","avatar_url":"https://avatars.githubusercontent.com/u/9008623?v=4"},{"login":"Aandree5","avatar_url":"https://avatars.githubusercontent.com/u/32734153?v=4"},{"login":"jackwellerreal","avatar_url":"https://avatars.githubusercontent.com/u/97435840?v=4"},{"login":"SergioChan","avatar_url":"https://avatars.githubusercontent.com/u/10103766?v=4"},{"login":"toineenzo","avatar_url":"https://avatars.githubusercontent.com/u/4921397?v=4"},{"login":"oben01","avatar_url":"https://avatars.githubusercontent.com/u/22369027?v=4"},{"login":"rezstje","avatar_url":"https://avatars.githubusercontent.com/u/45420315?v=4"},{"login":"castielwaverly","avatar_url":"https://avatars.githubusercontent.com/u/137005689?v=4"},{"login":"xoxyuxu","avatar_url":"https://avatars.githubusercontent.com/u/3543416?v=4"},{"login":"MaienM","avatar_url":"https://avatars.githubusercontent.com/u/583129?v=4"},{"login":"mvanhorn","avatar_url":"https://avatars.githubusercontent.com/u/455140?v=4"},{"login":"HeapReaper","avatar_url":"https://avatars.githubusercontent.com/u/31496522?v=4"},{"login":"Copilot","avatar_url":"https://avatars.githubusercontent.com/in/1143301?v=4"},{"login":"mairas","avatar_url":"https://avatars.githubusercontent.com/u/407010?v=4"},{"login":"itzTheMeow","avatar_url":"https://avatars.githubusercontent.com/u/50887230?v=4"},{"login":"NicolasNewman","avatar_url":"https://avatars.githubusercontent.com/u/16135852?v=4"},{"login":"NikeLaosClericus","avatar_url":"https://avatars.githubusercontent.com/u/39810627?v=4"},{"login":"noahcroghan","avatar_url":"https://avatars.githubusercontent.com/u/27422774?v=4"},{"login":"ohmzi","avatar_url":"https://avatars.githubusercontent.com/u/6551272?v=4"},{"login":"Rhiz3K","avatar_url":"https://avatars.githubusercontent.com/u/33246262?v=4"},{"login":"saschabuehrle","avatar_url":"https://avatars.githubusercontent.com/u/47737812?v=4"},{"login":"StrandedTurtle","avatar_url":"https://avatars.githubusercontent.com/u/132835255?v=4"},{"login":"CrazyWolf13","avatar_url":"https://avatars.githubusercontent.com/u/96661824?v=4"},{"login":"generalmat82","avatar_url":"https://avatars.githubusercontent.com/u/110256073?v=4"},{"login":"lthomsen","avatar_url":"https://avatars.githubusercontent.com/u/28560325?v=4"},{"login":"pitschi","avatar_url":"https://avatars.githubusercontent.com/u/6841565?v=4"},{"login":"tech62","avatar_url":"https://avatars.githubusercontent.com/u/16237642?v=4"},{"login":"leandroscardua","avatar_url":"https://avatars.githubusercontent.com/u/24698541?v=4"},{"login":"kylegrieder","avatar_url":"https://avatars.githubusercontent.com/u/25424229?v=4"},{"login":"hotrungnhan","avatar_url":"https://avatars.githubusercontent.com/u/40029631?v=4"},{"login":"KelianB","avatar_url":"https://avatars.githubusercontent.com/u/11216155?v=4"},{"login":"Kaotic3","avatar_url":"https://avatars.githubusercontent.com/u/80522225?v=4"},{"login":"frankvHoof93","avatar_url":"https://avatars.githubusercontent.com/u/7346516?v=4"},{"login":"faugusto-oliveira","avatar_url":"https://avatars.githubusercontent.com/u/37384074?v=4"},{"login":"ieugen","avatar_url":"https://avatars.githubusercontent.com/u/1050920?v=4"},{"login":"KartulUdus","avatar_url":"https://avatars.githubusercontent.com/u/23346150?v=4"},{"login":"dgshue","avatar_url":"https://avatars.githubusercontent.com/u/12952156?v=4"},{"login":"DZ945brH","avatar_url":"https://avatars.githubusercontent.com/u/42635243?v=4"},{"login":"Oupsman","avatar_url":"https://avatars.githubusercontent.com/u/11260343?v=4"},{"login":"m0s4ik","avatar_url":"https://avatars.githubusercontent.com/u/26578395?v=4"},{"login":"AartSchinkel","avatar_url":"https://avatars.githubusercontent.com/u/189675191?v=4"}] \ No newline at end of file +[{"login":"ajnart","avatar_url":"https://avatars.githubusercontent.com/u/49837342?v=4"},{"login":"manuel-rw","avatar_url":"https://avatars.githubusercontent.com/u/30572287?v=4"},{"login":"Meierschlumpf","avatar_url":"https://avatars.githubusercontent.com/u/63781622?v=4"},{"login":"SeDemal","avatar_url":"https://avatars.githubusercontent.com/u/26098587?v=4"},{"login":"lammersbjorn","avatar_url":"https://avatars.githubusercontent.com/u/71191962?v=4"},{"login":"LarveyOfficial","avatar_url":"https://avatars.githubusercontent.com/u/39219859?v=4"},{"login":"c00ldude1oo","avatar_url":"https://avatars.githubusercontent.com/u/15677803?v=4"},{"login":"InterN0te","avatar_url":"https://avatars.githubusercontent.com/u/10882916?v=4"},{"login":"Aimsucks","avatar_url":"https://avatars.githubusercontent.com/u/1828486?v=4"},{"login":"JannesV","avatar_url":"https://avatars.githubusercontent.com/u/5984244?v=4"},{"login":"MauriceNino","avatar_url":"https://avatars.githubusercontent.com/u/18658092?v=4"},{"login":"hillaliy","avatar_url":"https://avatars.githubusercontent.com/u/950010?v=4"},{"login":"Skeeww","avatar_url":"https://avatars.githubusercontent.com/u/9639992?v=4"},{"login":"RichyHBM","avatar_url":"https://avatars.githubusercontent.com/u/5472275?v=4"},{"login":"Bonfire","avatar_url":"https://avatars.githubusercontent.com/u/5704760?v=4"},{"login":"wieli99","avatar_url":"https://avatars.githubusercontent.com/u/46794825?v=4"},{"login":"ishaanparlikar","avatar_url":"https://avatars.githubusercontent.com/u/43013132?v=4"},{"login":"Zareix","avatar_url":"https://avatars.githubusercontent.com/u/29818713?v=4"},{"login":"tuggan","avatar_url":"https://avatars.githubusercontent.com/u/4325608?v=4"},{"login":"Spillebulle","avatar_url":"https://avatars.githubusercontent.com/u/46653946?v=4"},{"login":"spkesDE","avatar_url":"https://avatars.githubusercontent.com/u/1682314?v=4"},{"login":"j3lte","avatar_url":"https://avatars.githubusercontent.com/u/2557568?v=4"},{"login":"dslatt","avatar_url":"https://avatars.githubusercontent.com/u/5211001?v=4"},{"login":"Malong11-007","avatar_url":"https://avatars.githubusercontent.com/u/40298510?v=4"},{"login":"StefanB7","avatar_url":"https://avatars.githubusercontent.com/u/22056509?v=4"},{"login":"souravghosh01","avatar_url":"https://avatars.githubusercontent.com/u/37548139?v=4"},{"login":"SR3u","avatar_url":"https://avatars.githubusercontent.com/u/2380522?v=4"},{"login":"Rikpat","avatar_url":"https://avatars.githubusercontent.com/u/33869814?v=4"},{"login":"NormanJS","avatar_url":"https://avatars.githubusercontent.com/u/83409549?v=4"},{"login":"No-Maines-Land","avatar_url":"https://avatars.githubusercontent.com/u/20687725?v=4"},{"login":"stark1tty","avatar_url":"https://avatars.githubusercontent.com/u/69326376?v=4"},{"login":"Momcilo42","avatar_url":"https://avatars.githubusercontent.com/u/10118137?v=4"},{"login":"marius-arch","avatar_url":"https://avatars.githubusercontent.com/u/72494359?v=4"},{"login":"Lumilias","avatar_url":"https://avatars.githubusercontent.com/u/10852161?v=4"},{"login":"Havock94","avatar_url":"https://avatars.githubusercontent.com/u/7635248?v=4"},{"login":"Lollyde","avatar_url":"https://avatars.githubusercontent.com/u/11347524?v=4"},{"login":"krishnamuppaneni","avatar_url":"https://avatars.githubusercontent.com/u/4703366?v=4"},{"login":"devtobi","avatar_url":"https://avatars.githubusercontent.com/u/28538704?v=4"},{"login":"TyxTang","avatar_url":"https://avatars.githubusercontent.com/u/90897955?v=4"},{"login":"alotlikebeans","avatar_url":"https://avatars.githubusercontent.com/u/19630511?v=4"},{"login":"WillyJL","avatar_url":"https://avatars.githubusercontent.com/u/49810075?v=4"},{"login":"anonysoul","avatar_url":"https://avatars.githubusercontent.com/u/105715150?v=4"},{"login":"cospeedster","avatar_url":"https://avatars.githubusercontent.com/u/52749645?v=4"},{"login":"diederbert","avatar_url":"https://avatars.githubusercontent.com/u/162878798?v=4"},{"login":"digdilem","avatar_url":"https://avatars.githubusercontent.com/u/4052275?v=4"},{"login":"dinghino","avatar_url":"https://avatars.githubusercontent.com/u/14729459?v=4"},{"login":"gfomichev","avatar_url":"https://avatars.githubusercontent.com/u/1596146?v=4"},{"login":"gnattu","avatar_url":"https://avatars.githubusercontent.com/u/12995396?v=4"},{"login":"tuxpizza","avatar_url":"https://avatars.githubusercontent.com/u/84710786?v=4"},{"login":"xmarkurion","avatar_url":"https://avatars.githubusercontent.com/u/46654687?v=4"},{"login":"huanga","avatar_url":"https://avatars.githubusercontent.com/u/732970?v=4"},{"login":"taos15","avatar_url":"https://avatars.githubusercontent.com/u/122130728?v=4"},{"login":"arghyadipchak","avatar_url":"https://avatars.githubusercontent.com/u/32430374?v=4"},{"login":"AuthorShin","avatar_url":"https://avatars.githubusercontent.com/u/4959043?v=4"},{"login":"benniblot","avatar_url":"https://avatars.githubusercontent.com/u/47495914?v=4"},{"login":"bebsworthy","avatar_url":"https://avatars.githubusercontent.com/u/5266759?v=4"},{"login":"catrielmuller","avatar_url":"https://avatars.githubusercontent.com/u/2272323?v=4"},{"login":"Vysp3r","avatar_url":"https://avatars.githubusercontent.com/u/62019735?v=4"},{"login":"DR-Blogs","avatar_url":"https://avatars.githubusercontent.com/u/96393186?v=4"},{"login":"singular0","avatar_url":"https://avatars.githubusercontent.com/u/1925883?v=4"},{"login":"diogovalentte","avatar_url":"https://avatars.githubusercontent.com/u/49578155?v=4"},{"login":"codezninja","avatar_url":"https://avatars.githubusercontent.com/u/4400773?v=4"},{"login":"fabricionaweb","avatar_url":"https://avatars.githubusercontent.com/u/15933?v=4"},{"login":"nyok1912","avatar_url":"https://avatars.githubusercontent.com/u/32163949?v=4"},{"login":"bo3bdo","avatar_url":"https://avatars.githubusercontent.com/u/5271380?v=4"},{"login":"hskrtich","avatar_url":"https://avatars.githubusercontent.com/u/1214484?v=4"},{"login":"ishults","avatar_url":"https://avatars.githubusercontent.com/u/7275442?v=4"},{"login":"jelliuk","avatar_url":"https://avatars.githubusercontent.com/u/4790959?v=4"},{"login":"Moohan","avatar_url":"https://avatars.githubusercontent.com/u/5982260?v=4"},{"login":"tesar-tech","avatar_url":"https://avatars.githubusercontent.com/u/33880579?v=4"},{"login":"jbruell","avatar_url":"https://avatars.githubusercontent.com/u/31685172?v=4"},{"login":"JasonLeeB06","avatar_url":"https://avatars.githubusercontent.com/u/82266978?v=4"},{"login":"jeffersonraimon","avatar_url":"https://avatars.githubusercontent.com/u/80064475?v=4"},{"login":"jo-chemla","avatar_url":"https://avatars.githubusercontent.com/u/16822841?v=4"},{"login":"joser93","avatar_url":"https://avatars.githubusercontent.com/u/6912089?v=4"},{"login":"justijndepover","avatar_url":"https://avatars.githubusercontent.com/u/9008623?v=4"},{"login":"Aandree5","avatar_url":"https://avatars.githubusercontent.com/u/32734153?v=4"},{"login":"jackwellerreal","avatar_url":"https://avatars.githubusercontent.com/u/97435840?v=4"},{"login":"mvanhorn","avatar_url":"https://avatars.githubusercontent.com/u/455140?v=4"},{"login":"SergioChan","avatar_url":"https://avatars.githubusercontent.com/u/10103766?v=4"},{"login":"toineenzo","avatar_url":"https://avatars.githubusercontent.com/u/4921397?v=4"},{"login":"oben01","avatar_url":"https://avatars.githubusercontent.com/u/22369027?v=4"},{"login":"rezstje","avatar_url":"https://avatars.githubusercontent.com/u/45420315?v=4"},{"login":"castielwaverly","avatar_url":"https://avatars.githubusercontent.com/u/137005689?v=4"},{"login":"xoxyuxu","avatar_url":"https://avatars.githubusercontent.com/u/3543416?v=4"},{"login":"MaienM","avatar_url":"https://avatars.githubusercontent.com/u/583129?v=4"},{"login":"kylegrieder","avatar_url":"https://avatars.githubusercontent.com/u/25424229?v=4"},{"login":"HeapReaper","avatar_url":"https://avatars.githubusercontent.com/u/31496522?v=4"},{"login":"Copilot","avatar_url":"https://avatars.githubusercontent.com/in/1143301?v=4"},{"login":"itzTheMeow","avatar_url":"https://avatars.githubusercontent.com/u/50887230?v=4"},{"login":"NicolasNewman","avatar_url":"https://avatars.githubusercontent.com/u/16135852?v=4"},{"login":"NikeLaosClericus","avatar_url":"https://avatars.githubusercontent.com/u/39810627?v=4"},{"login":"noahcroghan","avatar_url":"https://avatars.githubusercontent.com/u/27422774?v=4"},{"login":"ohmzi","avatar_url":"https://avatars.githubusercontent.com/u/6551272?v=4"},{"login":"Rhiz3K","avatar_url":"https://avatars.githubusercontent.com/u/33246262?v=4"},{"login":"saschabuehrle","avatar_url":"https://avatars.githubusercontent.com/u/47737812?v=4"},{"login":"StrandedTurtle","avatar_url":"https://avatars.githubusercontent.com/u/132835255?v=4"},{"login":"CrazyWolf13","avatar_url":"https://avatars.githubusercontent.com/u/96661824?v=4"},{"login":"generalmat82","avatar_url":"https://avatars.githubusercontent.com/u/110256073?v=4"},{"login":"lthomsen","avatar_url":"https://avatars.githubusercontent.com/u/28560325?v=4"},{"login":"pitschi","avatar_url":"https://avatars.githubusercontent.com/u/6841565?v=4"},{"login":"sharpsalat","avatar_url":"https://avatars.githubusercontent.com/u/15666932?v=4"},{"login":"tech62","avatar_url":"https://avatars.githubusercontent.com/u/16237642?v=4"},{"login":"mairas","avatar_url":"https://avatars.githubusercontent.com/u/407010?v=4"},{"login":"leandroscardua","avatar_url":"https://avatars.githubusercontent.com/u/24698541?v=4"},{"login":"hotrungnhan","avatar_url":"https://avatars.githubusercontent.com/u/40029631?v=4"},{"login":"KelianB","avatar_url":"https://avatars.githubusercontent.com/u/11216155?v=4"},{"login":"Kaotic3","avatar_url":"https://avatars.githubusercontent.com/u/80522225?v=4"},{"login":"febrile42","avatar_url":"https://avatars.githubusercontent.com/u/14597122?v=4"},{"login":"frankvHoof93","avatar_url":"https://avatars.githubusercontent.com/u/7346516?v=4"},{"login":"faugusto-oliveira","avatar_url":"https://avatars.githubusercontent.com/u/37384074?v=4"},{"login":"ieugen","avatar_url":"https://avatars.githubusercontent.com/u/1050920?v=4"},{"login":"KartulUdus","avatar_url":"https://avatars.githubusercontent.com/u/23346150?v=4"},{"login":"dgshue","avatar_url":"https://avatars.githubusercontent.com/u/12952156?v=4"},{"login":"DZ945brH","avatar_url":"https://avatars.githubusercontent.com/u/42635243?v=4"},{"login":"Oupsman","avatar_url":"https://avatars.githubusercontent.com/u/11260343?v=4"},{"login":"m0s4ik","avatar_url":"https://avatars.githubusercontent.com/u/26578395?v=4"},{"login":"AartSchinkel","avatar_url":"https://avatars.githubusercontent.com/u/189675191?v=4"}] \ No newline at end of file From a474dcd961d55472a63cf774cbbaaf61ebe92690 Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Fri, 8 May 2026 15:37:41 +0200 Subject: [PATCH 02/11] chore: exclude renovate managed files from codeowners (#5676) --- CODEOWNERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index ed482fd41..b798cfada 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -3,7 +3,11 @@ # Exempt Renovate‑managed files (no owners) package.json +**/package.json package-lock.json +**/package-lock.json pnpm-lock.yaml +**/pnpm-lock.yaml +pnpm-workspace.yaml Dockerfile docker-compose.yml From 00a055283e8848542b67d88a656a99fdd0bcb444 Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Fri, 8 May 2026 15:44:04 +0200 Subject: [PATCH 03/11] fix(qbittorrent): support version 5.2 (#5672) --- pnpm-lock.yaml | 29 +++++++++++++++++++++-------- pnpm-workspace.yaml | 2 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6873a362e..086fcd1f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,8 +16,8 @@ catalogs: specifier: ^8.0.0 version: 8.0.0 '@ctrl/qbittorrent': - specifier: ^9.11.2 - version: 9.11.2 + specifier: ^9.12.1 + version: 9.12.1 '@ctrl/transmission': specifier: ^7.4.0 version: 7.4.0 @@ -1985,7 +1985,7 @@ importers: version: 8.0.0 '@ctrl/qbittorrent': specifier: 'catalog:' - version: 9.11.2 + version: 9.12.1 '@ctrl/transmission': specifier: 'catalog:' version: 7.4.0 @@ -3209,8 +3209,8 @@ packages: resolution: {integrity: sha512-fEfw3AeQ8XhVsNzogZrnyTNDD/Tpbfl3ybHsspBMvj0UKctabApv1JV3JJUQG/hoX6hiO+DtQS+acN7dMPX01g==} engines: {node: '>20'} - '@ctrl/qbittorrent@9.11.2': - resolution: {integrity: sha512-ZIayGA72R4rzXaCcEYrxBwOMYZ1iT0EABJPwjTkwaO3VYRBBltwHSAxNfMWaz4GVmqLA12/WCfx+IPXBN9Gtxg==} + '@ctrl/qbittorrent@9.12.1': + resolution: {integrity: sha512-6rSTWPV0UwehqLCyBLh9Avw5FPA1nh8SO+aTxrEXu6okZPjz+3tn7EGZdLhOfy+6poIc7miX/1g1VAOVo3JSTA==} engines: {node: '>=18'} '@ctrl/shared-torrent@6.5.1': @@ -10521,6 +10521,10 @@ packages: resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} engines: {node: '>=20'} + type-fest@5.6.0: + resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} + engines: {node: '>=20'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -10562,6 +10566,9 @@ packages: ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} @@ -11440,7 +11447,7 @@ snapshots: rfc4648: 1.5.4 uint8array-extras: 1.5.0 - '@ctrl/qbittorrent@9.11.2': + '@ctrl/qbittorrent@9.12.1': dependencies: '@ctrl/magnet-link': 4.3.0 '@ctrl/shared-torrent': 6.5.1(ofetch@1.5.1) @@ -11448,8 +11455,8 @@ snapshots: cookie: 1.1.1 node-fetch-native: 1.6.7 ofetch: 1.5.1 - type-fest: 5.5.0 - ufo: 1.6.3 + type-fest: 5.6.0 + ufo: 1.6.4 uint8array-extras: 1.5.0 '@ctrl/shared-torrent@6.5.1(ofetch@1.5.1)': @@ -19428,6 +19435,10 @@ snapshots: dependencies: tagged-tag: 1.0.0 + type-fest@5.6.0: + dependencies: + tagged-tag: 1.0.0 + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -19489,6 +19500,8 @@ snapshots: ufo@1.6.3: {} + ufo@1.6.4: {} + uglify-js@3.19.3: optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ce173e1db..e5d22df4d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -22,7 +22,7 @@ catalog: "@auth/core": ^0.41.2 "@auth/drizzle-adapter": ^1.11.2 "@ctrl/deluge": ^8.0.0 - "@ctrl/qbittorrent": ^9.11.2 + "@ctrl/qbittorrent": ^9.12.1 "@ctrl/transmission": ^7.4.0 "@dnd-kit/core": ^6.3.1 "@dnd-kit/modifiers": ^9.0.0 From 44a2973b1aba1e2c6bd818be022205f3cdb7c943 Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Fri, 8 May 2026 16:03:12 +0200 Subject: [PATCH 04/11] revert(deps): downgrade pnpm to v10 (#5673) --- .github/renovate.json5 | 4 +- .npmrc | 6 + deployments/prebuilt-debian/Dockerfile | 1 - deployments/prebuilt-debian/package.json | 9 +- .../prebuilt-debian/pnpm-workspace.yaml | 2 - package.json | 51 ++++++- pnpm-lock.yaml | 135 +++++++++++++++--- pnpm-workspace.yaml | 43 +----- test/renovate.spec.ts | 13 +- 9 files changed, 185 insertions(+), 79 deletions(-) create mode 100644 .npmrc delete mode 100644 deployments/prebuilt-debian/pnpm-workspace.yaml diff --git a/.github/renovate.json5 b/.github/renovate.json5 index ebfca8af4..269a4d2ff 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -22,7 +22,7 @@ automerge: true, }, { - // disallow automerge for dependencies requiring postinstall scripts + // disallow automerge for onlyBuiltDependencies matchPackageNames: [ "@tree-sitter-grammars/tree-sitter-yaml", "bcrypt", @@ -39,7 +39,7 @@ ], // Updates lockfile for prebuilt-debian after if package.json is updated, otherwise only root lockfile is updated postUpgradeTasks: { - commands: ["cd deployments/prebuilt-debian && pnpm install --lockfile-only"], + commands: ["cd deployments/prebuilt-debian && pnpm install --ignore-workspace --lockfile-only"], fileFilters: ["deployments/prebuilt-debian/pnpm-lock.yaml"], executionMode: "update", }, diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..34451fb2f --- /dev/null +++ b/.npmrc @@ -0,0 +1,6 @@ +# Expo doesn't play nice with pnpm by default. +# The symbolic links of pnpm break the rules of Expo monorepos. +# @link https://docs.expo.dev/guides/monorepos/#common-issues +node-linker=hoisted +strict-peer-dependencies=false +engine-strict=true \ No newline at end of file diff --git a/deployments/prebuilt-debian/Dockerfile b/deployments/prebuilt-debian/Dockerfile index 7ca2aafb1..8ac61693e 100644 --- a/deployments/prebuilt-debian/Dockerfile +++ b/deployments/prebuilt-debian/Dockerfile @@ -2,6 +2,5 @@ FROM node:24.15.0-trixie AS base WORKDIR /app COPY package.json . COPY pnpm-lock.yaml . -COPY pnpm-workspace.yaml . RUN corepack enable pnpm && pnpm install --frozen-lockfile CMD ["sleep", "60s"] \ No newline at end of file diff --git a/deployments/prebuilt-debian/package.json b/deployments/prebuilt-debian/package.json index 6d326193c..15876ecc1 100644 --- a/deployments/prebuilt-debian/package.json +++ b/deployments/prebuilt-debian/package.json @@ -4,9 +4,14 @@ "dependencies": { "better-sqlite3": "^12.9.0" }, - "packageManager": "pnpm@11.0.4", + "packageManager": "pnpm@10.33.2", "engines": { "node": ">=24.15.0", - "pnpm": ">=11.0.4" + "pnpm": ">=10.33.2" + }, + "pnpm": { + "onlyBuiltDependencies": [ + "better-sqlite3" + ] } } diff --git a/deployments/prebuilt-debian/pnpm-workspace.yaml b/deployments/prebuilt-debian/pnpm-workspace.yaml deleted file mode 100644 index 65783dc34..000000000 --- a/deployments/prebuilt-debian/pnpm-workspace.yaml +++ /dev/null @@ -1,2 +0,0 @@ -allowBuilds: - better-sqlite3: true diff --git a/package.json b/package.json index d81206e10..5cdd91982 100644 --- a/package.json +++ b/package.json @@ -57,12 +57,55 @@ "turbo": "catalog:", "typescript": "catalog:", "vite-tsconfig-paths": "catalog:", - "vitest": "catalog:", - "yaml": "catalog:" + "vitest": "catalog:" }, - "packageManager": "pnpm@11.0.4", + "packageManager": "pnpm@10.33.2", "engines": { "node": ">=24.15.0", - "pnpm": ">=11.0.4" + "pnpm": ">=10.33.2" + }, + "pnpm": { + "onlyBuiltDependencies": [ + "@tree-sitter-grammars/tree-sitter-yaml", + "bcrypt", + "better-sqlite3", + "cpu-features", + "esbuild", + "sharp", + "ssh2", + "tree-sitter", + "tree-sitter-json" + ], + "overrides": { + "@babel/helpers@<7.26.10": ">=7.29.2", + "@babel/runtime@<7.26.10": ">=7.29.2", + "axios@>=1.0.0 <1.8.2": ">=1.16.0", + "brace-expansion@>=2.0.0 <=2.0.1": ">=5.0.5", + "brace-expansion@>=1.0.0 <=1.1.11": ">=5.0.5", + "esbuild@<=0.24.2": ">=0.28.0", + "form-data@>=4.0.0 <4.0.4": ">=4.0.5", + "hono@<4.6.5": ">=4.12.16", + "linkifyjs@<4.3.2": ">=4.3.2", + "nanoid@>=4.0.0 <5.0.9": ">=5.1.11", + "prismjs@<1.30.0": ">=1.30.0", + "proxmox-api>undici": "7.24.6", + "react-is": "^19.2.5", + "rollup@>=4.0.0 <4.22.4": ">=4.60.2", + "sha.js@<=2.4.11": ">=2.4.12", + "tar-fs@>=3.0.0 <3.0.9": ">=3.1.2", + "tar-fs@>=2.0.0 <2.1.3": ">=3.1.2", + "tmp@<=0.2.3": ">=0.2.5", + "vite@>=5.0.0 <=5.4.18": ">=8.0.10" + }, + "patchedDependencies": { + "@types/node-unifi": "patches/@types__node-unifi.patch", + "trpc-to-openapi": "patches/trpc-to-openapi.patch" + }, + "allowUnusedPatches": true, + "ignoredBuiltDependencies": [ + "@scarf/scarf", + "core-js-pure", + "protobufjs" + ] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 086fcd1f1..647b98e2d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -566,8 +566,8 @@ overrides: '@babel/helpers@<7.26.10': '>=7.29.2' '@babel/runtime@<7.26.10': '>=7.29.2' axios@>=1.0.0 <1.8.2: '>=1.16.0' - brace-expansion@>=1.0.0 <=1.1.11: '>=5.0.5' brace-expansion@>=2.0.0 <=2.0.1: '>=5.0.5' + brace-expansion@>=1.0.0 <=1.1.11: '>=5.0.5' esbuild@<=0.24.2: '>=0.28.0' form-data@>=4.0.0 <4.0.4: '>=4.0.5' hono@<4.6.5: '>=4.12.16' @@ -578,14 +578,18 @@ overrides: react-is: ^19.2.5 rollup@>=4.0.0 <4.22.4: '>=4.60.2' sha.js@<=2.4.11: '>=2.4.12' - tar-fs@>=2.0.0 <2.1.3: '>=3.1.2' tar-fs@>=3.0.0 <3.0.9: '>=3.1.2' + tar-fs@>=2.0.0 <2.1.3: '>=3.1.2' tmp@<=0.2.3: '>=0.2.5' vite@>=5.0.0 <=5.4.18: '>=8.0.10' patchedDependencies: - '@types/node-unifi': 5e6ae51e2a17a7f9729bfa30b0eb3d0842a5810ac6db47603ab4a6efa1ed84c5 - trpc-to-openapi: 2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c + '@types/node-unifi': + hash: 5e6ae51e2a17a7f9729bfa30b0eb3d0842a5810ac6db47603ab4a6efa1ed84c5 + path: patches/@types__node-unifi.patch + trpc-to-openapi: + hash: 2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c + path: patches/trpc-to-openapi.patch importers: @@ -660,9 +664,6 @@ importers: vitest: specifier: 'catalog:' version: 4.1.5(@types/node@24.12.2)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1(@noble/hashes@2.0.1))(vite@7.1.12(@types/node@24.12.2)(sass@1.99.0)(sugarss@5.0.0(postcss@8.5.8))(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.4)) - yaml: - specifier: 'catalog:' - version: 2.8.4 apps/nextjs: dependencies: @@ -1454,7 +1455,7 @@ importers: dependencies: '@t3-oss/env-nextjs': specifier: 'catalog:' - version: 0.13.11(typescript@5.9.3)(zod@4.4.2) + version: 0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2) better-sqlite3: specifier: 'catalog:' version: 12.9.0 @@ -1463,7 +1464,7 @@ importers: version: 0.2.9 drizzle-orm: specifier: 'catalog:' - version: 0.45.2(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) + version: 0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) ioredis: specifier: 'catalog:' version: 5.10.1 @@ -1717,10 +1718,10 @@ importers: version: 0.31.10 drizzle-orm: specifier: 'catalog:' - version: 0.45.2(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) + version: 0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) drizzle-zod: specifier: 'catalog:' - version: 0.8.3(drizzle-orm@0.45.2(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.2) + version: 0.8.3(drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.2) mysql2: specifier: 'catalog:' version: 3.22.3(@types/node@24.12.2) @@ -3000,6 +3001,12 @@ packages: resolution: {integrity: sha512-2aDL3WUv8hMJb2L3r/PIQWsTLyq7RQr3v9xD16fiz6O8ys1xEyLhhTOv8gxtZvJiTzjTF5pHoArvRdesGL1DMQ==} hasBin: true + '@ark/schema@0.46.0': + resolution: {integrity: sha512-c2UQdKgP2eqqDArfBqQIJppxJHvNNXuQPeuSPlDML4rjw+f1cu0qAlzOG4b8ujgm9ctIDWwhpyw6gjG5ledIVQ==} + + '@ark/util@0.46.0': + resolution: {integrity: sha512-JPy/NGWn/lvf1WmGCPw2VGpBg5utZraE84I7wli18EDF3p3zc/e9WolT35tINeZO3l7C77SjqRJeAUoT0CvMRg==} + '@asamuzakjp/css-color@5.1.11': resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -4276,6 +4283,14 @@ packages: '@kwsites/file-exists@1.1.1': resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} + '@libsql/client-wasm@0.14.0': + resolution: {integrity: sha512-gB/jtz0xuwrqAHApBv9e9JSew2030Fhj2edyZ83InZ4yPj/Q2LTUlEhaspEYT0T0xsAGqPy38uGrmq/OGS+DdQ==} + bundledDependencies: + - '@libsql/libsql-wasm-experimental' + + '@libsql/core@0.14.0': + resolution: {integrity: sha512-nhbuXf7GP3PSZgdCY2Ecj8vz187ptHlZQ0VRc751oB2C1W8jQUXKKklvt7t1LJiUTQBVJuadF628eUk+3cRi4Q==} + '@mantine/charts@8.3.18': resolution: {integrity: sha512-oudif3EUH7Nb9DPm0abAPxpFYDWWjR3k2S5ll0/CcB+pJzlhwaBG19QwpOJaRA6VAvAXDDKOXCO4mi9XCEN78g==} peerDependencies: @@ -4370,7 +4385,6 @@ packages: '@million/lint@1.0.14': resolution: {integrity: sha512-u6/kglVwZRu5+GMmtkNlGLqJVkgTl0TtM+hLa9rBg7pldx+5NG5bk45NvL37uZmAr2Xfa1C6qHb7GrFwfP372g==} - deprecated: This package is no longer maintained hasBin: true '@ndaidong/bellajs@12.0.1': @@ -4651,6 +4665,9 @@ packages: resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} engines: {node: '>= 10.0.0'} + '@petamoriken/float16@3.9.3': + resolution: {integrity: sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==} + '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} @@ -6108,6 +6125,9 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + arktype@2.1.20: + resolution: {integrity: sha512-IZCEEXaJ8g+Ijd59WtSYwtjnqXiwM8sWQ5EjGamcto7+HVN9eK0C4p0zDlCuAwWhpqr6fIBkxPuYDl4/Mcj/+Q==} + array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -7084,6 +7104,10 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} @@ -7547,6 +7571,11 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + gel@2.0.0: + resolution: {integrity: sha512-Oq3Fjay71s00xzDc0BF/mpcLmnA+uRqMEJK8p5K4PaZjUEsxaeo+kR9OHBVAf289/qPd+0OcLOLUN0UhqiUCog==} + engines: {node: '>= 18.0.0'} + hasBin: true + generate-function@2.3.1: resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} @@ -8096,6 +8125,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isexe@3.1.5: + resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} + engines: {node: '>=18'} + isomorphic-dompurify@3.12.0: resolution: {integrity: sha512-8n+j+6ypTHvriJwFOQ2qusQ6bzGjZVcR3jbe1pBpLcGI1dn4WIl0ctLBngqE5QttquQBAlKXwJeTMw+X7x7qKw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} @@ -8164,6 +8197,9 @@ packages: react: optional: true + js-base64@3.7.8: + resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} + js-file-download@0.4.12: resolution: {integrity: sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==} @@ -10956,6 +10992,11 @@ packages: engines: {node: '>= 8'} hasBin: true + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -11184,6 +11225,14 @@ snapshots: '@antfu/ni@0.21.12': {} + '@ark/schema@0.46.0': + dependencies: + '@ark/util': 0.46.0 + optional: true + + '@ark/util@0.46.0': + optional: true + '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1 @@ -12277,6 +12326,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@libsql/client-wasm@0.14.0': + dependencies: + '@libsql/core': 0.14.0 + js-base64: 3.7.8 + optional: true + + '@libsql/core@0.14.0': + dependencies: + js-base64: 3.7.8 + optional: true + '@mantine/charts@8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/hooks@8.3.18(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(recharts@3.8.1(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react-is@19.2.5)(react@19.2.5)(redux@5.0.1))': dependencies: '@mantine/core': 8.3.18(@mantine/hooks@8.3.18(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) @@ -12681,6 +12741,9 @@ snapshots: '@parcel/watcher-win32-ia32': 2.4.1 '@parcel/watcher-win32-x64': 2.4.1 + '@petamoriken/float16@3.9.3': + optional: true + '@pinojs/redact@0.4.0': {} '@pkgjs/parseargs@0.11.0': @@ -13436,15 +13499,17 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@t3-oss/env-core@0.13.11(typescript@5.9.3)(zod@4.4.2)': + '@t3-oss/env-core@0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2)': optionalDependencies: + arktype: 2.1.20 typescript: 5.9.3 zod: 4.4.2 - '@t3-oss/env-nextjs@0.13.11(typescript@5.9.3)(zod@4.4.2)': + '@t3-oss/env-nextjs@0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2)': dependencies: - '@t3-oss/env-core': 0.13.11(typescript@5.9.3)(zod@4.4.2) + '@t3-oss/env-core': 0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2) optionalDependencies: + arktype: 2.1.20 typescript: 5.9.3 zod: 4.4.2 @@ -14483,6 +14548,12 @@ snapshots: aria-query@5.3.2: {} + arktype@2.1.20: + dependencies: + '@ark/schema': 0.46.0 + '@ark/util': 0.46.0 + optional: true + array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -15310,17 +15381,19 @@ snapshots: esbuild: 0.25.12 tsx: 4.21.0 - drizzle-orm@0.45.2(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0): + drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0): optionalDependencies: + '@libsql/client-wasm': 0.14.0 '@types/better-sqlite3': 7.6.13 '@types/pg': 8.20.0 better-sqlite3: 12.9.0 + gel: 2.0.0 mysql2: 3.22.3(@types/node@24.12.2) pg: 8.20.0 - drizzle-zod@0.8.3(drizzle-orm@0.45.2(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.2): + drizzle-zod@0.8.3(drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.2): dependencies: - drizzle-orm: 0.45.2(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) + drizzle-orm: 0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) zod: 4.4.2 dunder-proto@1.0.1: @@ -15403,6 +15476,9 @@ snapshots: env-paths@2.2.1: {} + env-paths@3.0.0: + optional: true + environment@1.1.0: {} error-causes@3.0.2: {} @@ -16073,6 +16149,18 @@ snapshots: functions-have-names@1.2.3: {} + gel@2.0.0: + dependencies: + '@petamoriken/float16': 3.9.3 + debug: 4.4.3 + env-paths: 3.0.0 + semver: 7.7.4 + shell-quote: 1.8.3 + which: 4.0.0 + transitivePeerDependencies: + - supports-color + optional: true + generate-function@2.3.1: dependencies: is-property: 1.0.2 @@ -16609,6 +16697,9 @@ snapshots: isexe@2.0.0: {} + isexe@3.1.5: + optional: true + isomorphic-dompurify@3.12.0(@noble/hashes@2.0.1): dependencies: dompurify: 3.4.2 @@ -16692,6 +16783,9 @@ snapshots: '@types/react': 19.2.14 react: 19.2.5 + js-base64@3.7.8: + optional: true + js-file-download@0.4.12: {} js-tokens@10.0.0: {} @@ -19919,6 +20013,11 @@ snapshots: dependencies: isexe: 2.0.0 + which@4.0.0: + dependencies: + isexe: 3.1.5 + optional: true + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e5d22df4d..bfff3f1d6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,22 +2,6 @@ packages: - apps/* - packages/* - tooling/* -allowBuilds: - "@scarf/scarf": false - "@swc/core": false - "@tree-sitter-grammars/tree-sitter-yaml": true - bcrypt: true - better-sqlite3: true - core-js-pure: false - cpu-features: true - esbuild: true - protobufjs: false - sharp: true - ssh2: true - tree-sitter: true - tree-sitter-json: true - nice-napi: false -allowUnusedPatches: true catalog: "@auth/core": ^0.41.2 "@auth/drizzle-adapter": ^1.11.2 @@ -29,7 +13,7 @@ catalog: "@dnd-kit/sortable": ^10.0.0 "@dnd-kit/utilities": ^3.2.2 "@drizzle-team/brocli": ^0.12.0 - "@eslint/js": 10.0.1 + '@eslint/js': 10.0.1 "@extractus/feed-extractor": 7.1.7 "@gitbeaker/rest": ^43.8.0 "@homarr/gridstack": ^1.12.0 @@ -205,32 +189,7 @@ catalog: zod-form-data: ^3.0.1 zod-validation-error: ^5.0.0 catalogMode: strict -engineStrict: true minimumReleaseAge: 4320 minimumReleaseAgeExclude: - next - "@next/*" -nodeLinker: hoisted -overrides: - "@babel/helpers@<7.26.10": ">=7.29.2" - "@babel/runtime@<7.26.10": ">=7.29.2" - "axios@>=1.0.0 <1.8.2": ">=1.16.0" - "brace-expansion@>=1.0.0 <=1.1.11": ">=5.0.5" - "brace-expansion@>=2.0.0 <=2.0.1": ">=5.0.5" - "esbuild@<=0.24.2": ">=0.28.0" - "form-data@>=4.0.0 <4.0.4": ">=4.0.5" - "hono@<4.6.5": ">=4.12.16" - "linkifyjs@<4.3.2": ">=4.3.2" - "nanoid@>=4.0.0 <5.0.9": ">=5.1.11" - "prismjs@<1.30.0": ">=1.30.0" - "proxmox-api>undici": "7.24.6" - "react-is": "^19.2.5" - "rollup@>=4.0.0 <4.22.4": ">=4.60.2" - "sha.js@<=2.4.11": ">=2.4.12" - "tar-fs@>=2.0.0 <2.1.3": ">=3.1.2" - "tar-fs@>=3.0.0 <3.0.9": ">=3.1.2" - "tmp@<=0.2.3": ">=0.2.5" - "vite@>=5.0.0 <=5.4.18": ">=8.0.10" -patchedDependencies: - "@types/node-unifi": "patches/@types__node-unifi.patch" - trpc-to-openapi: "patches/trpc-to-openapi.patch" diff --git a/test/renovate.spec.ts b/test/renovate.spec.ts index 2b8236ce6..0f40a8061 100644 --- a/test/renovate.spec.ts +++ b/test/renovate.spec.ts @@ -2,24 +2,21 @@ import fs from "fs/promises"; import { join } from "path"; import json5 from "json5"; import { describe, test } from "vitest"; -import { parse as parseYaml } from "yaml"; describe("Renovate configuration tests", () => { - test("automerge should be disabled for built dependencies", async () => { - const pnpmConfig = await fs.readFile(join(__dirname, "../pnpm-workspace.yaml"), "utf-8").then(parseYaml); + test("automerge should be disabled for onlyBuiltDependencies", async () => { + const packageJson = await import("../package.json"); const renovateConfig = await fs.readFile(join(__dirname, "../.github/renovate.json5"), "utf-8").then(json5.parse); - const dependenciesWithBuilt = Object.entries(pnpmConfig.allowBuilds) - .filter(([_, value]) => value === true) - .map(([key, _]) => key); + const onlyBuiltDependencies = packageJson.pnpm.onlyBuiltDependencies; const automergeDisabledDeps = renovateConfig.packageRules .filter((rule: any) => rule.automerge === false) .flatMap((rule: any) => rule.matchPackageNames || []); - const missingDeps = dependenciesWithBuilt.filter((dep: string) => !automergeDisabledDeps.includes(dep)); + const missingDeps = onlyBuiltDependencies.filter((dep: string) => !automergeDisabledDeps.includes(dep)); if (missingDeps.length > 0) { throw new Error( - `The following built dependencies are missing automerge disable rules in renovate.json5: ${missingDeps.join(", ")}`, + `The following onlyBuiltDependencies are missing automerge disable rules in renovate.json5: ${missingDeps.join(", ")}`, ); } }); From 2d15b3d4078381a803128413e1300d999efc2675 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Fri, 8 May 2026 17:10:22 +0200 Subject: [PATCH 05/11] chore(deps): update dependency zod to v4.4.3 (#5675) --- pnpm-lock.yaml | 129 ++++++++++++++++++++------------------------ pnpm-workspace.yaml | 2 +- 2 files changed, 59 insertions(+), 72 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 647b98e2d..e7e2835e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -553,8 +553,8 @@ catalogs: specifier: 2.8.4 version: 2.8.4 zod: - specifier: ^4.4.2 - version: 4.4.2 + specifier: ^4.4.3 + version: 4.4.3 zod-form-data: specifier: ^3.0.1 version: 3.0.1 @@ -888,7 +888,7 @@ importers: version: 2.8.4 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1234,10 +1234,10 @@ importers: version: 2.2.6 trpc-to-openapi: specifier: 'catalog:' - version: 3.2.0(patch_hash=2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c)(@trpc/server@11.17.0(typescript@5.9.3))(zod-openapi@5.3.0(zod@4.4.2))(zod@4.4.2) + version: 3.2.0(patch_hash=2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c)(@trpc/server@11.17.0(typescript@5.9.3))(zod-openapi@5.3.0(zod@4.4.3))(zod@4.4.3) zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1304,7 +1304,7 @@ importers: version: 19.2.5(react@19.2.5) zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1430,10 +1430,10 @@ importers: version: 7.24.6 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 zod-validation-error: specifier: 'catalog:' - version: 5.0.0(zod@4.4.2) + version: 5.0.0(zod@4.4.3) devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1455,7 +1455,7 @@ importers: dependencies: '@t3-oss/env-nextjs': specifier: 'catalog:' - version: 0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2) + version: 0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.3) better-sqlite3: specifier: 'catalog:' version: 12.9.0 @@ -1482,7 +1482,7 @@ importers: version: 3.19.0 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1534,7 +1534,7 @@ importers: version: 19.2.5 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1721,7 +1721,7 @@ importers: version: 0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) drizzle-zod: specifier: 'catalog:' - version: 0.8.3(drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.2) + version: 0.8.3(drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.3) mysql2: specifier: 'catalog:' version: 3.22.3(@types/node@24.12.2) @@ -1776,7 +1776,7 @@ importers: version: 5.7.2 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1844,10 +1844,10 @@ importers: version: 8.3.18(react@19.2.5) mantine-form-zod-resolver: specifier: 'catalog:' - version: 1.3.0(@mantine/form@8.3.18(react@19.2.5))(zod@4.4.2) + version: 1.3.0(@mantine/form@8.3.18(react@19.2.5))(zod@4.4.3) zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -1899,7 +1899,7 @@ importers: version: 19.2.5 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2055,7 +2055,7 @@ importers: version: 0.6.2 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2168,7 +2168,7 @@ importers: version: 19.2.5(react@19.2.5) zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2272,10 +2272,10 @@ importers: version: 2.2.6 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 zod-form-data: specifier: 'catalog:' - version: 3.0.1(zod@4.4.2) + version: 3.0.1(zod@4.4.3) devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2303,7 +2303,7 @@ importers: version: link:../common zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2423,7 +2423,7 @@ importers: version: 7.24.6 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2705,10 +2705,10 @@ importers: version: link:../translation zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 zod-form-data: specifier: 'catalog:' - version: 3.0.1(zod@4.4.2) + version: 3.0.1(zod@4.4.3) devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -2865,7 +2865,7 @@ importers: version: 1.11.20 mantine-form-zod-resolver: specifier: 'catalog:' - version: 1.3.0(@mantine/form@8.3.18(react@19.2.5))(zod@4.4.2) + version: 1.3.0(@mantine/form@8.3.18(react@19.2.5))(zod@4.4.3) mantine-react-table: specifier: 'catalog:' version: 2.0.0-beta.9(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/dates@8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/hooks@8.3.18(react@19.2.5))(dayjs@1.11.20)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/hooks@8.3.18(react@19.2.5))(@tabler/icons-react@3.41.1(react@19.2.5))(clsx@2.1.1)(dayjs@1.11.20)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) @@ -2892,7 +2892,7 @@ importers: version: 8.23.7 zod: specifier: 'catalog:' - version: 4.4.2 + version: 4.4.3 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -10553,10 +10553,6 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - type-fest@5.5.0: - resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} - engines: {node: '>=20'} - type-fest@5.6.0: resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} engines: {node: '>=20'} @@ -10599,9 +10595,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.3: - resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} - ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} @@ -11194,8 +11187,8 @@ packages: peerDependencies: zod: ^3.25.0 || ^4.0.0 - zod@4.4.2: - resolution: {integrity: sha512-IynmDyxsEsb9RKzO3J9+4SxXnl2FTFSzNBaKKaMV6tsSk0rw9gYw9gs+JFCq/qk2LCZ78KDwyj+Z289TijSkUw==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -11487,8 +11480,8 @@ snapshots: cookie-es: 3.0.1 node-fetch-native: 1.6.7 ofetch: 1.5.1 - type-fest: 5.5.0 - ufo: 1.6.3 + type-fest: 5.6.0 + ufo: 1.6.4 uint8array-extras: 1.5.0 '@ctrl/magnet-link@4.3.0': @@ -11520,7 +11513,7 @@ snapshots: '@ctrl/shared-torrent': 6.5.1(ofetch@1.5.1) ofetch: 1.5.1 type-fest: 4.41.0 - ufo: 1.6.3 + ufo: 1.6.4 uint8array-extras: 1.5.0 '@dabh/diagnostics@2.0.8': @@ -13499,19 +13492,19 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@t3-oss/env-core@0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2)': + '@t3-oss/env-core@0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.3)': optionalDependencies: arktype: 2.1.20 typescript: 5.9.3 - zod: 4.4.2 + zod: 4.4.3 - '@t3-oss/env-nextjs@0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2)': + '@t3-oss/env-nextjs@0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.3)': dependencies: - '@t3-oss/env-core': 0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.2) + '@t3-oss/env-core': 0.13.11(arktype@2.1.20)(typescript@5.9.3)(zod@4.4.3) optionalDependencies: arktype: 2.1.20 typescript: 5.9.3 - zod: 4.4.2 + zod: 4.4.3 '@tabler/icons-react@3.41.1(react@19.2.5)': dependencies: @@ -15391,10 +15384,10 @@ snapshots: mysql2: 3.22.3(@types/node@24.12.2) pg: 8.20.0 - drizzle-zod@0.8.3(drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.2): + drizzle-zod@0.8.3(drizzle-orm@0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0))(zod@4.4.3): dependencies: drizzle-orm: 0.45.2(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.20.0)(better-sqlite3@12.9.0)(gel@2.0.0)(mysql2@3.22.3(@types/node@24.12.2))(pg@8.20.0) - zod: 4.4.2 + zod: 4.4.3 dunder-proto@1.0.1: dependencies: @@ -15772,8 +15765,8 @@ snapshots: '@babel/core': 7.29.0 '@babel/parser': 7.29.2 eslint: 10.3.0 - zod: 4.4.2 - zod-validation-error: 4.0.2(zod@4.4.2) + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) transitivePeerDependencies: - supports-color @@ -16283,7 +16276,7 @@ snapshots: iron-webcrypto: 1.2.1 node-mock-http: 1.0.2 radix3: 1.1.2 - ufo: 1.6.3 + ufo: 1.6.4 uncrypto: 0.1.3 handlebars@4.7.8: @@ -17022,10 +17015,10 @@ snapshots: dependencies: semver: 7.7.4 - mantine-form-zod-resolver@1.3.0(@mantine/form@8.3.18(react@19.2.5))(zod@4.4.2): + mantine-form-zod-resolver@1.3.0(@mantine/form@8.3.18(react@19.2.5))(zod@4.4.3): dependencies: '@mantine/form': 8.3.18(react@19.2.5) - zod: 4.4.2 + zod: 4.4.3 mantine-react-table@2.0.0-beta.9(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/dates@8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/hooks@8.3.18(react@19.2.5))(dayjs@1.11.20)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@mantine/hooks@8.3.18(react@19.2.5))(@tabler/icons-react@3.41.1(react@19.2.5))(clsx@2.1.1)(dayjs@1.11.20)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: @@ -17628,7 +17621,7 @@ snapshots: dependencies: destr: 2.0.5 node-fetch-native: 1.6.7 - ufo: 1.6.3 + ufo: 1.6.4 ohash@1.1.4: {} @@ -18345,14 +18338,14 @@ snapshots: dependencies: find-up-simple: 1.0.1 read-pkg: 10.0.0 - type-fest: 5.5.0 + type-fest: 5.6.0 read-pkg@10.0.0: dependencies: '@types/normalize-package-data': 2.4.4 normalize-package-data: 8.0.0 parse-json: 8.3.0 - type-fest: 5.5.0 + type-fest: 5.6.0 unicorn-magic: 0.3.0 read-pkg@9.0.1: @@ -19440,14 +19433,14 @@ snapshots: trough@2.2.0: {} - trpc-to-openapi@3.2.0(patch_hash=2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c)(@trpc/server@11.17.0(typescript@5.9.3))(zod-openapi@5.3.0(zod@4.4.2))(zod@4.4.2): + trpc-to-openapi@3.2.0(patch_hash=2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c)(@trpc/server@11.17.0(typescript@5.9.3))(zod-openapi@5.3.0(zod@4.4.3))(zod@4.4.3): dependencies: '@trpc/server': 11.17.0(typescript@5.9.3) co-body: 6.2.0 h3: 1.15.1 openapi3-ts: 4.4.0 - zod: 4.4.2 - zod-openapi: 5.3.0(zod@4.4.2) + zod: 4.4.3 + zod-openapi: 5.3.0(zod@4.4.3) optionalDependencies: '@rollup/rollup-linux-x64-gnu': 4.6.1 @@ -19525,10 +19518,6 @@ snapshots: type-fest@4.41.0: {} - type-fest@5.5.0: - dependencies: - tagged-tag: 1.0.0 - type-fest@5.6.0: dependencies: tagged-tag: 1.0.0 @@ -19592,8 +19581,6 @@ snapshots: typescript@5.9.3: {} - ufo@1.6.3: {} - ufo@1.6.4: {} uglify-js@3.19.3: @@ -20183,23 +20170,23 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.5.2 - zod-form-data@3.0.1(zod@4.4.2): + zod-form-data@3.0.1(zod@4.4.3): dependencies: '@rvf/set-get': 7.0.1 - zod: 4.4.2 + zod: 4.4.3 - zod-openapi@5.3.0(zod@4.4.2): + zod-openapi@5.3.0(zod@4.4.3): dependencies: - zod: 4.4.2 + zod: 4.4.3 - zod-validation-error@4.0.2(zod@4.4.2): + zod-validation-error@4.0.2(zod@4.4.3): dependencies: - zod: 4.4.2 + zod: 4.4.3 - zod-validation-error@5.0.0(zod@4.4.2): + zod-validation-error@5.0.0(zod@4.4.3): dependencies: - zod: 4.4.2 + zod: 4.4.3 - zod@4.4.2: {} + zod@4.4.3: {} zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bfff3f1d6..9d53deda1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -185,7 +185,7 @@ catalog: ws: ^8.20.0 xml2js: ^0.6.2 yaml: 2.8.4 - zod: ^4.4.2 + zod: ^4.4.3 zod-form-data: ^3.0.1 zod-validation-error: ^5.0.0 catalogMode: strict From 4d30a2e8c48f818bb4947a651b0fec5f64cbf569 Mon Sep 17 00:00:00 2001 From: Borislaw Sotnikow Date: Fri, 8 May 2026 17:11:08 +0200 Subject: [PATCH 06/11] feat(installations): support secrets file for all environment variables (#5125) Co-authored-by: Meier Lukas --- scripts/entrypoint.sh | 13 +++++++++++++ scripts/run.sh | 5 ----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index c362eac3a..f4d7c9fa4 100644 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -18,6 +18,19 @@ if [ "${PUID}" != "0" ] || [ "${PGID}" != "0" ]; then echo "Changing owner to $PUID:$PGID, done." fi +# support _FILE Suffix for environment variables +for file_var in $(env | cut -d '=' -f 1 | grep "_FILE$"); do + target_var=$(echo "$file_var" | cut -d'=' -f1 | sed 's/_FILE//') + file_path=$(printenv "$file_var") + + if [ -f "$file_path" ]; then + export "$target_var"=$(cat "$file_path" | tr -d '\n\r') + echo "Info: Loaded secret for $target_var from $file_path" + else + echo "Warning: Secret file $file_path not found for $target_var" + fi +done + if [ "${PUID}" != "0" ]; then exec su-exec $PUID:$PGID "$@" else diff --git a/scripts/run.sh b/scripts/run.sh index 4d90499d5..78659a04a 100644 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -19,11 +19,6 @@ export AUTH_SECRET=$(openssl rand -base64 32) # Cron job API key is generated every time the container starts as it is required for communication between nextjs-api and tasks-api export CRON_JOB_API_KEY=$(openssl rand -base64 32) -# Support secret file for encryption key (is not empty and file exists) -if [ -n "$SECRET_ENCRYPTION_KEY_FILE" ] && [ -f "$SECRET_ENCRYPTION_KEY_FILE" ]; then - export SECRET_ENCRYPTION_KEY=$(cat $SECRET_ENCRYPTION_KEY_FILE) -fi - # Start nginx proxy # 1. Replace the HOSTNAME in the nginx template file # 2. Create the nginx configuration file from the template From 84b269a80df1ed2514ac381bc7471dc4a71ae5d4 Mon Sep 17 00:00:00 2001 From: "homarr-renovate[bot]" <158783068+homarr-renovate[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 15:30:26 +0000 Subject: [PATCH 07/11] chore(deps): update tanstack-query monorepo to ^5.100.9 (#5678) Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com> --- pnpm-lock.yaml | 89 +++++++++++++++++++++++---------------------- pnpm-workspace.yaml | 6 +-- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7e2835e8..2de02eff3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,14 +133,14 @@ catalogs: specifier: ^3.41.1 version: 3.41.1 '@tanstack/react-query': - specifier: ^5.100.8 - version: 5.100.8 + specifier: ^5.100.9 + version: 5.100.9 '@tanstack/react-query-devtools': - specifier: ^5.100.8 - version: 5.100.8 + specifier: ^5.100.9 + version: 5.100.9 '@tanstack/react-query-next-experimental': - specifier: ^5.100.8 - version: 5.100.8 + specifier: ^5.100.9 + version: 5.100.9 '@testcontainers/mysql': specifier: ^11.14.0 version: 11.14.0 @@ -792,22 +792,22 @@ importers: version: 3.41.1(react@19.2.5) '@tanstack/react-query': specifier: 'catalog:' - version: 5.100.8(react@19.2.5) + version: 5.100.9(react@19.2.5) '@tanstack/react-query-devtools': specifier: 'catalog:' - version: 5.100.8(@tanstack/react-query@5.100.8(react@19.2.5))(react@19.2.5) + version: 5.100.9(@tanstack/react-query@5.100.9(react@19.2.5))(react@19.2.5) '@tanstack/react-query-next-experimental': specifier: 'catalog:' - version: 5.100.8(@tanstack/react-query@5.100.8(react@19.2.5))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react@19.2.5) + version: 5.100.9(@tanstack/react-query@5.100.9(react@19.2.5))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react@19.2.5) '@trpc/client': specifier: 'catalog:' version: 11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3) '@trpc/next': specifier: 'catalog:' - version: 11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3) + version: 11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3) '@trpc/react-query': specifier: 'catalog:' - version: 11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) + version: 11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) '@trpc/server': specifier: 'catalog:' version: 11.17.0(typescript@5.9.3) @@ -1204,19 +1204,19 @@ importers: version: 1.4.0 '@tanstack/react-query': specifier: 'catalog:' - version: 5.100.8(react@19.2.5) + version: 5.100.9(react@19.2.5) '@trpc/client': specifier: 'catalog:' version: 11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3) '@trpc/react-query': specifier: 'catalog:' - version: 11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) + version: 11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) '@trpc/server': specifier: 'catalog:' version: 11.17.0(typescript@5.9.3) '@trpc/tanstack-react-query': specifier: 'catalog:' - version: 11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) + version: 11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) lodash.clonedeep: specifier: 'catalog:' version: 4.5.0 @@ -1519,7 +1519,7 @@ importers: version: link:../cron-jobs '@tanstack/react-query': specifier: 'catalog:' - version: 5.100.8(react@19.2.5) + version: 5.100.9(react@19.2.5) '@trpc/client': specifier: 'catalog:' version: 11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3) @@ -1528,7 +1528,7 @@ importers: version: 11.17.0(typescript@5.9.3) '@trpc/tanstack-react-query': specifier: 'catalog:' - version: 11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) + version: 11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) react: specifier: 'catalog:' version: 19.2.5 @@ -4385,6 +4385,7 @@ packages: '@million/lint@1.0.14': resolution: {integrity: sha512-u6/kglVwZRu5+GMmtkNlGLqJVkgTl0TtM+hLa9rBg7pldx+5NG5bk45NvL37uZmAr2Xfa1C6qHb7GrFwfP372g==} + deprecated: This package is no longer maintained hasBin: true '@ndaidong/bellajs@12.0.1': @@ -5213,27 +5214,27 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/query-core@5.100.8': - resolution: {integrity: sha512-ceYwSFOqjPwET5TA6IOYxzxlGc0ekyH/gfOtWkP0PX43rzX9bxW48Iuw8KAduKCToi4rJAQ6nRy2kAe8gszdmg==} + '@tanstack/query-core@5.100.9': + resolution: {integrity: sha512-SJSFw1S8+kQ0+knv/XGfrbocWoAlT7vDKsSImtLx3ZPQmEcR46hkDjLSvynSy25N8Ms4tIEini1FuBd5k7IscQ==} - '@tanstack/query-devtools@5.100.8': - resolution: {integrity: sha512-29D6k564h7eudwNdfRcq6Je2VFUWGxHwADPg1xC2yHxrovYBwZiqzIv/DkPRsK/EMoOIPIvPq+IU0uCxiQXYPA==} + '@tanstack/query-devtools@5.100.9': + resolution: {integrity: sha512-gqiptrTIhbK2PuCaPRHmWXfJG1NGYVFpAr0HqogEqiSBNB5xDz6fmesQt7w4WgMOqOQPnPHJ3ZDMuhDaXvNO8g==} - '@tanstack/react-query-devtools@5.100.8': - resolution: {integrity: sha512-BKpysWo1u3kVMtv92XOv/Gu6eCbE/IxBLJPs0GG/qyySUQvZI2h7mqRwyf8Aa6WfUoX8Yf2AAh0uugQLAr8KtQ==} + '@tanstack/react-query-devtools@5.100.9': + resolution: {integrity: sha512-mM3slaVGXJmz+pOLgXdANj75ikgQCyudyl3kmFvm6brI1JyVeY/+IeD17uDHIvZrD8hfoO2sdZ54RFsHdYAuhA==} peerDependencies: - '@tanstack/react-query': ^5.100.8 + '@tanstack/react-query': ^5.100.9 react: ^18 || ^19 - '@tanstack/react-query-next-experimental@5.100.8': - resolution: {integrity: sha512-B1p5yeqWeLrWasZ0s2pG7b7do37XNXIlzHnj8RcEsoJ8DsGWXvAfSjXgnLvG0HdZUTPWjHrVRMIJ0Pgmy+bCtw==} + '@tanstack/react-query-next-experimental@5.100.9': + resolution: {integrity: sha512-cXkeZW/lEQaVmB3l0eiej5lJUNix4xxWWxOzgIJYC8D4fwgl1Kwf/bb9Av92hm6MKjWyixNCJ1wmjWrhFtuCGA==} peerDependencies: - '@tanstack/react-query': ^5.100.8 + '@tanstack/react-query': ^5.100.9 next: ^13 || ^14 || ^15 || ^16 react: ^18 || ^19 - '@tanstack/react-query@5.100.8': - resolution: {integrity: sha512-iNNEekixXU5vtAGKKZX2lx3jTooG5yNY+kv0wSgEdEYG0Mj0JM5bcuQtC35ZAP3nDopT6jciUK3xeX65U7AnfA==} + '@tanstack/react-query@5.100.9': + resolution: {integrity: sha512-Oa44XkaI3kCNN6ME0KByU3xT3SEUNOMfZpHxL6+wFoTm+OeUFYHKdeYVe0aOXlRDm/f15sgLwEt2HDorIdW8+A==} peerDependencies: react: ^18 || ^19 @@ -13517,25 +13518,25 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/query-core@5.100.8': {} + '@tanstack/query-core@5.100.9': {} - '@tanstack/query-devtools@5.100.8': {} + '@tanstack/query-devtools@5.100.9': {} - '@tanstack/react-query-devtools@5.100.8(@tanstack/react-query@5.100.8(react@19.2.5))(react@19.2.5)': + '@tanstack/react-query-devtools@5.100.9(@tanstack/react-query@5.100.9(react@19.2.5))(react@19.2.5)': dependencies: - '@tanstack/query-devtools': 5.100.8 - '@tanstack/react-query': 5.100.8(react@19.2.5) + '@tanstack/query-devtools': 5.100.9 + '@tanstack/react-query': 5.100.9(react@19.2.5) react: 19.2.5 - '@tanstack/react-query-next-experimental@5.100.8(@tanstack/react-query@5.100.8(react@19.2.5))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react@19.2.5)': + '@tanstack/react-query-next-experimental@5.100.9(@tanstack/react-query@5.100.9(react@19.2.5))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react@19.2.5)': dependencies: - '@tanstack/react-query': 5.100.8(react@19.2.5) + '@tanstack/react-query': 5.100.9(react@19.2.5) next: 16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0) react: 19.2.5 - '@tanstack/react-query@5.100.8(react@19.2.5)': + '@tanstack/react-query@5.100.9(react@19.2.5)': dependencies: - '@tanstack/query-core': 5.100.8 + '@tanstack/query-core': 5.100.9 react: 19.2.5 '@tanstack/react-table@8.20.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': @@ -13808,7 +13809,7 @@ snapshots: '@trpc/server': 11.17.0(typescript@5.9.3) typescript: 5.9.3 - '@trpc/next@11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3)': + '@trpc/next@11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/react-query@11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(next@16.2.4(@babel/core@7.26.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3)': dependencies: '@trpc/client': 11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3) '@trpc/server': 11.17.0(typescript@5.9.3) @@ -13817,12 +13818,12 @@ snapshots: react-dom: 19.2.5(react@19.2.5) typescript: 5.9.3 optionalDependencies: - '@tanstack/react-query': 5.100.8(react@19.2.5) - '@trpc/react-query': 11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) + '@tanstack/react-query': 5.100.9(react@19.2.5) + '@trpc/react-query': 11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3) - '@trpc/react-query@11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3)': + '@trpc/react-query@11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3)': dependencies: - '@tanstack/react-query': 5.100.8(react@19.2.5) + '@tanstack/react-query': 5.100.9(react@19.2.5) '@trpc/client': 11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3) '@trpc/server': 11.17.0(typescript@5.9.3) react: 19.2.5 @@ -13832,9 +13833,9 @@ snapshots: dependencies: typescript: 5.9.3 - '@trpc/tanstack-react-query@11.17.0(@tanstack/react-query@5.100.8(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3)': + '@trpc/tanstack-react-query@11.17.0(@tanstack/react-query@5.100.9(react@19.2.5))(@trpc/client@11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.17.0(typescript@5.9.3))(react@19.2.5)(typescript@5.9.3)': dependencies: - '@tanstack/react-query': 5.100.8(react@19.2.5) + '@tanstack/react-query': 5.100.9(react@19.2.5) '@trpc/client': 11.17.0(@trpc/server@11.17.0(typescript@5.9.3))(typescript@5.9.3) '@trpc/server': 11.17.0(typescript@5.9.3) react: 19.2.5 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9d53deda1..d0a6b89ef 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -45,9 +45,9 @@ catalog: "@semantic-release/release-notes-generator": ^14.1.0 "@t3-oss/env-nextjs": ^0.13.11 "@tabler/icons-react": ^3.41.1 - "@tanstack/react-query": ^5.100.8 - "@tanstack/react-query-devtools": ^5.100.8 - "@tanstack/react-query-next-experimental": ^5.100.8 + "@tanstack/react-query": ^5.100.9 + "@tanstack/react-query-devtools": ^5.100.9 + "@tanstack/react-query-next-experimental": ^5.100.9 "@testcontainers/mysql": ^11.14.0 "@testcontainers/postgresql": ^11.14.0 "@testcontainers/redis": ^11.14.0 From 56af6bcaf00e980e4c7a40d8e912901cd1395f5a Mon Sep 17 00:00:00 2001 From: Ashton Batty <230635+ashtonbatty@users.noreply.github.com> Date: Sat, 9 May 2026 01:31:56 +1000 Subject: [PATCH 08/11] feat(docker): Podman compatibility, multi-socket support, per-host error isolation (#5425) Co-authored-by: Meier Lukas --- .env.example | 6 + .../manage/tools/docker/docker-table.tsx | 12 ++ .../api/src/router/docker/docker-router.ts | 1 + packages/docker/src/env.ts | 4 +- packages/docker/src/singleton.ts | 52 +++++--- packages/docker/src/test/singleton.spec.ts | 110 ++++++++++++++++ packages/request-handler/src/docker.ts | 44 +++++-- .../request-handler/src/test/docker.spec.ts | 121 ++++++++++++++++++ packages/translation/src/lang/en.json | 3 + packages/widgets/src/docker/component.tsx | 13 ++ turbo.json | 1 + 11 files changed, 334 insertions(+), 33 deletions(-) create mode 100644 packages/docker/src/test/singleton.spec.ts create mode 100644 packages/request-handler/src/test/docker.spec.ts diff --git a/.env.example b/.env.example index d643c1194..745d45954 100644 --- a/.env.example +++ b/.env.example @@ -45,6 +45,12 @@ DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE' TURBO_TELEMETRY_DISABLED=1 +# Comma-separated paths to Docker-compatible Unix sockets. +# Useful for connecting to multiple runtimes (Docker + Podman) simultaneously. +# When unset and no TCP hosts configured, defaults to /var/run/docker.sock. +# Example: DOCKER_SOCKET_PATHS=/var/run/docker.sock,/run/user/1000/podman/podman.sock +# DOCKER_SOCKET_PATHS= + # Enable kubernetes tool # ENABLE_KUBERNETES=true diff --git a/apps/nextjs/src/app/[locale]/manage/tools/docker/docker-table.tsx b/apps/nextjs/src/app/[locale]/manage/tools/docker/docker-table.tsx index 537c85e7c..de7e781a1 100644 --- a/apps/nextjs/src/app/[locale]/manage/tools/docker/docker-table.tsx +++ b/apps/nextjs/src/app/[locale]/manage/tools/docker/docker-table.tsx @@ -58,6 +58,18 @@ const createColumns = ( return ; }, }, + { + accessorKey: "host", + header: t("docker.field.host.label"), + size: 140, + Cell({ row }) { + return ( + + {row.original.host} + + ); + }, + }, { accessorKey: "image", header: t("docker.field.containerImage.label"), diff --git a/packages/api/src/router/docker/docker-router.ts b/packages/api/src/router/docker/docker-router.ts index e5a4b4796..4527482f0 100644 --- a/packages/api/src/router/docker/docker-router.ts +++ b/packages/api/src/router/docker/docker-router.ts @@ -138,6 +138,7 @@ const getContainerOrThrowAsync = async (id: string) => { interface DockerContainer { name: string; id: string; + host: string; state: ContainerState; image: string; ports: Port[] | undefined; diff --git a/packages/docker/src/env.ts b/packages/docker/src/env.ts index e858d3e69..003a9bfa6 100644 --- a/packages/docker/src/env.ts +++ b/packages/docker/src/env.ts @@ -4,9 +4,11 @@ import { createBooleanSchema, createEnv } from "@homarr/core/infrastructure/env" export const env = createEnv({ server: { - // Comma separated list of docker hostnames that can be used to connect to query the docker endpoints (localhost:2375,host.docker.internal:2375, ...) + // Comma separated list of docker hostnames that can be used to connect to query the docker endpoints (localhost,host.docker.internal, ...) DOCKER_HOSTNAMES: z.string().optional(), DOCKER_PORTS: z.string().optional(), + // Comma separated paths to Docker-compatible Unix sockets (e.g., /var/run/docker.sock,/run/user/1000/podman/podman.sock) + DOCKER_SOCKET_PATHS: z.string().optional(), ENABLE_DOCKER: createBooleanSchema(true), ENABLE_KUBERNETES: createBooleanSchema(false), }, diff --git a/packages/docker/src/singleton.ts b/packages/docker/src/singleton.ts index 86ce9661e..f24e8eb9c 100644 --- a/packages/docker/src/singleton.ts +++ b/packages/docker/src/singleton.ts @@ -11,31 +11,43 @@ export class DockerSingleton { private static instances: DockerInstance[] | null = null; private createInstances() { + const socketPaths = env.DOCKER_SOCKET_PATHS; const hostVariable = env.DOCKER_HOSTNAMES; const portVariable = env.DOCKER_PORTS; - if (hostVariable === undefined || portVariable === undefined) { + + // Socket instances from DOCKER_SOCKET_PATHS + const socketInstances: DockerInstance[] = socketPaths + ? socketPaths.split(",").map((socketPath) => ({ + host: socketPath, + instance: new Docker({ socketPath }), + })) + : []; + + // TCP instances from existing DOCKER_HOSTNAMES/DOCKER_PORTS + let tcpInstances: DockerInstance[] = []; + if (hostVariable !== undefined && portVariable !== undefined) { + const hostnames = hostVariable.split(","); + const ports = portVariable.split(","); + + if (hostnames.length !== ports.length) { + throw new Error("The number of hosts and ports must match"); + } + + tcpInstances = hostnames.map((host, i) => ({ + host: `${host}:${ports[i]}`, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + instance: new Docker({ host, port: parseInt(ports[i]!, 10) }), + })); + } + + const instances = [...socketInstances, ...tcpInstances]; + + // Default: local socket if nothing else configured + if (instances.length === 0) { return [{ host: "socket", instance: new Docker() }]; } - const hostnames = hostVariable.split(","); - const ports = portVariable.split(","); - if (hostnames.length !== ports.length) { - throw new Error("The number of hosts and ports must match"); - } - - return hostnames.map((host, i) => { - // Check above ensures that ports[i] is not undefined - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const port = ports[i]!; - - return { - host: `${host}:${port}`, - instance: new Docker({ - host, - port: parseInt(port, 10), - }), - }; - }); + return instances; } public static findInstance(host: string): DockerInstance | undefined { diff --git a/packages/docker/src/test/singleton.spec.ts b/packages/docker/src/test/singleton.spec.ts new file mode 100644 index 000000000..53af453af --- /dev/null +++ b/packages/docker/src/test/singleton.spec.ts @@ -0,0 +1,110 @@ +import { beforeEach, describe, expect, test, vi } from "vitest"; + +import { DockerSingleton } from "../singleton"; + +const mockEnv = vi.hoisted(() => ({ + DOCKER_SOCKET_PATHS: undefined as string | undefined, + DOCKER_HOSTNAMES: undefined as string | undefined, + DOCKER_PORTS: undefined as string | undefined, + ENABLE_DOCKER: true, + ENABLE_KUBERNETES: false, +})); + +vi.mock("dockerode", () => { + return { + default: class MockDocker { + constructor(public opts?: Record) {} + }, + }; +}); + +vi.mock("../env", () => ({ + env: mockEnv, +})); + +describe("DockerSingleton", () => { + beforeEach(() => { + // Reset singleton cache between tests + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access + (DockerSingleton as any).instances = null; + + // Reset env to defaults + mockEnv.DOCKER_SOCKET_PATHS = undefined; + mockEnv.DOCKER_HOSTNAMES = undefined; + mockEnv.DOCKER_PORTS = undefined; + }); + + test("should return default socket when no env vars set", () => { + const instances = DockerSingleton.getInstances(); + + expect(instances).toHaveLength(1); + expect(instances[0]?.host).toBe("socket"); + }); + + test("should return TCP instances only when DOCKER_HOSTNAMES and DOCKER_PORTS set", () => { + mockEnv.DOCKER_HOSTNAMES = "remote-host"; + mockEnv.DOCKER_PORTS = "2375"; + + const instances = DockerSingleton.getInstances(); + + expect(instances).toHaveLength(1); + expect(instances[0]?.host).toBe("remote-host:2375"); + }); + + test("should return multiple TCP instances", () => { + mockEnv.DOCKER_HOSTNAMES = "host1,host2"; + mockEnv.DOCKER_PORTS = "2375,2376"; + + const instances = DockerSingleton.getInstances(); + + expect(instances).toHaveLength(2); + expect(instances[0]?.host).toBe("host1:2375"); + expect(instances[1]?.host).toBe("host2:2376"); + }); + + test("should throw when hostname and port counts do not match", () => { + mockEnv.DOCKER_HOSTNAMES = "host1,host2"; + mockEnv.DOCKER_PORTS = "2375"; + + expect(() => DockerSingleton.getInstances()).toThrow("The number of hosts and ports must match"); + }); + + test("should return socket instances when DOCKER_SOCKET_PATHS set", () => { + mockEnv.DOCKER_SOCKET_PATHS = "/var/run/docker.sock"; + + const instances = DockerSingleton.getInstances(); + + expect(instances).toHaveLength(1); + expect(instances[0]?.host).toBe("/var/run/docker.sock"); + }); + + test("should return multiple socket instances", () => { + mockEnv.DOCKER_SOCKET_PATHS = "/var/run/docker.sock,/run/user/1000/podman/podman.sock"; + + const instances = DockerSingleton.getInstances(); + + expect(instances).toHaveLength(2); + expect(instances[0]?.host).toBe("/var/run/docker.sock"); + expect(instances[1]?.host).toBe("/run/user/1000/podman/podman.sock"); + }); + + test("should combine socket and TCP instances", () => { + mockEnv.DOCKER_SOCKET_PATHS = "/var/run/docker.sock,/run/user/1000/podman/podman.sock"; + mockEnv.DOCKER_HOSTNAMES = "remote-host"; + mockEnv.DOCKER_PORTS = "2375"; + + const instances = DockerSingleton.getInstances(); + + expect(instances).toHaveLength(3); + expect(instances[0]?.host).toBe("/var/run/docker.sock"); + expect(instances[1]?.host).toBe("/run/user/1000/podman/podman.sock"); + expect(instances[2]?.host).toBe("remote-host:2375"); + }); + + test("should cache instances on subsequent calls", () => { + const first = DockerSingleton.getInstances(); + const second = DockerSingleton.getInstances(); + + expect(first).toBe(second); + }); +}); diff --git a/packages/request-handler/src/docker.ts b/packages/request-handler/src/docker.ts index 7b873ec00..6610aba7e 100644 --- a/packages/request-handler/src/docker.ts +++ b/packages/request-handler/src/docker.ts @@ -2,6 +2,8 @@ import dayjs from "dayjs"; import type { ContainerInfo, ContainerStats } from "dockerode"; import type Dockerode from "dockerode"; +import { createLogger } from "@homarr/core/infrastructure/logs"; +import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error"; import { db, like, or } from "@homarr/db"; import { icons } from "@homarr/db/schema"; import type { ContainerState } from "@homarr/docker"; @@ -9,6 +11,8 @@ import { dockerLabels, DockerSingleton } from "@homarr/docker"; import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler"; +const logger = createLogger({ module: "dockerRequestHandler" }); + export const dockerContainersRequestHandler = createCachedWidgetRequestHandler({ queryKey: "dockerContainersResult", widgetKind: "dockerContainers", @@ -18,19 +22,34 @@ export const dockerContainersRequestHandler = createCachedWidgetRequestHandler({ cacheDuration: dayjs.duration(20, "seconds"), }); -const dockerInstances = DockerSingleton.getInstances(); - const extractImage = (container: ContainerInfo) => container.Image.split("/").at(-1)?.split(":").at(0) ?? ""; async function getContainersWithStatsAsync() { - const containers = await Promise.all( + const dockerInstances = DockerSingleton.getInstances(); + const results = await Promise.allSettled( dockerInstances.map(async ({ instance, host }) => { const instanceContainers = await instance.listContainers({ all: true }); return instanceContainers .filter((container) => !(dockerLabels.hide in container.Labels)) .map((container) => ({ ...container, instance: host })); }), - ).then((res) => res.flat()); + ); + + const containers = results.flatMap((result, index) => { + if (result.status === "fulfilled") return result.value; + logger.warn( + new ErrorWithMetadata( + "Failed to list containers from Docker host", + { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + host: dockerInstances[index]!.host, + }, + { cause: result.reason }, + ), + ); + + return []; + }); const likeQueries = containers.map((container) => like(icons.name, `%${extractImage(container)}%`)); const dbIcons = @@ -44,8 +63,6 @@ async function getContainersWithStatsAsync() { const instance = dockerInstances.find(({ host }) => host === container.instance)?.instance; if (!instance) return null; - // Get stats, falling back to an empty stats object if fetch fails - // calculateCpuUsage and calculateMemoryUsage will return 0 for invalid/missing stats const stats = await instance .getContainer(container.Id) .stats({ stream: false, "one-shot": true }) @@ -63,6 +80,7 @@ async function getContainersWithStatsAsync() { return { id: container.Id, name: container.Names[0]?.split("/")[1] ?? "Unknown", + host: container.instance, state: container.State as ContainerState, iconUrl: dbIcons.find((icon) => { @@ -80,9 +98,10 @@ async function getContainersWithStatsAsync() { return (await Promise.all(containerStatsPromises)).filter((container) => container !== null); } -function calculateCpuUsage(stats: ContainerStats): number { - // Handle containers with missing or invalid stats (e.g., exited, dead containers) - if (!stats.cpu_stats.online_cpus || stats.cpu_stats.online_cpus === 0 || !stats.cpu_stats.cpu_usage.total_usage) { +export function calculateCpuUsage(stats: ContainerStats): number { + // Handle containers with missing or invalid stats (e.g., exited, dead containers, Podman responses) + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (!stats.cpu_stats?.online_cpus || stats.cpu_stats.online_cpus === 0 || !stats.cpu_stats.cpu_usage?.total_usage) { return 0; } @@ -95,9 +114,10 @@ function calculateCpuUsage(stats: ContainerStats): number { return (stats.cpu_stats.cpu_usage.total_usage / usage) * numberOfCpus * 100; } -function calculateMemoryUsage(stats: ContainerStats): number { - // Handle containers with missing or invalid stats (e.g., exited, dead containers) - if (!stats.memory_stats.usage) { +export function calculateMemoryUsage(stats: ContainerStats): number { + // Handle containers with missing or invalid stats (e.g., exited, dead containers, Podman responses) + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (!stats.memory_stats?.usage) { return 0; } diff --git a/packages/request-handler/src/test/docker.spec.ts b/packages/request-handler/src/test/docker.spec.ts new file mode 100644 index 000000000..b4e34f816 --- /dev/null +++ b/packages/request-handler/src/test/docker.spec.ts @@ -0,0 +1,121 @@ +import type { ContainerStats } from "dockerode"; +import { describe, expect, test, vi } from "vitest"; + +import { createDb } from "@homarr/db/test"; + +import { calculateCpuUsage, calculateMemoryUsage } from "../docker"; + +vi.mock("@homarr/db", async (importActual) => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const actual = await importActual(); + return { + ...actual, + db: createDb(), + }; +}); + +// Helper to create a partial stats object, cast to ContainerStats. +// This mirrors what Podman and other Docker-compatible runtimes may return +// at runtime, even though @types/dockerode declares all fields as required. +const createStats = (overrides: Record = {}) => overrides as unknown as ContainerStats; + +describe("calculateCpuUsage", () => { + test("should return 0 when cpu_stats is undefined (Podman)", () => { + const stats = createStats({ cpu_stats: undefined }); + expect(calculateCpuUsage(stats)).toBe(0); + }); + + test("should return 0 when online_cpus is 0", () => { + const stats = createStats({ + cpu_stats: { online_cpus: 0, cpu_usage: { total_usage: 1000 }, system_cpu_usage: 5000 }, + }); + expect(calculateCpuUsage(stats)).toBe(0); + }); + + test("should return 0 when online_cpus is undefined", () => { + const stats = createStats({ + cpu_stats: { cpu_usage: { total_usage: 1000 }, system_cpu_usage: 5000 }, + }); + expect(calculateCpuUsage(stats)).toBe(0); + }); + + test("should return 0 when cpu_usage is undefined", () => { + const stats = createStats({ + cpu_stats: { online_cpus: 4, system_cpu_usage: 5000 }, + }); + expect(calculateCpuUsage(stats)).toBe(0); + }); + + test("should return 0 when total_usage is 0", () => { + const stats = createStats({ + cpu_stats: { online_cpus: 4, cpu_usage: { total_usage: 0 }, system_cpu_usage: 5000 }, + }); + expect(calculateCpuUsage(stats)).toBe(0); + }); + + test("should return 0 when system_cpu_usage is 0", () => { + const stats = createStats({ + cpu_stats: { online_cpus: 4, cpu_usage: { total_usage: 1000 }, system_cpu_usage: 0 }, + }); + expect(calculateCpuUsage(stats)).toBe(0); + }); + + test("should calculate correct CPU percentage for valid stats", () => { + const stats = createStats({ + cpu_stats: { online_cpus: 4, cpu_usage: { total_usage: 2000 }, system_cpu_usage: 10000 }, + }); + // (2000 / 10000) * 4 * 100 = 80 + expect(calculateCpuUsage(stats)).toBe(80); + }); + + test("should handle fractional CPU usage", () => { + const stats = createStats({ + cpu_stats: { online_cpus: 2, cpu_usage: { total_usage: 500 }, system_cpu_usage: 100000 }, + }); + // (500 / 100000) * 2 * 100 = 1 + expect(calculateCpuUsage(stats)).toBe(1); + }); +}); + +describe("calculateMemoryUsage", () => { + test("should return 0 when memory_stats is undefined (Podman)", () => { + const stats = createStats({ memory_stats: undefined }); + expect(calculateMemoryUsage(stats)).toBe(0); + }); + + test("should return 0 when memory_stats.usage is 0", () => { + const stats = createStats({ memory_stats: { usage: 0 } }); + expect(calculateMemoryUsage(stats)).toBe(0); + }); + + test("should return 0 when memory_stats.usage is undefined", () => { + const stats = createStats({ memory_stats: {} }); + expect(calculateMemoryUsage(stats)).toBe(0); + }); + + test("should subtract cache from usage", () => { + const stats = createStats({ + memory_stats: { usage: 1000, stats: { cache: 200 } }, + }); + expect(calculateMemoryUsage(stats)).toBe(800); + }); + + test("should use total_inactive_file when cache is absent", () => { + const stats = createStats({ + memory_stats: { usage: 1000, stats: { total_inactive_file: 300 } }, + }); + expect(calculateMemoryUsage(stats)).toBe(700); + }); + + test("should use inactive_file as last fallback", () => { + const stats = createStats({ + memory_stats: { usage: 1000, stats: { inactive_file: 150 } }, + }); + expect(calculateMemoryUsage(stats)).toBe(850); + }); + + test("should return raw usage when memory_stats.stats is undefined", () => { + const stats = createStats({ memory_stats: { usage: 512 } }); + expect(calculateMemoryUsage(stats)).toBe(512); + }); +}); diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json index 981839c3b..29e86458e 100644 --- a/packages/translation/src/lang/en.json +++ b/packages/translation/src/lang/en.json @@ -3970,6 +3970,9 @@ }, "ports": { "label": "Ports" + }, + "host": { + "label": "Host" } }, "action": { diff --git a/packages/widgets/src/docker/component.tsx b/packages/widgets/src/docker/component.tsx index 869b76f0b..c135484a8 100644 --- a/packages/widgets/src/docker/component.tsx +++ b/packages/widgets/src/docker/component.tsx @@ -79,6 +79,19 @@ const createColumns = ( return ; }, }, + { + id: "host", + accessorKey: "host", + size: 100, + header: t("field.host.label"), + Cell({ row }) { + return ( + + {row.original.host} + + ); + }, + }, { id: "cpuUsage", sortingFn: (rowA, rowB) => { diff --git a/turbo.json b/turbo.json index 208d42365..33b661f69 100644 --- a/turbo.json +++ b/turbo.json @@ -37,6 +37,7 @@ "DB_DRIVER", "DOCKER_HOSTNAMES", "DOCKER_PORTS", + "DOCKER_SOCKET_PATHS", "NODE_ENV", "PORT", "LOCAL_CERTIFICATE_PATH", From 7c64de5cbc7e491d1247b381368354dfead7c452 Mon Sep 17 00:00:00 2001 From: "homarr-renovate[bot]" <158783068+homarr-renovate[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 17:25:39 +0000 Subject: [PATCH 09/11] chore(deps): update turbo monorepo to ^2.9.8 (#5669) Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com> --- pnpm-lock.yaml | 6 +++--- pnpm-workspace.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2de02eff3..73fea2a52 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -214,7 +214,7 @@ catalogs: specifier: ^11.17.0 version: 11.17.0 '@turbo/gen': - specifier: ^2.9.7 + specifier: ^2.9.8 version: 2.9.8 '@types/adm-zip': specifier: 0.5.8 @@ -367,7 +367,7 @@ catalogs: specifier: ^10.1.8 version: 10.1.8 eslint-config-turbo: - specifier: ^2.9.7 + specifier: ^2.9.8 version: 2.9.8 eslint-plugin-import: specifier: ^2.32.0 @@ -517,7 +517,7 @@ catalogs: specifier: 4.20.4 version: 4.20.4 turbo: - specifier: ^2.9.7 + specifier: ^2.9.8 version: 2.9.8 typescript: specifier: ^5.9.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d0a6b89ef..ef2f695b5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -72,7 +72,7 @@ catalog: "@trpc/react-query": ^11.17.0 "@trpc/server": ^11.17.0 "@trpc/tanstack-react-query": ^11.17.0 - "@turbo/gen": ^2.9.7 + "@turbo/gen": ^2.9.8 "@types/adm-zip": 0.5.8 "@types/bcrypt": 6.0.0 "@types/better-sqlite3": 7.6.13 @@ -123,7 +123,7 @@ catalog: esbuild: ^0.28.0 eslint: ^10.3.0 eslint-config-prettier: ^10.1.8 - eslint-config-turbo: ^2.9.7 + eslint-config-turbo: ^2.9.8 eslint-plugin-import: ^2.32.0 eslint-plugin-jsx-a11y: ^6.10.2 eslint-plugin-react: ^7.37.5 @@ -173,7 +173,7 @@ catalog: trpc-to-openapi: ^3.2.0 tsdav: ^2.2.0 tsx: 4.20.4 - turbo: ^2.9.7 + turbo: ^2.9.8 typescript: ^5.9.3 typescript-eslint: ^8.58.2 undici: 7.24.6 From 756e8d172455f91e40cd8fb5faff6953cc9778c5 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Fri, 8 May 2026 20:08:37 +0200 Subject: [PATCH 10/11] feat(qbittorrent): add api-key support (#5677) --- packages/definitions/src/integration.ts | 2 +- .../qbittorrent/qbittorrent-integration.ts | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/definitions/src/integration.ts b/packages/definitions/src/integration.ts index 81c58b0af..dfc862fbb 100644 --- a/packages/definitions/src/integration.ts +++ b/packages/definitions/src/integration.ts @@ -61,7 +61,7 @@ export const integrationDefs = { }, qBittorrent: { name: "qBittorrent", - secretKinds: [["username", "password"]], + secretKinds: [["apiKey"], ["username", "password"]], iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/qbittorrent.svg", category: ["downloadClient", "torrent"], documentationUrl: createDocumentationLink("/docs/integrations/q-bittorent"), diff --git a/packages/integrations/src/download-client/qbittorrent/qbittorrent-integration.ts b/packages/integrations/src/download-client/qbittorrent/qbittorrent-integration.ts index 1076bca5e..a142fb1a3 100644 --- a/packages/integrations/src/download-client/qbittorrent/qbittorrent-integration.ts +++ b/packages/integrations/src/download-client/qbittorrent/qbittorrent-integration.ts @@ -90,10 +90,18 @@ export class QBitTorrentIntegration extends Integration implements IDownloadClie } private async getClientAsync(dispatcher?: Dispatcher) { + const credentials = this.hasSecretValue("apiKey") + ? { + apiKey: this.getSecretValue("apiKey"), + } + : { + username: this.getSecretValue("username"), + password: this.getSecretValue("password"), + }; + return new QBittorrent({ + ...credentials, baseUrl: this.url("/").toString(), - username: this.getSecretValue("username"), - password: this.getSecretValue("password"), dispatcher: dispatcher ?? (await createCertificateAgentAsync()), }); } From b581f9b11a6c7f7f48c5a3b122f364f5e27fcdec Mon Sep 17 00:00:00 2001 From: "homarr-renovate[bot]" <158783068+homarr-renovate[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 19:26:12 +0000 Subject: [PATCH 11/11] chore(deps): update dependency @extractus/feed-extractor to v7.2.1 (#5670) Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com> --- pnpm-lock.yaml | 37 +++++++++++++------------------------ pnpm-workspace.yaml | 2 +- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73fea2a52..20ad25153 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ catalogs: specifier: 10.0.1 version: 10.0.1 '@extractus/feed-extractor': - specifier: 7.1.7 - version: 7.1.7 + specifier: 7.2.1 + version: 7.2.1 '@gitbeaker/rest': specifier: ^43.8.0 version: 43.8.0 @@ -2387,7 +2387,7 @@ importers: dependencies: '@extractus/feed-extractor': specifier: 'catalog:' - version: 7.1.7 + version: 7.2.1 '@homarr/common': specifier: workspace:^0.1.0 version: link:../common @@ -3801,8 +3801,8 @@ packages: '@noble/hashes': optional: true - '@extractus/feed-extractor@7.1.7': - resolution: {integrity: sha512-eNeddvKK9rBxWSHj5zBo6ODihJqJtq+QzEQdVeadkOK48avmdela+c2JAfMcPEBMFaWcAYV4bUMhI9Tqi8mX2Q==} + '@extractus/feed-extractor@7.2.1': + resolution: {integrity: sha512-vc84NZST31wLDTesAkmHL8GBxSB2zw2/h9ZKiQMB71az13sC65EeAcDeLJ2z3atsIhtxESnCMaKmQdOrFiFLcg==} engines: {node: '>= 20'} '@fastify/ajv-compiler@4.0.5': @@ -4388,9 +4388,6 @@ packages: deprecated: This package is no longer maintained hasBin: true - '@ndaidong/bellajs@12.0.1': - resolution: {integrity: sha512-1iY42uiHz0cxNMbde7O3zVN+ZX1viOOUOBRt6ht6lkRZbSjwOnFV34Zv4URp3hGzEe6L9Byk7BOq/41H0PzAOQ==} - '@next/env@16.2.4': resolution: {integrity: sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw==} @@ -4721,6 +4718,10 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@pwshub/bellajs@13.0.2': + resolution: {integrity: sha512-OWOaE7Ieufo7VMv957iahOzv/w5oXyyXO28Jh2x6rLU96ZLqC508kAKTgdMJRXgVjda2s+/0C6Kno+k16OmJsQ==} + engines: {bun: '>=1.0.0', node: '>=20.0.0'} + '@reduxjs/toolkit@2.11.2': resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} peerDependencies: @@ -6661,9 +6662,6 @@ packages: engines: {node: '>=20'} hasBin: true - cross-fetch@4.1.0: - resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -11848,14 +11846,11 @@ snapshots: optionalDependencies: '@noble/hashes': 2.0.1 - '@extractus/feed-extractor@7.1.7': + '@extractus/feed-extractor@7.2.1': dependencies: - '@ndaidong/bellajs': 12.0.1 - cross-fetch: 4.1.0 + '@pwshub/bellajs': 13.0.2 fast-xml-parser: 5.7.2 html-entities: 2.6.0 - transitivePeerDependencies: - - encoding '@fastify/ajv-compiler@4.0.5': dependencies: @@ -12474,8 +12469,6 @@ snapshots: - utf-8-validate - webpack-sources - '@ndaidong/bellajs@12.0.1': {} - '@next/env@16.2.4': {} '@next/eslint-plugin-next@16.2.4': @@ -12780,6 +12773,8 @@ snapshots: '@protobufjs/utf8@1.1.0': {} + '@pwshub/bellajs@13.0.2': {} + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1))(react@19.2.5)': dependencies: '@standard-schema/spec': 1.1.0 @@ -15109,12 +15104,6 @@ snapshots: '@epic-web/invariant': 1.0.0 cross-spawn: 7.0.6 - cross-fetch@4.1.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ef2f695b5..b42e515a5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -14,7 +14,7 @@ catalog: "@dnd-kit/utilities": ^3.2.2 "@drizzle-team/brocli": ^0.12.0 '@eslint/js': 10.0.1 - "@extractus/feed-extractor": 7.1.7 + "@extractus/feed-extractor": 7.2.1 "@gitbeaker/rest": ^43.8.0 "@homarr/gridstack": ^1.12.0 "@homarr/node-unifi": ^2.6.0