From 2394159f8b546e8b6e2d3cdc7c6bd0f75483209c Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Fri, 18 Jul 2025 20:23:21 +0000
Subject: [PATCH 01/13] fix(deps): update testcontainers-node monorepo to
^11.3.0 (#3652)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
package.json | 2 +-
packages/db/package.json | 2 +-
pnpm-lock.yaml | 23 ++++++++++++-----------
3 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/package.json b/package.json
index 05013280c..0ccdec702 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
"jsdom": "^26.1.0",
"prettier": "^3.6.2",
"semantic-release": "^24.2.7",
- "testcontainers": "^11.2.1",
+ "testcontainers": "^11.3.0",
"turbo": "^2.5.5",
"typescript": "^5.8.3",
"vite-tsconfig-paths": "^5.1.4",
diff --git a/packages/db/package.json b/packages/db/package.json
index 0c2dd493b..fe2e1814b 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -46,7 +46,7 @@
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.1.3",
"@paralleldrive/cuid2": "^2.2.2",
- "@testcontainers/mysql": "^11.2.1",
+ "@testcontainers/mysql": "^11.3.0",
"better-sqlite3": "^12.2.0",
"dotenv": "^17.2.0",
"drizzle-kit": "^0.31.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 08e6419b3..d4c5e6932 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -65,8 +65,8 @@ importers:
specifier: ^24.2.7
version: 24.2.7(typescript@5.8.3)
testcontainers:
- specifier: ^11.2.1
- version: 11.2.1
+ specifier: ^11.3.0
+ version: 11.3.0
turbo:
specifier: ^2.5.5
version: 2.5.5
@@ -1072,8 +1072,8 @@ importers:
specifier: ^2.2.2
version: 2.2.2
'@testcontainers/mysql':
- specifier: ^11.2.1
- version: 11.2.1
+ specifier: ^11.3.0
+ version: 11.3.0
better-sqlite3:
specifier: ^12.2.0
version: 12.2.0
@@ -4377,8 +4377,8 @@ packages:
'@tanstack/virtual-core@3.11.2':
resolution: {integrity: sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==}
- '@testcontainers/mysql@11.2.1':
- resolution: {integrity: sha512-grOpOcFvDBuwSGVgtIT1lOb/RcVGVfuoxsnngO/TeepZ5XXS50Wjj/HmdxG88XXAKEjVv2I9A/6T02nAV8JyLw==}
+ '@testcontainers/mysql@11.3.0':
+ resolution: {integrity: sha512-5zOzAcsQUVbN9tCC6cbD0zkxOu/P8NdFsYc+w1YFctGUOf5DL0QBBwDv5LkFj92+eic4veggPlzVd2SX8LT3SQ==}
'@tiptap/core@2.26.1':
resolution: {integrity: sha512-fymyd/XZvYiHjBoLt1gxs024xP/LY26d43R1vluYq7AHBL/7DE3ywzy+1GEsGyAv5Je2L0KBhNIR/izbq3Kaqg==}
@@ -6494,6 +6494,7 @@ packages:
eslint-config-prettier@10.1.7:
resolution: {integrity: sha512-xztdELuHs7grBM+qdMUF4M4SjPpeOMN3kx7sGU6ifl5yibck/GRa0+0d+m1lPsGNkd+2bIWh2lUUTzX7MX/obw==}
+ deprecated: This is a malicious version, don't use
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
@@ -9987,8 +9988,8 @@ packages:
resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
engines: {node: '>=18'}
- testcontainers@11.2.1:
- resolution: {integrity: sha512-KJALGi8ButKDZgzHr0PtJUVNBOSlSFncumZ34MCQTN4VEU9AK4tWTn9gCcAFzG4zBmzzC2aEbHMFUujqkbDvBg==}
+ testcontainers@11.3.0:
+ resolution: {integrity: sha512-bfSfWDZl5Ima/wRkDjoyuntLIp7wFv7jc+97/BL1zJyKszMFEDHsDcH1ryv8L4kYqVfl6V0efMzY4tluypa1nw==}
text-decoder@1.2.0:
resolution: {integrity: sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==}
@@ -13117,9 +13118,9 @@ snapshots:
'@tanstack/virtual-core@3.11.2': {}
- '@testcontainers/mysql@11.2.1':
+ '@testcontainers/mysql@11.3.0':
dependencies:
- testcontainers: 11.2.1
+ testcontainers: 11.3.0
transitivePeerDependencies:
- bare-buffer
- supports-color
@@ -19701,7 +19702,7 @@ snapshots:
glob: 10.4.5
minimatch: 9.0.5
- testcontainers@11.2.1:
+ testcontainers@11.3.0:
dependencies:
'@balena/dockerignore': 1.0.2
'@types/dockerode': 3.3.42
From 42301b4a1ed9e9f638b449a460862db9cd7ed50b Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Fri, 18 Jul 2025 21:22:56 +0000
Subject: [PATCH 02/13] fix(deps): update nextjs monorepo to v15.4.2 (#3654)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
apps/nextjs/package.json | 2 +-
packages/api/package.json | 2 +-
packages/auth/package.json | 2 +-
packages/common/package.json | 2 +-
packages/modals-collection/package.json | 2 +-
packages/old-import/package.json | 2 +-
packages/settings/package.json | 2 +-
packages/spotlight/package.json | 2 +-
packages/translation/package.json | 2 +-
packages/ui/package.json | 2 +-
packages/widgets/package.json | 2 +-
pnpm-lock.yaml | 185 ++++++++++++------------
tooling/eslint/package.json | 2 +-
13 files changed, 104 insertions(+), 105 deletions(-)
diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json
index 26b998837..895379e9c 100644
--- a/apps/nextjs/package.json
+++ b/apps/nextjs/package.json
@@ -75,7 +75,7 @@
"glob": "^11.0.3",
"jotai": "^2.12.5",
"mantine-react-table": "2.0.0-beta.9",
- "next": "15.4.1",
+ "next": "15.4.2",
"postcss-preset-mantine": "^1.18.0",
"prismjs": "^1.30.0",
"react": "19.1.0",
diff --git a/packages/api/package.json b/packages/api/package.json
index 3a3d5fd75..c7f7c4f00 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -46,7 +46,7 @@
"@trpc/server": "^11.4.3",
"@trpc/tanstack-react-query": "^11.4.3",
"lodash.clonedeep": "^4.5.0",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"superjson": "2.2.2",
diff --git a/packages/auth/package.json b/packages/auth/package.json
index e99b57c3d..0f114538e 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -35,7 +35,7 @@
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.0.6",
- "next": "15.4.1",
+ "next": "15.4.2",
"next-auth": "5.0.0-beta.29",
"react": "19.1.0",
"react-dom": "19.1.0",
diff --git a/packages/common/package.json b/packages/common/package.json
index c3f7c0551..caa0362ba 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -31,7 +31,7 @@
"@homarr/log": "workspace:^0.1.0",
"@paralleldrive/cuid2": "^2.2.2",
"dayjs": "^1.11.13",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"undici": "7.12.0",
diff --git a/packages/modals-collection/package.json b/packages/modals-collection/package.json
index 7aa2f8f7a..14c527cf8 100644
--- a/packages/modals-collection/package.json
+++ b/packages/modals-collection/package.json
@@ -36,7 +36,7 @@
"@mantine/core": "^8.1.3",
"@tabler/icons-react": "^3.34.0",
"dayjs": "^1.11.13",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"zod": "^3.25.76"
diff --git a/packages/old-import/package.json b/packages/old-import/package.json
index a3e9e4af3..0d6c5db1c 100644
--- a/packages/old-import/package.json
+++ b/packages/old-import/package.json
@@ -40,7 +40,7 @@
"@mantine/core": "^8.1.3",
"@mantine/hooks": "^8.1.3",
"adm-zip": "0.5.16",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"superjson": "2.2.2",
diff --git a/packages/settings/package.json b/packages/settings/package.json
index 80f761233..bb6bd7d8c 100644
--- a/packages/settings/package.json
+++ b/packages/settings/package.json
@@ -27,7 +27,7 @@
"@homarr/db": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/dates": "^8.1.3",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0"
},
diff --git a/packages/spotlight/package.json b/packages/spotlight/package.json
index 9ccce4b4c..82c9e60b7 100644
--- a/packages/spotlight/package.json
+++ b/packages/spotlight/package.json
@@ -38,7 +38,7 @@
"@mantine/spotlight": "^8.1.3",
"@tabler/icons-react": "^3.34.0",
"jotai": "^2.12.5",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"use-deep-compare-effect": "^1.8.1"
diff --git a/packages/translation/package.json b/packages/translation/package.json
index c36730612..2baf1d489 100644
--- a/packages/translation/package.json
+++ b/packages/translation/package.json
@@ -32,7 +32,7 @@
"dayjs": "^1.11.13",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
- "next": "15.4.1",
+ "next": "15.4.2",
"next-intl": "4.3.4",
"react": "19.1.0",
"react-dom": "19.1.0"
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 72ade1ec0..3cec20442 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -35,7 +35,7 @@
"@mantine/hooks": "^8.1.3",
"@tabler/icons-react": "^3.34.0",
"mantine-react-table": "2.0.0-beta.9",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"svgson": "^5.3.1"
diff --git a/packages/widgets/package.json b/packages/widgets/package.json
index aa4779b7c..965e20883 100644
--- a/packages/widgets/package.json
+++ b/packages/widgets/package.json
@@ -71,7 +71,7 @@
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"mantine-react-table": "2.0.0-beta.9",
- "next": "15.4.1",
+ "next": "15.4.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-markdown": "^10.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d4c5e6932..771066265 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -216,13 +216,13 @@ importers:
version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0)
'@tanstack/react-query-next-experimental':
specifier: ^5.83.0
- version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(next@15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)
+ version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(next@15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)
'@trpc/client':
specifier: ^11.4.3
version: 11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3)
'@trpc/next':
specifier: ^11.4.3
- version: 11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/react-query@11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(next@15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)
+ version: 11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/react-query@11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(next@15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)
'@trpc/react-query':
specifier: ^11.4.3
version: 11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)
@@ -263,8 +263,8 @@ importers:
specifier: 2.0.0-beta.9
version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
postcss-preset-mantine:
specifier: ^1.18.0
version: 1.18.0(postcss@8.4.47)
@@ -606,8 +606,8 @@ importers:
specifier: ^4.5.0
version: 4.5.0
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -682,11 +682,11 @@ importers:
specifier: 8.0.6
version: 8.0.6
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
next-auth:
specifier: 5.0.0-beta.29
- version: 5.0.0-beta.29(next@15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)
+ version: 5.0.0-beta.29(next@15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)
react:
specifier: 19.1.0
version: 19.1.0
@@ -833,8 +833,8 @@ importers:
specifier: ^1.11.13
version: 1.11.13
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1529,8 +1529,8 @@ importers:
specifier: ^1.11.13
version: 1.11.13
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1630,8 +1630,8 @@ importers:
specifier: 0.5.16
version: 0.5.16
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1818,8 +1818,8 @@ importers:
specifier: ^8.1.3
version: 8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1891,8 +1891,8 @@ importers:
specifier: ^2.12.5
version: 2.12.5(@types/react@19.1.8)(react@19.1.0)
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1937,11 +1937,11 @@ importers:
specifier: 2.0.0-beta.9
version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
next-intl:
specifier: 4.3.4
- version: 4.3.4(next@15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)(typescript@5.8.3)
+ version: 4.3.4(next@15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)(typescript@5.8.3)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1998,8 +1998,8 @@ importers:
specifier: 2.0.0-beta.9
version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -2201,8 +2201,8 @@ importers:
specifier: 2.0.0-beta.9
version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
- specifier: 15.4.1
- version: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ specifier: 15.4.2
+ version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react:
specifier: 19.1.0
version: 19.1.0
@@ -2244,8 +2244,8 @@ importers:
tooling/eslint:
dependencies:
'@next/eslint-plugin-next':
- specifier: 15.4.1
- version: 15.4.1
+ specifier: 15.4.2
+ version: 15.4.2
eslint-config-prettier:
specifier: ^10.1.7
version: 10.1.7(eslint@9.31.0)
@@ -3682,56 +3682,56 @@ packages:
'@ndaidong/bellajs@12.0.1':
resolution: {integrity: sha512-1iY42uiHz0cxNMbde7O3zVN+ZX1viOOUOBRt6ht6lkRZbSjwOnFV34Zv4URp3hGzEe6L9Byk7BOq/41H0PzAOQ==}
- '@next/env@15.4.1':
- resolution: {integrity: sha512-DXQwFGAE2VH+f2TJsKepRXpODPU+scf5fDbKOME8MMyeyswe4XwgRdiiIYmBfkXU+2ssliLYznajTrOQdnLR5A==}
+ '@next/env@15.4.2':
+ resolution: {integrity: sha512-kd7MvW3pAP7tmk1NaiX4yG15xb2l4gNhteKQxt3f+NGR22qwPymn9RBuv26QKfIKmfo6z2NpgU8W2RT0s0jlvg==}
- '@next/eslint-plugin-next@15.4.1':
- resolution: {integrity: sha512-lQnHUxN7mMksK7IxgKDIXNMWFOBmksVrjamMEURXiYfo7zgsc30lnU8u4y/MJktSh+nB80ktTQeQbWdQO6c8Ow==}
+ '@next/eslint-plugin-next@15.4.2':
+ resolution: {integrity: sha512-k0rjdWjXBY6tAOty1ckrMETE6Mx66d85NsgcAIdDp7/cXOsTJ93ywmbg3uUcpxX5TUHFEcCWI5mb8nPhwCe9jg==}
- '@next/swc-darwin-arm64@15.4.1':
- resolution: {integrity: sha512-L+81yMsiHq82VRXS2RVq6OgDwjvA4kDksGU8hfiDHEXP+ncKIUhUsadAVB+MRIp2FErs/5hpXR0u2eluWPAhig==}
+ '@next/swc-darwin-arm64@15.4.2':
+ resolution: {integrity: sha512-ovqjR8NjCBdBf1U+R/Gvn0RazTtXS9n6wqs84iFaCS1NHbw9ksVE4dfmsYcLoyUVd9BWE0bjkphOWrrz8uz/uw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@15.4.1':
- resolution: {integrity: sha512-jfz1RXu6SzL14lFl05/MNkcN35lTLMJWPbqt7Xaj35+ZWAX342aePIJrN6xBdGeKl6jPXJm0Yqo3Xvh3Gpo3Uw==}
+ '@next/swc-darwin-x64@15.4.2':
+ resolution: {integrity: sha512-I8d4W7tPqbdbHRI4z1iBfaoJIBrEG4fnWKIe+Rj1vIucNZ5cEinfwkBt3RcDF00bFRZRDpvKuDjgMFD3OyRBnw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@15.4.1':
- resolution: {integrity: sha512-k0tOFn3dsnkaGfs6iQz8Ms6f1CyQe4GacXF979sL8PNQxjYS1swx9VsOyUQYaPoGV8nAZ7OX8cYaeiXGq9ahPQ==}
+ '@next/swc-linux-arm64-gnu@15.4.2':
+ resolution: {integrity: sha512-lvhz02dU3Ec5thzfQ2RCUeOFADjNkS/px1W7MBt7HMhf0/amMfT8Z/aXOwEA+cVWN7HSDRSUc8hHILoHmvajsg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@15.4.1':
- resolution: {integrity: sha512-4ogGQ/3qDzbbK3IwV88ltihHFbQVq6Qr+uEapzXHXBH1KsVBZOB50sn6BWHPcFjwSoMX2Tj9eH/fZvQnSIgc3g==}
+ '@next/swc-linux-arm64-musl@15.4.2':
+ resolution: {integrity: sha512-v+5PPfL8UP+KKHS3Mox7QMoeFdMlaV0zeNMIF7eLC4qTiVSO0RPNnK0nkBZSD5BEkkf//c+vI9s/iHxddCZchA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@15.4.1':
- resolution: {integrity: sha512-Jj0Rfw3wIgp+eahMz/tOGwlcYYEFjlBPKU7NqoOkTX0LY45i5W0WcDpgiDWSLrN8KFQq/LW7fZq46gxGCiOYlQ==}
+ '@next/swc-linux-x64-gnu@15.4.2':
+ resolution: {integrity: sha512-PHLYOC9W2cu6I/JEKo77+LW4uPNvyEQiSkVRUQPsOIsf01PRr8PtPhwtz3XNnC9At8CrzPkzqQ9/kYDg4R4Inw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@15.4.1':
- resolution: {integrity: sha512-9WlEZfnw1vFqkWsTMzZDgNL7AUI1aiBHi0S2m8jvycPyCq/fbZjtE/nDkhJRYbSjXbtRHYLDBlmP95kpjEmJbw==}
+ '@next/swc-linux-x64-musl@15.4.2':
+ resolution: {integrity: sha512-lpmUF9FfLFns4JbTu+5aJGA8aR9dXaA12eoNe9CJbVkGib0FDiPa4kBGTwy0xDxKNGlv3bLDViyx1U+qafmuJQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@15.4.1':
- resolution: {integrity: sha512-WodRbZ9g6CQLRZsG3gtrA9w7Qfa9BwDzhFVdlI6sV0OCPq9JrOrJSp9/ioLsezbV8w9RCJ8v55uzJuJ5RgWLZg==}
+ '@next/swc-win32-arm64-msvc@15.4.2':
+ resolution: {integrity: sha512-aMjogoGnRepas0LQ/PBPsvvUzj+IoXw2IoDSEShEtrsu2toBiaxEWzOQuPZ8nie8+1iF7TA63S7rlp3YWAjNEg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@15.4.1':
- resolution: {integrity: sha512-y+wTBxelk2xiNofmDOVU7O5WxTHcvOoL3srOM0kxTzKDjQ57kPU0tpnPJ/BWrRnsOwXEv0+3QSbGR7hY4n9LkQ==}
+ '@next/swc-win32-x64-msvc@15.4.2':
+ resolution: {integrity: sha512-FxwauyexSFu78wEqR/+NB9MnqXVj6SxJKwcVs2CRjeSX/jBagDCgtR2W36PZUYm0WPgY1pQ3C1+nn7zSnwROuw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -8256,8 +8256,8 @@ packages:
typescript:
optional: true
- next@15.4.1:
- resolution: {integrity: sha512-eNKB1q8C7o9zXF8+jgJs2CzSLIU3T6bQtX6DcTnCq1sIR1CJ0GlSyRs1BubQi3/JgCnr9Vr+rS5mOMI38FFyQw==}
+ next@15.4.2:
+ resolution: {integrity: sha512-oH1rmFso+84NIkocfuxaGKcXIjMUTmnzV2x0m8qsYtB4gD6iflLMESXt5XJ8cFgWMBei4v88rNr/j+peNg72XA==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
hasBin: true
peerDependencies:
@@ -12204,34 +12204,34 @@ snapshots:
'@ndaidong/bellajs@12.0.1': {}
- '@next/env@15.4.1': {}
+ '@next/env@15.4.2': {}
- '@next/eslint-plugin-next@15.4.1':
+ '@next/eslint-plugin-next@15.4.2':
dependencies:
fast-glob: 3.3.1
- '@next/swc-darwin-arm64@15.4.1':
+ '@next/swc-darwin-arm64@15.4.2':
optional: true
- '@next/swc-darwin-x64@15.4.1':
+ '@next/swc-darwin-x64@15.4.2':
optional: true
- '@next/swc-linux-arm64-gnu@15.4.1':
+ '@next/swc-linux-arm64-gnu@15.4.2':
optional: true
- '@next/swc-linux-arm64-musl@15.4.1':
+ '@next/swc-linux-arm64-musl@15.4.2':
optional: true
- '@next/swc-linux-x64-gnu@15.4.1':
+ '@next/swc-linux-x64-gnu@15.4.2':
optional: true
- '@next/swc-linux-x64-musl@15.4.1':
+ '@next/swc-linux-x64-musl@15.4.2':
optional: true
- '@next/swc-win32-arm64-msvc@15.4.1':
+ '@next/swc-win32-arm64-msvc@15.4.2':
optional: true
- '@next/swc-win32-x64-msvc@15.4.1':
+ '@next/swc-win32-x64-msvc@15.4.2':
optional: true
'@noble/hashes@1.5.0': {}
@@ -13091,10 +13091,10 @@ snapshots:
'@tanstack/react-query': 5.83.0(react@19.1.0)
react: 19.1.0
- '@tanstack/react-query-next-experimental@5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(next@15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)':
+ '@tanstack/react-query-next-experimental@5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(next@15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)':
dependencies:
'@tanstack/react-query': 5.83.0(react@19.1.0)
- next: 15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ next: 15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react: 19.1.0
'@tanstack/react-query@5.83.0(react@19.1.0)':
@@ -13352,11 +13352,11 @@ snapshots:
'@trpc/server': 11.4.3(typescript@5.8.3)
typescript: 5.8.3
- '@trpc/next@11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/react-query@11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(next@15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)':
+ '@trpc/next@11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/react-query@11.4.3(@tanstack/react-query@5.83.0(react@19.1.0))(@trpc/client@11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3))(@trpc/server@11.4.3(typescript@5.8.3))(next@15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)':
dependencies:
'@trpc/client': 11.4.3(@trpc/server@11.4.3(typescript@5.8.3))(typescript@5.8.3)
'@trpc/server': 11.4.3(typescript@5.8.3)
- next: 15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ next: 15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
typescript: 5.8.3
@@ -17208,7 +17208,7 @@ snapshots:
make-dir@4.0.0:
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
make-error@1.3.6: {}
@@ -17616,25 +17616,25 @@ snapshots:
netmask@2.0.2: {}
- next-auth@5.0.0-beta.29(next@15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0):
+ next-auth@5.0.0-beta.29(next@15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0):
dependencies:
'@auth/core': 0.40.0
- next: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ next: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react: 19.1.0
- next-intl@4.3.4(next@15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)(typescript@5.8.3):
+ next-intl@4.3.4(next@15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2))(react@19.1.0)(typescript@5.8.3):
dependencies:
'@formatjs/intl-localematcher': 0.5.5
negotiator: 1.0.0
- next: 15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
+ next: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
react: 19.1.0
use-intl: 4.3.4(react@19.1.0)
optionalDependencies:
typescript: 5.8.3
- next@15.4.1(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2):
+ next@15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2):
dependencies:
- '@next/env': 15.4.1
+ '@next/env': 15.4.2
'@swc/helpers': 0.5.15
caniuse-lite: 1.0.30001703
postcss: 8.4.31
@@ -17642,23 +17642,23 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
styled-jsx: 5.1.6(@babel/core@7.26.0)(react@19.1.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 15.4.1
- '@next/swc-darwin-x64': 15.4.1
- '@next/swc-linux-arm64-gnu': 15.4.1
- '@next/swc-linux-arm64-musl': 15.4.1
- '@next/swc-linux-x64-gnu': 15.4.1
- '@next/swc-linux-x64-musl': 15.4.1
- '@next/swc-win32-arm64-msvc': 15.4.1
- '@next/swc-win32-x64-msvc': 15.4.1
+ '@next/swc-darwin-arm64': 15.4.2
+ '@next/swc-darwin-x64': 15.4.2
+ '@next/swc-linux-arm64-gnu': 15.4.2
+ '@next/swc-linux-arm64-musl': 15.4.2
+ '@next/swc-linux-x64-gnu': 15.4.2
+ '@next/swc-linux-x64-musl': 15.4.2
+ '@next/swc-win32-arm64-msvc': 15.4.2
+ '@next/swc-win32-x64-msvc': 15.4.2
sass: 1.89.2
sharp: 0.34.3
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
- next@15.4.1(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2):
+ next@15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2):
dependencies:
- '@next/env': 15.4.1
+ '@next/env': 15.4.2
'@swc/helpers': 0.5.15
caniuse-lite: 1.0.30001703
postcss: 8.4.31
@@ -17666,14 +17666,14 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
styled-jsx: 5.1.6(@babel/core@7.28.0)(react@19.1.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 15.4.1
- '@next/swc-darwin-x64': 15.4.1
- '@next/swc-linux-arm64-gnu': 15.4.1
- '@next/swc-linux-arm64-musl': 15.4.1
- '@next/swc-linux-x64-gnu': 15.4.1
- '@next/swc-linux-x64-musl': 15.4.1
- '@next/swc-win32-arm64-msvc': 15.4.1
- '@next/swc-win32-x64-msvc': 15.4.1
+ '@next/swc-darwin-arm64': 15.4.2
+ '@next/swc-darwin-x64': 15.4.2
+ '@next/swc-linux-arm64-gnu': 15.4.2
+ '@next/swc-linux-arm64-musl': 15.4.2
+ '@next/swc-linux-x64-gnu': 15.4.2
+ '@next/swc-linux-x64-musl': 15.4.2
+ '@next/swc-win32-arm64-msvc': 15.4.2
+ '@next/swc-win32-x64-msvc': 15.4.2
sass: 1.89.2
sharp: 0.34.3
transitivePeerDependencies:
@@ -17692,7 +17692,7 @@ snapshots:
node-abi@3.67.0:
dependencies:
- semver: 7.7.1
+ semver: 7.7.2
node-abort-controller@3.1.1: {}
@@ -17770,7 +17770,7 @@ snapshots:
normalize-package-data@6.0.2:
dependencies:
hosted-git-info: 7.0.2
- semver: 7.7.1
+ semver: 7.7.2
validate-npm-package-license: 3.0.4
normalize-path@3.0.0: {}
@@ -19062,8 +19062,7 @@ snapshots:
semver@7.7.1: {}
- semver@7.7.2:
- optional: true
+ semver@7.7.2: {}
sentence-case@2.1.1:
dependencies:
diff --git a/tooling/eslint/package.json b/tooling/eslint/package.json
index b24895d78..72f88418f 100644
--- a/tooling/eslint/package.json
+++ b/tooling/eslint/package.json
@@ -17,7 +17,7 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
- "@next/eslint-plugin-next": "15.4.1",
+ "@next/eslint-plugin-next": "15.4.2",
"eslint-config-prettier": "^10.1.7",
"eslint-config-turbo": "^2.5.5",
"eslint-plugin-import": "^2.32.0",
From 6fca92ac49cc69d48c1f7e62ab71f14d76265975 Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Fri, 18 Jul 2025 23:21:52 +0000
Subject: [PATCH 03/13] chore(deps): update dependency esbuild to ^0.25.7
(#3655)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
apps/tasks/package.json | 2 +-
apps/websocket/package.json | 2 +-
packages/cli/package.json | 2 +-
packages/db/package.json | 2 +-
pnpm-lock.yaml | 240 ++++++++++++++++++------------------
5 files changed, 124 insertions(+), 124 deletions(-)
diff --git a/apps/tasks/package.json b/apps/tasks/package.json
index b7f236b2e..f6a0761cb 100644
--- a/apps/tasks/package.json
+++ b/apps/tasks/package.json
@@ -46,7 +46,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^22.16.4",
"dotenv-cli": "^8.0.0",
- "esbuild": "^0.25.6",
+ "esbuild": "^0.25.7",
"eslint": "^9.31.0",
"prettier": "^3.6.2",
"tsx": "4.20.3",
diff --git a/apps/websocket/package.json b/apps/websocket/package.json
index 48aab2e93..d4a494834 100644
--- a/apps/websocket/package.json
+++ b/apps/websocket/package.json
@@ -34,7 +34,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.18.1",
- "esbuild": "^0.25.6",
+ "esbuild": "^0.25.7",
"eslint": "^9.31.0",
"prettier": "^3.6.2",
"typescript": "^5.8.3"
diff --git a/packages/cli/package.json b/packages/cli/package.json
index caabe59be..a6424550e 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -34,7 +34,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "esbuild": "^0.25.6",
+ "esbuild": "^0.25.7",
"eslint": "^9.31.0",
"typescript": "^5.8.3"
}
diff --git a/packages/db/package.json b/packages/db/package.json
index fe2e1814b..ab01ac847 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -61,7 +61,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/better-sqlite3": "7.6.13",
"dotenv-cli": "^8.0.0",
- "esbuild": "^0.25.6",
+ "esbuild": "^0.25.7",
"eslint": "^9.31.0",
"prettier": "^3.6.2",
"tsx": "4.20.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 771066265..14d0b85e6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -418,8 +418,8 @@ importers:
specifier: ^8.0.0
version: 8.0.0
esbuild:
- specifier: ^0.25.6
- version: 0.25.6
+ specifier: ^0.25.7
+ version: 0.25.7
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -482,8 +482,8 @@ importers:
specifier: ^8.18.1
version: 8.18.1
esbuild:
- specifier: ^0.25.6
- version: 0.25.6
+ specifier: ^0.25.7
+ version: 0.25.7
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -809,8 +809,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
esbuild:
- specifier: ^0.25.6
- version: 0.25.6
+ specifier: ^0.25.7
+ version: 0.25.7
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -1112,8 +1112,8 @@ importers:
specifier: ^8.0.0
version: 8.0.0
esbuild:
- specifier: ^0.25.6
- version: 0.25.6
+ specifier: ^0.25.7
+ version: 0.25.7
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -2657,8 +2657,8 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/aix-ppc64@0.25.6':
- resolution: {integrity: sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==}
+ '@esbuild/aix-ppc64@0.25.7':
+ resolution: {integrity: sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@@ -2681,8 +2681,8 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm64@0.25.6':
- resolution: {integrity: sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==}
+ '@esbuild/android-arm64@0.25.7':
+ resolution: {integrity: sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@@ -2705,8 +2705,8 @@ packages:
cpu: [arm]
os: [android]
- '@esbuild/android-arm@0.25.6':
- resolution: {integrity: sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==}
+ '@esbuild/android-arm@0.25.7':
+ resolution: {integrity: sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@@ -2729,8 +2729,8 @@ packages:
cpu: [x64]
os: [android]
- '@esbuild/android-x64@0.25.6':
- resolution: {integrity: sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==}
+ '@esbuild/android-x64@0.25.7':
+ resolution: {integrity: sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@@ -2753,8 +2753,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-arm64@0.25.6':
- resolution: {integrity: sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==}
+ '@esbuild/darwin-arm64@0.25.7':
+ resolution: {integrity: sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@@ -2777,8 +2777,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@esbuild/darwin-x64@0.25.6':
- resolution: {integrity: sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==}
+ '@esbuild/darwin-x64@0.25.7':
+ resolution: {integrity: sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@@ -2801,8 +2801,8 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-arm64@0.25.6':
- resolution: {integrity: sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==}
+ '@esbuild/freebsd-arm64@0.25.7':
+ resolution: {integrity: sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@@ -2825,8 +2825,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.25.6':
- resolution: {integrity: sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==}
+ '@esbuild/freebsd-x64@0.25.7':
+ resolution: {integrity: sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@@ -2849,8 +2849,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm64@0.25.6':
- resolution: {integrity: sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==}
+ '@esbuild/linux-arm64@0.25.7':
+ resolution: {integrity: sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@@ -2873,8 +2873,8 @@ packages:
cpu: [arm]
os: [linux]
- '@esbuild/linux-arm@0.25.6':
- resolution: {integrity: sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==}
+ '@esbuild/linux-arm@0.25.7':
+ resolution: {integrity: sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@@ -2897,8 +2897,8 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-ia32@0.25.6':
- resolution: {integrity: sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==}
+ '@esbuild/linux-ia32@0.25.7':
+ resolution: {integrity: sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@@ -2921,8 +2921,8 @@ packages:
cpu: [loong64]
os: [linux]
- '@esbuild/linux-loong64@0.25.6':
- resolution: {integrity: sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==}
+ '@esbuild/linux-loong64@0.25.7':
+ resolution: {integrity: sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@@ -2945,8 +2945,8 @@ packages:
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-mips64el@0.25.6':
- resolution: {integrity: sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==}
+ '@esbuild/linux-mips64el@0.25.7':
+ resolution: {integrity: sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@@ -2969,8 +2969,8 @@ packages:
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-ppc64@0.25.6':
- resolution: {integrity: sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==}
+ '@esbuild/linux-ppc64@0.25.7':
+ resolution: {integrity: sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@@ -2993,8 +2993,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-riscv64@0.25.6':
- resolution: {integrity: sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==}
+ '@esbuild/linux-riscv64@0.25.7':
+ resolution: {integrity: sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@@ -3017,8 +3017,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@esbuild/linux-s390x@0.25.6':
- resolution: {integrity: sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==}
+ '@esbuild/linux-s390x@0.25.7':
+ resolution: {integrity: sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@@ -3041,14 +3041,14 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/linux-x64@0.25.6':
- resolution: {integrity: sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==}
+ '@esbuild/linux-x64@0.25.7':
+ resolution: {integrity: sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-arm64@0.25.6':
- resolution: {integrity: sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==}
+ '@esbuild/netbsd-arm64@0.25.7':
+ resolution: {integrity: sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
@@ -3071,14 +3071,14 @@ packages:
cpu: [x64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.25.6':
- resolution: {integrity: sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==}
+ '@esbuild/netbsd-x64@0.25.7':
+ resolution: {integrity: sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.25.6':
- resolution: {integrity: sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==}
+ '@esbuild/openbsd-arm64@0.25.7':
+ resolution: {integrity: sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@@ -3101,14 +3101,14 @@ packages:
cpu: [x64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.25.6':
- resolution: {integrity: sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==}
+ '@esbuild/openbsd-x64@0.25.7':
+ resolution: {integrity: sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
- '@esbuild/openharmony-arm64@0.25.6':
- resolution: {integrity: sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==}
+ '@esbuild/openharmony-arm64@0.25.7':
+ resolution: {integrity: sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
@@ -3131,8 +3131,8 @@ packages:
cpu: [x64]
os: [sunos]
- '@esbuild/sunos-x64@0.25.6':
- resolution: {integrity: sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==}
+ '@esbuild/sunos-x64@0.25.7':
+ resolution: {integrity: sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@@ -3155,8 +3155,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@esbuild/win32-arm64@0.25.6':
- resolution: {integrity: sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==}
+ '@esbuild/win32-arm64@0.25.7':
+ resolution: {integrity: sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@@ -3179,8 +3179,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@esbuild/win32-ia32@0.25.6':
- resolution: {integrity: sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==}
+ '@esbuild/win32-ia32@0.25.7':
+ resolution: {integrity: sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@@ -3203,8 +3203,8 @@ packages:
cpu: [x64]
os: [win32]
- '@esbuild/win32-x64@0.25.6':
- resolution: {integrity: sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==}
+ '@esbuild/win32-x64@0.25.7':
+ resolution: {integrity: sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -6462,8 +6462,8 @@ packages:
engines: {node: '>=12'}
hasBin: true
- esbuild@0.25.6:
- resolution: {integrity: sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==}
+ esbuild@0.25.7:
+ resolution: {integrity: sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==}
engines: {node: '>=18'}
hasBin: true
@@ -11380,7 +11380,7 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
- '@esbuild/aix-ppc64@0.25.6':
+ '@esbuild/aix-ppc64@0.25.7':
optional: true
'@esbuild/android-arm64@0.18.20':
@@ -11392,7 +11392,7 @@ snapshots:
'@esbuild/android-arm64@0.21.5':
optional: true
- '@esbuild/android-arm64@0.25.6':
+ '@esbuild/android-arm64@0.25.7':
optional: true
'@esbuild/android-arm@0.18.20':
@@ -11404,7 +11404,7 @@ snapshots:
'@esbuild/android-arm@0.21.5':
optional: true
- '@esbuild/android-arm@0.25.6':
+ '@esbuild/android-arm@0.25.7':
optional: true
'@esbuild/android-x64@0.18.20':
@@ -11416,7 +11416,7 @@ snapshots:
'@esbuild/android-x64@0.21.5':
optional: true
- '@esbuild/android-x64@0.25.6':
+ '@esbuild/android-x64@0.25.7':
optional: true
'@esbuild/darwin-arm64@0.18.20':
@@ -11428,7 +11428,7 @@ snapshots:
'@esbuild/darwin-arm64@0.21.5':
optional: true
- '@esbuild/darwin-arm64@0.25.6':
+ '@esbuild/darwin-arm64@0.25.7':
optional: true
'@esbuild/darwin-x64@0.18.20':
@@ -11440,7 +11440,7 @@ snapshots:
'@esbuild/darwin-x64@0.21.5':
optional: true
- '@esbuild/darwin-x64@0.25.6':
+ '@esbuild/darwin-x64@0.25.7':
optional: true
'@esbuild/freebsd-arm64@0.18.20':
@@ -11452,7 +11452,7 @@ snapshots:
'@esbuild/freebsd-arm64@0.21.5':
optional: true
- '@esbuild/freebsd-arm64@0.25.6':
+ '@esbuild/freebsd-arm64@0.25.7':
optional: true
'@esbuild/freebsd-x64@0.18.20':
@@ -11464,7 +11464,7 @@ snapshots:
'@esbuild/freebsd-x64@0.21.5':
optional: true
- '@esbuild/freebsd-x64@0.25.6':
+ '@esbuild/freebsd-x64@0.25.7':
optional: true
'@esbuild/linux-arm64@0.18.20':
@@ -11476,7 +11476,7 @@ snapshots:
'@esbuild/linux-arm64@0.21.5':
optional: true
- '@esbuild/linux-arm64@0.25.6':
+ '@esbuild/linux-arm64@0.25.7':
optional: true
'@esbuild/linux-arm@0.18.20':
@@ -11488,7 +11488,7 @@ snapshots:
'@esbuild/linux-arm@0.21.5':
optional: true
- '@esbuild/linux-arm@0.25.6':
+ '@esbuild/linux-arm@0.25.7':
optional: true
'@esbuild/linux-ia32@0.18.20':
@@ -11500,7 +11500,7 @@ snapshots:
'@esbuild/linux-ia32@0.21.5':
optional: true
- '@esbuild/linux-ia32@0.25.6':
+ '@esbuild/linux-ia32@0.25.7':
optional: true
'@esbuild/linux-loong64@0.18.20':
@@ -11512,7 +11512,7 @@ snapshots:
'@esbuild/linux-loong64@0.21.5':
optional: true
- '@esbuild/linux-loong64@0.25.6':
+ '@esbuild/linux-loong64@0.25.7':
optional: true
'@esbuild/linux-mips64el@0.18.20':
@@ -11524,7 +11524,7 @@ snapshots:
'@esbuild/linux-mips64el@0.21.5':
optional: true
- '@esbuild/linux-mips64el@0.25.6':
+ '@esbuild/linux-mips64el@0.25.7':
optional: true
'@esbuild/linux-ppc64@0.18.20':
@@ -11536,7 +11536,7 @@ snapshots:
'@esbuild/linux-ppc64@0.21.5':
optional: true
- '@esbuild/linux-ppc64@0.25.6':
+ '@esbuild/linux-ppc64@0.25.7':
optional: true
'@esbuild/linux-riscv64@0.18.20':
@@ -11548,7 +11548,7 @@ snapshots:
'@esbuild/linux-riscv64@0.21.5':
optional: true
- '@esbuild/linux-riscv64@0.25.6':
+ '@esbuild/linux-riscv64@0.25.7':
optional: true
'@esbuild/linux-s390x@0.18.20':
@@ -11560,7 +11560,7 @@ snapshots:
'@esbuild/linux-s390x@0.21.5':
optional: true
- '@esbuild/linux-s390x@0.25.6':
+ '@esbuild/linux-s390x@0.25.7':
optional: true
'@esbuild/linux-x64@0.18.20':
@@ -11572,10 +11572,10 @@ snapshots:
'@esbuild/linux-x64@0.21.5':
optional: true
- '@esbuild/linux-x64@0.25.6':
+ '@esbuild/linux-x64@0.25.7':
optional: true
- '@esbuild/netbsd-arm64@0.25.6':
+ '@esbuild/netbsd-arm64@0.25.7':
optional: true
'@esbuild/netbsd-x64@0.18.20':
@@ -11587,10 +11587,10 @@ snapshots:
'@esbuild/netbsd-x64@0.21.5':
optional: true
- '@esbuild/netbsd-x64@0.25.6':
+ '@esbuild/netbsd-x64@0.25.7':
optional: true
- '@esbuild/openbsd-arm64@0.25.6':
+ '@esbuild/openbsd-arm64@0.25.7':
optional: true
'@esbuild/openbsd-x64@0.18.20':
@@ -11602,10 +11602,10 @@ snapshots:
'@esbuild/openbsd-x64@0.21.5':
optional: true
- '@esbuild/openbsd-x64@0.25.6':
+ '@esbuild/openbsd-x64@0.25.7':
optional: true
- '@esbuild/openharmony-arm64@0.25.6':
+ '@esbuild/openharmony-arm64@0.25.7':
optional: true
'@esbuild/sunos-x64@0.18.20':
@@ -11617,7 +11617,7 @@ snapshots:
'@esbuild/sunos-x64@0.21.5':
optional: true
- '@esbuild/sunos-x64@0.25.6':
+ '@esbuild/sunos-x64@0.25.7':
optional: true
'@esbuild/win32-arm64@0.18.20':
@@ -11629,7 +11629,7 @@ snapshots:
'@esbuild/win32-arm64@0.21.5':
optional: true
- '@esbuild/win32-arm64@0.25.6':
+ '@esbuild/win32-arm64@0.25.7':
optional: true
'@esbuild/win32-ia32@0.18.20':
@@ -11641,7 +11641,7 @@ snapshots:
'@esbuild/win32-ia32@0.21.5':
optional: true
- '@esbuild/win32-ia32@0.25.6':
+ '@esbuild/win32-ia32@0.25.7':
optional: true
'@esbuild/win32-x64@0.18.20':
@@ -11653,7 +11653,7 @@ snapshots:
'@esbuild/win32-x64@0.21.5':
optional: true
- '@esbuild/win32-x64@0.25.6':
+ '@esbuild/win32-x64@0.25.7':
optional: true
'@eslint-community/eslint-utils@4.7.0(eslint@9.31.0)':
@@ -15155,8 +15155,8 @@ snapshots:
dependencies:
'@drizzle-team/brocli': 0.10.2
'@esbuild-kit/esm-loader': 2.6.5
- esbuild: 0.25.6
- esbuild-register: 3.6.0(esbuild@0.25.6)
+ esbuild: 0.25.7
+ esbuild-register: 3.6.0(esbuild@0.25.7)
transitivePeerDependencies:
- supports-color
@@ -15488,10 +15488,10 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
- esbuild-register@3.6.0(esbuild@0.25.6):
+ esbuild-register@3.6.0(esbuild@0.25.7):
dependencies:
debug: 4.4.1
- esbuild: 0.25.6
+ esbuild: 0.25.7
transitivePeerDependencies:
- supports-color
@@ -15572,34 +15572,34 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
- esbuild@0.25.6:
+ esbuild@0.25.7:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.6
- '@esbuild/android-arm': 0.25.6
- '@esbuild/android-arm64': 0.25.6
- '@esbuild/android-x64': 0.25.6
- '@esbuild/darwin-arm64': 0.25.6
- '@esbuild/darwin-x64': 0.25.6
- '@esbuild/freebsd-arm64': 0.25.6
- '@esbuild/freebsd-x64': 0.25.6
- '@esbuild/linux-arm': 0.25.6
- '@esbuild/linux-arm64': 0.25.6
- '@esbuild/linux-ia32': 0.25.6
- '@esbuild/linux-loong64': 0.25.6
- '@esbuild/linux-mips64el': 0.25.6
- '@esbuild/linux-ppc64': 0.25.6
- '@esbuild/linux-riscv64': 0.25.6
- '@esbuild/linux-s390x': 0.25.6
- '@esbuild/linux-x64': 0.25.6
- '@esbuild/netbsd-arm64': 0.25.6
- '@esbuild/netbsd-x64': 0.25.6
- '@esbuild/openbsd-arm64': 0.25.6
- '@esbuild/openbsd-x64': 0.25.6
- '@esbuild/openharmony-arm64': 0.25.6
- '@esbuild/sunos-x64': 0.25.6
- '@esbuild/win32-arm64': 0.25.6
- '@esbuild/win32-ia32': 0.25.6
- '@esbuild/win32-x64': 0.25.6
+ '@esbuild/aix-ppc64': 0.25.7
+ '@esbuild/android-arm': 0.25.7
+ '@esbuild/android-arm64': 0.25.7
+ '@esbuild/android-x64': 0.25.7
+ '@esbuild/darwin-arm64': 0.25.7
+ '@esbuild/darwin-x64': 0.25.7
+ '@esbuild/freebsd-arm64': 0.25.7
+ '@esbuild/freebsd-x64': 0.25.7
+ '@esbuild/linux-arm': 0.25.7
+ '@esbuild/linux-arm64': 0.25.7
+ '@esbuild/linux-ia32': 0.25.7
+ '@esbuild/linux-loong64': 0.25.7
+ '@esbuild/linux-mips64el': 0.25.7
+ '@esbuild/linux-ppc64': 0.25.7
+ '@esbuild/linux-riscv64': 0.25.7
+ '@esbuild/linux-s390x': 0.25.7
+ '@esbuild/linux-x64': 0.25.7
+ '@esbuild/netbsd-arm64': 0.25.7
+ '@esbuild/netbsd-x64': 0.25.7
+ '@esbuild/openbsd-arm64': 0.25.7
+ '@esbuild/openbsd-x64': 0.25.7
+ '@esbuild/openharmony-arm64': 0.25.7
+ '@esbuild/sunos-x64': 0.25.7
+ '@esbuild/win32-arm64': 0.25.7
+ '@esbuild/win32-ia32': 0.25.7
+ '@esbuild/win32-x64': 0.25.7
escalade@3.2.0: {}
@@ -19918,7 +19918,7 @@ snapshots:
tsx@4.20.3:
dependencies:
- esbuild: 0.25.6
+ esbuild: 0.25.7
get-tsconfig: 4.8.1
optionalDependencies:
fsevents: 2.3.3
From 18c3ed559e69c7fc4a7070f83702c08c688c9c9f Mon Sep 17 00:00:00 2001
From: Manuel <30572287+manuel-rw@users.noreply.github.com>
Date: Sat, 19 Jul 2025 15:25:12 +0200
Subject: [PATCH 04/13] chore: update issue template with 1.29.0
---
.github/ISSUE_TEMPLATE/bug_report.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 3a39ba344..11004a3ef 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -31,6 +31,7 @@ body:
label: Version
description: What version of Homarr are you running?
options:
+ - 1.29.0
- 1.28.1
- 1.28.0
- 1.27.0
From 36b0f576e5a00726d76695fd3300710be6f925f8 Mon Sep 17 00:00:00 2001
From: Andre Silva <32734153+Aandree5@users.noreply.github.com>
Date: Sat, 19 Jul 2025 20:22:11 +0100
Subject: [PATCH 05/13] fix: improved import from docker parsing (#3642)
---
...widget-multiReleasesRepositories-input.tsx | 103 ++++++++++--------
1 file changed, 57 insertions(+), 46 deletions(-)
diff --git a/packages/widgets/src/_inputs/widget-multiReleasesRepositories-input.tsx b/packages/widgets/src/_inputs/widget-multiReleasesRepositories-input.tsx
index 0eecc8e2e..556322084 100644
--- a/packages/widgets/src/_inputs/widget-multiReleasesRepositories-input.tsx
+++ b/packages/widgets/src/_inputs/widget-multiReleasesRepositories-input.tsx
@@ -509,19 +509,19 @@ interface ReleasesRepositoryImport extends ReleasesRepository {
alreadyImported: boolean;
}
-interface ContainerImageSelectorProps {
- containerImage: ReleasesRepositoryImport;
+interface ImportRepositorySelectProps {
+ repository: ReleasesRepositoryImport;
integration?: Integration;
versionFilterPrecisionOptions: string[];
onImageSelectionChanged?: (isSelected: boolean) => void;
}
-const ContainerImageSelector = ({
- containerImage,
+const ImportRepositorySelect = ({
+ repository,
integration,
versionFilterPrecisionOptions,
onImageSelectionChanged,
-}: ContainerImageSelectorProps) => {
+}: ImportRepositorySelectProps) => {
const tRepository = useScopedI18n("widget.releases.option.repositories");
const checkBoxProps: CheckboxProps = !onImageSelectionChanged
? {
@@ -539,29 +539,29 @@ const ContainerImageSelector = ({
label={
- {containerImage.identifier}
+ {repository.identifier}
}
{...checkBoxProps}
/>
- {containerImage.versionFilter && (
+ {repository.versionFilter && (
{tRepository("versionFilter.label")}:
- {containerImage.versionFilter.prefix && containerImage.versionFilter.prefix}
+ {repository.versionFilter.prefix && repository.versionFilter.prefix}
- {versionFilterPrecisionOptions[containerImage.versionFilter.precision]}
+ {versionFilterPrecisionOptions[repository.versionFilter.precision]}
- {containerImage.versionFilter.suffix && containerImage.versionFilter.suffix}
+ {repository.versionFilter.suffix && repository.versionFilter.suffix}
)}
@@ -610,36 +610,47 @@ const RepositoryImportModal = createModal(({ innerProps,
enabled: innerProps.isAdmin,
});
- const containersImages: ReleasesRepositoryImport[] = useMemo(
+ const importRepositories: ReleasesRepositoryImport[] = useMemo(
() =>
- docker.data?.containers.reduce((acc, containerImage) => {
- const imageParts = containerImage.image.split("/");
- const source = imageParts.length > 1 ? imageParts[0] : "docker.io";
- const identifierImage = imageParts.length > 1 ? imageParts[1] : imageParts[0];
+ docker.data?.containers.reduce((acc, container) => {
+ const [maybeSource, maybeIdentifierAndVersion] = container.image.split(/\/(.*)/);
+ const hasSource = maybeSource && maybeSource in sourceToProviderKind;
+ const source = hasSource ? maybeSource : "docker.io";
+ const identifierAndVersion = hasSource ? maybeIdentifierAndVersion : container.image;
- if (!source || !identifierImage) return acc;
+ if (!identifierAndVersion) return acc;
- const providerKey = source in containerImageToProviderKind ? containerImageToProviderKind[source] : "dockerHub";
+ const providerKey = sourceToProviderKind[source];
const integrationId = Object.values(innerProps.integrations).find(
(integration) => integration.kind === providerKey,
)?.id;
- const [identifier, version] = identifierImage.split(":");
+ const [identifier, version] = identifierAndVersion.split(":");
if (!identifier || !integrationId) return acc;
- if (acc.some((item) => item.providerIntegrationId === integrationId && item.identifier === identifier))
+ if (
+ acc.some(
+ (item) =>
+ item.providerIntegrationId !== undefined &&
+ innerProps.integrations[item.providerIntegrationId]?.kind === providerKey &&
+ item.identifier === identifier,
+ )
+ )
return acc;
acc.push({
id: createId(),
providerIntegrationId: integrationId,
identifier,
- iconUrl: containerImage.iconUrl ?? undefined,
+ iconUrl: container.iconUrl ?? undefined,
name: formatIdentifierName(identifier),
versionFilter: version ? parseImageVersionToVersionFilter(version) : undefined,
alreadyImported: innerProps.repositories.some(
- (item) => item.providerIntegrationId === integrationId && item.identifier === identifier,
+ (item) =>
+ item.providerIntegrationId !== undefined &&
+ innerProps.integrations[item.providerIntegrationId]?.kind === providerKey &&
+ item.identifier === identifier,
),
});
return acc;
@@ -657,13 +668,13 @@ const RepositoryImportModal = createModal(({ innerProps,
}, [innerProps, selectedImages, actions]);
const allImagesImported = useMemo(
- () => containersImages.every((containerImage) => containerImage.alreadyImported),
- [containersImages],
+ () => importRepositories.every((repository) => repository.alreadyImported),
+ [importRepositories],
);
const anyImagesImported = useMemo(
- () => containersImages.some((containerImage) => containerImage.alreadyImported),
- [containersImages],
+ () => importRepositories.some((repository) => repository.alreadyImported),
+ [importRepositories],
);
return (
@@ -673,7 +684,7 @@ const RepositoryImportModal = createModal(({ innerProps,
{tRepository("importRepositories.loading")}
- ) : containersImages.length === 0 ? (
+ ) : importRepositories.length === 0 ? (
{tRepository("importRepositories.noImagesFound")}
@@ -694,23 +705,23 @@ const RepositoryImportModal = createModal(({ innerProps,
{!allImagesImported &&
- containersImages
- .filter((containerImage) => !containerImage.alreadyImported)
- .map((containerImage) => {
- const integration = containerImage.providerIntegrationId
- ? innerProps.integrations[containerImage.providerIntegrationId]
+ importRepositories
+ .filter((repository) => !repository.alreadyImported)
+ .map((repository) => {
+ const integration = repository.providerIntegrationId
+ ? innerProps.integrations[repository.providerIntegrationId]
: undefined;
return (
-
isSelected
- ? setSelectedImages([...selectedImages, containerImage])
- : setSelectedImages(selectedImages.filter((img) => img !== containerImage))
+ ? setSelectedImages([...selectedImages, repository])
+ : setSelectedImages(selectedImages.filter((img) => img !== repository))
}
/>
);
@@ -723,17 +734,17 @@ const RepositoryImportModal = createModal(({ innerProps,
{anyImagesImported &&
- containersImages
- .filter((containerImage) => containerImage.alreadyImported)
- .map((containerImage) => {
- const integration = containerImage.providerIntegrationId
- ? innerProps.integrations[containerImage.providerIntegrationId]
+ importRepositories
+ .filter((repository) => repository.alreadyImported)
+ .map((repository) => {
+ const integration = repository.providerIntegrationId
+ ? innerProps.integrations[repository.providerIntegrationId]
: undefined;
return (
-
@@ -763,7 +774,7 @@ const RepositoryImportModal = createModal(({ innerProps,
size: "xl",
});
-const containerImageToProviderKind: Record = {
+const sourceToProviderKind: Record = {
"ghcr.io": "github",
"docker.io": "dockerHub",
};
From 3f29a453b9030b0db80ddbf8f10cd259eb9d06b0 Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Sat, 19 Jul 2025 20:22:44 +0000
Subject: [PATCH 06/13] chore(deps): update dependency esbuild to ^0.25.8
(#3657)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
apps/tasks/package.json | 2 +-
apps/websocket/package.json | 2 +-
packages/cli/package.json | 2 +-
packages/db/package.json | 2 +-
pnpm-lock.yaml | 240 ++++++++++++++++++------------------
5 files changed, 124 insertions(+), 124 deletions(-)
diff --git a/apps/tasks/package.json b/apps/tasks/package.json
index f6a0761cb..b04236f7a 100644
--- a/apps/tasks/package.json
+++ b/apps/tasks/package.json
@@ -46,7 +46,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^22.16.4",
"dotenv-cli": "^8.0.0",
- "esbuild": "^0.25.7",
+ "esbuild": "^0.25.8",
"eslint": "^9.31.0",
"prettier": "^3.6.2",
"tsx": "4.20.3",
diff --git a/apps/websocket/package.json b/apps/websocket/package.json
index d4a494834..c53718f53 100644
--- a/apps/websocket/package.json
+++ b/apps/websocket/package.json
@@ -34,7 +34,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.18.1",
- "esbuild": "^0.25.7",
+ "esbuild": "^0.25.8",
"eslint": "^9.31.0",
"prettier": "^3.6.2",
"typescript": "^5.8.3"
diff --git a/packages/cli/package.json b/packages/cli/package.json
index a6424550e..72e1c5e32 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -34,7 +34,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "esbuild": "^0.25.7",
+ "esbuild": "^0.25.8",
"eslint": "^9.31.0",
"typescript": "^5.8.3"
}
diff --git a/packages/db/package.json b/packages/db/package.json
index ab01ac847..0d1dc7063 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -61,7 +61,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/better-sqlite3": "7.6.13",
"dotenv-cli": "^8.0.0",
- "esbuild": "^0.25.7",
+ "esbuild": "^0.25.8",
"eslint": "^9.31.0",
"prettier": "^3.6.2",
"tsx": "4.20.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 14d0b85e6..7e34cb0cc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -418,8 +418,8 @@ importers:
specifier: ^8.0.0
version: 8.0.0
esbuild:
- specifier: ^0.25.7
- version: 0.25.7
+ specifier: ^0.25.8
+ version: 0.25.8
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -482,8 +482,8 @@ importers:
specifier: ^8.18.1
version: 8.18.1
esbuild:
- specifier: ^0.25.7
- version: 0.25.7
+ specifier: ^0.25.8
+ version: 0.25.8
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -809,8 +809,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
esbuild:
- specifier: ^0.25.7
- version: 0.25.7
+ specifier: ^0.25.8
+ version: 0.25.8
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -1112,8 +1112,8 @@ importers:
specifier: ^8.0.0
version: 8.0.0
esbuild:
- specifier: ^0.25.7
- version: 0.25.7
+ specifier: ^0.25.8
+ version: 0.25.8
eslint:
specifier: ^9.31.0
version: 9.31.0
@@ -2657,8 +2657,8 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/aix-ppc64@0.25.7':
- resolution: {integrity: sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==}
+ '@esbuild/aix-ppc64@0.25.8':
+ resolution: {integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@@ -2681,8 +2681,8 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm64@0.25.7':
- resolution: {integrity: sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==}
+ '@esbuild/android-arm64@0.25.8':
+ resolution: {integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@@ -2705,8 +2705,8 @@ packages:
cpu: [arm]
os: [android]
- '@esbuild/android-arm@0.25.7':
- resolution: {integrity: sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==}
+ '@esbuild/android-arm@0.25.8':
+ resolution: {integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@@ -2729,8 +2729,8 @@ packages:
cpu: [x64]
os: [android]
- '@esbuild/android-x64@0.25.7':
- resolution: {integrity: sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==}
+ '@esbuild/android-x64@0.25.8':
+ resolution: {integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@@ -2753,8 +2753,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-arm64@0.25.7':
- resolution: {integrity: sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==}
+ '@esbuild/darwin-arm64@0.25.8':
+ resolution: {integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@@ -2777,8 +2777,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@esbuild/darwin-x64@0.25.7':
- resolution: {integrity: sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==}
+ '@esbuild/darwin-x64@0.25.8':
+ resolution: {integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@@ -2801,8 +2801,8 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-arm64@0.25.7':
- resolution: {integrity: sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==}
+ '@esbuild/freebsd-arm64@0.25.8':
+ resolution: {integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@@ -2825,8 +2825,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.25.7':
- resolution: {integrity: sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==}
+ '@esbuild/freebsd-x64@0.25.8':
+ resolution: {integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@@ -2849,8 +2849,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm64@0.25.7':
- resolution: {integrity: sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==}
+ '@esbuild/linux-arm64@0.25.8':
+ resolution: {integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@@ -2873,8 +2873,8 @@ packages:
cpu: [arm]
os: [linux]
- '@esbuild/linux-arm@0.25.7':
- resolution: {integrity: sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==}
+ '@esbuild/linux-arm@0.25.8':
+ resolution: {integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@@ -2897,8 +2897,8 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-ia32@0.25.7':
- resolution: {integrity: sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==}
+ '@esbuild/linux-ia32@0.25.8':
+ resolution: {integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@@ -2921,8 +2921,8 @@ packages:
cpu: [loong64]
os: [linux]
- '@esbuild/linux-loong64@0.25.7':
- resolution: {integrity: sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==}
+ '@esbuild/linux-loong64@0.25.8':
+ resolution: {integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@@ -2945,8 +2945,8 @@ packages:
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-mips64el@0.25.7':
- resolution: {integrity: sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==}
+ '@esbuild/linux-mips64el@0.25.8':
+ resolution: {integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@@ -2969,8 +2969,8 @@ packages:
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-ppc64@0.25.7':
- resolution: {integrity: sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==}
+ '@esbuild/linux-ppc64@0.25.8':
+ resolution: {integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@@ -2993,8 +2993,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-riscv64@0.25.7':
- resolution: {integrity: sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==}
+ '@esbuild/linux-riscv64@0.25.8':
+ resolution: {integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@@ -3017,8 +3017,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@esbuild/linux-s390x@0.25.7':
- resolution: {integrity: sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==}
+ '@esbuild/linux-s390x@0.25.8':
+ resolution: {integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@@ -3041,14 +3041,14 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/linux-x64@0.25.7':
- resolution: {integrity: sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==}
+ '@esbuild/linux-x64@0.25.8':
+ resolution: {integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-arm64@0.25.7':
- resolution: {integrity: sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==}
+ '@esbuild/netbsd-arm64@0.25.8':
+ resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
@@ -3071,14 +3071,14 @@ packages:
cpu: [x64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.25.7':
- resolution: {integrity: sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==}
+ '@esbuild/netbsd-x64@0.25.8':
+ resolution: {integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.25.7':
- resolution: {integrity: sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==}
+ '@esbuild/openbsd-arm64@0.25.8':
+ resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@@ -3101,14 +3101,14 @@ packages:
cpu: [x64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.25.7':
- resolution: {integrity: sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==}
+ '@esbuild/openbsd-x64@0.25.8':
+ resolution: {integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
- '@esbuild/openharmony-arm64@0.25.7':
- resolution: {integrity: sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==}
+ '@esbuild/openharmony-arm64@0.25.8':
+ resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
@@ -3131,8 +3131,8 @@ packages:
cpu: [x64]
os: [sunos]
- '@esbuild/sunos-x64@0.25.7':
- resolution: {integrity: sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==}
+ '@esbuild/sunos-x64@0.25.8':
+ resolution: {integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@@ -3155,8 +3155,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@esbuild/win32-arm64@0.25.7':
- resolution: {integrity: sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==}
+ '@esbuild/win32-arm64@0.25.8':
+ resolution: {integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@@ -3179,8 +3179,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@esbuild/win32-ia32@0.25.7':
- resolution: {integrity: sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==}
+ '@esbuild/win32-ia32@0.25.8':
+ resolution: {integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@@ -3203,8 +3203,8 @@ packages:
cpu: [x64]
os: [win32]
- '@esbuild/win32-x64@0.25.7':
- resolution: {integrity: sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==}
+ '@esbuild/win32-x64@0.25.8':
+ resolution: {integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -6462,8 +6462,8 @@ packages:
engines: {node: '>=12'}
hasBin: true
- esbuild@0.25.7:
- resolution: {integrity: sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==}
+ esbuild@0.25.8:
+ resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==}
engines: {node: '>=18'}
hasBin: true
@@ -11380,7 +11380,7 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
- '@esbuild/aix-ppc64@0.25.7':
+ '@esbuild/aix-ppc64@0.25.8':
optional: true
'@esbuild/android-arm64@0.18.20':
@@ -11392,7 +11392,7 @@ snapshots:
'@esbuild/android-arm64@0.21.5':
optional: true
- '@esbuild/android-arm64@0.25.7':
+ '@esbuild/android-arm64@0.25.8':
optional: true
'@esbuild/android-arm@0.18.20':
@@ -11404,7 +11404,7 @@ snapshots:
'@esbuild/android-arm@0.21.5':
optional: true
- '@esbuild/android-arm@0.25.7':
+ '@esbuild/android-arm@0.25.8':
optional: true
'@esbuild/android-x64@0.18.20':
@@ -11416,7 +11416,7 @@ snapshots:
'@esbuild/android-x64@0.21.5':
optional: true
- '@esbuild/android-x64@0.25.7':
+ '@esbuild/android-x64@0.25.8':
optional: true
'@esbuild/darwin-arm64@0.18.20':
@@ -11428,7 +11428,7 @@ snapshots:
'@esbuild/darwin-arm64@0.21.5':
optional: true
- '@esbuild/darwin-arm64@0.25.7':
+ '@esbuild/darwin-arm64@0.25.8':
optional: true
'@esbuild/darwin-x64@0.18.20':
@@ -11440,7 +11440,7 @@ snapshots:
'@esbuild/darwin-x64@0.21.5':
optional: true
- '@esbuild/darwin-x64@0.25.7':
+ '@esbuild/darwin-x64@0.25.8':
optional: true
'@esbuild/freebsd-arm64@0.18.20':
@@ -11452,7 +11452,7 @@ snapshots:
'@esbuild/freebsd-arm64@0.21.5':
optional: true
- '@esbuild/freebsd-arm64@0.25.7':
+ '@esbuild/freebsd-arm64@0.25.8':
optional: true
'@esbuild/freebsd-x64@0.18.20':
@@ -11464,7 +11464,7 @@ snapshots:
'@esbuild/freebsd-x64@0.21.5':
optional: true
- '@esbuild/freebsd-x64@0.25.7':
+ '@esbuild/freebsd-x64@0.25.8':
optional: true
'@esbuild/linux-arm64@0.18.20':
@@ -11476,7 +11476,7 @@ snapshots:
'@esbuild/linux-arm64@0.21.5':
optional: true
- '@esbuild/linux-arm64@0.25.7':
+ '@esbuild/linux-arm64@0.25.8':
optional: true
'@esbuild/linux-arm@0.18.20':
@@ -11488,7 +11488,7 @@ snapshots:
'@esbuild/linux-arm@0.21.5':
optional: true
- '@esbuild/linux-arm@0.25.7':
+ '@esbuild/linux-arm@0.25.8':
optional: true
'@esbuild/linux-ia32@0.18.20':
@@ -11500,7 +11500,7 @@ snapshots:
'@esbuild/linux-ia32@0.21.5':
optional: true
- '@esbuild/linux-ia32@0.25.7':
+ '@esbuild/linux-ia32@0.25.8':
optional: true
'@esbuild/linux-loong64@0.18.20':
@@ -11512,7 +11512,7 @@ snapshots:
'@esbuild/linux-loong64@0.21.5':
optional: true
- '@esbuild/linux-loong64@0.25.7':
+ '@esbuild/linux-loong64@0.25.8':
optional: true
'@esbuild/linux-mips64el@0.18.20':
@@ -11524,7 +11524,7 @@ snapshots:
'@esbuild/linux-mips64el@0.21.5':
optional: true
- '@esbuild/linux-mips64el@0.25.7':
+ '@esbuild/linux-mips64el@0.25.8':
optional: true
'@esbuild/linux-ppc64@0.18.20':
@@ -11536,7 +11536,7 @@ snapshots:
'@esbuild/linux-ppc64@0.21.5':
optional: true
- '@esbuild/linux-ppc64@0.25.7':
+ '@esbuild/linux-ppc64@0.25.8':
optional: true
'@esbuild/linux-riscv64@0.18.20':
@@ -11548,7 +11548,7 @@ snapshots:
'@esbuild/linux-riscv64@0.21.5':
optional: true
- '@esbuild/linux-riscv64@0.25.7':
+ '@esbuild/linux-riscv64@0.25.8':
optional: true
'@esbuild/linux-s390x@0.18.20':
@@ -11560,7 +11560,7 @@ snapshots:
'@esbuild/linux-s390x@0.21.5':
optional: true
- '@esbuild/linux-s390x@0.25.7':
+ '@esbuild/linux-s390x@0.25.8':
optional: true
'@esbuild/linux-x64@0.18.20':
@@ -11572,10 +11572,10 @@ snapshots:
'@esbuild/linux-x64@0.21.5':
optional: true
- '@esbuild/linux-x64@0.25.7':
+ '@esbuild/linux-x64@0.25.8':
optional: true
- '@esbuild/netbsd-arm64@0.25.7':
+ '@esbuild/netbsd-arm64@0.25.8':
optional: true
'@esbuild/netbsd-x64@0.18.20':
@@ -11587,10 +11587,10 @@ snapshots:
'@esbuild/netbsd-x64@0.21.5':
optional: true
- '@esbuild/netbsd-x64@0.25.7':
+ '@esbuild/netbsd-x64@0.25.8':
optional: true
- '@esbuild/openbsd-arm64@0.25.7':
+ '@esbuild/openbsd-arm64@0.25.8':
optional: true
'@esbuild/openbsd-x64@0.18.20':
@@ -11602,10 +11602,10 @@ snapshots:
'@esbuild/openbsd-x64@0.21.5':
optional: true
- '@esbuild/openbsd-x64@0.25.7':
+ '@esbuild/openbsd-x64@0.25.8':
optional: true
- '@esbuild/openharmony-arm64@0.25.7':
+ '@esbuild/openharmony-arm64@0.25.8':
optional: true
'@esbuild/sunos-x64@0.18.20':
@@ -11617,7 +11617,7 @@ snapshots:
'@esbuild/sunos-x64@0.21.5':
optional: true
- '@esbuild/sunos-x64@0.25.7':
+ '@esbuild/sunos-x64@0.25.8':
optional: true
'@esbuild/win32-arm64@0.18.20':
@@ -11629,7 +11629,7 @@ snapshots:
'@esbuild/win32-arm64@0.21.5':
optional: true
- '@esbuild/win32-arm64@0.25.7':
+ '@esbuild/win32-arm64@0.25.8':
optional: true
'@esbuild/win32-ia32@0.18.20':
@@ -11641,7 +11641,7 @@ snapshots:
'@esbuild/win32-ia32@0.21.5':
optional: true
- '@esbuild/win32-ia32@0.25.7':
+ '@esbuild/win32-ia32@0.25.8':
optional: true
'@esbuild/win32-x64@0.18.20':
@@ -11653,7 +11653,7 @@ snapshots:
'@esbuild/win32-x64@0.21.5':
optional: true
- '@esbuild/win32-x64@0.25.7':
+ '@esbuild/win32-x64@0.25.8':
optional: true
'@eslint-community/eslint-utils@4.7.0(eslint@9.31.0)':
@@ -15155,8 +15155,8 @@ snapshots:
dependencies:
'@drizzle-team/brocli': 0.10.2
'@esbuild-kit/esm-loader': 2.6.5
- esbuild: 0.25.7
- esbuild-register: 3.6.0(esbuild@0.25.7)
+ esbuild: 0.25.8
+ esbuild-register: 3.6.0(esbuild@0.25.8)
transitivePeerDependencies:
- supports-color
@@ -15488,10 +15488,10 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
- esbuild-register@3.6.0(esbuild@0.25.7):
+ esbuild-register@3.6.0(esbuild@0.25.8):
dependencies:
debug: 4.4.1
- esbuild: 0.25.7
+ esbuild: 0.25.8
transitivePeerDependencies:
- supports-color
@@ -15572,34 +15572,34 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
- esbuild@0.25.7:
+ esbuild@0.25.8:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.7
- '@esbuild/android-arm': 0.25.7
- '@esbuild/android-arm64': 0.25.7
- '@esbuild/android-x64': 0.25.7
- '@esbuild/darwin-arm64': 0.25.7
- '@esbuild/darwin-x64': 0.25.7
- '@esbuild/freebsd-arm64': 0.25.7
- '@esbuild/freebsd-x64': 0.25.7
- '@esbuild/linux-arm': 0.25.7
- '@esbuild/linux-arm64': 0.25.7
- '@esbuild/linux-ia32': 0.25.7
- '@esbuild/linux-loong64': 0.25.7
- '@esbuild/linux-mips64el': 0.25.7
- '@esbuild/linux-ppc64': 0.25.7
- '@esbuild/linux-riscv64': 0.25.7
- '@esbuild/linux-s390x': 0.25.7
- '@esbuild/linux-x64': 0.25.7
- '@esbuild/netbsd-arm64': 0.25.7
- '@esbuild/netbsd-x64': 0.25.7
- '@esbuild/openbsd-arm64': 0.25.7
- '@esbuild/openbsd-x64': 0.25.7
- '@esbuild/openharmony-arm64': 0.25.7
- '@esbuild/sunos-x64': 0.25.7
- '@esbuild/win32-arm64': 0.25.7
- '@esbuild/win32-ia32': 0.25.7
- '@esbuild/win32-x64': 0.25.7
+ '@esbuild/aix-ppc64': 0.25.8
+ '@esbuild/android-arm': 0.25.8
+ '@esbuild/android-arm64': 0.25.8
+ '@esbuild/android-x64': 0.25.8
+ '@esbuild/darwin-arm64': 0.25.8
+ '@esbuild/darwin-x64': 0.25.8
+ '@esbuild/freebsd-arm64': 0.25.8
+ '@esbuild/freebsd-x64': 0.25.8
+ '@esbuild/linux-arm': 0.25.8
+ '@esbuild/linux-arm64': 0.25.8
+ '@esbuild/linux-ia32': 0.25.8
+ '@esbuild/linux-loong64': 0.25.8
+ '@esbuild/linux-mips64el': 0.25.8
+ '@esbuild/linux-ppc64': 0.25.8
+ '@esbuild/linux-riscv64': 0.25.8
+ '@esbuild/linux-s390x': 0.25.8
+ '@esbuild/linux-x64': 0.25.8
+ '@esbuild/netbsd-arm64': 0.25.8
+ '@esbuild/netbsd-x64': 0.25.8
+ '@esbuild/openbsd-arm64': 0.25.8
+ '@esbuild/openbsd-x64': 0.25.8
+ '@esbuild/openharmony-arm64': 0.25.8
+ '@esbuild/sunos-x64': 0.25.8
+ '@esbuild/win32-arm64': 0.25.8
+ '@esbuild/win32-ia32': 0.25.8
+ '@esbuild/win32-x64': 0.25.8
escalade@3.2.0: {}
@@ -19918,7 +19918,7 @@ snapshots:
tsx@4.20.3:
dependencies:
- esbuild: 0.25.7
+ esbuild: 0.25.8
get-tsconfig: 4.8.1
optionalDependencies:
fsevents: 2.3.3
From fa8e7041127fca74908fe2d20b0ba5ea2540de7a Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Sun, 20 Jul 2025 14:21:07 +0000
Subject: [PATCH 07/13] chore(deps): update dependency
prettier-plugin-packagejson to ^2.5.19 (#3658)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
pnpm-lock.yaml | 28 ++++++++++++++--------------
tooling/prettier/package.json | 2 +-
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7e34cb0cc..8104b4a6d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2296,8 +2296,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../typescript
prettier-plugin-packagejson:
- specifier: ^2.5.18
- version: 2.5.18(prettier@3.6.2)
+ specifier: ^2.5.19
+ version: 2.5.19(prettier@3.6.2)
typescript:
specifier: ^5.8.3
version: 5.8.3
@@ -3954,8 +3954,8 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@pkgr/core@0.2.4':
- resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==}
+ '@pkgr/core@0.2.9':
+ resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
'@pnpm/config.env-replace@1.1.0':
@@ -8857,8 +8857,8 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
- prettier-plugin-packagejson@2.5.18:
- resolution: {integrity: sha512-NKznPGcGrcj4NPGxnh+w78JXPyfB6I4RQSCM0v+CAXwpDG7OEpJQ5zMyfC5NBgKH1k7Skwcj5ak5by2mrHvC5g==}
+ prettier-plugin-packagejson@2.5.19:
+ resolution: {integrity: sha512-Qsqp4+jsZbKMpEGZB1UP1pxeAT8sCzne2IwnKkr+QhUe665EXUo3BAvTf1kAPCqyMv9kg3ZmO0+7eOni/C6Uag==}
peerDependencies:
prettier: '>= 1.16.0'
peerDependenciesMeta:
@@ -9928,8 +9928,8 @@ packages:
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
- synckit@0.11.8:
- resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==}
+ synckit@0.11.11:
+ resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==}
engines: {node: ^14.18.0 || >=16.0.0}
tabbable@6.2.0:
@@ -12470,7 +12470,7 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
- '@pkgr/core@0.2.4': {}
+ '@pkgr/core@0.2.9': {}
'@pnpm/config.env-replace@1.1.0': {}
@@ -18237,10 +18237,10 @@ snapshots:
prelude-ls@1.2.1: {}
- prettier-plugin-packagejson@2.5.18(prettier@3.6.2):
+ prettier-plugin-packagejson@2.5.19(prettier@3.6.2):
dependencies:
sort-package-json: 3.4.0
- synckit: 0.11.8
+ synckit: 0.11.11
optionalDependencies:
prettier: 3.6.2
@@ -19290,7 +19290,7 @@ snapshots:
detect-newline: 4.0.1
git-hooks-list: 4.1.1
is-plain-obj: 4.1.0
- semver: 7.7.1
+ semver: 7.7.2
sort-object-keys: 1.1.3
tinyglobby: 0.2.14
@@ -19621,9 +19621,9 @@ snapshots:
symbol-tree@3.2.4: {}
- synckit@0.11.8:
+ synckit@0.11.11:
dependencies:
- '@pkgr/core': 0.2.4
+ '@pkgr/core': 0.2.9
tabbable@6.2.0: {}
diff --git a/tooling/prettier/package.json b/tooling/prettier/package.json
index 219b8a237..06573bf5f 100644
--- a/tooling/prettier/package.json
+++ b/tooling/prettier/package.json
@@ -15,7 +15,7 @@
},
"devDependencies": {
"@homarr/tsconfig": "workspace:^0.1.0",
- "prettier-plugin-packagejson": "^2.5.18",
+ "prettier-plugin-packagejson": "^2.5.19",
"typescript": "^5.8.3"
}
}
From 66ebb5061fd219f9c804ef3a6bbe3372d296f740 Mon Sep 17 00:00:00 2001
From: Meier Lukas
Date: Sun, 20 Jul 2025 16:59:03 +0200
Subject: [PATCH 08/13] feat(widgets): add media release widget (#3219)
---
apps/nextjs/package.json | 1 +
.../src/app/api/image-proxy/[id]/route.ts | 19 ++
apps/tasks/package.json | 2 +-
packages/api/src/router/widgets/index.ts | 2 +
.../api/src/router/widgets/media-release.ts | 67 ++++++
packages/common/src/index.ts | 1 +
packages/definitions/src/integration.ts | 8 +-
packages/definitions/src/widget.ts | 1 +
packages/image-proxy/eslint.config.js | 4 +
packages/image-proxy/package.json | 39 ++++
packages/image-proxy/src/index.ts | 133 +++++++++++
packages/image-proxy/tsconfig.json | 9 +
packages/integrations/package.json | 1 +
.../integrations/src/emby/emby-integration.ts | 96 +++++++-
.../src/interfaces/media-releases.ts | 76 +++++++
.../src/jellyfin/jellyfin-integration.ts | 42 +++-
.../src/mock/data/media-releases.ts | 128 +++++++++++
.../integrations/src/mock/mock-integration.ts | 7 +
.../integrations/src/plex/plex-integration.ts | 139 +++++++++++-
packages/integrations/src/types.ts | 1 +
packages/request-handler/src/media-release.ts | 20 ++
packages/translation/src/lang/en.json | 29 +++
packages/ui/src/components/overflow-badge.tsx | 30 ++-
packages/widgets/src/index.tsx | 2 +
.../widgets/src/media-releases/component.tsx | 206 ++++++++++++++++++
packages/widgets/src/media-releases/index.ts | 35 +++
pnpm-lock.yaml | 43 ++++
27 files changed, 1117 insertions(+), 24 deletions(-)
create mode 100644 apps/nextjs/src/app/api/image-proxy/[id]/route.ts
create mode 100644 packages/api/src/router/widgets/media-release.ts
create mode 100644 packages/image-proxy/eslint.config.js
create mode 100644 packages/image-proxy/package.json
create mode 100644 packages/image-proxy/src/index.ts
create mode 100644 packages/image-proxy/tsconfig.json
create mode 100644 packages/integrations/src/interfaces/media-releases.ts
create mode 100644 packages/integrations/src/mock/data/media-releases.ts
create mode 100644 packages/request-handler/src/media-release.ts
create mode 100644 packages/widgets/src/media-releases/component.tsx
create mode 100644 packages/widgets/src/media-releases/index.ts
diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json
index 895379e9c..9382e48cd 100644
--- a/apps/nextjs/package.json
+++ b/apps/nextjs/package.json
@@ -34,6 +34,7 @@
"@homarr/forms-collection": "workspace:^0.1.0",
"@homarr/gridstack": "^1.12.0",
"@homarr/icons": "workspace:^0.1.0",
+ "@homarr/image-proxy": "workspace:^0.1.0",
"@homarr/integrations": "workspace:^0.1.0",
"@homarr/log": "workspace:^",
"@homarr/modals": "workspace:^0.1.0",
diff --git a/apps/nextjs/src/app/api/image-proxy/[id]/route.ts b/apps/nextjs/src/app/api/image-proxy/[id]/route.ts
new file mode 100644
index 000000000..26eb70dd8
--- /dev/null
+++ b/apps/nextjs/src/app/api/image-proxy/[id]/route.ts
@@ -0,0 +1,19 @@
+import { notFound } from "next/navigation";
+
+import { ImageProxy } from "@homarr/image-proxy";
+
+export const GET = async (_request: Request, props: { params: Promise<{ id: string }> }) => {
+ const { id } = await props.params;
+
+ const imageProxy = new ImageProxy();
+ const image = await imageProxy.forwardImageAsync(id);
+ if (!image) {
+ notFound();
+ }
+
+ return new Response(image, {
+ headers: {
+ "Cache-Control": "public, max-age=3600, immutable", // Cache for 1 hour
+ },
+ });
+};
diff --git a/apps/tasks/package.json b/apps/tasks/package.json
index b04236f7a..cbd6c21d0 100644
--- a/apps/tasks/package.json
+++ b/apps/tasks/package.json
@@ -10,7 +10,7 @@
"main": "./src/main.ts",
"types": "./src/main.ts",
"scripts": {
- "build": "esbuild src/main.ts --bundle --platform=node --loader:.scss=text --external:*.node --external:@opentelemetry/api --external:deasync --outfile=tasks.cjs",
+ "build": "esbuild src/main.ts --bundle --platform=node --loader:.scss=text --external:*.node --external:@opentelemetry/api --external:deasync --external:bcrypt --outfile=tasks.cjs",
"clean": "rm -rf .turbo node_modules",
"dev": "pnpm with-env tsx ./src/main.ts",
"format": "prettier --check . --ignore-path ../../.gitignore",
diff --git a/packages/api/src/router/widgets/index.ts b/packages/api/src/router/widgets/index.ts
index 77a1bd2ef..2ad920b5d 100644
--- a/packages/api/src/router/widgets/index.ts
+++ b/packages/api/src/router/widgets/index.ts
@@ -5,6 +5,7 @@ import { dnsHoleRouter } from "./dns-hole";
import { downloadsRouter } from "./downloads";
import { healthMonitoringRouter } from "./health-monitoring";
import { indexerManagerRouter } from "./indexer-manager";
+import { mediaReleaseRouter } from "./media-release";
import { mediaRequestsRouter } from "./media-requests";
import { mediaServerRouter } from "./media-server";
import { mediaTranscodingRouter } from "./media-transcoding";
@@ -27,6 +28,7 @@ export const widgetRouter = createTRPCRouter({
smartHome: smartHomeRouter,
stockPrice: stockPriceRouter,
mediaServer: mediaServerRouter,
+ mediaRelease: mediaReleaseRouter,
calendar: calendarRouter,
downloads: downloadsRouter,
mediaRequests: mediaRequestsRouter,
diff --git a/packages/api/src/router/widgets/media-release.ts b/packages/api/src/router/widgets/media-release.ts
new file mode 100644
index 000000000..fddc174cc
--- /dev/null
+++ b/packages/api/src/router/widgets/media-release.ts
@@ -0,0 +1,67 @@
+import { observable } from "@trpc/server/observable";
+
+import type { Modify } from "@homarr/common/types";
+import type { Integration } from "@homarr/db/schema";
+import type { IntegrationKindByCategory } from "@homarr/definitions";
+import { getIntegrationKindsByCategory } from "@homarr/definitions";
+import type { MediaRelease } from "@homarr/integrations/types";
+import { mediaReleaseRequestHandler } from "@homarr/request-handler/media-release";
+
+import { createManyIntegrationMiddleware } from "../../middlewares/integration";
+import { createTRPCRouter, publicProcedure } from "../../trpc";
+
+export const mediaReleaseRouter = createTRPCRouter({
+ getMediaReleases: publicProcedure
+ .concat(createManyIntegrationMiddleware("query", ...getIntegrationKindsByCategory("mediaRelease")))
+ .query(async ({ ctx }) => {
+ const results = await Promise.all(
+ ctx.integrations.map(async (integration) => {
+ const innerHandler = mediaReleaseRequestHandler.handler(integration, {});
+ const { data, timestamp } = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
+
+ return {
+ integration: {
+ id: integration.id,
+ name: integration.name,
+ kind: integration.kind,
+ updatedAt: timestamp,
+ },
+ releases: data,
+ };
+ }),
+ );
+ return results.flatMap((result) =>
+ result.releases.map((release) => ({
+ ...release,
+ integration: result.integration,
+ })),
+ );
+ }),
+
+ subscribeToReleases: publicProcedure
+ .concat(createManyIntegrationMiddleware("query", ...getIntegrationKindsByCategory("mediaRelease")))
+ .subscription(({ ctx }) => {
+ return observable<{
+ integration: Modify }>;
+ releases: MediaRelease[];
+ }>((emit) => {
+ const unsubscribes: (() => void)[] = [];
+ for (const integrationWithSecrets of ctx.integrations) {
+ const { decryptedSecrets: _, ...integration } = integrationWithSecrets;
+ const innerHandler = mediaReleaseRequestHandler.handler(integrationWithSecrets, {});
+ const unsubscribe = innerHandler.subscribe((releases) => {
+ emit.next({
+ integration,
+ releases,
+ });
+ });
+ unsubscribes.push(unsubscribe);
+ }
+ return () => {
+ unsubscribes.forEach((unsubscribe) => {
+ unsubscribe();
+ });
+ };
+ });
+ }),
+});
diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts
index 7ffe71664..f7d667155 100644
--- a/packages/common/src/index.ts
+++ b/packages/common/src/index.ts
@@ -12,3 +12,4 @@ export * from "./error";
export * from "./fetch-with-timeout";
export * from "./theme";
export * from "./function";
+export * from "./id";
diff --git a/packages/definitions/src/integration.ts b/packages/definitions/src/integration.ts
index 1506182f1..7a1112aba 100644
--- a/packages/definitions/src/integration.ts
+++ b/packages/definitions/src/integration.ts
@@ -92,19 +92,19 @@ export const integrationDefs = {
name: "Jellyfin",
secretKinds: [["username", "password"], ["apiKey"]],
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/jellyfin.svg",
- category: ["mediaService"],
+ category: ["mediaService", "mediaRelease"],
},
emby: {
name: "Emby",
secretKinds: [["apiKey"]],
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/emby.svg",
- category: ["mediaService"],
+ category: ["mediaService", "mediaRelease"],
},
plex: {
name: "Plex",
secretKinds: [["apiKey"]],
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/plex.svg",
- category: ["mediaService"],
+ category: ["mediaService", "mediaRelease"],
},
jellyseerr: {
name: "Jellyseerr",
@@ -224,6 +224,7 @@ export const integrationDefs = {
"downloadClient",
"healthMonitoring",
"indexerManager",
+ "mediaRelease",
"mediaRequest",
"mediaService",
"mediaTranscoding",
@@ -282,6 +283,7 @@ export const integrationCategories = [
"mediaService",
"calendar",
"mediaSearch",
+ "mediaRelease",
"mediaRequest",
"downloadClient",
"usenet",
diff --git a/packages/definitions/src/widget.ts b/packages/definitions/src/widget.ts
index 609e8bf9a..24da8f214 100644
--- a/packages/definitions/src/widget.ts
+++ b/packages/definitions/src/widget.ts
@@ -24,6 +24,7 @@ export const widgetKinds = [
"indexerManager",
"healthMonitoring",
"releases",
+ "mediaReleases",
"dockerContainers",
"notifications",
] as const;
diff --git a/packages/image-proxy/eslint.config.js b/packages/image-proxy/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/image-proxy/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/image-proxy/package.json b/packages/image-proxy/package.json
new file mode 100644
index 000000000..638d21704
--- /dev/null
+++ b/packages/image-proxy/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@homarr/image-proxy",
+ "version": "0.1.0",
+ "private": true,
+ "license": "Apache-2.0",
+ "type": "module",
+ "exports": {
+ ".": "./src/index.ts"
+ },
+ "typesVersions": {
+ "*": {
+ "*": [
+ "src/*"
+ ]
+ }
+ },
+ "scripts": {
+ "clean": "rm -rf .turbo node_modules",
+ "format": "prettier --check . --ignore-path ../../.gitignore",
+ "lint": "eslint",
+ "typecheck": "tsc --noEmit"
+ },
+ "prettier": "@homarr/prettier-config",
+ "dependencies": {
+ "@homarr/certificates": "workspace:^0.1.0",
+ "@homarr/common": "workspace:^0.1.0",
+ "@homarr/log": "workspace:^0.1.0",
+ "@homarr/redis": "workspace:^0.1.0",
+ "bcrypt": "^6.0.0"
+ },
+ "devDependencies": {
+ "@homarr/eslint-config": "workspace:^0.2.0",
+ "@homarr/prettier-config": "workspace:^0.1.0",
+ "@homarr/tsconfig": "workspace:^0.1.0",
+ "@types/bcrypt": "5.0.2",
+ "eslint": "^9.31.0",
+ "typescript": "^5.8.3"
+ }
+}
diff --git a/packages/image-proxy/src/index.ts b/packages/image-proxy/src/index.ts
new file mode 100644
index 000000000..19f66e608
--- /dev/null
+++ b/packages/image-proxy/src/index.ts
@@ -0,0 +1,133 @@
+import bcrypt from "bcrypt";
+
+import { fetchWithTrustedCertificatesAsync } from "@homarr/certificates/server";
+import { createId } from "@homarr/common";
+import { decryptSecret, encryptSecret } from "@homarr/common/server";
+import { logger } from "@homarr/log";
+import { createGetSetChannel } from "@homarr/redis";
+
+const createHashChannel = (hash: `${string}.${string}`) => createGetSetChannel(`image-proxy:hash:${hash}`);
+const createUrlByIdChannel = (id: string) =>
+ createGetSetChannel<{
+ url: `${string}.${string}`;
+ headers: `${string}.${string}`;
+ }>(`image-proxy:url:${id}`);
+const saltChannel = createGetSetChannel("image-proxy:salt");
+
+export class ImageProxy {
+ private static salt: string | null = null;
+ private async getOrCreateSaltAsync(): Promise {
+ if (ImageProxy.salt) return ImageProxy.salt;
+ const existingSalt = await saltChannel.getAsync();
+ if (existingSalt) {
+ ImageProxy.salt = existingSalt;
+ return existingSalt;
+ }
+
+ const salt = await bcrypt.genSalt(10);
+ logger.debug(`Generated new salt for image proxy salt="${salt}"`);
+ ImageProxy.salt = salt;
+ await saltChannel.setAsync(salt);
+ return salt;
+ }
+
+ public async createImageAsync(url: string, headers?: Record): Promise {
+ const existingId = await this.getExistingIdAsync(url, headers);
+ if (existingId) {
+ logger.debug(
+ `Image already exists in the proxy id="${existingId}" url="${this.redactUrl(url)}" headers="${this.redactHeaders(headers ?? null)}"`,
+ );
+ return this.createImageUrl(existingId);
+ }
+
+ const id = createId();
+ await this.storeImageAsync(id, url, headers);
+
+ return this.createImageUrl(id);
+ }
+
+ public async forwardImageAsync(id: string): Promise {
+ const urlAndHeaders = await this.getImageUrlAndHeadersAsync(id);
+ if (!urlAndHeaders) {
+ return null;
+ }
+
+ const response = await fetchWithTrustedCertificatesAsync(urlAndHeaders.url, {
+ headers: urlAndHeaders.headers ?? {},
+ });
+
+ const proxyUrl = this.createImageUrl(id);
+ if (!response.ok) {
+ logger.error(
+ `Failed to fetch image id="${id}" url="${this.redactUrl(urlAndHeaders.url)}" headers="${this.redactHeaders(urlAndHeaders.headers)}" proxyUrl="${proxyUrl}" statusCode="${response.status}"`,
+ );
+ return null;
+ }
+
+ const blob = (await response.blob()) as Blob;
+ logger.debug(
+ `Forwarding image succeeded id="${id}" url="${this.redactUrl(urlAndHeaders.url)}" headers="${this.redactHeaders(urlAndHeaders.headers)}" proxyUrl="${proxyUrl} size="${(blob.size / 1024).toFixed(1)}KB"`,
+ );
+
+ return blob;
+ }
+
+ private createImageUrl(id: string): string {
+ return `/api/image-proxy/${id}`;
+ }
+
+ private async getImageUrlAndHeadersAsync(id: string) {
+ const urlHeaderChannel = createUrlByIdChannel(id);
+ const urlHeader = await urlHeaderChannel.getAsync();
+ if (!urlHeader) {
+ logger.warn(`Image not found in the proxy id="${id}"`);
+ return null;
+ }
+
+ return {
+ url: decryptSecret(urlHeader.url),
+ headers: JSON.parse(decryptSecret(urlHeader.headers)) as Record | null,
+ };
+ }
+
+ private async getExistingIdAsync(url: string, headers: Record | undefined): Promise {
+ const salt = await this.getOrCreateSaltAsync();
+ const urlHash = await bcrypt.hash(url, salt);
+ const headerHash = await bcrypt.hash(JSON.stringify(headers ?? null), salt);
+
+ const channel = createHashChannel(`${urlHash}.${headerHash}`);
+ return await channel.getAsync();
+ }
+
+ private async storeImageAsync(id: string, url: string, headers: Record | undefined): Promise {
+ const salt = await this.getOrCreateSaltAsync();
+ const urlHash = await bcrypt.hash(url, salt);
+ const headerHash = await bcrypt.hash(JSON.stringify(headers ?? null), salt);
+
+ const hashChannel = createHashChannel(`${urlHash}.${headerHash}`);
+ const urlHeaderChannel = createUrlByIdChannel(id);
+ await urlHeaderChannel.setAsync({
+ url: encryptSecret(url),
+ headers: encryptSecret(JSON.stringify(headers ?? null)),
+ });
+ await hashChannel.setAsync(id);
+
+ logger.debug(
+ `Stored image in the proxy id="${id}" url="${this.redactUrl(url)}" headers="${this.redactHeaders(headers ?? null)}"`,
+ );
+ }
+
+ private redactUrl(url: string): string {
+ const urlObject = new URL(url);
+
+ const redactedSearch = [...urlObject.searchParams.keys()].map((key) => `${key}=REDACTED`).join("&");
+
+ return `${urlObject.origin}${urlObject.pathname}${redactedSearch ? `?${redactedSearch}` : ""}`;
+ }
+
+ private redactHeaders(headers: Record | null): string | null {
+ if (!headers) return null;
+
+ return Object.keys(headers).join(", ");
+ }
+}
diff --git a/packages/image-proxy/tsconfig.json b/packages/image-proxy/tsconfig.json
new file mode 100644
index 000000000..612bef8df
--- /dev/null
+++ b/packages/image-proxy/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "@homarr/tsconfig/base.json",
+ "compilerOptions": {
+ "types": ["node"],
+ "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
+ },
+ "include": ["*.ts", "src"],
+ "exclude": ["node_modules"]
+}
diff --git a/packages/integrations/package.json b/packages/integrations/package.json
index da43daf54..7f063c4bd 100644
--- a/packages/integrations/package.json
+++ b/packages/integrations/package.json
@@ -33,6 +33,7 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
+ "@homarr/image-proxy": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/node-unifi": "^2.6.0",
"@homarr/redis": "workspace:^0.1.0",
diff --git a/packages/integrations/src/emby/emby-integration.ts b/packages/integrations/src/emby/emby-integration.ts
index e05ba96f5..2b354cbe1 100644
--- a/packages/integrations/src/emby/emby-integration.ts
+++ b/packages/integrations/src/emby/emby-integration.ts
@@ -2,6 +2,7 @@ import { BaseItemKind } from "@jellyfin/sdk/lib/generated-client/models";
import { z } from "zod";
import { fetchWithTrustedCertificatesAsync } from "@homarr/certificates/server";
+import { ResponseError } from "@homarr/common/server";
import type { IntegrationTestingInput } from "../base/integration";
import { Integration } from "../base/integration";
@@ -10,6 +11,7 @@ import type { TestingResult } from "../base/test-connection/test-connection-serv
import type { IMediaServerIntegration } from "../interfaces/media-server/media-server-integration";
import type { CurrentSessionsInput, StreamSession } from "../interfaces/media-server/media-server-types";
import { convertJellyfinType } from "../jellyfin/jellyfin-integration";
+import type { IMediaReleasesIntegration, MediaRelease } from "../types";
const sessionSchema = z.object({
NowPlayingItem: z
@@ -31,7 +33,34 @@ const sessionSchema = z.object({
UserName: z.string().nullish(),
});
-export class EmbyIntegration extends Integration implements IMediaServerIntegration {
+const itemSchema = z.object({
+ Id: z.string(),
+ ServerId: z.string(),
+ Name: z.string(),
+ Taglines: z.array(z.string()),
+ Studios: z.array(z.object({ Name: z.string() })),
+ Overview: z.string().optional(),
+ PremiereDate: z
+ .string()
+ .datetime()
+ .transform((date) => new Date(date))
+ .optional(),
+ DateCreated: z
+ .string()
+ .datetime()
+ .transform((date) => new Date(date)),
+ Genres: z.array(z.string()),
+ CommunityRating: z.number().optional(),
+ RunTimeTicks: z.number(),
+ Type: z.string(), // for example "Movie"
+});
+
+const userSchema = z.object({
+ Id: z.string(),
+ Name: z.string(),
+});
+
+export class EmbyIntegration extends Integration implements IMediaServerIntegration, IMediaReleasesIntegration {
private static readonly apiKeyHeader = "X-Emby-Token";
private static readonly deviceId = "homarr-emby-integration";
private static readonly authorizationHeaderValue = `Emby Client="Dashboard", Device="Homarr", DeviceId="${EmbyIntegration.deviceId}", Version="0.0.1"`;
@@ -103,4 +132,69 @@ export class EmbyIntegration extends Integration implements IMediaServerIntegrat
};
});
}
+
+ public async getMediaReleasesAsync(): Promise {
+ const limit = 100;
+ const users = await this.fetchUsersPublicAsync();
+ const userId = users.at(0)?.id;
+ if (!userId) {
+ throw new Error("No users found");
+ }
+
+ const apiKey = super.getSecretValue("apiKey");
+ const response = await fetchWithTrustedCertificatesAsync(
+ super.url(
+ `/Users/${userId}/Items/Latest?Limit=${limit}&Fields=CommunityRating,Studios,PremiereDate,Genres,ChildCount,ProductionYear,DateCreated,Overview,Taglines`,
+ ),
+ {
+ headers: {
+ [EmbyIntegration.apiKeyHeader]: apiKey,
+ Authorization: EmbyIntegration.authorizationHeaderValue,
+ },
+ },
+ );
+
+ if (!response.ok) {
+ throw new ResponseError(response);
+ }
+
+ const items = z.array(itemSchema).parse(await response.json());
+
+ return items.map((item) => ({
+ id: item.Id,
+ type: item.Type === "Movie" ? "movie" : item.Type === "Series" ? "tv" : "unknown",
+ title: item.Name,
+ subtitle: item.Taglines.at(0),
+ description: item.Overview,
+ releaseDate: item.PremiereDate ?? item.DateCreated,
+ imageUrls: {
+ poster: super.url(`/Items/${item.Id}/Images/Primary?maxHeight=492&maxWidth=328&quality=90`).toString(),
+ backdrop: super.url(`/Items/${item.Id}/Images/Backdrop/0?maxWidth=960&quality=70`).toString(),
+ },
+ producer: item.Studios.at(0)?.Name,
+ rating: item.CommunityRating?.toFixed(1),
+ tags: item.Genres,
+ href: super.url(`/web/index.html#!/item?id=${item.Id}&serverId=${item.ServerId}`).toString(),
+ }));
+ }
+
+ // https://dev.emby.media/reference/RestAPI/UserService/getUsersPublic.html
+ private async fetchUsersPublicAsync(): Promise<{ id: string; name: string }[]> {
+ const apiKey = super.getSecretValue("apiKey");
+ const response = await fetchWithTrustedCertificatesAsync(super.url("/Users/Public"), {
+ headers: {
+ [EmbyIntegration.apiKeyHeader]: apiKey,
+ Authorization: EmbyIntegration.authorizationHeaderValue,
+ },
+ });
+ if (!response.ok) {
+ throw new ResponseError(response);
+ }
+ const users = z.array(userSchema).parse(await response.json());
+
+ return users.map((user) => ({
+ id: user.Id,
+ name: user.Name,
+ }));
+ }
}
diff --git a/packages/integrations/src/interfaces/media-releases.ts b/packages/integrations/src/interfaces/media-releases.ts
new file mode 100644
index 000000000..face87f72
--- /dev/null
+++ b/packages/integrations/src/interfaces/media-releases.ts
@@ -0,0 +1,76 @@
+import type { MantineColor } from "@mantine/core";
+
+export const mediaTypeConfigurations = {
+ movie: {
+ color: "blue",
+ },
+ tv: {
+ color: "violet",
+ },
+ music: {
+ color: "green",
+ },
+ book: {
+ color: "orange",
+ },
+ game: {
+ color: "yellow",
+ },
+ video: {
+ color: "red",
+ },
+ article: {
+ color: "pink",
+ },
+ unknown: {
+ color: "gray",
+ },
+} satisfies Record;
+
+export type MediaType = keyof typeof mediaTypeConfigurations;
+
+export interface MediaRelease {
+ id: string;
+ type: MediaType;
+ title: string;
+ /**
+ * The subtitle of the media item, if applicable.
+ * Can also contain the season number for TV shows.
+ */
+ subtitle?: string;
+ description?: string;
+ releaseDate: Date;
+ imageUrls: {
+ poster: string | undefined;
+ backdrop: string | undefined;
+ };
+ /**
+ * The name of the studio, publisher or author.
+ */
+ producer?: string;
+ /**
+ * Price in USD
+ */
+ price?: number;
+ /**
+ * Rating in any format (e.g. 5/10, 4.5/5, 90%, etc.)
+ */
+ rating?: string;
+ /**
+ * List of tags / genres / categories
+ */
+ tags: string[];
+ /**
+ * Link to the media item
+ */
+ href: string;
+ /*
+ * Video / Music: duration in seconds
+ * Book: number of pages
+ */
+ length?: number;
+}
+
+export interface IMediaReleasesIntegration {
+ getMediaReleasesAsync(): Promise;
+}
diff --git a/packages/integrations/src/jellyfin/jellyfin-integration.ts b/packages/integrations/src/jellyfin/jellyfin-integration.ts
index 5bfcb2e3f..0a31af85b 100644
--- a/packages/integrations/src/jellyfin/jellyfin-integration.ts
+++ b/packages/integrations/src/jellyfin/jellyfin-integration.ts
@@ -2,6 +2,8 @@ import { Jellyfin } from "@jellyfin/sdk";
import { BaseItemKind } from "@jellyfin/sdk/lib/generated-client/models";
import { getSessionApi } from "@jellyfin/sdk/lib/utils/api/session-api";
import { getSystemApi } from "@jellyfin/sdk/lib/utils/api/system-api";
+import { getUserApi } from "@jellyfin/sdk/lib/utils/api/user-api";
+import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api/user-library-api";
import type { AxiosInstance } from "axios";
import { createAxiosCertificateInstanceAsync } from "@homarr/certificates/server";
@@ -13,9 +15,10 @@ import { Integration } from "../base/integration";
import type { TestingResult } from "../base/test-connection/test-connection-service";
import type { IMediaServerIntegration } from "../interfaces/media-server/media-server-integration";
import type { CurrentSessionsInput, StreamSession } from "../interfaces/media-server/media-server-types";
+import type { IMediaReleasesIntegration, MediaRelease } from "../types";
@HandleIntegrationErrors([integrationAxiosHttpErrorHandler])
-export class JellyfinIntegration extends Integration implements IMediaServerIntegration {
+export class JellyfinIntegration extends Integration implements IMediaServerIntegration, IMediaReleasesIntegration {
private readonly jellyfin: Jellyfin = new Jellyfin({
clientInfo: {
name: "Homarr",
@@ -70,6 +73,43 @@ export class JellyfinIntegration extends Integration implements IMediaServerInte
});
}
+ public async getMediaReleasesAsync(): Promise {
+ const apiClient = await this.getApiAsync();
+ const userLibraryApi = getUserLibraryApi(apiClient);
+ const userApi = getUserApi(apiClient);
+
+ const users = await userApi.getUsers();
+ const userId = users.data.at(0)?.Id;
+ if (!userId) {
+ throw new Error("No users found");
+ }
+
+ const result = await userLibraryApi.getLatestMedia({
+ fields: ["CustomRating", "Studios", "Genres", "ChildCount", "DateCreated", "Overview", "Taglines"],
+ userId,
+ limit: 100,
+ });
+ return result.data.map((item) => ({
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ id: item.Id!,
+ type: item.Type === "Movie" ? "movie" : item.Type === "Series" ? "tv" : "unknown",
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ title: item.Name!,
+ subtitle: item.Taglines?.at(0),
+ description: item.Overview ?? undefined,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ releaseDate: new Date(item.PremiereDate ?? item.DateCreated!),
+ imageUrls: {
+ poster: super.url(`/Items/${item.Id}/Images/Primary?maxHeight=492&maxWidth=328&quality=90`).toString(),
+ backdrop: super.url(`/Items/${item.Id}/Images/Backdrop/0?maxWidth=960&quality=70`).toString(),
+ },
+ producer: item.Studios?.at(0)?.Name ?? undefined,
+ rating: item.CommunityRating?.toFixed(1),
+ tags: item.Genres ?? [],
+ href: super.url(`/web/index.html#!/details?id=${item.Id}&serverId=${item.ServerId}`).toString(),
+ }));
+ }
+
/**
* Constructs an ApiClient synchronously with an ApiKey or asynchronously
* with a username and password.
diff --git a/packages/integrations/src/mock/data/media-releases.ts b/packages/integrations/src/mock/data/media-releases.ts
new file mode 100644
index 000000000..d820a9aa4
--- /dev/null
+++ b/packages/integrations/src/mock/data/media-releases.ts
@@ -0,0 +1,128 @@
+import type { IMediaReleasesIntegration, MediaRelease } from "../../interfaces/media-releases";
+
+export class MediaReleasesMockService implements IMediaReleasesIntegration {
+ public async getMediaReleasesAsync(): Promise {
+ return await Promise.resolve(mockMediaReleases);
+ }
+}
+
+export const mockMediaReleases: MediaRelease[] = [
+ {
+ id: "1",
+ type: "movie",
+ title: "Inception",
+ subtitle: "A mind-bending thriller",
+ description:
+ "A thief who steals corporate secrets through the use of dream-sharing technology is given the inverse task of planting an idea into the mind of a CEO.",
+ releaseDate: new Date("2010-07-16"),
+ imageUrls: {
+ poster: "https://media.outnow.ch/Movies/Bilder/2025/MinecraftMovie/015.jpg",
+ backdrop: "https://example.com/inception_backdrop.jpg",
+ },
+ producer: "Warner Bros.",
+ price: 14.99,
+ rating: "8.8/10",
+ tags: ["Sci-Fi", "Thriller"],
+ href: "https://example.com/inception",
+ length: 148,
+ },
+ {
+ id: "2",
+ type: "tv",
+ title: "Breaking Bad",
+ subtitle: "S5E14 - Ozymandias",
+ description: "When Walter White's secret is revealed, he must face the consequences of his actions.",
+ releaseDate: new Date("2013-09-15"),
+ imageUrls: {
+ poster: "https://media.outnow.ch/Movies/Bilder/2025/MinecraftMovie/015.jpg",
+ backdrop: "https://example.com/breaking_bad_backdrop.jpg",
+ },
+ producer: "AMC",
+ rating: "9.5/10",
+ tags: ["Crime", "Drama"],
+ href: "https://example.com/breaking_bad",
+ },
+ {
+ id: "3",
+ type: "music",
+ title: "Random Access Memories",
+ subtitle: "Daft Punk",
+ description: "The fourth studio album by French electronic music duo Daft Punk.",
+ releaseDate: new Date("2013-05-17"),
+ imageUrls: {
+ poster: "https://media.outnow.ch/Movies/Bilder/2025/MinecraftMovie/015.jpg",
+ backdrop: "https://example.com/ram_backdrop.jpg",
+ },
+ producer: "Columbia Records",
+ price: 9.99,
+ rating: "8.5/10",
+ tags: ["Electronic", "Dance", "Pop", "Funk"],
+ href: "https://example.com/ram",
+ },
+ {
+ id: "4",
+ type: "book",
+ title: "The Great Gatsby",
+ subtitle: "F. Scott Fitzgerald",
+ description: "A novel about the American dream and the disillusionment that comes with it.",
+ releaseDate: new Date("1925-04-10"),
+ imageUrls: {
+ poster: "https://media.outnow.ch/Movies/Bilder/2025/MinecraftMovie/015.jpg",
+ backdrop: "https://example.com/gatsby_backdrop.jpg",
+ },
+ producer: "Scribner",
+ price: 10.99,
+ rating: "4.2/5",
+ tags: ["Classic", "Fiction"],
+ href: "https://example.com/gatsby",
+ },
+ {
+ id: "5",
+ type: "game",
+ title: "The Legend of Zelda: Breath of the Wild",
+ subtitle: "Nintendo Switch",
+ description: "An open-world action-adventure game set in the fantasy land of Hyrule.",
+ releaseDate: new Date("2017-03-03"),
+ imageUrls: {
+ poster: "https://media.outnow.ch/Movies/Bilder/2025/MinecraftMovie/015.jpg",
+ backdrop: "https://example.com/zelda_backdrop.jpg",
+ },
+ producer: "Nintendo",
+ price: 59.99,
+ rating: "10/10",
+ tags: ["Action", "Adventure"],
+ href: "https://example.com/zelda",
+ },
+ {
+ id: "6",
+ type: "article",
+ title: "The Rise of AI in Healthcare",
+ subtitle: "Tech Innovations",
+ description: "Exploring the impact of artificial intelligence on the healthcare industry.",
+ releaseDate: new Date("2023-10-01"),
+ imageUrls: {
+ poster: "https://media.outnow.ch/Movies/Bilder/2025/MinecraftMovie/015.jpg",
+ backdrop: "https://example.com/ai_healthcare_backdrop.jpg",
+ },
+ producer: "Tech Innovations",
+ rating: "4.8/5",
+ tags: ["Technology", "Healthcare"],
+ href: "https://example.com/ai_healthcare",
+ },
+ {
+ id: "7",
+ type: "video",
+ title: "Wir LIEBEN unsere MAMAS | 50 Fragen zu Mamas",
+ releaseDate: new Date("2024-05-18T17:00:00Z"),
+ imageUrls: {
+ poster:
+ "https://i.ytimg.com/vi/a3qyfXc1Pfg/hq720.jpg?sqp=-oaymwEnCNAFEJQDSFryq4qpAxkIARUAAIhCGAHYAQHiAQoIGBACGAY4AUAB&rs=AOn4CLBQKm0viRlfRjTV-V24vGO83rPaVw",
+ backdrop:
+ "https://i.ytimg.com/vi/a3qyfXc1Pfg/hq720.jpg?sqp=-oaymwEnCNAFEJQDSFryq4qpAxkIARUAAIhCGAHYAQHiAQoIGBACGAY4AUAB&rs=AOn4CLBQKm0viRlfRjTV-V24vGO83rPaVw",
+ },
+ producer: "PietSmiet",
+ rating: "1K",
+ tags: [],
+ href: "https://www.youtube.com/watch?v=a3qyfXc1Pfg",
+ },
+];
diff --git a/packages/integrations/src/mock/mock-integration.ts b/packages/integrations/src/mock/mock-integration.ts
index c3fc71c4d..f04959171 100644
--- a/packages/integrations/src/mock/mock-integration.ts
+++ b/packages/integrations/src/mock/mock-integration.ts
@@ -9,6 +9,7 @@ import type {
ISystemHealthMonitoringIntegration,
} from "../interfaces/health-monitoring/health-monitoring-integration";
import type { IIndexerManagerIntegration } from "../interfaces/indexer-manager/indexer-manager-integration";
+import type { IMediaReleasesIntegration } from "../interfaces/media-releases";
import type { IMediaRequestIntegration } from "../interfaces/media-requests/media-request-integration";
import type { IMediaServerIntegration } from "../interfaces/media-server/media-server-integration";
import type { IMediaTranscodingIntegration } from "../interfaces/media-transcoding/media-transcoding-integration";
@@ -19,6 +20,7 @@ import { ClusterHealthMonitoringMockService } from "./data/cluster-health-monito
import { DnsHoleMockService } from "./data/dns-hole";
import { DownloadClientMockService } from "./data/download";
import { IndexerManagerMockService } from "./data/indexer-manager";
+import { MediaReleasesMockService } from "./data/media-releases";
import { MediaRequestMockService } from "./data/media-request";
import { MediaServerMockService } from "./data/media-server";
import { MediaTranscodingMockService } from "./data/media-transcoding";
@@ -36,6 +38,7 @@ export class MockIntegration
IClusterHealthMonitoringIntegration,
ISystemHealthMonitoringIntegration,
IIndexerManagerIntegration,
+ IMediaReleasesIntegration,
IMediaRequestIntegration,
IMediaServerIntegration,
IMediaTranscodingIntegration,
@@ -48,6 +51,7 @@ export class MockIntegration
private static readonly clusterMonitoring = new ClusterHealthMonitoringMockService();
private static readonly systemMonitoring = new SystemHealthMonitoringMockService();
private static readonly indexerManager = new IndexerManagerMockService();
+ private static readonly mediaReleases = new MediaReleasesMockService();
private static readonly mediaRequest = new MediaRequestMockService();
private static readonly mediaServer = new MediaServerMockService();
private static readonly mediaTranscoding = new MediaTranscodingMockService();
@@ -87,6 +91,9 @@ export class MockIntegration
getIndexersAsync = MockIntegration.indexerManager.getIndexersAsync.bind(MockIntegration.indexerManager);
testAllAsync = MockIntegration.indexerManager.testAllAsync.bind(MockIntegration.indexerManager);
+ // MediaReleasesIntegration
+ getMediaReleasesAsync = MockIntegration.mediaReleases.getMediaReleasesAsync.bind(MockIntegration.mediaReleases);
+
// MediaRequestIntegration
getSeriesInformationAsync = MockIntegration.mediaRequest.getSeriesInformationAsync.bind(MockIntegration.mediaRequest);
requestMediaAsync = MockIntegration.mediaRequest.requestMediaAsync.bind(MockIntegration.mediaRequest);
diff --git a/packages/integrations/src/plex/plex-integration.ts b/packages/integrations/src/plex/plex-integration.ts
index 1025d9df2..c8d4582e8 100644
--- a/packages/integrations/src/plex/plex-integration.ts
+++ b/packages/integrations/src/plex/plex-integration.ts
@@ -1,7 +1,9 @@
import { parseStringPromise } from "xml2js";
+import { z } from "zod";
import { fetchWithTrustedCertificatesAsync } from "@homarr/certificates/server";
import { ParseError } from "@homarr/common/server";
+import { ImageProxy } from "@homarr/image-proxy";
import { logger } from "@homarr/log";
import type { IntegrationTestingInput } from "../base/integration";
@@ -10,9 +12,10 @@ import { TestConnectionError } from "../base/test-connection/test-connection-err
import type { TestingResult } from "../base/test-connection/test-connection-service";
import type { IMediaServerIntegration } from "../interfaces/media-server/media-server-integration";
import type { CurrentSessionsInput, StreamSession } from "../interfaces/media-server/media-server-types";
+import type { IMediaReleasesIntegration, MediaRelease } from "../types";
import type { PlexResponse } from "./interface";
-export class PlexIntegration extends Integration implements IMediaServerIntegration {
+export class PlexIntegration extends Integration implements IMediaServerIntegration, IMediaReleasesIntegration {
public async getCurrentSessionsAsync(_options: CurrentSessionsInput): Promise {
const token = super.getSecretValue("apiKey");
@@ -66,6 +69,93 @@ export class PlexIntegration extends Integration implements IMediaServerIntegrat
return medias;
}
+ public async getMediaReleasesAsync(): Promise {
+ const token = super.getSecretValue("apiKey");
+ const machineIdentifier = await this.getMachineIdentifierAsync();
+ const response = await fetchWithTrustedCertificatesAsync(super.url("/library/recentlyAdded"), {
+ headers: {
+ "X-Plex-Token": token,
+ Accept: "application/json",
+ },
+ });
+
+ const data = await recentlyAddedSchema.parseAsync(await response.json());
+ const imageProxy = new ImageProxy();
+
+ const images =
+ data.MediaContainer.Metadata?.flatMap((item) => [
+ {
+ mediaKey: item.key,
+ type: "poster",
+ url: item.Image.find((image) => image?.type === "coverPoster")?.url,
+ },
+ {
+ mediaKey: item.key,
+ type: "backdrop",
+ url: item.Image.find((image) => image?.type === "background")?.url,
+ },
+ ]).filter(
+ (image): image is { mediaKey: string; type: "poster" | "backdrop"; url: string } => image.url !== undefined,
+ ) ?? [];
+
+ const proxiedImages = await Promise.all(
+ images.map(async (image) => {
+ const imageUrl = super.url(image.url as `/${string}`);
+ const proxiedImageUrl = await imageProxy
+ .createImageAsync(imageUrl.toString(), {
+ "X-Plex-Token": token,
+ })
+ .catch((error) => {
+ logger.debug(new Error("Failed to proxy image", { cause: error }));
+ return undefined;
+ });
+ return {
+ mediaKey: image.mediaKey,
+ type: image.type,
+ url: proxiedImageUrl,
+ };
+ }),
+ );
+
+ return (
+ data.MediaContainer.Metadata?.map((item) => {
+ return {
+ id: item.Media.at(0)?.id.toString() ?? item.key,
+ type: item.type === "movie" ? "movie" : item.type === "tv" ? "tv" : "unknown",
+ title: item.title,
+ subtitle: item.tagline,
+ description: item.summary,
+ releaseDate: item.originallyAvailableAt
+ ? new Date(item.originallyAvailableAt)
+ : new Date(item.addedAt * 1000),
+ imageUrls: {
+ poster: proxiedImages.find((image) => image.mediaKey === item.key && image.type === "poster")?.url,
+ backdrop: proxiedImages.find((image) => image.mediaKey === item.key && image.type === "backdrop")?.url,
+ },
+ producer: item.studio,
+ rating: item.rating?.toFixed(1),
+ tags: item.Genre.map((genre) => genre.tag),
+ href: super
+ .url(`/web/index.html#!/server/${machineIdentifier}/details?key=${encodeURIComponent(item.key)}`)
+ .toString(),
+ length: item.duration ? Math.round(item.duration / 1000) : undefined,
+ };
+ }) ?? []
+ );
+ }
+
+ private async getMachineIdentifierAsync(): Promise {
+ const token = super.getSecretValue("apiKey");
+ const response = await fetchWithTrustedCertificatesAsync(super.url("/identity"), {
+ headers: {
+ "X-Plex-Token": token,
+ Accept: "application/json",
+ },
+ });
+ const data = await identitySchema.parseAsync(await response.json());
+ return data.MediaContainer.machineIdentifier;
+ }
+
protected async testingAsync(input: IntegrationTestingInput): Promise {
const token = super.getSecretValue("apiKey");
@@ -111,3 +201,50 @@ export class PlexIntegration extends Integration implements IMediaServerIntegrat
}
}
}
+
+// https://plexapi.dev/api-reference/library/get-recently-added
+const recentlyAddedSchema = z.object({
+ MediaContainer: z.object({
+ Metadata: z
+ .array(
+ z.object({
+ key: z.string(),
+ studio: z.string().optional(),
+ type: z.string(), // For example "movie"
+ title: z.string(),
+ summary: z.string().optional(),
+ duration: z.number().optional(),
+ addedAt: z.number(),
+ rating: z.number().optional(),
+ tagline: z.string().optional(),
+ originallyAvailableAt: z.string().optional(),
+ Media: z.array(
+ z.object({
+ id: z.number(),
+ }),
+ ),
+ Image: z.array(
+ z
+ .object({
+ type: z.string(), // for example "coverPoster" or "background"
+ url: z.string(),
+ })
+ .optional(),
+ ),
+ Genre: z.array(
+ z.object({
+ tag: z.string(),
+ }),
+ ),
+ }),
+ )
+ .optional(),
+ }),
+});
+
+// https://plexapi.dev/api-reference/server/get-server-identity
+const identitySchema = z.object({
+ MediaContainer: z.object({
+ machineIdentifier: z.string(),
+ }),
+});
diff --git a/packages/integrations/src/types.ts b/packages/integrations/src/types.ts
index b8dc464d4..827c100b3 100644
--- a/packages/integrations/src/types.ts
+++ b/packages/integrations/src/types.ts
@@ -8,3 +8,4 @@ export * from "./base/searchable-integration";
export * from "./homeassistant/homeassistant-types";
export * from "./proxmox/proxmox-types";
export * from "./unifi-controller/unifi-controller-types";
+export * from "./interfaces/media-releases";
diff --git a/packages/request-handler/src/media-release.ts b/packages/request-handler/src/media-release.ts
new file mode 100644
index 000000000..c0ffe48f3
--- /dev/null
+++ b/packages/request-handler/src/media-release.ts
@@ -0,0 +1,20 @@
+import dayjs from "dayjs";
+
+import type { IntegrationKindByCategory } from "@homarr/definitions";
+import { createIntegrationAsync } from "@homarr/integrations";
+import type { MediaRelease } from "@homarr/integrations/types";
+
+import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler";
+
+export const mediaReleaseRequestHandler = createCachedIntegrationRequestHandler<
+ MediaRelease[],
+ IntegrationKindByCategory<"mediaRelease">,
+ Record
+>({
+ async requestAsync(integration, _input) {
+ const integrationInstance = await createIntegrationAsync(integration);
+ return await integrationInstance.getMediaReleasesAsync();
+ },
+ cacheDuration: dayjs.duration(5, "minutes"),
+ queryKey: "mediaReleases",
+});
diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json
index b09f08258..5df3d35d6 100644
--- a/packages/translation/src/lang/en.json
+++ b/packages/translation/src/lang/en.json
@@ -2079,6 +2079,35 @@
},
"globalRatio": "Global Ratio"
},
+ "mediaReleases": {
+ "name": "Media releases",
+ "description": "Display newly added medias or upcoming releases from different integrations",
+ "option": {
+ "layout": {
+ "label": "Layout",
+ "option": {
+ "backdrop": {
+ "label": "Backdrop"
+ },
+ "poster": {
+ "label": "Poster"
+ }
+ }
+ },
+ "showDescriptionTooltip": {
+ "label": "Show description tooltip"
+ },
+ "showType": {
+ "label": "Show media type badge"
+ },
+ "showSource": {
+ "label": "Show source integration"
+ }
+ },
+ "length": {
+ "duration": "{length}min"
+ }
+ },
"mediaRequests-requestList": {
"name": "Media Requests List",
"description": "See a list of all media requests from your Overseerr or Jellyseerr instance",
diff --git a/packages/ui/src/components/overflow-badge.tsx b/packages/ui/src/components/overflow-badge.tsx
index 976f8e2fd..253597ea8 100644
--- a/packages/ui/src/components/overflow-badge.tsx
+++ b/packages/ui/src/components/overflow-badge.tsx
@@ -1,13 +1,17 @@
-import type { BadgeProps } from "@mantine/core";
-import { ActionIcon, Badge, Group, Popover, Stack } from "@mantine/core";
+import type { BadgeProps, MantineSpacing } from "@mantine/core";
+import { Badge, Group, Popover, Stack, UnstyledButton } from "@mantine/core";
export function OverflowBadge({
data,
overflowCount = 3,
+ disablePopover = false,
+ groupGap = "xs",
...props
}: {
data: string[];
overflowCount?: number;
+ disablePopover?: boolean;
+ groupGap?: MantineSpacing;
} & BadgeProps) {
const badgeProps = {
variant: "default",
@@ -16,8 +20,8 @@ export function OverflowBadge({
...props,
};
return (
-
-
+
+
{data.slice(0, overflowCount).map((item) => (
{item}
@@ -25,19 +29,11 @@ export function OverflowBadge({
))}
{data.length > overflowCount && (
-
- +{data.length - overflowCount}
-
+
+
+ +{data.length - overflowCount}
+
+
)}
diff --git a/packages/widgets/src/index.tsx b/packages/widgets/src/index.tsx
index fc2fbc8e4..91ec26ac3 100644
--- a/packages/widgets/src/index.tsx
+++ b/packages/widgets/src/index.tsx
@@ -20,6 +20,7 @@ import * as healthMonitoring from "./health-monitoring";
import * as iframe from "./iframe";
import type { WidgetImportRecord } from "./import";
import * as indexerManager from "./indexer-manager";
+import * as mediaReleases from "./media-releases";
import * as mediaRequestsList from "./media-requests/list";
import * as mediaRequestsStats from "./media-requests/stats";
import * as mediaServer from "./media-server";
@@ -69,6 +70,7 @@ export const widgetImports = {
dockerContainers,
releases,
notifications,
+ mediaReleases,
} satisfies WidgetImportRecord;
export type WidgetImports = typeof widgetImports;
diff --git a/packages/widgets/src/media-releases/component.tsx b/packages/widgets/src/media-releases/component.tsx
new file mode 100644
index 000000000..cd2432ddb
--- /dev/null
+++ b/packages/widgets/src/media-releases/component.tsx
@@ -0,0 +1,206 @@
+"use client";
+
+import { Fragment } from "react";
+import { Avatar, Badge, Box, Divider, Group, Image, Stack, Text, TooltipFloating, UnstyledButton } from "@mantine/core";
+import { IconBook, IconCalendar, IconClock, IconStarFilled } from "@tabler/icons-react";
+
+import type { RouterOutputs } from "@homarr/api";
+import { clientApi } from "@homarr/api/client";
+import { getMantineColor } from "@homarr/common";
+import { getIconUrl } from "@homarr/definitions";
+import type { MediaRelease } from "@homarr/integrations/types";
+import { mediaTypeConfigurations } from "@homarr/integrations/types";
+import type { TranslationFunction } from "@homarr/translation";
+import { useCurrentLocale, useI18n } from "@homarr/translation/client";
+import type { TablerIcon } from "@homarr/ui";
+import { OverflowBadge } from "@homarr/ui";
+
+import type { WidgetComponentProps } from "../definition";
+
+export default function MediaReleasesWidget({ options, integrationIds }: WidgetComponentProps<"mediaReleases">) {
+ const [releases] = clientApi.widget.mediaRelease.getMediaReleases.useSuspenseQuery({
+ integrationIds,
+ });
+
+ return (
+
+ {releases.map((item, index) => (
+
+ {index !== 0 && options.layout === "poster" && }
+
+
+ ))}
+
+ );
+}
+
+interface ItemProps {
+ item: RouterOutputs["widget"]["mediaRelease"]["getMediaReleases"][number];
+ options: WidgetComponentProps<"mediaReleases">["options"];
+}
+
+const Item = ({ item, options }: ItemProps) => {
+ const locale = useCurrentLocale();
+ const t = useI18n();
+ const length = formatLength(item.length, item.type, t);
+
+ return (
+
+
+ {options.layout === "backdrop" && (
+
+ )}
+
+
+ {options.layout === "poster" && }
+
+
+
+ {item.title}
+
+ {item.subtitle !== undefined && (
+
+ {item.subtitle}
+
+ )}
+
+
+
+ {length !== undefined && (
+ <>
+
+
+ >
+ )}
+ {item.producer !== undefined && (
+ <>
+
+
+ >
+ )}
+ {item.rating !== undefined && (
+ <>
+
+
+ >
+ )}
+ {item.price !== undefined && (
+ <>
+
+
+ >
+ )}
+
+ {item.tags.length > 0 && (
+
+ )}
+
+
+ {(options.showType || options.showSource) && (
+
+ {options.showType && (
+
+ {item.type}
+
+ )}
+
+ {options.showSource && (
+
+ )}
+
+ )}
+
+
+
+ );
+};
+
+interface IconAndLabelProps {
+ icon?: TablerIcon;
+ label: string;
+}
+
+const InfoDivider = () => (
+
+ •
+
+);
+
+const Info = ({ icon: Icon, label }: IconAndLabelProps) => {
+ return (
+
+ {Icon && }
+
+ {label}
+
+
+ );
+};
+
+const formatLength = (length: number | undefined, type: MediaRelease["type"], t: TranslationFunction) => {
+ if (!length) return undefined;
+ if (type === "movie" || type === "tv" || type === "video" || type === "music" || type === "article") {
+ return {
+ type: "duration" as const,
+ label: t("widget.mediaReleases.length.duration", {
+ length: Math.round(length / 60).toString(),
+ }),
+ };
+ }
+ if (type === "book") {
+ return {
+ type: "page" as const,
+ label: length.toString(),
+ };
+ }
+
+ return undefined;
+};
diff --git a/packages/widgets/src/media-releases/index.ts b/packages/widgets/src/media-releases/index.ts
new file mode 100644
index 000000000..af650eef7
--- /dev/null
+++ b/packages/widgets/src/media-releases/index.ts
@@ -0,0 +1,35 @@
+import { IconTicket } from "@tabler/icons-react";
+
+import { createWidgetDefinition } from "../definition";
+import { optionsBuilder } from "../options";
+
+export const { definition, componentLoader } = createWidgetDefinition("mediaReleases", {
+ icon: IconTicket,
+ createOptions() {
+ return optionsBuilder.from((factory) => ({
+ layout: factory.select({
+ defaultValue: "backdrop",
+ options: [
+ {
+ value: "backdrop",
+ label: (t) => t("widget.mediaReleases.option.layout.option.backdrop.label"),
+ },
+ {
+ value: "poster",
+ label: (t) => t("widget.mediaReleases.option.layout.option.poster.label"),
+ },
+ ],
+ }),
+ showDescriptionTooltip: factory.switch({
+ defaultValue: true,
+ }),
+ showType: factory.switch({
+ defaultValue: true,
+ }),
+ showSource: factory.switch({
+ defaultValue: true,
+ }),
+ }));
+ },
+ supportedIntegrations: ["mock", "emby", "jellyfin", "plex"],
+}).withDynamicImport(() => import("./component"));
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8104b4a6d..3b483d1d3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -139,6 +139,9 @@ importers:
'@homarr/icons':
specifier: workspace:^0.1.0
version: link:../../packages/icons
+ '@homarr/image-proxy':
+ specifier: workspace:^0.1.0
+ version: link:../../packages/image-proxy
'@homarr/integrations':
specifier: workspace:^0.1.0
version: link:../../packages/integrations
@@ -1325,6 +1328,43 @@ importers:
specifier: ^5.8.3
version: 5.8.3
+ packages/image-proxy:
+ dependencies:
+ '@homarr/certificates':
+ specifier: workspace:^0.1.0
+ version: link:../certificates
+ '@homarr/common':
+ specifier: workspace:^0.1.0
+ version: link:../common
+ '@homarr/log':
+ specifier: workspace:^0.1.0
+ version: link:../log
+ '@homarr/redis':
+ specifier: workspace:^0.1.0
+ version: link:../redis
+ bcrypt:
+ specifier: ^6.0.0
+ version: 6.0.0
+ devDependencies:
+ '@homarr/eslint-config':
+ specifier: workspace:^0.2.0
+ version: link:../../tooling/eslint
+ '@homarr/prettier-config':
+ specifier: workspace:^0.1.0
+ version: link:../../tooling/prettier
+ '@homarr/tsconfig':
+ specifier: workspace:^0.1.0
+ version: link:../../tooling/typescript
+ '@types/bcrypt':
+ specifier: 5.0.2
+ version: 5.0.2
+ eslint:
+ specifier: ^9.31.0
+ version: 9.31.0
+ typescript:
+ specifier: ^5.8.3
+ version: 5.8.3
+
packages/integrations:
dependencies:
'@ctrl/deluge':
@@ -1351,6 +1391,9 @@ importers:
'@homarr/definitions':
specifier: workspace:^0.1.0
version: link:../definitions
+ '@homarr/image-proxy':
+ specifier: workspace:^0.1.0
+ version: link:../image-proxy
'@homarr/log':
specifier: workspace:^0.1.0
version: link:../log
From 732bce72aee6c99d0ee94d04e173d378c2552a16 Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Sun, 20 Jul 2025 17:00:34 +0200
Subject: [PATCH 09/13] fix(deps): update dependency @gitbeaker/rest to v43
(#3623)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
packages/integrations/package.json | 2 +-
pnpm-lock.yaml | 40 ++++++++++++++++++------------
2 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/packages/integrations/package.json b/packages/integrations/package.json
index 7f063c4bd..c4c4597b8 100644
--- a/packages/integrations/package.json
+++ b/packages/integrations/package.json
@@ -28,7 +28,7 @@
"@ctrl/deluge": "^7.1.0",
"@ctrl/qbittorrent": "^9.6.0",
"@ctrl/transmission": "^7.2.0",
- "@gitbeaker/rest": "^42.5.0",
+ "@gitbeaker/rest": "^43.3.0",
"@homarr/certificates": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3b483d1d3..deb1c9439 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1377,8 +1377,8 @@ importers:
specifier: ^7.2.0
version: 7.2.0
'@gitbeaker/rest':
- specifier: ^42.5.0
- version: 42.5.0
+ specifier: ^43.3.0
+ version: 43.3.0
'@homarr/certificates':
specifier: workspace:^0.1.0
version: link:../certificates
@@ -3352,16 +3352,16 @@ packages:
'@formatjs/intl-localematcher@0.5.5':
resolution: {integrity: sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==}
- '@gitbeaker/core@42.5.0':
- resolution: {integrity: sha512-rMWpOPaZi1iLiifnOIoVO57p2EmQQdfIwP4txqNyMvG4WjYP5Ez0U7jRD9Nra41x6K5kTPBZkuQcAdxVWRJcEQ==}
+ '@gitbeaker/core@43.3.0':
+ resolution: {integrity: sha512-hORHoQnDFHKOuKDAL6qfFTom+eZvHNGTELuwQ22rFmqW9D3el2XQ+L/fcXEcyEysTGB49b2t2FtRf0Us5Et10g==}
engines: {node: '>=18.20.0'}
- '@gitbeaker/requester-utils@42.5.0':
- resolution: {integrity: sha512-HLdLS9LPBMVQumvroQg/4qkphLDtwDB+ygEsrD2u4oYCMUtXV4V1xaVqU4yTXjbTJ5sItOtdB43vYRkBcgueBw==}
+ '@gitbeaker/requester-utils@43.3.0':
+ resolution: {integrity: sha512-A5bQQAi8cH6qFTiyWWiAgtdM1XV8vRD3OPWs0jOpEIEbT+rWJZQRclo3dlKhcsiM+Gz4SRAylwBwUYszdjOzdw==}
engines: {node: '>=18.20.0'}
- '@gitbeaker/rest@42.5.0':
- resolution: {integrity: sha512-oC5cM6jS7aFOp0luTw5mWSRuMgdxwHRLZQ/aWkI+ETMfsprR/HyxsXfljlMY/XJ/fRxTbRJiodR5Axf66WjO3w==}
+ '@gitbeaker/rest@43.3.0':
+ resolution: {integrity: sha512-3plSNawPLgHSfJmbBGGzCT3kvKE5rqS4fhzTyQFfiwm/+NvOTxEIqMQ5wxaYWlonYfR/eUVp09sMig1nG9Isww==}
engines: {node: '>=18.20.0'}
'@grpc/grpc-js@1.12.5':
@@ -9055,6 +9055,10 @@ packages:
resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==}
engines: {node: '>=0.6'}
+ qs@6.14.0:
+ resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
+ engines: {node: '>=0.6'}
+
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
@@ -11829,23 +11833,23 @@ snapshots:
dependencies:
tslib: 2.8.1
- '@gitbeaker/core@42.5.0':
+ '@gitbeaker/core@43.3.0':
dependencies:
- '@gitbeaker/requester-utils': 42.5.0
- qs: 6.13.1
+ '@gitbeaker/requester-utils': 43.3.0
+ qs: 6.14.0
xcase: 2.0.1
- '@gitbeaker/requester-utils@42.5.0':
+ '@gitbeaker/requester-utils@43.3.0':
dependencies:
picomatch-browser: 2.2.6
- qs: 6.13.1
+ qs: 6.14.0
rate-limiter-flexible: 4.0.1
xcase: 2.0.1
- '@gitbeaker/rest@42.5.0':
+ '@gitbeaker/rest@43.3.0':
dependencies:
- '@gitbeaker/core': 42.5.0
- '@gitbeaker/requester-utils': 42.5.0
+ '@gitbeaker/core': 43.3.0
+ '@gitbeaker/requester-utils': 43.3.0
'@grpc/grpc-js@1.12.5':
dependencies:
@@ -18489,6 +18493,10 @@ snapshots:
dependencies:
side-channel: 1.1.0
+ qs@6.14.0:
+ dependencies:
+ side-channel: 1.1.0
+
querystringify@2.2.0: {}
queue-microtask@1.2.3: {}
From 8e960324bcc43a64100fd9c6c1fd6822c7759160 Mon Sep 17 00:00:00 2001
From: Meier Lukas
Date: Sun, 20 Jul 2025 17:13:57 +0200
Subject: [PATCH 10/13] feat(infra): add external redis (#3639)
---
Dockerfile | 1 +
apps/nextjs/package.json | 2 +-
apps/nextjs/src/env.ts | 3 +-
e2e/health-checks.spec.ts | 30 ++++-
e2e/shared/redis-container.ts | 5 +
package.json | 1 +
packages/auth/env.ts | 3 +-
packages/auth/package.json | 2 +-
packages/common/env.ts | 2 +-
packages/common/package.json | 2 +-
packages/{env => core}/eslint.config.js | 7 +-
packages/{env => core}/package.json | 8 +-
.../src/infrastructure/env}/index.ts | 3 +
.../core/src/infrastructure/env/prefix.ts | 13 ++
.../src/infrastructure/env}/schemas.ts | 0
.../core/src/infrastructure/redis/client.ts | 26 ++++
packages/core/src/infrastructure/redis/env.ts | 17 +++
packages/{env => core}/tsconfig.json | 0
packages/cron-job-api/package.json | 2 +-
packages/cron-job-api/src/env.ts | 2 +-
packages/db/env.ts | 2 +-
packages/db/package.json | 2 +-
packages/docker/package.json | 2 +-
packages/docker/src/env.ts | 3 +-
packages/env/index.ts | 1 -
packages/log/package.json | 3 +-
packages/log/src/env.ts | 2 +-
packages/log/src/redis-transport.ts | 8 +-
packages/redis/package.json | 2 +
packages/redis/src/lib/connection.ts | 7 +-
pnpm-lock.yaml | 113 ++++++++++--------
scripts/run.sh | 11 +-
32 files changed, 201 insertions(+), 84 deletions(-)
create mode 100644 e2e/shared/redis-container.ts
rename packages/{env => core}/eslint.config.js (62%)
rename packages/{env => core}/package.json (77%)
rename packages/{env/src => core/src/infrastructure/env}/index.ts (88%)
create mode 100644 packages/core/src/infrastructure/env/prefix.ts
rename packages/{env/src => core/src/infrastructure/env}/schemas.ts (100%)
create mode 100644 packages/core/src/infrastructure/redis/client.ts
create mode 100644 packages/core/src/infrastructure/redis/env.ts
rename packages/{env => core}/tsconfig.json (100%)
delete mode 100644 packages/env/index.ts
diff --git a/Dockerfile b/Dockerfile
index cd7f063e4..5cc126cec 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -64,6 +64,7 @@ ENV DB_URL='/appdata/db/db.sqlite'
ENV DB_DIALECT='sqlite'
ENV DB_DRIVER='better-sqlite3'
ENV AUTH_PROVIDERS='credentials'
+ENV REDIS_IS_EXTERNAL='false'
ENV NODE_ENV='production'
ENTRYPOINT [ "/app/entrypoint.sh" ]
diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json
index 9382e48cd..0056c33b8 100644
--- a/apps/nextjs/package.json
+++ b/apps/nextjs/package.json
@@ -25,11 +25,11 @@
"@homarr/boards": "workspace:^0.1.0",
"@homarr/certificates": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0",
+ "@homarr/core": "workspace:^0.1.0",
"@homarr/cron-job-status": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/docker": "workspace:^0.1.0",
- "@homarr/env": "workspace:^0.1.0",
"@homarr/form": "workspace:^0.1.0",
"@homarr/forms-collection": "workspace:^0.1.0",
"@homarr/gridstack": "^1.12.0",
diff --git a/apps/nextjs/src/env.ts b/apps/nextjs/src/env.ts
index 8e62d4dc2..62b49dee8 100644
--- a/apps/nextjs/src/env.ts
+++ b/apps/nextjs/src/env.ts
@@ -1,5 +1,4 @@
-import { createEnv } from "@homarr/env";
-import { createBooleanSchema } from "@homarr/env/schemas";
+import { createBooleanSchema, createEnv } from "@homarr/core/infrastructure/env";
export const env = createEnv({
server: {
diff --git a/e2e/health-checks.spec.ts b/e2e/health-checks.spec.ts
index 24fd26c91..03d175525 100644
--- a/e2e/health-checks.spec.ts
+++ b/e2e/health-checks.spec.ts
@@ -1,9 +1,10 @@
import { describe, expect, test } from "vitest";
import { createHomarrContainer } from "./shared/create-homarr-container";
+import { createRedisContainer } from "./shared/redis-container";
describe("Health checks", () => {
- test("ready and live should return 200 OK", async () => {
+ test("ready and live should return 200 OK with normal image and no extra configuration", async () => {
// Arrange
const homarrContainer = await createHomarrContainer().start();
@@ -15,4 +16,31 @@ describe("Health checks", () => {
expect(readyResponse.status).toBe(200);
expect(liveResponse.status).toBe(200);
}, 20_000);
+
+ test("ready and live should return 200 OK with external redis", async () => {
+ // Arrange
+ const redisContainer = await createRedisContainer().start();
+ const homarrContainer = await createHomarrContainer({
+ environment: {
+ REDIS_IS_EXTERNAL: "true",
+ REDIS_HOST: "host.docker.internal",
+ REDIS_PORT: redisContainer.getMappedPort(6379).toString(),
+ REDIS_PASSWORD: redisContainer.getPassword(),
+ },
+ }).start();
+
+ // Act
+ const readyResponse = await fetch(`http://localhost:${homarrContainer.getMappedPort(7575)}/api/health/ready`);
+ const liveResponse = await fetch(`http://localhost:${homarrContainer.getMappedPort(7575)}/api/health/live`);
+
+ // Assert
+ expect(
+ readyResponse.status,
+ `Expected ready to return OK statusCode=${readyResponse.status} content=${await readyResponse.text()}`,
+ ).toBe(200);
+ expect(
+ liveResponse.status,
+ `Expected live to return OK statusCode=${liveResponse.status} content=${await liveResponse.text()}`,
+ ).toBe(200);
+ }, 20_000);
});
diff --git a/e2e/shared/redis-container.ts b/e2e/shared/redis-container.ts
new file mode 100644
index 000000000..cfd8ad4fb
--- /dev/null
+++ b/e2e/shared/redis-container.ts
@@ -0,0 +1,5 @@
+import { RedisContainer } from "@testcontainers/redis";
+
+export const createRedisContainer = () => {
+ return new RedisContainer("redis:latest").withPassword("homarr");
+};
diff --git a/package.json b/package.json
index 0ccdec702..5b9d3d38d 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"@semantic-release/github": "^11.0.3",
"@semantic-release/npm": "^12.0.2",
"@semantic-release/release-notes-generator": "^14.0.3",
+ "@testcontainers/redis": "^11.2.1",
"@turbo/gen": "^2.5.5",
"@vitejs/plugin-react": "^4.7.0",
"@vitest/coverage-v8": "^3.2.4",
diff --git a/packages/auth/env.ts b/packages/auth/env.ts
index 40878312f..12089d9c8 100644
--- a/packages/auth/env.ts
+++ b/packages/auth/env.ts
@@ -1,8 +1,7 @@
import { z } from "zod";
+import { createBooleanSchema, createDurationSchema, createEnv } from "@homarr/core/infrastructure/env";
import { supportedAuthProviders } from "@homarr/definitions";
-import { createEnv } from "@homarr/env";
-import { createBooleanSchema, createDurationSchema } from "@homarr/env/schemas";
const authProvidersSchema = z
.string()
diff --git a/packages/auth/package.json b/packages/auth/package.json
index 0f114538e..cb6bea4c0 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -27,9 +27,9 @@
"@auth/drizzle-adapter": "^1.10.0",
"@homarr/certificates": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0",
+ "@homarr/core": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
- "@homarr/env": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"bcrypt": "^6.0.0",
diff --git a/packages/common/env.ts b/packages/common/env.ts
index 9149bfc46..f9e734e0a 100644
--- a/packages/common/env.ts
+++ b/packages/common/env.ts
@@ -1,7 +1,7 @@
import { randomBytes } from "crypto";
import { z } from "zod";
-import { createEnv } from "@homarr/env";
+import { createEnv } from "@homarr/core/infrastructure/env";
const errorSuffix = `, please generate a 64 character secret in hex format or use the following: "${randomBytes(32).toString("hex")}"`;
diff --git a/packages/common/package.json b/packages/common/package.json
index caa0362ba..b9e745dc5 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -27,7 +27,7 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
- "@homarr/env": "workspace:^0.1.0",
+ "@homarr/core": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@paralleldrive/cuid2": "^2.2.2",
"dayjs": "^1.11.13",
diff --git a/packages/env/eslint.config.js b/packages/core/eslint.config.js
similarity index 62%
rename from packages/env/eslint.config.js
rename to packages/core/eslint.config.js
index 5b19b6f8a..f7a5a7d36 100644
--- a/packages/env/eslint.config.js
+++ b/packages/core/eslint.config.js
@@ -1,9 +1,4 @@
import baseConfig from "@homarr/eslint-config/base";
/** @type {import('typescript-eslint').Config} */
-export default [
- {
- ignores: [],
- },
- ...baseConfig,
-];
+export default [...baseConfig];
diff --git a/packages/env/package.json b/packages/core/package.json
similarity index 77%
rename from packages/env/package.json
rename to packages/core/package.json
index 8b2cd50db..92183a1a1 100644
--- a/packages/env/package.json
+++ b/packages/core/package.json
@@ -1,12 +1,13 @@
{
- "name": "@homarr/env",
+ "name": "@homarr/core",
"version": "0.1.0",
"private": true,
"license": "Apache-2.0",
"type": "module",
"exports": {
- ".": "./index.ts",
- "./schemas": "./src/schemas.ts"
+ "./infrastructure/redis": "./src/infrastructure/redis/client.ts",
+ "./infrastructure/env": "./src/infrastructure/env/index.ts",
+ ".": "./src/index.ts"
},
"typesVersions": {
"*": {
@@ -24,6 +25,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@t3-oss/env-nextjs": "^0.13.8",
+ "ioredis": "5.6.1",
"zod": "^3.25.76"
},
"devDependencies": {
diff --git a/packages/env/src/index.ts b/packages/core/src/infrastructure/env/index.ts
similarity index 88%
rename from packages/env/src/index.ts
rename to packages/core/src/infrastructure/env/index.ts
index e77d8f61a..e11f3323d 100644
--- a/packages/env/src/index.ts
+++ b/packages/core/src/infrastructure/env/index.ts
@@ -7,3 +7,6 @@ export const defaultEnvOptions = {
} satisfies Partial[0]>;
export const createEnv: typeof createEnvT3 = (options) => createEnvT3({ ...defaultEnvOptions, ...options });
+
+export * from "./prefix";
+export * from "./schemas";
diff --git a/packages/core/src/infrastructure/env/prefix.ts b/packages/core/src/infrastructure/env/prefix.ts
new file mode 100644
index 000000000..a113cd9e1
--- /dev/null
+++ b/packages/core/src/infrastructure/env/prefix.ts
@@ -0,0 +1,13 @@
+export const runtimeEnvWithPrefix = (prefix: `${string}_`) =>
+ Object.entries(process.env)
+ .filter(([key]) => key.startsWith(prefix))
+ .reduce(
+ (acc, [key, value]) => {
+ if (value === undefined) return acc;
+
+ const newKey = key.replace(prefix, "");
+ acc[newKey] = value;
+ return acc;
+ },
+ {} as Record,
+ );
diff --git a/packages/env/src/schemas.ts b/packages/core/src/infrastructure/env/schemas.ts
similarity index 100%
rename from packages/env/src/schemas.ts
rename to packages/core/src/infrastructure/env/schemas.ts
diff --git a/packages/core/src/infrastructure/redis/client.ts b/packages/core/src/infrastructure/redis/client.ts
new file mode 100644
index 000000000..e35ee9220
--- /dev/null
+++ b/packages/core/src/infrastructure/redis/client.ts
@@ -0,0 +1,26 @@
+import type { RedisOptions } from "ioredis";
+import { Redis } from "ioredis";
+
+import { redisEnv } from "./env";
+
+const defaultRedisOptions = {
+ connectionName: "homarr",
+} satisfies RedisOptions;
+
+export type { Redis as RedisClient } from "ioredis";
+
+export const createRedisClient = () =>
+ redisEnv.IS_EXTERNAL
+ ? new Redis({
+ ...defaultRedisOptions,
+ host: redisEnv.HOST,
+ port: redisEnv.PORT,
+ tls: redisEnv.TLS_CA
+ ? {
+ ca: redisEnv.TLS_CA,
+ }
+ : undefined,
+ username: redisEnv.USERNAME,
+ password: redisEnv.PASSWORD,
+ })
+ : new Redis(defaultRedisOptions);
diff --git a/packages/core/src/infrastructure/redis/env.ts b/packages/core/src/infrastructure/redis/env.ts
new file mode 100644
index 000000000..f54ec128c
--- /dev/null
+++ b/packages/core/src/infrastructure/redis/env.ts
@@ -0,0 +1,17 @@
+import { z } from "zod/v4";
+
+import { createEnv } from "../env";
+import { runtimeEnvWithPrefix } from "../env/prefix";
+import { createBooleanSchema } from "../env/schemas";
+
+export const redisEnv = createEnv({
+ server: {
+ IS_EXTERNAL: createBooleanSchema(false),
+ HOST: z.string().optional(),
+ PORT: z.coerce.number().default(6379).optional(),
+ TLS_CA: z.string().optional(),
+ USERNAME: z.string().optional(),
+ PASSWORD: z.string().optional(),
+ },
+ runtimeEnv: runtimeEnvWithPrefix("REDIS_"),
+});
diff --git a/packages/env/tsconfig.json b/packages/core/tsconfig.json
similarity index 100%
rename from packages/env/tsconfig.json
rename to packages/core/tsconfig.json
diff --git a/packages/cron-job-api/package.json b/packages/cron-job-api/package.json
index 828a5297f..88e248fbb 100644
--- a/packages/cron-job-api/package.json
+++ b/packages/cron-job-api/package.json
@@ -26,8 +26,8 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
+ "@homarr/core": "workspace:^0.1.0",
"@homarr/cron-jobs": "workspace:^0.1.0",
- "@homarr/env": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@tanstack/react-query": "^5.83.0",
"@trpc/client": "^11.4.3",
diff --git a/packages/cron-job-api/src/env.ts b/packages/cron-job-api/src/env.ts
index 1bc8f644a..7efb3f6e2 100644
--- a/packages/cron-job-api/src/env.ts
+++ b/packages/cron-job-api/src/env.ts
@@ -1,7 +1,7 @@
import { z } from "zod/v4";
import { env as commonEnv } from "@homarr/common/env";
-import { createEnv } from "@homarr/env";
+import { createEnv } from "@homarr/core/infrastructure/env";
export const env = createEnv({
server: {
diff --git a/packages/db/env.ts b/packages/db/env.ts
index dd8590b26..bb7ad0388 100644
--- a/packages/db/env.ts
+++ b/packages/db/env.ts
@@ -1,7 +1,7 @@
import { z } from "zod";
import { env as commonEnv } from "@homarr/common/env";
-import { createEnv } from "@homarr/env";
+import { createEnv } from "@homarr/core/infrastructure/env";
const drivers = {
betterSqlite3: "better-sqlite3",
diff --git a/packages/db/package.json b/packages/db/package.json
index 0d1dc7063..ecd1147fe 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -40,8 +40,8 @@
"dependencies": {
"@auth/core": "^0.40.0",
"@homarr/common": "workspace:^0.1.0",
+ "@homarr/core": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
- "@homarr/env": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.1.3",
diff --git a/packages/docker/package.json b/packages/docker/package.json
index 2de072d30..534211153 100644
--- a/packages/docker/package.json
+++ b/packages/docker/package.json
@@ -25,7 +25,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
- "@homarr/env": "workspace:^0.1.0",
+ "@homarr/core": "workspace:^0.1.0",
"dockerode": "^4.0.7"
},
"devDependencies": {
diff --git a/packages/docker/src/env.ts b/packages/docker/src/env.ts
index e71a26a66..a0ba6c5e2 100644
--- a/packages/docker/src/env.ts
+++ b/packages/docker/src/env.ts
@@ -1,7 +1,6 @@
import { z } from "zod";
-import { createEnv } from "@homarr/env";
-import { createBooleanSchema } from "@homarr/env/schemas";
+import { createBooleanSchema, createEnv } from "@homarr/core/infrastructure/env";
export const env = createEnv({
server: {
diff --git a/packages/env/index.ts b/packages/env/index.ts
deleted file mode 100644
index 3bd16e178..000000000
--- a/packages/env/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./src";
diff --git a/packages/log/package.json b/packages/log/package.json
index 8b0825d51..e53a7bd05 100644
--- a/packages/log/package.json
+++ b/packages/log/package.json
@@ -24,8 +24,7 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
- "@homarr/env": "workspace:^0.1.0",
- "ioredis": "5.6.1",
+ "@homarr/core": "workspace:^0.1.0",
"superjson": "2.2.2",
"winston": "3.17.0",
"zod": "^3.25.76"
diff --git a/packages/log/src/env.ts b/packages/log/src/env.ts
index a871914d2..cd6ea02d4 100644
--- a/packages/log/src/env.ts
+++ b/packages/log/src/env.ts
@@ -1,6 +1,6 @@
import { z } from "zod";
-import { createEnv } from "@homarr/env";
+import { createEnv } from "@homarr/core/infrastructure/env";
import { logLevels } from "./constants";
diff --git a/packages/log/src/redis-transport.ts b/packages/log/src/redis-transport.ts
index 4ca77ff2f..a674803bd 100644
--- a/packages/log/src/redis-transport.ts
+++ b/packages/log/src/redis-transport.ts
@@ -1,7 +1,9 @@
-import { Redis } from "ioredis";
import superjson from "superjson";
import Transport from "winston-transport";
+import type { RedisClient } from "@homarr/core/infrastructure/redis";
+import { createRedisClient } from "@homarr/core/infrastructure/redis";
+
const messageSymbol = Symbol.for("message");
const levelSymbol = Symbol.for("level");
@@ -10,7 +12,7 @@ const levelSymbol = Symbol.for("level");
// of the base functionality and `.exceptions.handle()`.
//
export class RedisTransport extends Transport {
- private redis: Redis | null = null;
+ private redis: RedisClient | null = null;
/**
* Log the info to the Redis channel
@@ -21,7 +23,7 @@ export class RedisTransport extends Transport {
});
// Is only initialized here because it did not work when initialized in the constructor or outside the class
- this.redis ??= new Redis();
+ this.redis ??= createRedisClient();
this.redis
.publish(
diff --git a/packages/redis/package.json b/packages/redis/package.json
index 77ab66b07..37624a09b 100644
--- a/packages/redis/package.json
+++ b/packages/redis/package.json
@@ -23,6 +23,8 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^",
+ "@homarr/core": "workspace:^",
+ "@homarr/db": "workspace:^",
"@homarr/definitions": "workspace:^",
"@homarr/log": "workspace:^",
"ioredis": "5.6.1",
diff --git a/packages/redis/src/lib/connection.ts b/packages/redis/src/lib/connection.ts
index af6c05fac..ba945de33 100644
--- a/packages/redis/src/lib/connection.ts
+++ b/packages/redis/src/lib/connection.ts
@@ -1,4 +1,5 @@
-import { Redis } from "ioredis";
+import type { RedisClient } from "@homarr/core/infrastructure/redis";
+import { createRedisClient } from "@homarr/core/infrastructure/redis";
/**
* Creates a new Redis connection
@@ -7,8 +8,8 @@ import { Redis } from "ioredis";
export const createRedisConnection = () => {
if (Boolean(process.env.CI) || Boolean(process.env.DISABLE_REDIS_LOGS)) {
// Return null if we are in CI as we don't want to connect to Redis
- return null as unknown as Redis;
+ return null as unknown as RedisClient;
}
- return new Redis();
+ return createRedisClient();
};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index deb1c9439..d524616b8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -37,6 +37,9 @@ importers:
'@semantic-release/release-notes-generator':
specifier: ^14.0.3
version: 14.0.3(semantic-release@24.2.7(typescript@5.8.3))
+ '@testcontainers/redis':
+ specifier: ^11.2.1
+ version: 11.2.1
'@turbo/gen':
specifier: ^2.5.5
version: 2.5.5(@types/node@22.16.4)(typescript@5.8.3)
@@ -112,6 +115,9 @@ importers:
'@homarr/common':
specifier: workspace:^0.1.0
version: link:../../packages/common
+ '@homarr/core':
+ specifier: workspace:^0.1.0
+ version: link:../../packages/core
'@homarr/cron-job-status':
specifier: workspace:^0.1.0
version: link:../../packages/cron-job-status
@@ -124,9 +130,6 @@ importers:
'@homarr/docker':
specifier: workspace:^0.1.0
version: link:../../packages/docker
- '@homarr/env':
- specifier: workspace:^0.1.0
- version: link:../../packages/env
'@homarr/form':
specifier: workspace:^0.1.0
version: link:../../packages/form
@@ -660,15 +663,15 @@ importers:
'@homarr/common':
specifier: workspace:^0.1.0
version: link:../common
+ '@homarr/core':
+ specifier: workspace:^0.1.0
+ version: link:../core
'@homarr/db':
specifier: workspace:^0.1.0
version: link:../db
'@homarr/definitions':
specifier: workspace:^0.1.0
version: link:../definitions
- '@homarr/env':
- specifier: workspace:^0.1.0
- version: link:../env
'@homarr/log':
specifier: workspace:^0.1.0
version: link:../log
@@ -823,9 +826,9 @@ importers:
packages/common:
dependencies:
- '@homarr/env':
+ '@homarr/core':
specifier: workspace:^0.1.0
- version: link:../env
+ version: link:../core
'@homarr/log':
specifier: workspace:^0.1.0
version: link:../log
@@ -870,17 +873,45 @@ importers:
specifier: ^5.8.3
version: 5.8.3
+ packages/core:
+ dependencies:
+ '@t3-oss/env-nextjs':
+ specifier: ^0.13.8
+ version: 0.13.8(arktype@2.1.20)(typescript@5.8.3)(zod@3.25.76)
+ ioredis:
+ specifier: 5.6.1
+ version: 5.6.1
+ zod:
+ specifier: ^3.25.76
+ version: 3.25.76
+ devDependencies:
+ '@homarr/eslint-config':
+ specifier: workspace:^0.2.0
+ version: link:../../tooling/eslint
+ '@homarr/prettier-config':
+ specifier: workspace:^0.1.0
+ version: link:../../tooling/prettier
+ '@homarr/tsconfig':
+ specifier: workspace:^0.1.0
+ version: link:../../tooling/typescript
+ eslint:
+ specifier: ^9.31.0
+ version: 9.31.0
+ typescript:
+ specifier: ^5.8.3
+ version: 5.8.3
+
packages/cron-job-api:
dependencies:
'@homarr/common':
specifier: workspace:^0.1.0
version: link:../common
+ '@homarr/core':
+ specifier: workspace:^0.1.0
+ version: link:../core
'@homarr/cron-jobs':
specifier: workspace:^0.1.0
version: link:../cron-jobs
- '@homarr/env':
- specifier: workspace:^0.1.0
- version: link:../env
'@homarr/log':
specifier: workspace:^0.1.0
version: link:../log
@@ -1056,12 +1087,12 @@ importers:
'@homarr/common':
specifier: workspace:^0.1.0
version: link:../common
+ '@homarr/core':
+ specifier: workspace:^0.1.0
+ version: link:../core
'@homarr/definitions':
specifier: workspace:^0.1.0
version: link:../definitions
- '@homarr/env':
- specifier: workspace:^0.1.0
- version: link:../env
'@homarr/log':
specifier: workspace:^0.1.0
version: link:../log
@@ -1166,9 +1197,9 @@ importers:
'@homarr/common':
specifier: workspace:^0.1.0
version: link:../common
- '@homarr/env':
+ '@homarr/core':
specifier: workspace:^0.1.0
- version: link:../env
+ version: link:../core
dockerode:
specifier: ^4.0.7
version: 4.0.7
@@ -1192,31 +1223,6 @@ importers:
specifier: ^5.8.3
version: 5.8.3
- packages/env:
- dependencies:
- '@t3-oss/env-nextjs':
- specifier: ^0.13.8
- version: 0.13.8(arktype@2.1.20)(typescript@5.8.3)(zod@3.25.76)
- zod:
- specifier: ^3.25.76
- version: 3.25.76
- devDependencies:
- '@homarr/eslint-config':
- specifier: workspace:^0.2.0
- version: link:../../tooling/eslint
- '@homarr/prettier-config':
- specifier: workspace:^0.1.0
- version: link:../../tooling/prettier
- '@homarr/tsconfig':
- specifier: workspace:^0.1.0
- version: link:../../tooling/typescript
- eslint:
- specifier: ^9.31.0
- version: 9.31.0
- typescript:
- specifier: ^5.8.3
- version: 5.8.3
-
packages/form:
dependencies:
'@homarr/common':
@@ -1461,12 +1467,9 @@ importers:
packages/log:
dependencies:
- '@homarr/env':
+ '@homarr/core':
specifier: workspace:^0.1.0
- version: link:../env
- ioredis:
- specifier: 5.6.1
- version: 5.6.1
+ version: link:../core
superjson:
specifier: 2.2.2
version: 2.2.2
@@ -1740,6 +1743,12 @@ importers:
'@homarr/common':
specifier: workspace:^
version: link:../common
+ '@homarr/core':
+ specifier: workspace:^
+ version: link:../core
+ '@homarr/db':
+ specifier: workspace:^
+ version: link:../db
'@homarr/definitions':
specifier: workspace:^
version: link:../definitions
@@ -4423,6 +4432,9 @@ packages:
'@testcontainers/mysql@11.3.0':
resolution: {integrity: sha512-5zOzAcsQUVbN9tCC6cbD0zkxOu/P8NdFsYc+w1YFctGUOf5DL0QBBwDv5LkFj92+eic4veggPlzVd2SX8LT3SQ==}
+ '@testcontainers/redis@11.2.1':
+ resolution: {integrity: sha512-Q5j+irNw0BLec3he30s2E0fhE06Zr9ROVutkyKUgcwQoZxEVW3xV69ke2AFCT5teEcIvTKqevObN4UDkq33Qow==}
+
'@tiptap/core@2.26.1':
resolution: {integrity: sha512-fymyd/XZvYiHjBoLt1gxs024xP/LY26d43R1vluYq7AHBL/7DE3ywzy+1GEsGyAv5Je2L0KBhNIR/izbq3Kaqg==}
peerDependencies:
@@ -13172,6 +13184,13 @@ snapshots:
- bare-buffer
- supports-color
+ '@testcontainers/redis@11.2.1':
+ dependencies:
+ testcontainers: 11.3.0
+ transitivePeerDependencies:
+ - bare-buffer
+ - supports-color
+
'@tiptap/core@2.26.1(@tiptap/pm@2.26.1)':
dependencies:
'@tiptap/pm': 2.26.1
@@ -16639,7 +16658,7 @@ snapshots:
dependencies:
'@ioredis/commands': 1.2.0
cluster-key-slot: 1.1.2
- debug: 4.4.0
+ debug: 4.4.1
denque: 2.1.0
lodash.defaults: 4.2.0
lodash.isarguments: 3.1.0
diff --git a/scripts/run.sh b/scripts/run.sh
index 296d39815..9fc481fdd 100644
--- a/scripts/run.sh
+++ b/scripts/run.sh
@@ -25,8 +25,15 @@ envsubst '${HOSTNAME}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf
nginx -g 'daemon off;' &
NGINX_PID=$!
-redis-server /app/redis.conf &
-REDIS_PID=$!
+if [ $REDIS_IS_EXTERNAL = "true" ]; then
+ echo "Using external Redis server at redis://$REDIS_HOST:$REDIS_PORT"
+else
+ echo "Starting internal Redis server"
+ redis-server /app/redis.conf &
+ REDIS_PID=$!
+fi
+
+
node apps/tasks/tasks.cjs &
TASKS_PID=$!
From 98f8279b61013c312d492522e317bcf93f10e2a6 Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Sun, 20 Jul 2025 15:21:47 +0000
Subject: [PATCH 11/13] fix(deps): update testcontainers-node monorepo to
^11.3.1 (#3659)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
package.json | 4 ++--
packages/db/package.json | 2 +-
pnpm-lock.yaml | 34 +++++++++++++++++-----------------
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/package.json b/package.json
index 5b9d3d38d..0f659878e 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"@semantic-release/github": "^11.0.3",
"@semantic-release/npm": "^12.0.2",
"@semantic-release/release-notes-generator": "^14.0.3",
- "@testcontainers/redis": "^11.2.1",
+ "@testcontainers/redis": "^11.3.1",
"@turbo/gen": "^2.5.5",
"@vitejs/plugin-react": "^4.7.0",
"@vitest/coverage-v8": "^3.2.4",
@@ -48,7 +48,7 @@
"jsdom": "^26.1.0",
"prettier": "^3.6.2",
"semantic-release": "^24.2.7",
- "testcontainers": "^11.3.0",
+ "testcontainers": "^11.3.1",
"turbo": "^2.5.5",
"typescript": "^5.8.3",
"vite-tsconfig-paths": "^5.1.4",
diff --git a/packages/db/package.json b/packages/db/package.json
index ecd1147fe..bca8c851d 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -46,7 +46,7 @@
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.1.3",
"@paralleldrive/cuid2": "^2.2.2",
- "@testcontainers/mysql": "^11.3.0",
+ "@testcontainers/mysql": "^11.3.1",
"better-sqlite3": "^12.2.0",
"dotenv": "^17.2.0",
"drizzle-kit": "^0.31.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d524616b8..9a56bae51 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,8 +38,8 @@ importers:
specifier: ^14.0.3
version: 14.0.3(semantic-release@24.2.7(typescript@5.8.3))
'@testcontainers/redis':
- specifier: ^11.2.1
- version: 11.2.1
+ specifier: ^11.3.1
+ version: 11.3.1
'@turbo/gen':
specifier: ^2.5.5
version: 2.5.5(@types/node@22.16.4)(typescript@5.8.3)
@@ -68,8 +68,8 @@ importers:
specifier: ^24.2.7
version: 24.2.7(typescript@5.8.3)
testcontainers:
- specifier: ^11.3.0
- version: 11.3.0
+ specifier: ^11.3.1
+ version: 11.3.1
turbo:
specifier: ^2.5.5
version: 2.5.5
@@ -1106,8 +1106,8 @@ importers:
specifier: ^2.2.2
version: 2.2.2
'@testcontainers/mysql':
- specifier: ^11.3.0
- version: 11.3.0
+ specifier: ^11.3.1
+ version: 11.3.1
better-sqlite3:
specifier: ^12.2.0
version: 12.2.0
@@ -4429,11 +4429,11 @@ packages:
'@tanstack/virtual-core@3.11.2':
resolution: {integrity: sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==}
- '@testcontainers/mysql@11.3.0':
- resolution: {integrity: sha512-5zOzAcsQUVbN9tCC6cbD0zkxOu/P8NdFsYc+w1YFctGUOf5DL0QBBwDv5LkFj92+eic4veggPlzVd2SX8LT3SQ==}
+ '@testcontainers/mysql@11.3.1':
+ resolution: {integrity: sha512-MC5AzgifmW8decbnAXrDSlU5cK2ZKwgBmIXFxVFQ34V+aR6tqf0boJlMjvVV5Th5+minRiliMd0wpw5RdGQNrg==}
- '@testcontainers/redis@11.2.1':
- resolution: {integrity: sha512-Q5j+irNw0BLec3he30s2E0fhE06Zr9ROVutkyKUgcwQoZxEVW3xV69ke2AFCT5teEcIvTKqevObN4UDkq33Qow==}
+ '@testcontainers/redis@11.3.1':
+ resolution: {integrity: sha512-fs3IDQuZa8fF9HzcY6HSWeT94Ovx84T0UhaiDuUDHS7dR/tZFlE5WBw4oGDSxsvYYu7n/O47KOMhTHfUS8x1IA==}
'@tiptap/core@2.26.1':
resolution: {integrity: sha512-fymyd/XZvYiHjBoLt1gxs024xP/LY26d43R1vluYq7AHBL/7DE3ywzy+1GEsGyAv5Je2L0KBhNIR/izbq3Kaqg==}
@@ -10047,8 +10047,8 @@ packages:
resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
engines: {node: '>=18'}
- testcontainers@11.3.0:
- resolution: {integrity: sha512-bfSfWDZl5Ima/wRkDjoyuntLIp7wFv7jc+97/BL1zJyKszMFEDHsDcH1ryv8L4kYqVfl6V0efMzY4tluypa1nw==}
+ testcontainers@11.3.1:
+ resolution: {integrity: sha512-5oO0oQjF7gdWdXCVYC3vH6iSTDW8rQsWq7p5xdR17ujhhiPfQgf0hptqmeCCcnht/Qw6wWk5h1JlZnaJPP/Bhg==}
text-decoder@1.2.0:
resolution: {integrity: sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==}
@@ -13177,16 +13177,16 @@ snapshots:
'@tanstack/virtual-core@3.11.2': {}
- '@testcontainers/mysql@11.3.0':
+ '@testcontainers/mysql@11.3.1':
dependencies:
- testcontainers: 11.3.0
+ testcontainers: 11.3.1
transitivePeerDependencies:
- bare-buffer
- supports-color
- '@testcontainers/redis@11.2.1':
+ '@testcontainers/redis@11.3.1':
dependencies:
- testcontainers: 11.3.0
+ testcontainers: 11.3.1
transitivePeerDependencies:
- bare-buffer
- supports-color
@@ -19771,7 +19771,7 @@ snapshots:
glob: 10.4.5
minimatch: 9.0.5
- testcontainers@11.3.0:
+ testcontainers@11.3.1:
dependencies:
'@balena/dockerignore': 1.0.2
'@types/dockerode': 3.3.42
From bf88f0d0918b4073a5770ab3589e00e5f89cacf1 Mon Sep 17 00:00:00 2001
From: "homarr-renovate[bot]"
<158783068+homarr-renovate[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 01:25:53 +0000
Subject: [PATCH 12/13] fix(deps): update dependency @tabler/icons-react to
^3.34.1 (#3661)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
---
apps/nextjs/package.json | 2 +-
packages/modals-collection/package.json | 2 +-
packages/notifications/package.json | 2 +-
packages/spotlight/package.json | 2 +-
packages/ui/package.json | 2 +-
packages/widgets/package.json | 2 +-
pnpm-lock.yaml | 59 ++++++++++++-------------
7 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json
index 0056c33b8..4add7f6f2 100644
--- a/apps/nextjs/package.json
+++ b/apps/nextjs/package.json
@@ -57,7 +57,7 @@
"@mantine/modals": "^8.1.3",
"@mantine/tiptap": "^8.1.3",
"@million/lint": "1.0.14",
- "@tabler/icons-react": "^3.34.0",
+ "@tabler/icons-react": "^3.34.1",
"@tanstack/react-query": "^5.83.0",
"@tanstack/react-query-devtools": "^5.83.0",
"@tanstack/react-query-next-experimental": "^5.83.0",
diff --git a/packages/modals-collection/package.json b/packages/modals-collection/package.json
index 14c527cf8..945cc4ed6 100644
--- a/packages/modals-collection/package.json
+++ b/packages/modals-collection/package.json
@@ -34,7 +34,7 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.1.3",
- "@tabler/icons-react": "^3.34.0",
+ "@tabler/icons-react": "^3.34.1",
"dayjs": "^1.11.13",
"next": "15.4.2",
"react": "19.1.0",
diff --git a/packages/notifications/package.json b/packages/notifications/package.json
index 4c4f09102..44f09359b 100644
--- a/packages/notifications/package.json
+++ b/packages/notifications/package.json
@@ -25,7 +25,7 @@
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^8.1.3",
- "@tabler/icons-react": "^3.34.0"
+ "@tabler/icons-react": "^3.34.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
diff --git a/packages/spotlight/package.json b/packages/spotlight/package.json
index 82c9e60b7..4c73cd086 100644
--- a/packages/spotlight/package.json
+++ b/packages/spotlight/package.json
@@ -36,7 +36,7 @@
"@mantine/core": "^8.1.3",
"@mantine/hooks": "^8.1.3",
"@mantine/spotlight": "^8.1.3",
- "@tabler/icons-react": "^3.34.0",
+ "@tabler/icons-react": "^3.34.1",
"jotai": "^2.12.5",
"next": "15.4.2",
"react": "19.1.0",
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 3cec20442..a7dbeb7d7 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -33,7 +33,7 @@
"@mantine/core": "^8.1.3",
"@mantine/dates": "^8.1.3",
"@mantine/hooks": "^8.1.3",
- "@tabler/icons-react": "^3.34.0",
+ "@tabler/icons-react": "^3.34.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.4.2",
"react": "19.1.0",
diff --git a/packages/widgets/package.json b/packages/widgets/package.json
index 965e20883..1ae4a995b 100644
--- a/packages/widgets/package.json
+++ b/packages/widgets/package.json
@@ -51,7 +51,7 @@
"@mantine/charts": "^8.1.3",
"@mantine/core": "^8.1.3",
"@mantine/hooks": "^8.1.3",
- "@tabler/icons-react": "^3.34.0",
+ "@tabler/icons-react": "^3.34.1",
"@tiptap/extension-color": "2.26.1",
"@tiptap/extension-highlight": "2.26.1",
"@tiptap/extension-image": "2.26.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9a56bae51..576dfdb41 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -212,8 +212,8 @@ importers:
specifier: 1.0.14
version: 1.0.14(rollup@4.21.3)(webpack-sources@3.2.3)
'@tabler/icons-react':
- specifier: ^3.34.0
- version: 3.34.0(react@19.1.0)
+ specifier: ^3.34.1
+ version: 3.34.1(react@19.1.0)
'@tanstack/react-query':
specifier: ^5.83.0
version: 5.83.0(react@19.1.0)
@@ -267,7 +267,7 @@ importers:
version: 2.12.5(@types/react@19.1.8)(react@19.1.0)
mantine-react-table:
specifier: 2.0.0-beta.9
- version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.1(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
specifier: 15.4.2
version: 15.4.2(@babel/core@7.26.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
@@ -1569,8 +1569,8 @@ importers:
specifier: ^8.1.3
version: 8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tabler/icons-react':
- specifier: ^3.34.0
- version: 3.34.0(react@19.1.0)
+ specifier: ^3.34.1
+ version: 3.34.1(react@19.1.0)
dayjs:
specifier: ^1.11.13
version: 1.11.13
@@ -1612,8 +1612,8 @@ importers:
specifier: ^8.1.3
version: 8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tabler/icons-react':
- specifier: ^3.34.0
- version: 3.34.0(react@19.1.0)
+ specifier: ^3.34.1
+ version: 3.34.1(react@19.1.0)
devDependencies:
'@homarr/eslint-config':
specifier: workspace:^0.2.0
@@ -1937,8 +1937,8 @@ importers:
specifier: ^8.1.3
version: 8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tabler/icons-react':
- specifier: ^3.34.0
- version: 3.34.0(react@19.1.0)
+ specifier: ^3.34.1
+ version: 3.34.1(react@19.1.0)
jotai:
specifier: ^2.12.5
version: 2.12.5(@types/react@19.1.8)(react@19.1.0)
@@ -1987,7 +1987,7 @@ importers:
version: 4.3.1
mantine-react-table:
specifier: 2.0.0-beta.9
- version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.1(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
specifier: 15.4.2
version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
@@ -2044,11 +2044,11 @@ importers:
specifier: ^8.1.3
version: 8.1.3(react@19.1.0)
'@tabler/icons-react':
- specifier: ^3.34.0
- version: 3.34.0(react@19.1.0)
+ specifier: ^3.34.1
+ version: 3.34.1(react@19.1.0)
mantine-react-table:
specifier: 2.0.0-beta.9
- version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.1(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
specifier: 15.4.2
version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
@@ -2193,8 +2193,8 @@ importers:
specifier: ^8.1.3
version: 8.1.3(react@19.1.0)
'@tabler/icons-react':
- specifier: ^3.34.0
- version: 3.34.0(react@19.1.0)
+ specifier: ^3.34.1
+ version: 3.34.1(react@19.1.0)
'@tiptap/extension-color':
specifier: 2.26.1
version: 2.26.1(@tiptap/core@2.26.1(@tiptap/pm@2.26.1))(@tiptap/extension-text-style@2.26.1(@tiptap/core@2.26.1(@tiptap/pm@2.26.1)))
@@ -2251,7 +2251,7 @@ importers:
version: 1.11.13
mantine-react-table:
specifier: 2.0.0-beta.9
- version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.1(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next:
specifier: 15.4.2
version: 15.4.2(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.2)
@@ -2300,7 +2300,7 @@ importers:
version: 15.4.2
eslint-config-prettier:
specifier: ^10.1.7
- version: 10.1.7(eslint@9.31.0)
+ version: 10.1.8(eslint@9.31.0)
eslint-config-turbo:
specifier: ^2.5.5
version: 2.5.5(eslint@9.31.0)(turbo@2.5.5)
@@ -4373,13 +4373,13 @@ packages:
zod:
optional: true
- '@tabler/icons-react@3.34.0':
- resolution: {integrity: sha512-OpEIR2iZsIXECtAIMbn1zfKfQ3zKJjXyIZlkgOGUL9UkMCFycEiF2Y8AVfEQsyre/3FnBdlWJvGr0NU47n2TbQ==}
+ '@tabler/icons-react@3.34.1':
+ resolution: {integrity: sha512-Ld6g0NqOO05kyyHsfU8h787PdHBm7cFmOycQSIrGp45XcXYDuOK2Bs0VC4T2FWSKZ6bx5g04imfzazf/nqtk1A==}
peerDependencies:
react: '>= 16'
- '@tabler/icons@3.34.0':
- resolution: {integrity: sha512-jtVqv0JC1WU2TTEBN32D9+R6mc1iEBuPwLnBsWaR02SIEciu9aq5806AWkCHuObhQ4ERhhXErLEK7Fs+tEZxiA==}
+ '@tabler/icons@3.34.1':
+ resolution: {integrity: sha512-9gTnUvd7Fd/DmQgr3MKY+oJLa1RfNsQo8c/ir3TJAWghOuZXodbtbVp0QBY2DxWuuvrSZFys0HEbv1CoiI5y6A==}
'@tanstack/match-sorter-utils@8.19.4':
resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==}
@@ -6547,9 +6547,8 @@ packages:
engines: {node: '>=6.0'}
hasBin: true
- eslint-config-prettier@10.1.7:
- resolution: {integrity: sha512-xztdELuHs7grBM+qdMUF4M4SjPpeOMN3kx7sGU6ifl5yibck/GRa0+0d+m1lPsGNkd+2bIWh2lUUTzX7MX/obw==}
- deprecated: This is a malicious version, don't use
+ eslint-config-prettier@10.1.8:
+ resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
@@ -13129,12 +13128,12 @@ snapshots:
typescript: 5.8.3
zod: 3.25.76
- '@tabler/icons-react@3.34.0(react@19.1.0)':
+ '@tabler/icons-react@3.34.1(react@19.1.0)':
dependencies:
- '@tabler/icons': 3.34.0
+ '@tabler/icons': 3.34.1
react: 19.1.0
- '@tabler/icons@3.34.0': {}
+ '@tabler/icons@3.34.1': {}
'@tanstack/match-sorter-utils@8.19.4':
dependencies:
@@ -15685,7 +15684,7 @@ snapshots:
optionalDependencies:
source-map: 0.6.1
- eslint-config-prettier@10.1.7(eslint@9.31.0):
+ eslint-config-prettier@10.1.8(eslint@9.31.0):
dependencies:
eslint: 9.31.0
@@ -17278,12 +17277,12 @@ snapshots:
make-error@1.3.6: {}
- mantine-react-table@2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ mantine-react-table@2.0.0-beta.9(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.1(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@mantine/core': 8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mantine/dates': 8.1.3(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mantine/hooks': 8.1.3(react@19.1.0)
- '@tabler/icons-react': 3.34.0(react@19.1.0)
+ '@tabler/icons-react': 3.34.1(react@19.1.0)
'@tanstack/match-sorter-utils': 8.19.4
'@tanstack/react-table': 8.20.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tanstack/react-virtual': 3.11.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
From ecda928bef407c67f01ce798c5f7a086cbd0dd9c Mon Sep 17 00:00:00 2001
From: Meier Lukas
Date: Mon, 21 Jul 2025 07:54:13 +0000
Subject: [PATCH 13/13] fix(security): upgrade eslint-config-prettier to latest
version without malicious code
---
pnpm-lock.yaml | 2 +-
tooling/eslint/package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 576dfdb41..7608d9e45 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2299,7 +2299,7 @@ importers:
specifier: 15.4.2
version: 15.4.2
eslint-config-prettier:
- specifier: ^10.1.7
+ specifier: ^10.1.8
version: 10.1.8(eslint@9.31.0)
eslint-config-turbo:
specifier: ^2.5.5
diff --git a/tooling/eslint/package.json b/tooling/eslint/package.json
index 72f88418f..79a94f1af 100644
--- a/tooling/eslint/package.json
+++ b/tooling/eslint/package.json
@@ -18,7 +18,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@next/eslint-plugin-next": "15.4.2",
- "eslint-config-prettier": "^10.1.7",
+ "eslint-config-prettier": "^10.1.8",
"eslint-config-turbo": "^2.5.5",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",