Compare commits

...
Author SHA1 Message Date
Releases Homarr 168b587c18 chore(release): 1.0.0-beta.10 [skip ci] 2024-12-31 10:42:11 +00:00
homarr-releases[bot] dc12a82805 chore(release): automatic release v1.0.0 2024-12-31 10:41:19 +00:00
ManuelandMeier Lukas f5076454cd feat(integration): add search engine creation (#1816)
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-31 11:40:37 +01:00
Meier Lukas aeb681a858 feat(docker): add support for pgid and puid env variables (#1759) 2024-12-31 11:36:28 +01:00
Meier Lukas 56b57ad171 fix(docker): replace anonymous docker volume with env variable for encrypting secrets (#1809) 2024-12-31 11:30:29 +01:00
Manuel 91e1cef611 feat: add request media (#1811) 2024-12-31 11:05:30 +01:00
homarr-renovate[bot] e53b06e8c2 chore(deps): update dependency concurrently to ^9.1.2 (#1818)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-31 08:46:41 +00:00
Meier Lukas 0ebf4bc55e feat(widget): add minecraft server status widget (#1801) 2024-12-31 09:45:48 +01:00
homarr-crowdin[bot] b8a155dd08 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-31 00:43:59 +00:00
Thomas CamlongandMeier Lukas 63786eed06 chore(lang): updated translations from crowdin (#1803)
* New translations en.json (Chinese Simplified)

* New translations en.json (Turkish)

* New translations en.json (Turkish)

* New translations en.json (Turkish)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Croatian)

* New translations en.json (Estonian)

* New translations en.json (Latvian)

* New translations en.json (Cree)

* New translations en.json (Hebrew)

* New translations en.json (Hebrew)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-30 21:44:23 +01:00
homarr-renovate[bot] 598f0047eb fix(deps): update dependency typescript-eslint to ^8.19.0 (#1814)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-30 17:33:38 +00:00
homarr-renovate[bot] eacda4c397 fix(deps): update tiptap monorepo to v2.11.0 (#1813)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-30 16:54:00 +00:00
Meier Lukas 5cb726f793 ci(docker): always push image (#1812) 2024-12-30 17:38:27 +01:00
homarr-crowdin[bot] e8d29420e0 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-30 16:28:16 +00:00
Yossi Hillali 23c7d0bbf0 fix(media-server): redesign widget (#1775)
* fix: redisign media server widget

* fix: reviewed changes

* fix: reviewed chenges

* fix: add icon title

* fix: text resize
2024-12-29 19:24:38 +02:00
homarr-renovate[bot] 75aefcb0d5 fix(deps): update dependency octokit to ^4.0.3 (#1806)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-29 16:16:34 +00:00
homarr-crowdin[bot] b52a8a7935 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-29 08:27:17 +00:00
homarr-renovate[bot] 6d90209e00 chore(deps): update pnpm to v9.15.2 (#1804)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-29 08:26:48 +00:00
Thomas CamlongandMeier Lukas 8f0945f51a chore(lang): updated translations from crowdin (#1800)
* New translations en.json (German)

* New translations en.json (Hebrew)

* New translations en.json (Hebrew)

* New translations en.json (Turkish)

* New translations en.json (Chinese Simplified)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-28 18:50:25 +01:00
homarr-crowdin[bot] 5b04b93f23 chore(lang): updated translations from crowdin (#1802)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-28 18:49:22 +01:00
Thomas CamlongandMeier Lukas c8228b920c chore(lang): updated translations from crowdin (#1797)
* New translations en.json (Hebrew)

* New translations en.json (Turkish)

* New translations en.json (Turkish)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-28 10:25:14 +01:00
homarr-crowdin[bot] abf7942fb7 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-28 09:14:42 +00:00
homarr-crowdin[bot] 50746eb3e4 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-28 09:06:24 +00:00
Thomas CamlongandMeier Lukas 76abfca11b chore(lang): updated translations from crowdin (#1786)
* New translations en.json (Hebrew)

* New translations en.json (Dutch)

* New translations en.json (Hebrew)

* New translations en.json (Hebrew)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Vietnamese)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Croatian)

* New translations en.json (Latvian)

* New translations en.json (Cree)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-27 20:47:14 +01:00
homarr-crowdin[bot] fcab6a347d chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-27 19:43:44 +00:00
Yossi Hillali c91aae53ac fix(health-monitoring): add months to uptime, fix status update (#1792) 2024-12-27 21:32:04 +02:00
homarr-renovate[bot]andMeier Lukas 4943e7b851 fix(deps): update dependency trpc-to-openapi to ^2.1.1 (#1788)
* fix(deps): update dependency trpc-to-openapi to ^2.1.1

* fix(deps): missing dependency lodash.clonedeep in api package

---------

Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-27 20:31:15 +01:00
Releases Homarr 88c423fca6 chore(release): 1.0.0-beta.9 [skip ci] 2024-12-27 19:13:01 +00:00
homarr-releases[bot] f238663ec7 chore(release): automatic release v1.0.0 2024-12-27 19:12:07 +00:00
homarr-renovate[bot] e9870e7ee7 fix(deps): update tanstack-query monorepo to ^5.62.11 (#1791)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-27 13:22:52 +00:00
homarr-renovate[bot] 9c0a0ced04 chore(deps): update dependency concurrently to ^9.1.1 (#1790)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-27 11:53:46 +00:00
homarr-crowdin[bot] 4c27635066 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-27 00:44:11 +00:00
homarr-renovate[bot] 3d66ff9148 fix(deps): update nextjs monorepo to ^14.2.22 (#1787)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-26 18:20:53 +00:00
Meier Lukas ec257e5f60 chore(env): remove unused vercel-url env variable (#1779)
* chore(env): remove unused vercel-url env variable

* chore: remove vercel-json file
2024-12-26 08:58:27 +01:00
Meier Lukas ef24370a8c refactor: revert assignment of oldmarr widget mapping (#1780) 2024-12-26 08:58:06 +01:00
Releases Homarr 1fa0fc50c5 chore(release): 1.0.0-beta.8 [skip ci] 2024-12-25 14:19:38 +00:00
homarr-releases[bot] e9a1dae857 chore(release): automatic release v1.0.0 2024-12-25 14:18:45 +00:00
Meier Lukas e37279fe80 fix: oldmarr import user casing wrong (#1784) 2024-12-25 15:17:51 +01:00
homarr-renovate[bot] 82c6ce7b77 fix(deps): update dependency drizzle-orm to ^0.38.3 (#1783)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-25 12:25:14 +00:00
homarr-renovate[bot] 555212e2dc fix(deps): update dependency drizzle-zod to ^0.6.1 (#1782)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-25 10:53:06 +00:00
homarr-crowdin[bot] c831539772 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-25 00:43:00 +00:00
homarr-renovate[bot] 3e2ffbd7bf fix(deps): update dependency @ctrl/transmission to ^7.2.0 (#1777)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-24 20:33:01 +00:00
Thomas Camlong 22d7f676eb chore(lang): updated translations from crowdin (#1774)
* New translations en.json (Hebrew)

* New translations en.json (Hebrew)
2024-12-24 21:26:29 +01:00
homarr-crowdin[bot] 23bf262f4e chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-24 20:26:03 +00:00
homarr-renovate[bot] ecae80d741 fix(deps): update dependency @ctrl/deluge to ^7.1.0 (#1776)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-24 20:16:58 +00:00
Releases Homarr 162e8adf4c chore(release): 1.0.0-beta.7 [skip ci] 2024-12-24 13:34:42 +00:00
homarr-releases[bot] 620ec0315f chore(release): automatic release v1.0.0 2024-12-24 13:33:47 +00:00
Meier Lukas 8df398c3c7 feat(apps): remove url variables (#1771) 2024-12-24 14:16:24 +01:00
Meier Lukas 425359be02 fix(board): item background and border overridden by mantine card styles (#1769) 2024-12-24 14:16:11 +01:00
Meier Lukas 8893b72fe3 fix(board): tiles order not respected on firefox (#1770) 2024-12-24 14:15:58 +01:00
Meier Lukas b9483379dd fix(onboard): missing admin permission assignment for external group (#1764) 2024-12-24 14:15:46 +01:00
Meier Lukas 0336803550 fix(auth): oidc redirect does not respect https protocol (#1763) 2024-12-24 14:15:34 +01:00
Meier Lukas e220087e96 fix(icons): local icon repository does not work with medias (#1765) 2024-12-24 14:15:18 +01:00
Manuel f127c9325c config: update issue templates (#1751) 2024-12-24 13:05:59 +00:00
homarr-renovate[bot] c410b06a15 fix(deps): update tanstack-query monorepo to ^5.62.10 (#1772)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-24 12:25:11 +00:00
Thomas Camlong ce755efe4d chore(lang): updated translations from crowdin (#1760)
* New translations en.json (Hungarian)

* New translations en.json (Hebrew)

* New translations en.json (Hebrew)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Hebrew)
2024-12-24 11:01:14 +01:00
homarr-renovate[bot] 8b416a6dd3 fix(deps): update dependency @ctrl/qbittorrent to ^9.2.0 (#1768)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-24 04:18:59 +00:00
homarr-renovate[bot] fe95334aa7 fix(deps): update dependency eslint-plugin-react to ^7.37.3 (#1767)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-24 03:02:21 +00:00
homarr-crowdin[bot] b0facfd77a chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-24 00:44:22 +00:00
homarr-renovate[bot] 01db27c34f fix(deps): update dependency react-error-boundary to v5 (#1748)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 20:17:53 +01:00
homarr-renovate[bot] 999cf58625 chore(deps): update dependency dotenv-cli to v8 (#1741)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 20:14:01 +01:00
homarr-renovate[bot] 9223dd06ee fix(deps): update dependency typescript-eslint to ^8.18.2 (#1762)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 17:34:06 +00:00
homarr-renovate[bot] 42da2b9b06 fix(deps): update tanstack-query monorepo to ^5.62.9 (#1761)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 17:15:12 +00:00
Thomas CamlongandMeier Lukas a73eed63eb chore(lang): updated translations from crowdin (#1754)
* New translations en.json (Italian)

* New translations en.json (Hungarian)

* New translations en.json (Hungarian)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-23 12:01:12 +01:00
homarr-crowdin[bot] 44dcc72d43 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-23 10:51:54 +00:00
homarr-renovate[bot] d02ded5511 fix(deps): update dependency mysql2 to v3.12.0 (#1758)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 10:38:45 +00:00
homarr-renovate[bot] dfacb08dbd fix(deps): update mantine monorepo to ^7.15.2 (#1757)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 10:17:37 +00:00
homarr-renovate[bot] 4e85bbbad0 fix(deps): update dependency jotai to ^2.11.0 (#1756)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-23 06:21:05 +00:00
ManuelandMeier Lukas d78c6ed529 fix: copy media link (#1750)
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-22 20:20:33 +01:00
Thomas CamlongandMeier Lukas 210ce3669f chore(lang): updated translations from crowdin (#1747)
* New translations en.json (German)

* New translations en.json (German)

* New translations en.json (German)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-22 18:39:19 +01:00
homarr-crowdin[bot] 44e5346d75 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-22 17:25:57 +00:00
Meier Lukas d34d665229 docs: update crowdin badge to new translation project (#1745) 2024-12-22 15:40:57 +01:00
Thomas CamlongandMeier Lukas b6dc38483d chore(lang): updated translations from crowdin (#1738)
* New translations en.json (Turkish)

* New translations en.json (Turkish)

* New translations en.json (German)

* New translations en.json (Turkish)

* New translations en.json (German)

* New translations en.json (Hebrew)

* New translations en.json (Chinese Simplified)

* New translations en.json (Hebrew)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Simplified)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-21 12:13:42 +01:00
homarr-crowdin[bot] a7e387e54c chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-21 11:10:45 +00:00
homarr-crowdin[bot] 189f35f3cb chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-21 11:05:13 +00:00
Releases Homarr 3c8d4f5018 chore(release): 1.0.0-beta.6 [skip ci] 2024-12-20 19:13:19 +00:00
homarr-releases[bot] 2b59f19a7f chore(release): automatic release v1.0.0 2024-12-20 19:12:27 +00:00
homarr-renovate[bot] fff1da88bd fix(deps): update dependency next-intl to v3.26.3 (#1740)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-20 13:23:18 +00:00
homarr-renovate[bot] 720fdb772c fix(deps): update dependency ioredis to v5.4.2 (#1739)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-20 12:25:58 +00:00
homarr-renovate[bot] a225bdd70c chore(deps): update pnpm to v9.15.1 (#1737)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-20 00:55:05 +00:00
homarr-crowdin[bot] e40c348352 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-20 00:44:25 +00:00
Thomas Camlong 28e1175565 chore(lang): updated translations from crowdin (#1734)
* New translations en.json (Slovak)

* New translations en.json (Slovak)
2024-12-19 23:28:56 +01:00
homarr-crowdin[bot] b450b00934 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-19 22:28:10 +00:00
Thomas CamlongandMeier Lukas 8e0bf87c56 chore(lang): updated translations from crowdin (#1722)
* New translations en.json (Hungarian)

* New translations en.json (Russian)

* New translations en.json (Turkish)

* New translations en.json (Hungarian)

* New translations en.json (Turkish)

* New translations en.json (Hungarian)

* New translations en.json (Turkish)

* New translations en.json (Turkish)

* New translations en.json (Chinese Traditional)

* New translations en.json (Czech)

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-12-19 19:45:58 +01:00
homarr-crowdin[bot] 9e061f8fc7 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2024-12-19 18:34:13 +00:00
Releases Homarr 10855bd84c chore(release): 1.0.0-beta.5 [skip ci] 2024-12-19 16:52:00 +00:00
homarr-releases[bot] 93d5ca683b chore(release): automatic release v1.0.0 2024-12-19 16:51:02 +00:00
Meier Lukas d2584b63c5 fix: always require db-user and password for mysql (#1730) 2024-12-19 17:48:10 +01:00
Meier Lukas 8c1156240c fix: about version is one behind because of missing package-json update in deploy (#1725) 2024-12-19 16:11:12 +01:00
Meier Lukas bb7f751481 fix: update of dev branch has no credentials (#1724) 2024-12-19 16:10:55 +01:00
Meier Lukas 1e8a5359b7 fix: allow additional file-type for oldmarr import (#1723) 2024-12-19 16:10:33 +01:00
Meier Lukas 550bca6dee fix: mysql operations not working (#1728) 2024-12-19 16:10:22 +01:00
homarr-renovate[bot] 2ae3d938ee fix(deps): update tiptap monorepo to v2.10.4 (#1729)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-19 13:05:35 +00:00
homarr-renovate[bot] 2b4bc8352e fix(deps): update nextjs monorepo to ^14.2.21 (#1727)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-19 11:16:50 +00:00
homarr-renovate[bot] c0f681637d fix(deps): update dependency tldts to ^6.1.69 (#1726)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-19 11:15:50 +00:00
Thomas Camlong 92cd1c5bd0 chore(lang): updated translations from crowdin (#1721)
* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Croatian)

* New translations en.json (Latvian)

* New translations en.json (Cree)

* New translations en.json (Turkish)

* New translations en.json (Hebrew)

* New translations en.json (Russian)

* New translations en.json (Turkish)
2024-12-19 07:59:10 +01:00
homarr-renovate[bot] 3b7e6cc083 fix(deps): update dependency zod-form-data to ^2.0.4 (#1719)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-18 18:46:07 +00:00
homarr-renovate[bot] 61afab518f fix(deps): update dependency undici to v7.2.0 (#1718)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-18 18:20:57 +00:00
homarr-renovate[bot] a7bd664c5c fix(deps): update dependency zod-form-data to ^2.0.3 (#1717)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-18 17:34:58 +00:00
homarr-renovate[bot] a2c3bee66c chore(deps): update dependency @types/react to ^19.0.2 (#1716)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-18 16:21:01 +00:00
SeDemal b6dad438c2 feat: Add quick filters for integration and status + minor UI improvement from feedback (#1641) 2024-12-18 15:16:54 +01:00
Releases Homarr 044c60bdec chore(release): 1.0.0-beta.4 [skip ci] 2024-12-18 13:16:17 +00:00
homarr-releases[bot] de8485d5c3 chore(release): automatic release v1.0.0 2024-12-18 13:15:07 +00:00
SeDemal 26b6ca2445 refactor: Move integration search flag to categories (#1637) 2024-12-18 14:14:31 +01:00
Manuel 63a7be35a4 fix: jellyfin integration does not allow username password auth (#1714) 2024-12-18 14:10:58 +01:00
Meier Lukas 1baa9fc74c fix: docker statup permission issue (#1709) 2024-12-18 14:10:43 +01:00
Meier Lukas a51999457b fix: import sidebar issues (#1712) 2024-12-18 13:52:10 +01:00
Manuel 5fbbf037ce fix: permission required for home page (#1711) 2024-12-18 13:28:20 +01:00
Meier Lukas 3c0f272707 fix: conflicts between common admin group for ldap or oidc and credentials default group (#1710) 2024-12-18 13:18:01 +01:00
Meier Lukas d2b4bf5ae4 chore: update homarr-docs-sitemap (#1707) 2024-12-18 11:30:12 +01:00
Meier Lukas d803087345 fix: about version reads nextjs package-json (#1706) 2024-12-18 11:29:49 +01:00
homarr-renovate[bot] d3a883a252 fix(deps): update dependency next-intl to v3.26.2 (#1703)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-18 08:58:00 +00:00
homarr-renovate[bot] 694350583a fix(deps): update dependency ldapts to v7.3.0 (#1696)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-17 20:17:45 +00:00
Releases Homarr ecc4586d02 chore(release): 1.0.0-beta.3 [skip ci] 2024-12-17 20:12:24 +00:00
homarr-releases[bot] ce4fa5ff67 chore(release): automatic release v1.0.0 2024-12-17 20:11:19 +00:00
Meier Lukas 649506b56a fix: boolean checks do not work correctly in deploy workflow 2024-12-17 21:10:21 +01:00
Releases Homarr 9ab36f8956 chore(release): 1.0.0-beta.2 [skip ci] 2024-12-17 20:07:46 +00:00
homarr-releases[bot] bf59a2ad87 chore(release): automatic release v1.0.0 2024-12-17 20:06:34 +00:00
Meier Lukas 463607c805 Merge branch 'dev' of https://github.com/homarr-labs/homarr into dev 2024-12-17 21:05:57 +01:00
Meier Lukas 50697eb21f fix: add missing branch-name to discord deploy notification 2024-12-17 21:05:53 +01:00
Meier Lukas 70e0a11819 ci: add beta image tag for all beta releases (#1693) 2024-12-17 21:00:21 +01:00
homarr-renovate[bot] b384ebd342 chore(deps): update dependency @semantic-release/release-notes-generator to ^14.0.2 (#1685)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2024-12-17 19:14:47 +00:00
236 changed files with 20891 additions and 8411 deletions

No files matched your search

+8 -5
View File
@@ -4,6 +4,14 @@
# This file will be committed to version control, so make sure not to have any secrets in it.
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
# The below secret is not used anywhere but required for Auth.js (Would encrypt JWTs and Mail hashes, both not used)
AUTH_SECRET="supersecret"
# The below secret is used to encrypt integration secrets in the database.
# It should be a 32-byte string, generated by running `openssl rand -hex 32` on Unix
# or starting the project without any (which will show a randomly generated one).
SECRET_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000
# This is how you can use the sqlite driver:
DB_DRIVER='better-sqlite3'
DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE'
@@ -20,11 +28,6 @@ DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE'
# DB_PASSWORD='password'
# DB_NAME='name-of-database'
# You can generate the secret via 'openssl rand -base64 32' on Unix
# @see https://next-auth.js.org/configuration/options#secret
AUTH_SECRET='supersecret'
TURBO_TELEMETRY_DISABLED=1
# Configure logging to use winston logger
+58 -17
View File
@@ -1,37 +1,78 @@
name: 🐞 Bug Report
description: Create a bug report to help us improve
description: Report that something is broken, not working as intended or causes side-effects
title: "bug: "
labels: ["🐞❔ unconfirmed bug"]
labels: ["needs triage"]
body:
- type: textarea
attributes:
label: Provide environment information
description: |
Run this command in your project root and paste the results in a code block:
```bash
npx envinfo --system --binaries
```
validations:
required: true
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of the bug, as well as what you expected to happen when encountering it.
validations:
required: true
- type: input
- type: textarea
attributes:
label: Link to reproduction
description: Please provide a link to a reproduction of the bug. Issues without a reproduction repo may be ignored.
label: Steps to reproduce
description: Describe how to reproduce your bug. Steps, code snippets, reproduction repos etc.
validations:
required: true
- type: textarea
attributes:
label: To reproduce
description: Describe how to reproduce your bug. Steps, code snippets, reproduction repos etc.
label: Impact
description: How big is the impact of this bug? Does it make Homarr unusable? Is there any workaround that you're aware of?
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the bug here, screenshots if applicable.
- type: dropdown
id: version
attributes:
label: Version
description: What version of Homarr are you running?
options:
- 1.0.0-beta
- Other (describe in "additional information")
default: 0
validations:
required: true
- type: dropdown
id: installationMethod
attributes:
label: Installation method
description: How do you run Homarr? Post docker-compose, configs or screenshots if applicable.
options:
- Docker Run
- Docker Compose
- Portainer
- Helm
- QNAP
- Saltbox
- EasyPanel
- Unraid Apps
- TrueNAS Apps
- Synology
- HomeAssistant Addon
- From Source
- Other (describe in "additional information")
default: 0
validations:
required: true
- type: dropdown
id: browser
attributes:
label: Browser
description: If relevant, what browser do you use?
options:
- Firefox
- Edge (Chromium)
- Edge (Proprietary)
- Chrome
- Safari
- Vivaldi
- Brave
- Samsung Internet
- Other (describe in "additional information")
default: 0
validations:
required: false
+2 -12
View File
@@ -2,26 +2,16 @@
# See here: https://github.com/vercel/next.js/blob/canary/.github/ISSUE_TEMPLATE/3.feature_request.yml
name: 🛠 Feature Request
description: Create a feature request for the core packages
description: Request a new feature that you would like to have implemented
title: "feat: "
labels: ["✨ enhancement"]
labels: ["needs triage"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to file a feature request. Please fill out this form as completely as possible.
- type: textarea
attributes:
label: Describe the feature you'd like to request
description: Please describe the feature as clear and concise as possible. Remember to add context as to why you believe this feature is needed.
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like to see
description: Please describe the solution you would like to see. Adding example usage is a good way to provide context.
validations:
required: true
- type: textarea
attributes:
label: Additional information
+40
View File
@@ -0,0 +1,40 @@
name: 🛠 Integration request
description: Request support for a new integration (eg. Sonarr, Radarr)
title: "feat: "
labels: ["needs triage"]
body:
- type: input
attributes:
label: Project Website
description: Post the link to the website of the application. Paste the official link.
placeholder: ex. https://sonarr.tv/
validations:
required: true
- type: textarea
attributes:
label: Describe what data should be consumed by Homarr
description: Please describe what data Homarr should fetch from the integration. Specify in what interval data should be fetched and whether the user can also perform write operations (eg. deleting a movie or adding a user).
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the integration.
- type: dropdown
attributes:
label: Public API available?
description: Is there a public API available, that we can consume in Homarr?
options:
- Yes, available on a website
- Yes, available in the application itself
- No
validations:
required: true
- type: dropdown
attributes:
label: Are you willing to contribute this yourself?
options:
- Yes
- No
validations:
required: true
+30
View File
@@ -0,0 +1,30 @@
name: 🛠 Widget request
description: Request a new widget (eg. Clock, Calendar, ...)
title: "feat: "
labels: ["needs triage"]
body:
- type: input
attributes:
label: Compatible integrations
description: Post a list of the integrations that should be compatible with this widget. Divide using comma. Leave empty if no integration is needed.
placeholder: ex. Sonarr, Radarr, Lidarr, Readarr, Nextcloud
validations:
required: false
- type: textarea
attributes:
label: Describe what data should be displayed
description: Please describe what data Homarr should display. Describe how elements should be intractable and what actions the user can perform.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the widget.
- type: dropdown
attributes:
label: Are you willing to contribute this yourself?
options:
- Yes
- No
validations:
required: true
+16 -10
View File
@@ -13,11 +13,6 @@ on:
required: false
default: true
description: Send notifications
push-image:
type: boolean
required: false
default: true
description: Push Docker Image
permissions:
contents: write
@@ -40,6 +35,7 @@ jobs:
SKIP_RELEASE: ${{ github.event_name == 'workflow_dispatch' || github.ref_name == 'dev' }}
outputs:
version: ${{ steps.read-semver.outputs.version || steps.version-fallback.outputs.version }}
git_ref: ${{ steps.read-git-ref.outputs.ref || github.ref }}
steps:
- run: echo "Skipping release for workflow_dispatch event"
@@ -87,9 +83,16 @@ jobs:
run: |
git fetch --tags
echo "version=$(git describe --tags --abbrev=0)" >> "$GITHUB_OUTPUT"
- name: Read git ref
if: env.SKIP_RELEASE == 'false'
id: read-git-ref
run: |
echo "ref=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Update dev branch
if: env.SKIP_RELEASE == 'false'
continue-on-error: true # Prevent pipeline from failing when merge fails
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
run: |
git fetch origin dev
git checkout dev
@@ -103,9 +106,11 @@ jobs:
env:
NEXT_VERSION: ${{ needs.release.outputs.version }}
DEPLOY_LATEST: ${{ github.ref_name == 'main' }}
PUSH_IMAGE: ${{ github.event_name != 'workflow_dispatch' || github.events.inputs.push-image == 'true' }}
DEPLOY_BETA: ${{ github.ref_name == 'beta' }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.git_ref }}
- name: Discord notification
if: ${{ github.events.inputs.send-notifications != false }}
env:
@@ -129,15 +134,16 @@ jobs:
with:
images: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
tags: |
${{ env.DEPLOY_LATEST == true && 'type=raw,value=latest' || null }}
${{ env.DEPLOY_LATEST == 'true' && 'type=raw,value=latest' || null }}
${{ env.DEPLOY_BETA == 'true' && 'type=raw,value=beta' || null }}
type=raw,value=${{ env.NEXT_VERSION }}
- name: Build and maybe push
- name: Build and push
id: buildPushAction
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
context: .
push: ${{ env.PUSH_IMAGE}}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
network: host
@@ -148,4 +154,4 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@master
with:
args: "Deployment of image has completed. Image ID is '${{ steps.buildPushAction.outputs.imageid }}'. ${{ env.PUSH_IMAGE == true && '' || 'This was a dry run' }}"
args: "Deployment of image has completed for branch ${{ github.ref_name }}. Image ID is '${{ steps.buildPushAction.outputs.imageid }}'."
+1 -1
View File
@@ -39,5 +39,5 @@
"i18n-ally.localesPaths": [
"packages/translation/src/lang",
],
"i18n-ally.keystyle": "auto",
"i18n-ally.keystyle": "nested",
}
+112
View File
@@ -1,3 +1,115 @@
## [1.0.0-beta.10](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.9...v1.0.0-beta.10) (2024-12-31)
### Features
* add request media ([#1811](https://github.com/homarr-labs/homarr/issues/1811)) ([91e1cef](https://github.com/homarr-labs/homarr/commit/91e1cef611a47d57b42c91c0c6d49fcf2e6a10bb))
* **docker:** add support for pgid and puid env variables ([#1759](https://github.com/homarr-labs/homarr/issues/1759)) ([aeb681a](https://github.com/homarr-labs/homarr/commit/aeb681a85839e31284e8f1566adc4191a68ea385))
* **integration:** add search engine creation ([#1816](https://github.com/homarr-labs/homarr/issues/1816)) ([f507645](https://github.com/homarr-labs/homarr/commit/f5076454cd644a99439b697f24bb0b1f871b2205))
* **widget:** add minecraft server status widget ([#1801](https://github.com/homarr-labs/homarr/issues/1801)) ([0ebf4bc](https://github.com/homarr-labs/homarr/commit/0ebf4bc55e62caf5917340496abb350d564df255))
### Bug Fixes
* **deps:** update dependency octokit to ^4.0.3 ([#1806](https://github.com/homarr-labs/homarr/issues/1806)) ([75aefcb](https://github.com/homarr-labs/homarr/commit/75aefcb0d5210a53e8a00b675dbbce847aa8add4))
* **deps:** update dependency trpc-to-openapi to ^2.1.1 ([#1788](https://github.com/homarr-labs/homarr/issues/1788)) ([4943e7b](https://github.com/homarr-labs/homarr/commit/4943e7b851cd29291b5e8f2f9d0e084b4deeffc0))
* **deps:** update dependency typescript-eslint to ^8.19.0 ([#1814](https://github.com/homarr-labs/homarr/issues/1814)) ([598f004](https://github.com/homarr-labs/homarr/commit/598f0047eb13d6d0d6b68c9032a7a6648f4b6aa3))
* **deps:** update tiptap monorepo to v2.11.0 ([#1813](https://github.com/homarr-labs/homarr/issues/1813)) ([eacda4c](https://github.com/homarr-labs/homarr/commit/eacda4c397cb384a35e9eec0305f9b26f2a22a4a))
* **docker:** replace anonymous docker volume with env variable for encrypting secrets ([#1809](https://github.com/homarr-labs/homarr/issues/1809)) ([56b57ad](https://github.com/homarr-labs/homarr/commit/56b57ad171da170c2d8edd6112092cef0b586852))
* **health-monitoring:** add months to uptime, fix status update ([#1792](https://github.com/homarr-labs/homarr/issues/1792)) ([c91aae5](https://github.com/homarr-labs/homarr/commit/c91aae53acf27eab96a9150281f98a2156e9e2af))
* **media-server:** redesign widget ([#1775](https://github.com/homarr-labs/homarr/issues/1775)) ([23c7d0b](https://github.com/homarr-labs/homarr/commit/23c7d0bbf01215b680f346e7eef8072d8b9db09e))
## [1.0.0-beta.9](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.8...v1.0.0-beta.9) (2024-12-27)
### Bug Fixes
* **deps:** update nextjs monorepo to ^14.2.22 ([#1787](https://github.com/homarr-labs/homarr/issues/1787)) ([3d66ff9](https://github.com/homarr-labs/homarr/commit/3d66ff914883a665c0329c8fc4fd087f4d220692))
* **deps:** update tanstack-query monorepo to ^5.62.11 ([#1791](https://github.com/homarr-labs/homarr/issues/1791)) ([e9870e7](https://github.com/homarr-labs/homarr/commit/e9870e7ee78227d3be773d9d93aa732760cc8e21))
## [1.0.0-beta.8](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2024-12-25)
### Bug Fixes
* **deps:** update dependency @ctrl/deluge to ^7.1.0 ([#1776](https://github.com/homarr-labs/homarr/issues/1776)) ([ecae80d](https://github.com/homarr-labs/homarr/commit/ecae80d741213f12ff08f87992cc4d906cbe0085))
* **deps:** update dependency @ctrl/transmission to ^7.2.0 ([#1777](https://github.com/homarr-labs/homarr/issues/1777)) ([3e2ffbd](https://github.com/homarr-labs/homarr/commit/3e2ffbd7bf2793ff58136ed75b38e0d96b4a5ca8))
* **deps:** update dependency drizzle-orm to ^0.38.3 ([#1783](https://github.com/homarr-labs/homarr/issues/1783)) ([82c6ce7](https://github.com/homarr-labs/homarr/commit/82c6ce7b77023881bd4c74fb43437e777f9b219e))
* **deps:** update dependency drizzle-zod to ^0.6.1 ([#1782](https://github.com/homarr-labs/homarr/issues/1782)) ([555212e](https://github.com/homarr-labs/homarr/commit/555212e2dc82c4b71b8c25a5f20964b3441b5ab9))
* oldmarr import user casing wrong ([#1784](https://github.com/homarr-labs/homarr/issues/1784)) ([e37279f](https://github.com/homarr-labs/homarr/commit/e37279fe8071773f1a9773e3233bc81cbb336798))
## [1.0.0-beta.7](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2024-12-24)
### Features
* **apps:** remove url variables ([#1771](https://github.com/homarr-labs/homarr/issues/1771)) ([8df398c](https://github.com/homarr-labs/homarr/commit/8df398c3c706369f6990719603a357c161606f81))
### Bug Fixes
* **auth:** oidc redirect does not respect https protocol ([#1763](https://github.com/homarr-labs/homarr/issues/1763)) ([0336803](https://github.com/homarr-labs/homarr/commit/033680355044b1ebfa5d8fe07b59929bbcfcb3a0))
* **board:** item background and border overridden by mantine card styles ([#1769](https://github.com/homarr-labs/homarr/issues/1769)) ([425359b](https://github.com/homarr-labs/homarr/commit/425359be02f66242f7db0dc77bed0355495e21d5))
* **board:** tiles order not respected on firefox ([#1770](https://github.com/homarr-labs/homarr/issues/1770)) ([8893b72](https://github.com/homarr-labs/homarr/commit/8893b72fe363691b91b6aca75d4ad37f4b8e9f6a))
* copy media link ([#1750](https://github.com/homarr-labs/homarr/issues/1750)) ([d78c6ed](https://github.com/homarr-labs/homarr/commit/d78c6ed5299e1f975c2e85ec3ecad38e00457677))
* **deps:** update dependency @ctrl/qbittorrent to ^9.2.0 ([#1768](https://github.com/homarr-labs/homarr/issues/1768)) ([8b416a6](https://github.com/homarr-labs/homarr/commit/8b416a6dd354b22a3e4f527b793dde2c538b1e6a))
* **deps:** update dependency eslint-plugin-react to ^7.37.3 ([#1767](https://github.com/homarr-labs/homarr/issues/1767)) ([fe95334](https://github.com/homarr-labs/homarr/commit/fe95334aa70c95faefcf904591fa9d33159b0905))
* **deps:** update dependency jotai to ^2.11.0 ([#1756](https://github.com/homarr-labs/homarr/issues/1756)) ([4e85bbb](https://github.com/homarr-labs/homarr/commit/4e85bbbad034f08ab84e331d376b7a9c6f54e507))
* **deps:** update dependency mysql2 to v3.12.0 ([#1758](https://github.com/homarr-labs/homarr/issues/1758)) ([d02ded5](https://github.com/homarr-labs/homarr/commit/d02ded5511aa2d54307db0ac7f4e0a5dee5a707d))
* **deps:** update dependency react-error-boundary to v5 ([#1748](https://github.com/homarr-labs/homarr/issues/1748)) ([01db27c](https://github.com/homarr-labs/homarr/commit/01db27c34f3daf6e67e35bbd357df31dcb154b41))
* **deps:** update dependency typescript-eslint to ^8.18.2 ([#1762](https://github.com/homarr-labs/homarr/issues/1762)) ([9223dd0](https://github.com/homarr-labs/homarr/commit/9223dd06ee0c2b51e036f607d7b3252c61ab77ea))
* **deps:** update mantine monorepo to ^7.15.2 ([#1757](https://github.com/homarr-labs/homarr/issues/1757)) ([dfacb08](https://github.com/homarr-labs/homarr/commit/dfacb08dbddb6864646ece2fca6978207f0c58ac))
* **deps:** update tanstack-query monorepo to ^5.62.10 ([#1772](https://github.com/homarr-labs/homarr/issues/1772)) ([c410b06](https://github.com/homarr-labs/homarr/commit/c410b06a15ed5426931ad764cc861f66f11a40da))
* **deps:** update tanstack-query monorepo to ^5.62.9 ([#1761](https://github.com/homarr-labs/homarr/issues/1761)) ([42da2b9](https://github.com/homarr-labs/homarr/commit/42da2b9b062bd8a08c37e45ab129953e8b0e3624))
* **icons:** local icon repository does not work with medias ([#1765](https://github.com/homarr-labs/homarr/issues/1765)) ([e220087](https://github.com/homarr-labs/homarr/commit/e220087e96c7096303b1d245ccf3941118e692f3))
* **onboard:** missing admin permission assignment for external group ([#1764](https://github.com/homarr-labs/homarr/issues/1764)) ([b948337](https://github.com/homarr-labs/homarr/commit/b9483379dd56a8dab2b9b636b66b970da4cf9d83))
## [1.0.0-beta.6](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2024-12-20)
### Bug Fixes
* **deps:** update dependency ioredis to v5.4.2 ([#1739](https://github.com/homarr-labs/homarr/issues/1739)) ([720fdb7](https://github.com/homarr-labs/homarr/commit/720fdb772c2142e23b2bfa2ecaddf0063fbe192c))
* **deps:** update dependency next-intl to v3.26.3 ([#1740](https://github.com/homarr-labs/homarr/issues/1740)) ([fff1da8](https://github.com/homarr-labs/homarr/commit/fff1da88bd44162b08a76f8b2f49e2b929fc56e8))
## [1.0.0-beta.5](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2024-12-19)
### Features
* Add quick filters for integration and status + minor UI improvement from feedback ([#1641](https://github.com/homarr-labs/homarr/issues/1641)) ([b6dad43](https://github.com/homarr-labs/homarr/commit/b6dad438c2f44aa8d7a740c1a22c9d4c39edf43e))
### Bug Fixes
* about version is one behind because of missing package-json update in deploy ([#1725](https://github.com/homarr-labs/homarr/issues/1725)) ([8c11562](https://github.com/homarr-labs/homarr/commit/8c1156240c8a0d332301ae6dd0a4521f3db19d9a))
* allow additional file-type for oldmarr import ([#1723](https://github.com/homarr-labs/homarr/issues/1723)) ([1e8a535](https://github.com/homarr-labs/homarr/commit/1e8a5359b78e28db7683ba837a962685446c6c32))
* always require db-user and password for mysql ([#1730](https://github.com/homarr-labs/homarr/issues/1730)) ([d2584b6](https://github.com/homarr-labs/homarr/commit/d2584b63c55ca143a2b5dc6a71cb00fd5612b78a))
* **deps:** update dependency tldts to ^6.1.69 ([#1726](https://github.com/homarr-labs/homarr/issues/1726)) ([c0f6816](https://github.com/homarr-labs/homarr/commit/c0f681637db1d6e7abdf3326b3a3c17283440d09))
* **deps:** update dependency undici to v7.2.0 ([#1718](https://github.com/homarr-labs/homarr/issues/1718)) ([61afab5](https://github.com/homarr-labs/homarr/commit/61afab518f6193a700a547faffa4619b28fb0837))
* **deps:** update dependency zod-form-data to ^2.0.3 ([#1717](https://github.com/homarr-labs/homarr/issues/1717)) ([a7bd664](https://github.com/homarr-labs/homarr/commit/a7bd664c5cee578574bf37b7149a2142be9f8b7a))
* **deps:** update dependency zod-form-data to ^2.0.4 ([#1719](https://github.com/homarr-labs/homarr/issues/1719)) ([3b7e6cc](https://github.com/homarr-labs/homarr/commit/3b7e6cc083220a0e3a0cf4f5243c073067ba5bc7))
* **deps:** update nextjs monorepo to ^14.2.21 ([#1727](https://github.com/homarr-labs/homarr/issues/1727)) ([2b4bc83](https://github.com/homarr-labs/homarr/commit/2b4bc8352efa1e2cffb71a6d4d6e42f941358f02))
* **deps:** update tiptap monorepo to v2.10.4 ([#1729](https://github.com/homarr-labs/homarr/issues/1729)) ([2ae3d93](https://github.com/homarr-labs/homarr/commit/2ae3d938eeea5bd49a74d9c09b4cb2c680b059d0))
* mysql operations not working ([#1728](https://github.com/homarr-labs/homarr/issues/1728)) ([550bca6](https://github.com/homarr-labs/homarr/commit/550bca6dee743a4ed68ec15677304ecfd7a9a385))
* update of dev branch has no credentials ([#1724](https://github.com/homarr-labs/homarr/issues/1724)) ([bb7f751](https://github.com/homarr-labs/homarr/commit/bb7f7514814d49a77ac79f63d68923d08148573e))
## [1.0.0-beta.4](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2024-12-18)
### Bug Fixes
* about version reads nextjs package-json ([#1706](https://github.com/homarr-labs/homarr/issues/1706)) ([d803087](https://github.com/homarr-labs/homarr/commit/d8030873452d2248d79d16a2fc4464ff2fbb478d))
* conflicts between common admin group for ldap or oidc and credentials default group ([#1710](https://github.com/homarr-labs/homarr/issues/1710)) ([3c0f272](https://github.com/homarr-labs/homarr/commit/3c0f272707ee66fd00bffb0d16e30df98b4f1aff))
* **deps:** update dependency ldapts to v7.3.0 ([#1696](https://github.com/homarr-labs/homarr/issues/1696)) ([6943505](https://github.com/homarr-labs/homarr/commit/694350583a0e53014a950c4a5bed4d487ad4ca7b))
* **deps:** update dependency next-intl to v3.26.2 ([#1703](https://github.com/homarr-labs/homarr/issues/1703)) ([d3a883a](https://github.com/homarr-labs/homarr/commit/d3a883a252167612f3f64579730c8f26453897e3))
* docker statup permission issue ([#1709](https://github.com/homarr-labs/homarr/issues/1709)) ([1baa9fc](https://github.com/homarr-labs/homarr/commit/1baa9fc74cf15df8ead7bbe6d1615f7bf0895813))
* import sidebar issues ([#1712](https://github.com/homarr-labs/homarr/issues/1712)) ([a519994](https://github.com/homarr-labs/homarr/commit/a51999457b57c042b543768bc1ef43647d62a85d))
* jellyfin integration does not allow username password auth ([#1714](https://github.com/homarr-labs/homarr/issues/1714)) ([63a7be3](https://github.com/homarr-labs/homarr/commit/63a7be35a4cf0f11610c2097afc32d2ced0ef9e1))
* permission required for home page ([#1711](https://github.com/homarr-labs/homarr/issues/1711)) ([5fbbf03](https://github.com/homarr-labs/homarr/commit/5fbbf037ce8a06642533c7f68c1c34ed8b01e4e4))
## [1.0.0-beta.3](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2024-12-17)
### Bug Fixes
* boolean checks do not work correctly in deploy workflow ([649506b](https://github.com/homarr-labs/homarr/commit/649506b56a5f3cbbee9b782b637730f2196785cc))
## [1.0.0-beta.2](https://github.com/homarr-labs/homarr/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2024-12-17)
### Bug Fixes
* add missing branch-name to discord deploy notification ([50697eb](https://github.com/homarr-labs/homarr/commit/50697eb21f923bbe9a6811c964cfc313f79a2806))
## 1.0.0-beta.1 (2024-12-17)
### ⚠ BREAKING CHANGES
+21 -30
View File
@@ -25,51 +25,41 @@ RUN corepack enable pnpm && pnpm build
FROM base AS runner
WORKDIR /app
# gettext is required for envsubst
RUN apk add --no-cache redis nginx bash gettext
# gettext is required for envsubst, openssl for generating AUTH_SECRET, su-exec for running application as non-root
RUN apk add --no-cache redis nginx bash gettext su-exec openssl
RUN mkdir /appdata
VOLUME /appdata
RUN mkdir /secrets
VOLUME /secrets
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Enable homarr cli
COPY --from=builder --chown=nextjs:nodejs /app/packages/cli/cli.cjs /app/apps/cli/cli.cjs
COPY --from=builder /app/packages/cli/cli.cjs /app/apps/cli/cli.cjs
RUN echo $'#!/bin/bash\ncd /app/apps/cli && node ./cli.cjs "$@"' > /usr/bin/homarr
RUN chmod +x /usr/bin/homarr
# Don't run production as root
RUN chown -R nextjs:nodejs /appdata
RUN chown -R nextjs:nodejs /secrets
RUN mkdir -p /var/cache/nginx && chown -R nextjs:nodejs /var/cache/nginx && \
mkdir -p /var/log/nginx && chown -R nextjs:nodejs /var/log/nginx && \
mkdir -p /var/lib/nginx && chown -R nextjs:nodejs /var/lib/nginx && \
touch /run/nginx/nginx.pid && chown -R nextjs:nodejs /run/nginx/nginx.pid && \
mkdir -p /etc/nginx/templates /etc/nginx/ssl/certs && chown -R nextjs:nodejs /etc/nginx
USER nextjs
RUN mkdir -p /var/cache/nginx && \
mkdir -p /var/log/nginx && \
mkdir -p /var/lib/nginx && \
touch /run/nginx/nginx.pid && \
mkdir -p /etc/nginx/templates /etc/nginx/ssl/certs
COPY --from=builder /app/apps/nextjs/next.config.mjs .
COPY --from=builder /app/apps/nextjs/package.json .
COPY --from=builder --chown=nextjs:nodejs /app/apps/tasks/tasks.cjs ./apps/tasks/tasks.cjs
COPY --from=builder --chown=nextjs:nodejs /app/apps/websocket/wssServer.cjs ./apps/websocket/wssServer.cjs
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/better-sqlite3/build/Release/better_sqlite3.node /app/build/better_sqlite3.node
COPY --from=builder /app/apps/tasks/tasks.cjs ./apps/tasks/tasks.cjs
COPY --from=builder /app/apps/websocket/wssServer.cjs ./apps/websocket/wssServer.cjs
COPY --from=builder /app/node_modules/better-sqlite3/build/Release/better_sqlite3.node /app/build/better_sqlite3.node
COPY --from=builder --chown=nextjs:nodejs /app/packages/db/migrations ./db/migrations
COPY --from=builder /app/packages/db/migrations ./db/migrations
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/apps/nextjs/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/apps/nextjs/.next/static ./apps/nextjs/.next/static
COPY --from=builder --chown=nextjs:nodejs /app/apps/nextjs/public ./apps/nextjs/public
COPY --chown=nextjs:nodejs scripts/run.sh ./run.sh
COPY --chown=nextjs:nodejs scripts/generateRandomSecureKey.js ./generateRandomSecureKey.js
COPY --chown=nextjs:nodejs packages/redis/redis.conf /app/redis.conf
COPY --chown=nextjs:nodejs nginx.conf /etc/nginx/templates/nginx.conf
COPY --from=builder /app/apps/nextjs/.next/standalone ./
COPY --from=builder /app/apps/nextjs/.next/static ./apps/nextjs/.next/static
COPY --from=builder /app/apps/nextjs/public ./apps/nextjs/public
COPY scripts/run.sh ./run.sh
COPY --chmod=777 scripts/entrypoint.sh ./entrypoint.sh
COPY packages/redis/redis.conf /app/redis.conf
COPY nginx.conf /etc/nginx/templates/nginx.conf
ENV DB_URL='/appdata/db/db.sqlite'
@@ -77,4 +67,5 @@ ENV DB_DIALECT='sqlite'
ENV DB_DRIVER='better-sqlite3'
ENV AUTH_PROVIDERS='credentials'
CMD ["sh", "run.sh"]
ENTRYPOINT [ "/app/entrypoint.sh" ]
CMD ["sh", "run.sh"]
+2
View File
@@ -1,5 +1,7 @@
// Importing env files here to validate on build
import "@homarr/auth/env.mjs";
import "@homarr/db/env.mjs";
import "@homarr/common/env.mjs";
import MillionLint from "@million/lint";
import createNextIntlPlugin from "next-intl/plugin";
+14 -14
View File
@@ -38,18 +38,18 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"@mantine/colors-generator": "^7.15.1",
"@mantine/core": "^7.15.1",
"@mantine/dropzone": "^7.15.1",
"@mantine/hooks": "^7.15.1",
"@mantine/modals": "^7.15.1",
"@mantine/tiptap": "^7.15.1",
"@mantine/colors-generator": "^7.15.2",
"@mantine/core": "^7.15.2",
"@mantine/dropzone": "^7.15.2",
"@mantine/hooks": "^7.15.2",
"@mantine/modals": "^7.15.2",
"@mantine/tiptap": "^7.15.2",
"@million/lint": "1.0.14",
"@t3-oss/env-nextjs": "^0.11.1",
"@tabler/icons-react": "^3.26.0",
"@tanstack/react-query": "^5.62.8",
"@tanstack/react-query-devtools": "^5.62.8",
"@tanstack/react-query-next-experimental": "5.62.8",
"@tanstack/react-query": "^5.62.11",
"@tanstack/react-query-devtools": "^5.62.11",
"@tanstack/react-query-next-experimental": "5.62.11",
"@trpc/client": "next",
"@trpc/next": "next",
"@trpc/react-query": "next",
@@ -63,14 +63,14 @@
"dotenv": "^16.4.7",
"flag-icons": "^7.2.3",
"glob": "^11.0.0",
"jotai": "^2.10.4",
"jotai": "^2.11.0",
"mantine-react-table": "2.0.0-beta.7",
"next": "^14.2.20",
"next": "^14.2.22",
"postcss-preset-mantine": "^1.17.0",
"prismjs": "^1.29.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-error-boundary": "^4.1.2",
"react-error-boundary": "^5.0.0",
"react-simple-code-editor": "^0.14.1",
"sass": "^1.83.0",
"superjson": "2.2.2",
@@ -84,10 +84,10 @@
"@types/chroma-js": "2.4.5",
"@types/node": "^22.10.2",
"@types/prismjs": "^1.26.5",
"@types/react": "^19.0.1",
"@types/react": "^19.0.2",
"@types/react-dom": "^19.0.2",
"@types/swagger-ui-react": "^4.18.3",
"concurrently": "^9.1.0",
"concurrently": "^9.1.2",
"eslint": "^9.17.0",
"node-loader": "^2.1.0",
"prettier": "^3.4.2",
@@ -4,7 +4,7 @@ import { Card, Center, Stack, Text, Title } from "@mantine/core";
import { auth } from "@homarr/auth/next";
import { isProviderEnabled } from "@homarr/auth/server";
import { and, db, eq } from "@homarr/db";
import { invites } from "@homarr/db/schema/sqlite";
import { invites } from "@homarr/db/schema";
import { getScopedI18n } from "@homarr/translation/server";
import { HomarrLogoWithTitle } from "~/components/layout/logo/homarr-logo";
@@ -2,7 +2,7 @@ import { IconHomeOff } from "@tabler/icons-react";
import { auth } from "@homarr/auth/next";
import { db } from "@homarr/db";
import { boards } from "@homarr/db/schema/sqlite";
import { boards } from "@homarr/db/schema";
import { getI18n } from "@homarr/translation/server";
import type { BoardNotFoundProps } from "~/components/board/not-found";
@@ -24,10 +24,19 @@ export const ImportDropZone = ({ loading, updateFile }: ImportDropZoneProps) =>
}}
acceptColor="blue.6"
rejectColor="red.6"
accept={[MIME_TYPES.zip]}
accept={[MIME_TYPES.zip, "application/x-zip-compressed"]}
loading={loading}
multiple={false}
maxSize={1024 * 1024 * 1024 * 64} // 64 MB
onReject={(rejections) => {
console.error(
"Rejected files",
rejections.map(
(rejection) =>
`File: ${rejection.file.name} size=${rejection.file.size} fileType=${rejection.file.type}\n - ${rejection.errors.map((error) => error.message).join("\n - ")}`,
),
);
}}
>
<Group justify="center" gap="xl" mih={220} style={{ pointerEvents: "none" }}>
<Dropzone.Accept>
@@ -6,7 +6,6 @@ import { IconBox, IconPencil } from "@tabler/icons-react";
import type { RouterOutputs } from "@homarr/api";
import { api } from "@homarr/api/server";
import { auth } from "@homarr/auth/next";
import { parseAppHrefWithVariablesServer } from "@homarr/common/server";
import { getI18n, getScopedI18n } from "@homarr/translation/server";
import { ManageContainer } from "~/components/manage/manage-container";
@@ -82,8 +81,8 @@ const AppCard = async ({ app }: AppCardProps) => {
</Text>
)}
{app.href && (
<Anchor href={parseAppHrefWithVariablesServer(app.href)} lineClamp={1} size="sm" w="min-content">
{parseAppHrefWithVariablesServer(app.href)}
<Anchor href={app.href} lineClamp={1} size="sm" w="min-content">
{app.href}
</Anchor>
)}
</Stack>
@@ -3,13 +3,13 @@
import { useCallback } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { Alert, Button, Fieldset, Group, SegmentedControl, Stack, Text, TextInput } from "@mantine/core";
import { Alert, Button, Checkbox, Fieldset, Group, SegmentedControl, Stack, Text, TextInput } from "@mantine/core";
import { IconInfoCircle } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
import { getAllSecretKindOptions, getIntegrationName } from "@homarr/definitions";
import { getAllSecretKindOptions, getIntegrationName, integrationDefs } from "@homarr/definitions";
import type { UseFormReturnType } from "@homarr/form";
import { useZodForm } from "@homarr/form";
import { convertIntegrationTestConnectionError } from "@homarr/integrations/client";
@@ -38,6 +38,7 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
kind,
value: "",
})),
attemptSearchEngineCreation: true,
},
});
const { mutateAsync, isPending } = clientApi.integration.create.useMutation();
@@ -78,6 +79,8 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
);
};
const supportsSearchEngine = integrationDefs[searchParams.kind].category.flat().includes("search");
return (
<form onSubmit={form.onSubmit((value) => void handleSubmitAsync(value))}>
<Stack>
@@ -104,6 +107,16 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
</Stack>
</Fieldset>
{supportsSearchEngine && (
<Checkbox
label={t("integration.field.attemptSearchEngineCreation.label")}
description={t("integration.field.attemptSearchEngineCreation.description", {
kind: getIntegrationName(searchParams.kind),
})}
{...form.getInputProps("attemptSearchEngineCreation", { type: "checkbox" })}
/>
)}
<Group justify="end" align="center">
<Button variant="default" component={Link} href="/manage/integrations">
{t("common.action.backToOverview")}
@@ -13,10 +13,7 @@ interface CopyMediaProps {
export const CopyMedia = ({ media }: CopyMediaProps) => {
const t = useI18n();
const url =
typeof window !== "undefined"
? `${window.location.protocol}://${window.location.hostname}:${window.location.port}/api/user-medias/${media.id}`
: "";
const url = typeof window !== "undefined" ? `${window.location.origin}/api/user-medias/${media.id}` : "";
return (
<CopyButton value={url}>
@@ -3,7 +3,7 @@ import { notFound } from "next/navigation";
import { auth } from "@homarr/auth/next";
import { isProviderEnabled } from "@homarr/auth/server";
import { db, inArray } from "@homarr/db";
import { groups } from "@homarr/db/schema/sqlite";
import { groups } from "@homarr/db/schema";
import { everyoneGroup } from "@homarr/definitions";
import { getScopedI18n } from "@homarr/translation/server";
+1 -1
View File
@@ -8,7 +8,7 @@ import { hashPasswordAsync } from "@homarr/auth";
import type { Session } from "@homarr/auth";
import { createSessionAsync } from "@homarr/auth/server";
import { db, eq } from "@homarr/db";
import { apiKeys } from "@homarr/db/schema/sqlite";
import { apiKeys } from "@homarr/db/schema";
import { logger } from "@homarr/log";
const handlerAsync = async (req: NextRequest) => {
@@ -3,7 +3,7 @@ import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { db, eq } from "@homarr/db";
import { medias } from "@homarr/db/schema/sqlite";
import { medias } from "@homarr/db/schema";
export async function GET(_req: NextRequest, { params }: { params: { id: string } }) {
const image = await db.query.medias.findFirst({
@@ -10,6 +10,12 @@ import { useSectionContext } from "./section-context";
export const SectionContent = () => {
const { section, innerSections, refs } = useSectionContext();
const board = useRequiredBoard();
/**
* IMPORTANT: THE ORDER OF THE BELOW ITEMS HAS TO MATCH THE ORDER OF
* THE ITEMS RENDERED WITH GRIDSTACK, OTHERWISE THE ITEMS WILL BE MIXED UP
* @see https://github.com/homarr-labs/homarr/pull/1770
*/
const sortedItems = useMemo(() => {
return [
...section.items.map((item) => ({ ...item, type: "item" as const })),
@@ -19,7 +25,7 @@ export const SectionContent = () => {
return itemA.xOffset - itemB.xOffset;
}
return itemA.yOffset - itemB.xOffset;
return itemA.yOffset - itemB.yOffset;
});
}, [section.items, innerSections]);
@@ -7,6 +7,6 @@
--background-color: rgb(from var(--mantine-color-white) r g b / var(--opacity));
--border-color: rgb(from var(--mantine-color-gray-3) r g b / var(--opacity));
}
background-color: var(--background-color);
border-color: var(--border-color);
background-color: var(--background-color) !important;
border-color: var(--border-color) !important;
}
@@ -7,13 +7,13 @@ import { CurrentUserAvatar } from "~/components/user-avatar";
import { UserAvatarMenu } from "~/components/user-avatar-menu";
export const UserButton = async () => {
const data = await api.updateChecker.getAvailableUpdates();
const session = await auth();
const isAdmin = session?.user.permissions.includes("admin");
const data = isAdmin ? await api.updateChecker.getAvailableUpdates() : undefined;
return (
<UserAvatarMenu availableUpdates={isAdmin ? data : undefined}>
<UserAvatarMenu availableUpdates={data}>
<UnstyledButton>
<Indicator disabled={data.length === 0 || !isAdmin} size={15} processing withBorder>
<Indicator disabled={data?.length === 0 || !isAdmin} size={15} processing withBorder>
<CurrentUserAvatar size="md" />
</Indicator>
</UnstyledButton>
-31
View File
@@ -1,16 +1,8 @@
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
const isUsingDbUrl = Boolean(process.env.DB_URL);
const isUsingDbHost = Boolean(process.env.DB_HOST);
const isUsingDbCredentials = process.env.DB_DRIVER === "mysql2";
export const env = createEnv({
shared: {
VERCEL_URL: z
.string()
.optional()
.transform((url) => (url ? `https://${url}` : undefined)),
PORT: z.coerce.number().default(3000),
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
},
@@ -19,21 +11,6 @@ export const env = createEnv({
* built with invalid env vars.
*/
server: {
DB_DRIVER: z.enum(["better-sqlite3", "mysql2"]).default("better-sqlite3"),
// If the DB_HOST is set, the DB_URL is optional
DB_URL: isUsingDbHost ? z.string().optional() : z.string(),
DB_HOST: isUsingDbUrl ? z.string().optional() : z.string(),
DB_PORT: isUsingDbUrl
? z.string().regex(/\d+/).transform(Number).optional()
: z
.string()
.regex(/\d+/)
.transform(Number)
.refine((number) => number >= 1)
.default("3306"),
DB_USER: isUsingDbCredentials ? z.string() : z.string().optional(),
DB_PASSWORD: isUsingDbCredentials ? z.string() : z.string().optional(),
DB_NAME: isUsingDbUrl ? z.string().optional() : z.string(),
// Comma separated list of docker hostnames that can be used to connect to query the docker endpoints (localhost:2375,host.docker.internal:2375, ...)
DOCKER_HOSTNAMES: z.string().optional(),
DOCKER_PORTS: z.number().optional(),
@@ -49,15 +26,7 @@ export const env = createEnv({
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
*/
runtimeEnv: {
VERCEL_URL: process.env.VERCEL_URL,
PORT: process.env.PORT,
DB_URL: process.env.DB_URL,
DB_HOST: process.env.DB_HOST,
DB_USER: process.env.DB_USER,
DB_PASSWORD: process.env.DB_PASSWORD,
DB_NAME: process.env.DB_NAME,
DB_PORT: process.env.DB_PORT,
DB_DRIVER: process.env.DB_DRIVER,
NODE_ENV: process.env.NODE_ENV,
DOCKER_HOSTNAMES: process.env.DOCKER_HOSTNAMES,
DOCKER_PORTS: process.env.DOCKER_PORTS,
+1 -1
View File
@@ -1,7 +1,7 @@
import fsPromises from "fs/promises";
import { glob } from "glob";
import packageJson from "~/../package.json";
import packageJson from "../../../../package.json";
const getPackageVersion = () => packageJson.version;
const getDependenciesAsync = async (): Promise<PackageJsonDependencies> => {
+2 -2
View File
@@ -38,14 +38,14 @@
"dayjs": "^1.11.13",
"dotenv": "^16.4.7",
"superjson": "2.2.2",
"undici": "7.1.1"
"undici": "7.2.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^22.10.2",
"dotenv-cli": "^7.4.4",
"dotenv-cli": "^8.0.0",
"eslint": "^9.17.0",
"prettier": "^3.4.2",
"tsx": "4.19.2",
+2 -2
View File
@@ -10,8 +10,8 @@
<a href="https://github.com/homarr-labs/homarr/actions/workflows/deployment-docker-image.yml">
  <img title="Docker CI Status" src="https://github.com/homarr-labs/homarr/actions/workflows/deployment-docker-image.yml/badge.svg" alt="CI Status">
</a>
<a href=https://translate.homarr.dev/>
<img title="Translations" src="https://badges.crowdin.net/homarr/localized.svg" />
<a href="https://crowdin.com/project/homarr_labs">
<img title="Translations" src="https://badges.crowdin.net/homarr_labs/localized.svg" />
</a>
<a href="https://discord.gg/aCsmEV5RgA">
  <img title="Discord" src="https://discordapp.com/api/guilds/972958686051962910/widget.png?style=shield">
+18 -3
View File
@@ -5,7 +5,22 @@ export const createHomarrContainer = () => {
throw new Error("This test should only be run in CI or with a homarr image named 'homarr-e2e'");
}
return new GenericContainer("homarr-e2e")
.withExposedPorts(7575)
.withWaitStrategy(Wait.forHttp("/api/health/ready", 7575));
return withLogs(
new GenericContainer("homarr-e2e")
.withExposedPorts(7575)
.withEnvironment({
SECRET_ENCRYPTION_KEY: "0".repeat(64),
})
.withWaitStrategy(Wait.forHttp("/api/health/ready", 7575)),
);
};
export const withLogs = (container: GenericContainer) => {
container.withLogConsumer((stream) =>
stream
.on("data", (line) => console.log(line))
.on("err", (line) => console.error(line))
.on("end", () => console.log("Stream closed")),
);
return container;
};
+1 -1
View File
@@ -21,7 +21,7 @@ http {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "homarr",
"version": "1.0.0-beta.1",
"version": "1.0.0-beta.10",
"private": true,
"scripts": {
"build": "cross-env CI=true turbo build",
@@ -36,7 +36,7 @@
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^11.0.1",
"@semantic-release/npm": "^12.0.1",
"@semantic-release/release-notes-generator": "^14.0.1",
"@semantic-release/release-notes-generator": "^14.0.2",
"@turbo/gen": "^2.3.3",
"@vitejs/plugin-react": "^4.3.4",
"@vitest/coverage-v8": "^2.1.8",
@@ -52,7 +52,7 @@
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^2.1.8"
},
"packageManager": "pnpm@9.15.0",
"packageManager": "pnpm@9.15.2",
"engines": {
"node": ">=22.12.0"
},
@@ -3,7 +3,7 @@ import { Umami } from "@umami/node";
import { count, db } from "@homarr/db";
import { getServerSettingByKeyAsync } from "@homarr/db/queries";
import { integrations, items, users } from "@homarr/db/schema/sqlite";
import { integrations, items, users } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import type { defaultServerSettings } from "@homarr/server-settings";
+4 -2
View File
@@ -27,6 +27,7 @@
"@homarr/cron-jobs": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/icons": "workspace:^0.1.0",
"@homarr/integrations": "workspace:^0.1.0",
"@homarr/log": "workspace:^",
"@homarr/old-import": "workspace:^0.1.0",
@@ -40,10 +41,11 @@
"@trpc/react-query": "next",
"@trpc/server": "next",
"dockerode": "^4.0.2",
"next": "^14.2.20",
"lodash.clonedeep": "^4.5.0",
"next": "^14.2.22",
"react": "^19.0.0",
"superjson": "2.2.2",
"trpc-to-openapi": "^2.1.0"
"trpc-to-openapi": "^2.1.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
-1
View File
@@ -16,7 +16,6 @@ export const fetchApi = createTRPCClient<AppRouter>({
function getBaseUrl() {
if (typeof window !== "undefined") return window.location.origin;
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
return `http://localhost:${process.env.PORT ?? 3000}`;
}
+1 -1
View File
@@ -7,7 +7,7 @@ import { decryptSecret } from "@homarr/common/server";
import type { AtLeastOneOf } from "@homarr/common/types";
import type { Database } from "@homarr/db";
import { and, eq, inArray } from "@homarr/db";
import { integrations } from "@homarr/db/schema/sqlite";
import { integrations } from "@homarr/db/schema";
import type { IntegrationKind } from "@homarr/definitions";
import { z } from "@homarr/validation";
+1 -1
View File
@@ -1,7 +1,7 @@
import { TRPCError } from "@trpc/server";
import { and, eq } from "@homarr/db";
import { items } from "@homarr/db/schema/sqlite";
import { items } from "@homarr/db/schema";
import type { WidgetKind } from "@homarr/definitions";
import { z } from "@homarr/validation";
+1 -1
View File
@@ -1,7 +1,7 @@
import { createSaltAsync, hashPasswordAsync } from "@homarr/auth";
import { generateSecureRandomToken } from "@homarr/common/server";
import { createId, db } from "@homarr/db";
import { apiKeys } from "@homarr/db/schema/sqlite";
import { apiKeys } from "@homarr/db/schema";
import { createTRPCRouter, permissionRequiredProcedure } from "../trpc";
+1 -1
View File
@@ -1,7 +1,7 @@
import { TRPCError } from "@trpc/server";
import { asc, createId, eq, inArray, like } from "@homarr/db";
import { apps } from "@homarr/db/schema/sqlite";
import { apps } from "@homarr/db/schema";
import { selectAppSchema } from "@homarr/db/validationSchemas";
import { validation, z } from "@homarr/validation";
@@ -2,7 +2,7 @@ import SuperJSON from "superjson";
import type { Session } from "@homarr/auth";
import { db, eq, or } from "@homarr/db";
import { items } from "@homarr/db/schema/sqlite";
import { items } from "@homarr/db/schema";
import type { WidgetComponentProps } from "../../../../widgets/src";
+1 -1
View File
@@ -15,7 +15,7 @@ import {
items,
sections,
users,
} from "@homarr/db/schema/sqlite";
} from "@homarr/db/schema";
import type { WidgetKind } from "@homarr/definitions";
import { getPermissionsWithParents, widgetKinds } from "@homarr/definitions";
import { importOldmarrAsync } from "@homarr/old-import";
@@ -4,7 +4,7 @@ import type { Session } from "@homarr/auth";
import { constructBoardPermissions } from "@homarr/auth/shared";
import type { Database, SQL } from "@homarr/db";
import { eq, inArray } from "@homarr/db";
import { boardGroupPermissions, boardUserPermissions, groupMembers } from "@homarr/db/schema/sqlite";
import { boardGroupPermissions, boardUserPermissions, groupMembers } from "@homarr/db/schema";
import type { BoardPermission } from "@homarr/definitions";
/**
@@ -3,7 +3,7 @@ import type Docker from "dockerode";
import type { Container } from "dockerode";
import { db, like, or } from "@homarr/db";
import { icons } from "@homarr/db/schema/sqlite";
import { icons } from "@homarr/db/schema";
import type { DockerContainerState } from "@homarr/definitions";
import { logger } from "@homarr/log";
import { createCacheChannel } from "@homarr/redis";
+8 -2
View File
@@ -2,7 +2,7 @@ import { TRPCError } from "@trpc/server";
import type { Database } from "@homarr/db";
import { and, createId, eq, like, not, sql } from "@homarr/db";
import { groupMembers, groupPermissions, groups } from "@homarr/db/schema/sqlite";
import { groupMembers, groupPermissions, groups } from "@homarr/db/schema";
import { everyoneGroup } from "@homarr/definitions";
import { validation, z } from "@homarr/validation";
@@ -152,11 +152,17 @@ export const groupRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
await checkSimilarNameAndThrowAsync(ctx.db, input.name);
const groupId = createId();
await ctx.db.insert(groups).values({
id: createId(),
id: groupId,
name: input.name,
});
await ctx.db.insert(groupPermissions).values({
groupId,
permission: "admin",
});
await nextOnboardingStepAsync(ctx.db, undefined);
}),
createGroup: permissionRequiredProcedure
+1 -1
View File
@@ -3,7 +3,7 @@ import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
import { isProviderEnabled } from "@homarr/auth/server";
import type { Database } from "@homarr/db";
import { count } from "@homarr/db";
import { apps, boards, groups, integrations, invites, users } from "@homarr/db/schema/sqlite";
import { apps, boards, groups, integrations, invites, users } from "@homarr/db/schema";
import { createTRPCRouter, publicProcedure } from "../trpc";
+1 -1
View File
@@ -1,5 +1,5 @@
import { count, like } from "@homarr/db";
import { icons } from "@homarr/db/schema/sqlite";
import { icons } from "@homarr/db/schema";
import { validation } from "@homarr/validation";
import { createTRPCRouter, publicProcedure } from "../trpc";
@@ -4,7 +4,7 @@ import type { Session } from "@homarr/auth";
import { constructIntegrationPermissions } from "@homarr/auth/shared";
import type { Database, SQL } from "@homarr/db";
import { eq, inArray } from "@homarr/db";
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema/sqlite";
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema";
import type { IntegrationPermission } from "@homarr/definitions";
/**
@@ -11,18 +11,21 @@ import {
integrations,
integrationSecrets,
integrationUserPermissions,
} from "@homarr/db/schema/sqlite";
searchEngines,
} from "@homarr/db/schema";
import type { IntegrationSecretKind } from "@homarr/definitions";
import {
getIconUrl,
getIntegrationKindsByCategory,
getPermissionsWithParents,
integrationDefs,
integrationKinds,
integrationSecretKindObject,
isIntegrationWithSearchSupport,
} from "@homarr/definitions";
import { integrationCreatorFromSecrets } from "@homarr/integrations";
import { integrationCreator } from "@homarr/integrations";
import { validation, z } from "@homarr/validation";
import { createOneIntegrationMiddleware } from "../../middlewares/integration";
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure, publicProcedure } from "../../trpc";
import { throwIfActionForbiddenAsync } from "./integration-access";
import { testConnectionAsync } from "./integration-test-connection";
@@ -90,7 +93,7 @@ export const integrationRouter = createTRPCRouter({
where: inArray(
integrations.kind,
objectEntries(integrationDefs)
.filter(([_, integration]) => integration.supportsSearch)
.filter(([_, integration]) => [...integration.category].includes("search"))
.map(([kind, _]) => kind),
),
});
@@ -191,6 +194,18 @@ export const integrationRouter = createTRPCRouter({
})),
);
}
if (input.attemptSearchEngineCreation) {
const icon = getIconUrl(input.kind);
await ctx.db.insert(searchEngines).values({
id: createId(),
name: input.name,
integrationId,
type: "fromIntegration",
iconUrl: icon,
short: await getNextValidShortNameForSearchEngineAsync(ctx.db, input.name),
});
}
}),
update: protectedProcedure.input(validation.integration.update).mutation(async ({ ctx, input }) => {
await throwIfActionForbiddenAsync(ctx, eq(integrations.id, input.id), "full");
@@ -383,31 +398,11 @@ export const integrationRouter = createTRPCRouter({
});
}),
searchInIntegration: protectedProcedure
.unstable_concat(createOneIntegrationMiddleware("query", ...getIntegrationKindsByCategory("search")))
.input(z.object({ integrationId: z.string(), query: z.string() }))
.query(async ({ ctx, input }) => {
const integration = await ctx.db.query.integrations.findFirst({
where: eq(integrations.id, input.integrationId),
with: {
secrets: true,
},
});
if (!integration) {
throw new TRPCError({
code: "NOT_FOUND",
message: "The requested integration does not exist",
});
}
if (!isIntegrationWithSearchSupport(integration)) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "The requested integration does not support searching",
});
}
const integrationInstance = integrationCreatorFromSecrets(integration);
return await integrationInstance.searchAsync(input.query);
const integrationInstance = integrationCreator(ctx.integration);
return await integrationInstance.searchAsync(encodeURI(input.query));
}),
});
@@ -430,6 +425,36 @@ interface AddSecretInput {
value: string;
kind: IntegrationSecretKind;
}
const getNextValidShortNameForSearchEngineAsync = async (db: Database, integrationName: string) => {
const searchEngines = await db.query.searchEngines.findMany({
columns: {
short: true,
},
});
const usedShortNames = searchEngines.flatMap((searchEngine) => searchEngine.short.toLowerCase());
const nameByIntegrationName = integrationName.slice(0, 1).toLowerCase();
if (!usedShortNames.includes(nameByIntegrationName)) {
return nameByIntegrationName;
}
// 8 is max length constraint
for (let i = 2; i < 9999999; i++) {
const generatedName = `${nameByIntegrationName}${i}`;
if (usedShortNames.includes(generatedName)) {
continue;
}
return generatedName;
}
throw new Error(
"Unable to automatically generate a short name. All possible variations were exhausted. Please disable the automatic creation and choose one later yourself.",
);
};
const addSecretAsync = async (db: Database, input: AddSecretInput) => {
await db.insert(integrationSecrets).values({
kind: input.kind,
@@ -1,5 +1,5 @@
import { decryptSecret } from "@homarr/common/server";
import type { Integration } from "@homarr/db/schema/sqlite";
import type { Integration } from "@homarr/db/schema";
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
import { getAllSecretKindOptions } from "@homarr/definitions";
import { integrationCreator, IntegrationTestConnectionError } from "@homarr/integrations";
+1 -1
View File
@@ -2,7 +2,7 @@ import { randomBytes } from "crypto";
import { TRPCError } from "@trpc/server";
import { asc, createId, eq } from "@homarr/db";
import { invites } from "@homarr/db/schema/sqlite";
import { invites } from "@homarr/db/schema";
import { selectInviteSchema } from "@homarr/db/validationSchemas";
import { z } from "@homarr/validation";
+22 -2
View File
@@ -1,7 +1,9 @@
import { TRPCError } from "@trpc/server";
import type { InferInsertModel } from "@homarr/db";
import { and, createId, desc, eq, like } from "@homarr/db";
import { medias } from "@homarr/db/schema/sqlite";
import { iconRepositories, icons, medias } from "@homarr/db/schema";
import { createLocalImageUrl, LOCAL_ICON_REPOSITORY_SLUG, mapMediaToIcon } from "@homarr/icons/local";
import { validation, z } from "@homarr/validation";
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
@@ -52,13 +54,29 @@ export const mediaRouter = createTRPCRouter({
.mutation(async ({ ctx, input }) => {
const content = Buffer.from(await input.file.arrayBuffer());
const id = createId();
await ctx.db.insert(medias).values({
const media = {
id,
creatorId: ctx.session.user.id,
content,
size: input.file.size,
contentType: input.file.type,
name: input.file.name,
} satisfies InferInsertModel<typeof medias>;
await ctx.db.insert(medias).values(media);
const localIconRepository = await ctx.db.query.iconRepositories.findFirst({
where: eq(iconRepositories.slug, LOCAL_ICON_REPOSITORY_SLUG),
});
if (!localIconRepository) return id;
const icon = mapMediaToIcon(media);
await ctx.db.insert(icons).values({
id: createId(),
checksum: icon.checksum,
name: icon.fileNameWithExtension,
url: icon.imageUrl,
iconRepositoryId: localIconRepository.id,
});
return id;
@@ -67,6 +85,7 @@ export const mediaRouter = createTRPCRouter({
const dbMedia = await ctx.db.query.medias.findFirst({
where: eq(medias.id, input.id),
columns: {
id: true,
creatorId: true,
},
});
@@ -87,5 +106,6 @@ export const mediaRouter = createTRPCRouter({
}
await ctx.db.delete(medias).where(eq(medias.id, input.id));
await ctx.db.delete(icons).where(eq(icons.url, createLocalImageUrl(input.id)));
}),
});
@@ -3,7 +3,7 @@ import { objectEntries } from "@homarr/common";
import type { MaybePromise } from "@homarr/common/types";
import type { Database } from "@homarr/db";
import { eq } from "@homarr/db";
import { groups, onboarding } from "@homarr/db/schema/sqlite";
import { groups, onboarding } from "@homarr/db/schema";
import type { OnboardingStep } from "@homarr/definitions";
import { credentialsAdminGroup } from "@homarr/definitions";
@@ -1,4 +1,4 @@
import { onboarding } from "@homarr/db/schema/sqlite";
import { onboarding } from "@homarr/db/schema";
import { onboardingSteps } from "@homarr/definitions";
import { z, zodEnumFromArray } from "@homarr/validation";
@@ -1,9 +1,11 @@
import { TRPCError } from "@trpc/server";
import { createId, eq, like, sql } from "@homarr/db";
import { searchEngines } from "@homarr/db/schema/sqlite";
import { searchEngines } from "@homarr/db/schema";
import { integrationCreator } from "@homarr/integrations";
import { validation } from "@homarr/validation";
import { createOneIntegrationMiddleware } from "../../middlewares/integration";
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
export const searchEngineRouter = createTRPCRouter({
@@ -56,9 +58,32 @@ export const searchEngineRouter = createTRPCRouter({
search: protectedProcedure.input(validation.common.search).query(async ({ ctx, input }) => {
return await ctx.db.query.searchEngines.findMany({
where: like(searchEngines.short, `${input.query.toLowerCase().trim()}%`),
with: {
integration: {
columns: {
kind: true,
url: true,
id: true,
},
},
},
limit: input.limit,
});
}),
getMediaRequestOptions: protectedProcedure
.unstable_concat(createOneIntegrationMiddleware("query", "jellyseerr", "overseerr"))
.input(validation.common.mediaRequestOptions)
.query(async ({ ctx, input }) => {
const integration = integrationCreator(ctx.integration);
return await integration.getSeriesInformationAsync(input.mediaType, input.mediaId);
}),
requestMedia: protectedProcedure
.unstable_concat(createOneIntegrationMiddleware("interact", "jellyseerr", "overseerr"))
.input(validation.common.requestMedia)
.mutation(async ({ ctx, input }) => {
const integration = integrationCreator(ctx.integration);
return await integration.requestMediaAsync(input.mediaType, input.mediaId, input.seasons);
}),
create: permissionRequiredProcedure
.requiresPermission("search-engine-create")
.input(validation.searchEngine.manage)
+1 -1
View File
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import { createId } from "@homarr/db";
import { apps } from "@homarr/db/schema/sqlite";
import { apps } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import type { GroupPermissionKey } from "@homarr/definitions";
+1 -1
View File
@@ -17,7 +17,7 @@ import {
sections,
serverSettings,
users,
} from "@homarr/db/schema/sqlite";
} from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import type { BoardPermission, GroupPermissionKey } from "@homarr/definitions";
@@ -2,7 +2,7 @@ import { describe, expect, test, vi } from "vitest";
import * as authShared from "@homarr/auth/shared";
import { createId, eq } from "@homarr/db";
import { boards, users } from "@homarr/db/schema/sqlite";
import { boards, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { throwIfActionForbiddenAsync } from "../../board/board-access";
+1 -1
View File
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import * as env from "@homarr/auth/env.mjs";
import { createId, eq } from "@homarr/db";
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema/sqlite";
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import type { GroupPermissionKey } from "@homarr/definitions";
@@ -2,7 +2,7 @@ import { describe, expect, test, vi } from "vitest";
import * as authShared from "@homarr/auth/shared";
import { createId, eq } from "@homarr/db";
import { integrations, users } from "@homarr/db/schema/sqlite";
import { integrations, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { throwIfActionForbiddenAsync } from "../../integration/integration-access";
@@ -4,7 +4,7 @@ import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import { encryptSecret } from "@homarr/common/server";
import { createId } from "@homarr/db";
import { integrations, integrationSecrets } from "@homarr/db/schema/sqlite";
import { integrations, integrationSecrets } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import type { GroupPermissionKey } from "@homarr/definitions";
@@ -179,6 +179,7 @@ describe("create should create a new integration", () => {
kind: "jellyfin" as const,
url: "http://jellyfin.local",
secrets: [{ kind: "apiKey" as const, value: "1234567890" }],
attemptSearchEngineCreation: false,
};
const fakeNow = new Date("2023-07-01T00:00:00Z");
@@ -201,6 +202,48 @@ describe("create should create a new integration", () => {
expect(dbSecret!.updatedAt).toEqual(fakeNow);
});
test("with create integration access should create a new integration when creating search engine", async () => {
const db = createDb();
const caller = integrationRouter.createCaller({
db,
session: defaultSessionWithPermissions(["integration-create"]),
});
const input = {
name: "Jellyseerr",
kind: "jellyseerr" as const,
url: "http://jellyseerr.local",
secrets: [{ kind: "apiKey" as const, value: "1234567890" }],
attemptSearchEngineCreation: true,
};
const fakeNow = new Date("2023-07-01T00:00:00Z");
vi.useFakeTimers();
vi.setSystemTime(fakeNow);
await caller.create(input);
vi.useRealTimers();
const dbIntegration = await db.query.integrations.findFirst();
const dbSecret = await db.query.integrationSecrets.findFirst();
const dbSearchEngine = await db.query.searchEngines.findFirst();
expect(dbIntegration).toBeDefined();
expect(dbIntegration!.name).toBe(input.name);
expect(dbIntegration!.kind).toBe(input.kind);
expect(dbIntegration!.url).toBe(input.url);
expect(dbSecret!.integrationId).toBe(dbIntegration!.id);
expect(dbSecret).toBeDefined();
expect(dbSecret!.kind).toBe(input.secrets[0]!.kind);
expect(dbSecret!.value).toMatch(/^[a-f0-9]+.[a-f0-9]+$/);
expect(dbSecret!.updatedAt).toEqual(fakeNow);
expect(dbSearchEngine!.integrationId).toBe(dbIntegration!.id);
expect(dbSearchEngine!.short).toBe("j");
expect(dbSearchEngine!.name).toBe(input.name);
expect(dbSearchEngine!.iconUrl).toBe(
"https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyseerr.png",
);
});
test("without create integration access should throw permission error", async () => {
// Arrange
const db = createDb();
@@ -213,6 +256,7 @@ describe("create should create a new integration", () => {
kind: "jellyfin" as const,
url: "http://jellyfin.local",
secrets: [{ kind: "apiKey" as const, value: "1234567890" }],
attemptSearchEngineCreation: false,
};
// Act
+1 -1
View File
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import { createId } from "@homarr/db";
import { invites, users } from "@homarr/db/schema/sqlite";
import { invites, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { inviteRouter } from "../invite";
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import { createId } from "@homarr/db";
import { serverSettings } from "@homarr/db/schema/sqlite";
import { serverSettings } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { defaultServerSettings, defaultServerSettingsKeys } from "@homarr/server-settings";
+10 -10
View File
@@ -2,8 +2,8 @@ import { describe, expect, it, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import type { Database } from "@homarr/db";
import { createId, eq, schema } from "@homarr/db";
import { onboarding, users } from "@homarr/db/schema/sqlite";
import { createId, eq } from "@homarr/db";
import { invites, onboarding, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import type { GroupPermissionKey, OnboardingStep } from "@homarr/definitions";
@@ -121,7 +121,7 @@ describe("register should create a user with valid invitation", () => {
await db.insert(users).values({
id: userId,
});
await db.insert(schema.invites).values({
await db.insert(invites).values({
id: inviteId,
token: inviteToken,
creatorId: userId,
@@ -176,7 +176,7 @@ describe("register should create a user with valid invitation", () => {
await db.insert(users).values({
id: userId,
});
await db.insert(schema.invites).values({
await db.insert(invites).values({
id: inviteId,
token: inviteToken,
creatorId: userId,
@@ -211,7 +211,7 @@ describe("editProfile shoud update user", () => {
const emailVerified = new Date(2024, 0, 5);
await db.insert(schema.users).values({
await db.insert(users).values({
id: defaultOwnerId,
name: "TEST 1",
email: "abc@gmail.com",
@@ -226,7 +226,7 @@ describe("editProfile shoud update user", () => {
});
// assert
const user = await db.select().from(schema.users).where(eq(schema.users.id, defaultOwnerId));
const user = await db.select().from(users).where(eq(users.id, defaultOwnerId));
expect(user).toHaveLength(1);
expect(user[0]).containSubset({
@@ -245,7 +245,7 @@ describe("editProfile shoud update user", () => {
session: defaultSession,
});
await db.insert(schema.users).values({
await db.insert(users).values({
id: defaultOwnerId,
name: "TEST 1",
email: "abc@gmail.com",
@@ -260,7 +260,7 @@ describe("editProfile shoud update user", () => {
});
// assert
const user = await db.select().from(schema.users).where(eq(schema.users.id, defaultOwnerId));
const user = await db.select().from(users).where(eq(users.id, defaultOwnerId));
expect(user).toHaveLength(1);
expect(user[0]).containSubset({
@@ -295,11 +295,11 @@ describe("delete should delete user", () => {
},
];
await db.insert(schema.users).values(initialUsers);
await db.insert(users).values(initialUsers);
await caller.delete({ userId: defaultOwnerId });
const usersInDb = await db.select().from(schema.users);
const usersInDb = await db.select().from(users);
expect(usersInDb).toHaveLength(2);
expect(usersInDb[0]).containSubset(initialUsers[0]);
expect(usersInDb[1]).containSubset(initialUsers[2]);
+3 -3
View File
@@ -2,8 +2,8 @@ import { TRPCError } from "@trpc/server";
import { createSaltAsync, hashPasswordAsync } from "@homarr/auth";
import type { Database } from "@homarr/db";
import { and, createId, eq, like, schema } from "@homarr/db";
import { groupMembers, groupPermissions, groups, invites, users } from "@homarr/db/schema/sqlite";
import { and, createId, eq, like } from "@homarr/db";
import { groupMembers, groupPermissions, groups, invites, users } from "@homarr/db/schema";
import { selectUserSchema } from "@homarr/db/validationSchemas";
import { credentialsAdminGroup } from "@homarr/definitions";
import type { SupportedAuthProvider } from "@homarr/definitions";
@@ -509,7 +509,7 @@ const createUserAsync = async (db: Database, input: Omit<z.infer<typeof validati
const username = input.username.toLowerCase();
const userId = createId();
await db.insert(schema.users).values({
await db.insert(users).values({
id: userId,
name: username,
email: input.email,
+1 -1
View File
@@ -1,7 +1,7 @@
import { observable } from "@trpc/server/observable";
import type { Modify } from "@homarr/common/types";
import type { Integration } from "@homarr/db/schema/sqlite";
import type { Integration } from "@homarr/db/schema";
import type { IntegrationKindByCategory } from "@homarr/definitions";
import { getIntegrationKindsByCategory } from "@homarr/definitions";
import { integrationCreator } from "@homarr/integrations";
+1 -1
View File
@@ -1,7 +1,7 @@
import { observable } from "@trpc/server/observable";
import type { Modify } from "@homarr/common/types";
import type { Integration } from "@homarr/db/schema/sqlite";
import type { Integration } from "@homarr/db/schema";
import type { IntegrationKindByCategory } from "@homarr/definitions";
import { getIntegrationKindsByCategory } from "@homarr/definitions";
import type { DownloadClientJobsAndStatus } from "@homarr/integrations";
+2
View File
@@ -8,6 +8,7 @@ import { indexerManagerRouter } from "./indexer-manager";
import { mediaRequestsRouter } from "./media-requests";
import { mediaServerRouter } from "./media-server";
import { mediaTranscodingRouter } from "./media-transcoding";
import { minecraftRouter } from "./minecraft";
import { notebookRouter } from "./notebook";
import { rssFeedRouter } from "./rssFeed";
import { smartHomeRouter } from "./smart-home";
@@ -27,4 +28,5 @@ export const widgetRouter = createTRPCRouter({
indexerManager: indexerManagerRouter,
healthMonitoring: healthMonitoringRouter,
mediaTranscoding: mediaTranscodingRouter,
minecraft: minecraftRouter,
});
@@ -21,6 +21,7 @@ export const mediaServerRouter = createTRPCRouter({
const { data } = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
return {
integrationId: integration.id,
integrationKind: integration.kind,
sessions: data,
};
}),
@@ -0,0 +1,36 @@
import { observable } from "@trpc/server/observable";
import { z } from "zod";
import type { MinecraftServerStatus } from "@homarr/request-handler/minecraft-server-status";
import { minecraftServerStatusRequestHandler } from "@homarr/request-handler/minecraft-server-status";
import { createTRPCRouter, publicProcedure } from "../../trpc";
const serverStatusInputSchema = z.object({
domain: z.string().nonempty(),
isBedrockServer: z.boolean(),
});
export const minecraftRouter = createTRPCRouter({
getServerStatus: publicProcedure.input(serverStatusInputSchema).query(async ({ input }) => {
const innerHandler = minecraftServerStatusRequestHandler.handler({
isBedrockServer: input.isBedrockServer,
domain: input.domain,
});
return await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true });
}),
subscribeServerStatus: publicProcedure.input(serverStatusInputSchema).subscription(({ input }) => {
return observable<MinecraftServerStatus>((emit) => {
const innerHandler = minecraftServerStatusRequestHandler.handler({
isBedrockServer: input.isBedrockServer,
domain: input.domain,
});
const unsubscribe = innerHandler.subscribe((data) => {
emit.next(data);
});
return () => {
unsubscribe();
};
});
}),
});
+1 -1
View File
@@ -2,7 +2,7 @@ import { TRPCError } from "@trpc/server";
import SuperJSON from "superjson";
import { eq } from "@homarr/db";
import { items } from "@homarr/db/schema/sqlite";
import { items } from "@homarr/db/schema";
import { z } from "@homarr/validation";
import { createTRPCRouter, protectedProcedure } from "../../trpc";
+1 -1
View File
@@ -3,7 +3,7 @@ import { DrizzleAdapter } from "@auth/drizzle-adapter";
import type { Database } from "@homarr/db";
import { and, eq } from "@homarr/db";
import { accounts, sessions, users } from "@homarr/db/schema/sqlite";
import { accounts, sessions, users } from "@homarr/db/schema";
import type { SupportedAuthProvider } from "@homarr/definitions";
export const createAdapter = (db: Database, provider: SupportedAuthProvider | "unknown"): Adapter => {
+1 -1
View File
@@ -4,7 +4,7 @@ import type { NextAuthConfig } from "next-auth";
import type { Session } from "@homarr/auth";
import type { Database } from "@homarr/db";
import { eq, inArray } from "@homarr/db";
import { groupMembers, groupPermissions, users } from "@homarr/db/schema/sqlite";
import { groupMembers, groupPermissions, users } from "@homarr/db/schema";
import { getPermissionsWithChildren } from "@homarr/definitions";
export const getCurrentUserPermissionsAsync = async (db: Database, userId: string) => {
-2
View File
@@ -64,7 +64,6 @@ export const env = createEnv({
server: {
AUTH_LOGOUT_REDIRECT_URL: z.string().url().optional(),
AUTH_SESSION_EXPIRY_TIME: createDurationSchema("30d"),
AUTH_SECRET: process.env.NODE_ENV === "production" ? z.string().min(1) : z.string().min(1).optional(),
AUTH_PROVIDERS: authProvidersSchema,
...(authProviders.includes("oidc")
? {
@@ -98,7 +97,6 @@ export const env = createEnv({
runtimeEnv: {
AUTH_LOGOUT_REDIRECT_URL: process.env.AUTH_LOGOUT_REDIRECT_URL,
AUTH_SESSION_EXPIRY_TIME: process.env.AUTH_SESSION_EXPIRY_TIME,
AUTH_SECRET: process.env.AUTH_SECRET,
AUTH_PROVIDERS: process.env.AUTH_PROVIDERS,
AUTH_LDAP_BASE: process.env.AUTH_LDAP_BASE,
AUTH_LDAP_BIND_DN: process.env.AUTH_LDAP_BIND_DN,
+1 -1
View File
@@ -4,7 +4,7 @@ import type { NextAuthConfig } from "next-auth";
import { and, eq, inArray } from "@homarr/db";
import type { Database } from "@homarr/db";
import { groupMembers, groups, users } from "@homarr/db/schema/sqlite";
import { groupMembers, groups, users } from "@homarr/db/schema";
import { colorSchemeCookieKey, everyoneGroup } from "@homarr/definitions";
import { logger } from "@homarr/log";
+2 -2
View File
@@ -33,8 +33,8 @@
"@t3-oss/env-nextjs": "^0.11.1",
"bcrypt": "^5.1.1",
"cookies": "^0.9.1",
"ldapts": "7.2.2",
"next": "^14.2.20",
"ldapts": "7.3.0",
"next": "^14.2.22",
"next-auth": "5.0.0-beta.25",
"react": "^19.0.0",
"react-dom": "^19.0.0"
@@ -2,7 +2,7 @@ import type { Session } from "next-auth";
import type { Database } from "@homarr/db";
import { and, eq, inArray, or } from "@homarr/db";
import { boards, boardUserPermissions, groupMembers } from "@homarr/db/schema/sqlite";
import { boards, boardUserPermissions, groupMembers } from "@homarr/db/schema";
import type { IntegrationPermission } from "@homarr/definitions";
import { constructIntegrationPermissions } from "./integration-permissions";
@@ -1,7 +1,7 @@
import type { Session } from "next-auth";
import { db, eq, inArray } from "@homarr/db";
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema/sqlite";
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema";
import { constructIntegrationPermissions } from "./integration-permissions";
@@ -3,14 +3,7 @@ import { describe, expect, test, vi } from "vitest";
import type { InferInsertModel } from "@homarr/db";
import { createId } from "@homarr/db";
import {
boardGroupPermissions,
boards,
boardUserPermissions,
groupMembers,
groups,
users,
} from "@homarr/db/schema/sqlite";
import { boardGroupPermissions, boards, boardUserPermissions, groupMembers, groups, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import * as integrationPermissions from "../integration-permissions";
@@ -2,7 +2,7 @@ import bcrypt from "bcrypt";
import type { Database } from "@homarr/db";
import { and, eq } from "@homarr/db";
import { users } from "@homarr/db/schema/sqlite";
import { users } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import type { validation, z } from "@homarr/validation";
@@ -2,7 +2,7 @@ import { CredentialsSignin } from "@auth/core/errors";
import type { Database, InferInsertModel } from "@homarr/db";
import { and, createId, eq } from "@homarr/db";
import { users } from "@homarr/db/schema/sqlite";
import { users } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import type { validation } from "@homarr/validation";
import { z } from "@homarr/validation";
@@ -23,7 +23,8 @@ export const OidcProvider = (headers: ReadonlyHeaders | null): OIDCConfig<Profil
authorization: {
params: {
scope: env.AUTH_OIDC_SCOPE_OVERWRITE,
redirect_uri: createRedirectUri(headers, "/api/auth/callback/oidc"),
// We fallback to https as generally oidc providers require https
redirect_uri: createRedirectUri(headers, "/api/auth/callback/oidc", "https"),
},
},
profile(profile) {
@@ -1,7 +1,7 @@
import { describe, expect, test } from "vitest";
import { createId } from "@homarr/db";
import { users } from "@homarr/db/schema/sqlite";
import { users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { createSaltAsync, hashPasswordAsync } from "../../security";
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
import type { Database } from "@homarr/db";
import { and, createId, eq } from "@homarr/db";
import { groups, users } from "@homarr/db/schema/sqlite";
import { groups, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { authorizeWithLdapCredentialsAsync } from "../credentials/authorization/ldap-authorization";
+6 -2
View File
@@ -8,12 +8,16 @@ import { extractBaseUrlFromHeaders } from "@homarr/common";
* @param pathname
* @returns
*/
export const createRedirectUri = (headers: ReadonlyHeaders | null, pathname: string) => {
export const createRedirectUri = (
headers: ReadonlyHeaders | null,
pathname: string,
fallbackProtocol: "http" | "https" = "http",
) => {
if (!headers) {
return pathname;
}
const baseUrl = extractBaseUrlFromHeaders(headers);
const baseUrl = extractBaseUrlFromHeaders(headers, fallbackProtocol);
const path = pathname.startsWith("/") ? pathname : `/${pathname}`;
+1 -1
View File
@@ -1,6 +1,6 @@
import { describe, expect, test } from "vitest";
import { users } from "@homarr/db/schema/sqlite";
import { users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { createAdapter } from "../adapter";
+1 -1
View File
@@ -3,7 +3,7 @@ import type { AdapterUser } from "@auth/core/adapters";
import type { JWT } from "next-auth/jwt";
import { describe, expect, test, vi } from "vitest";
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema/sqlite";
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import * as definitions from "@homarr/definitions";
+1 -1
View File
@@ -5,7 +5,7 @@ import { describe, expect, test, vi } from "vitest";
import { eq } from "@homarr/db";
import type { Database } from "@homarr/db";
import { groupMembers, groups, users } from "@homarr/db/schema/sqlite";
import { groupMembers, groups, users } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import { colorSchemeCookieKey, everyoneGroup } from "@homarr/definitions";
+1 -1
View File
@@ -3,7 +3,7 @@ import { command, string } from "@drizzle-team/brocli";
import { hashPasswordAsync } from "@homarr/auth";
import { generateSecureRandomToken } from "@homarr/common/server";
import { and, db, eq } from "@homarr/db";
import { sessions, users } from "@homarr/db/schema/sqlite";
import { sessions, users } from "@homarr/db/schema";
export const resetPassword = command({
name: "reset-password",
+28
View File
@@ -0,0 +1,28 @@
import { randomBytes } from "crypto";
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
const errorSuffix = `, please generate a 64 character secret in hex format or use the following: "${randomBytes(32).toString("hex")}"`;
export const env = createEnv({
server: {
SECRET_ENCRYPTION_KEY: z
.string({
required_error: `SECRET_ENCRYPTION_KEY is required${errorSuffix}`,
})
.min(64, {
message: `SECRET_ENCRYPTION_KEY has to be 64 characters${errorSuffix}`,
})
.max(64, {
message: `SECRET_ENCRYPTION_KEY has to be 64 characters${errorSuffix}`,
})
.regex(/^[0-9a-fA-F]{64}$/, {
message: `SECRET_ENCRYPTION_KEY must only contain hex characters${errorSuffix}`,
}),
},
runtimeEnv: {
SECRET_ENCRYPTION_KEY: process.env.SECRET_ENCRYPTION_KEY,
},
skipValidation:
Boolean(process.env.CI) || Boolean(process.env.SKIP_ENV_VALIDATION) || process.env.npm_lifecycle_event === "lint",
});
+4 -4
View File
@@ -8,7 +8,8 @@
".": "./index.ts",
"./types": "./src/types.ts",
"./server": "./src/server.ts",
"./client": "./src/client.ts"
"./client": "./src/client.ts",
"./env.mjs": "./env.mjs"
},
"typesVersions": {
"*": {
@@ -27,9 +28,8 @@
"dependencies": {
"@homarr/log": "workspace:^0.1.0",
"dayjs": "^1.11.13",
"next": "^14.2.20",
"react": "^19.0.0",
"tldts": "^6.1.68"
"next": "^14.2.22",
"react": "^19.0.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
-23
View File
@@ -1,23 +0,0 @@
import * as tldts from "tldts";
const safeParseTldts = (url: string) => {
try {
return tldts.parse(url);
} catch {
return null;
}
};
export const parseAppHrefWithVariables = <TInput extends string | null>(url: TInput, currentHref: string): TInput => {
if (!url || url.length === 0) return url;
const tldtsResult = safeParseTldts(currentHref);
const urlObject = new URL(currentHref);
return url
.replaceAll("[homarr_base]", `${urlObject.protocol}//${urlObject.hostname}`)
.replaceAll("[homarr_hostname]", tldtsResult?.hostname ?? "")
.replaceAll("[homarr_domain]", tldtsResult?.domain ?? "")
.replaceAll("[homarr_protocol]", urlObject.protocol.replace(":", "")) as TInput;
};
-6
View File
@@ -1,6 +0,0 @@
import { parseAppHrefWithVariables } from "./base";
export const parseAppHrefWithVariablesClient = <TInput extends string | null>(url: TInput): TInput => {
if (typeof window === "undefined") return url;
return parseAppHrefWithVariables(url, window.location.href);
};
-8
View File
@@ -1,8 +0,0 @@
import { headers } from "next/headers";
import { extractBaseUrlFromHeaders } from "../url";
import { parseAppHrefWithVariables } from "./base";
export const parseAppHrefWithVariablesServer = <TInput extends string | null>(url: TInput): TInput => {
return parseAppHrefWithVariables(url, extractBaseUrlFromHeaders(headers()));
};
-1
View File
@@ -1,2 +1 @@
export * from "./app-url/client";
export * from "./revalidate-path-action";
+4 -12
View File
@@ -1,20 +1,12 @@
import crypto from "crypto";
import { logger } from "@homarr/log";
import { env } from "../env.mjs";
const algorithm = "aes-256-cbc"; //Using AES encryption
const fallbackKey = "0000000000000000000000000000000000000000000000000000000000000000";
const encryptionKey = process.env.ENCRYPTION_KEY ?? fallbackKey; // Fallback to a default key for local development
if (encryptionKey === fallbackKey) {
logger.warn("Using a fallback encryption key, stored secrets are not secure");
// We never want to use the fallback key in production
if (process.env.NODE_ENV === "production" && process.env.CI !== "true") {
throw new Error("Encryption key is not set");
}
}
const key = Buffer.from(encryptionKey, "hex");
// We fallback to a key of 0s if the key was not provided because env validation was skipped
// This should only be the case in CI
const key = Buffer.from(env.SECRET_ENCRYPTION_KEY || "0".repeat(64), "hex");
export function encryptSecret(text: string): `${string}.${string}` {
const initializationVector = crypto.randomBytes(16);
-1
View File
@@ -1,3 +1,2 @@
export * from "./app-url/server";
export * from "./security";
export * from "./encryption";
+5
View File
@@ -11,3 +11,8 @@ export type RemoveReadonly<T> = {
};
export type MaybeArray<T> = T | T[];
export type Inverse<T extends Invertible> = {
[Key in keyof T as T[Key]]: Key;
};
type Invertible = Record<PropertyKey, PropertyKey>;
+10 -2
View File
@@ -4,8 +4,16 @@ export const removeTrailingSlash = (path: string) => {
return path.at(-1) === "/" ? path.substring(0, path.length - 1) : path;
};
export const extractBaseUrlFromHeaders = (headers: ReadonlyHeaders): `${string}://${string}` => {
let protocol = headers.get("x-forwarded-proto") ?? "http";
export const extractBaseUrlFromHeaders = (
headers: ReadonlyHeaders,
fallbackProtocol: "http" | "https" = "http",
): `${string}://${string}` => {
let protocol = headers.get("x-forwarded-proto");
// If the protocol is not set or an empty string
if (!protocol) {
protocol = fallbackProtocol;
}
// @see https://support.glitch.com/t/x-forwarded-proto-contains-multiple-protocols/17219
if (protocol.includes(",")) {
+2
View File
@@ -9,6 +9,7 @@ import { mediaOrganizerJob } from "./jobs/integrations/media-organizer";
import { mediaRequestListJob, mediaRequestStatsJob } from "./jobs/integrations/media-requests";
import { mediaServerJob } from "./jobs/integrations/media-server";
import { mediaTranscodingJob } from "./jobs/integrations/media-transcoding";
import { minecraftServerStatusJob } from "./jobs/minecraft-server-status";
import { pingJob } from "./jobs/ping";
import type { RssFeed } from "./jobs/rss-feeds";
import { rssFeedsJob } from "./jobs/rss-feeds";
@@ -33,6 +34,7 @@ export const jobGroup = createCronJobGroup({
sessionCleanup: sessionCleanupJob,
updateChecker: updateCheckerJob,
mediaTranscoding: mediaTranscodingJob,
minecraftServerStatus: minecraftServerStatusJob,
});
export type JobGroupKeys = ReturnType<(typeof jobGroup)["getKeys"]>[number];
+1 -1
View File
@@ -3,7 +3,7 @@ import { EVERY_WEEK } from "@homarr/cron-jobs-core/expressions";
import type { InferInsertModel } from "@homarr/db";
import { db, inArray } from "@homarr/db";
import { createId } from "@homarr/db/client";
import { iconRepositories, icons } from "@homarr/db/schema/sqlite";
import { iconRepositories, icons } from "@homarr/db/schema";
import { fetchIconsAsync } from "@homarr/icons";
import { logger } from "@homarr/log";
@@ -0,0 +1,25 @@
import SuperJSON from "superjson";
import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions";
import { db, eq } from "@homarr/db";
import { items } from "@homarr/db/schema";
import { minecraftServerStatusRequestHandler } from "@homarr/request-handler/minecraft-server-status";
import type { WidgetComponentProps } from "../../../widgets/src";
import { createCronJob } from "../lib";
export const minecraftServerStatusJob = createCronJob("minecraftServerStatus", EVERY_5_MINUTES).withCallback(
async () => {
const dbItems = await db.query.items.findMany({
where: eq(items.kind, "minecraftServerStatus"),
});
await Promise.allSettled(
dbItems.map(async (item) => {
const options = SuperJSON.parse<WidgetComponentProps<"minecraftServerStatus">["options"]>(item.options);
const innerHandler = minecraftServerStatusRequestHandler.handler(options);
await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true });
}),
);
},
);
+1 -1
View File
@@ -5,7 +5,7 @@ import SuperJSON from "superjson";
import type { Modify } from "@homarr/common/types";
import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions";
import { db, eq } from "@homarr/db";
import { items } from "@homarr/db/schema/sqlite";
import { items } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import { createItemChannel } from "@homarr/redis";
import { z } from "@homarr/validation";
Loaded 100 of 236 files, more files were not shown because too many files have changed in this diff. Show more