Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c8d4f5018 | ||
|
|
2b59f19a7f | ||
|
|
fff1da88bd | ||
|
|
720fdb772c | ||
|
|
a225bdd70c | ||
|
|
e40c348352 | ||
|
|
28e1175565 | ||
|
|
b450b00934 | ||
|
|
8e0bf87c56 | ||
|
|
9e061f8fc7 | ||
|
|
10855bd84c | ||
|
|
93d5ca683b | ||
|
|
d2584b63c5 | ||
|
|
8c1156240c | ||
|
|
bb7f751481 | ||
|
|
1e8a5359b7 | ||
|
|
550bca6dee | ||
|
|
2ae3d938ee | ||
|
|
2b4bc8352e | ||
|
|
c0f681637d | ||
|
|
92cd1c5bd0 | ||
|
|
3b7e6cc083 | ||
|
|
61afab518f | ||
|
|
a7bd664c5c | ||
|
|
a2c3bee66c | ||
|
|
b6dad438c2 | ||
|
|
044c60bdec | ||
|
|
de8485d5c3 | ||
|
|
26b6ca2445 | ||
|
|
63a7be35a4 | ||
|
|
1baa9fc74c | ||
|
|
a51999457b | ||
|
|
5fbbf037ce | ||
|
|
3c0f272707 | ||
|
|
d2b4bf5ae4 | ||
|
|
d803087345 | ||
|
|
d3a883a252 | ||
|
|
694350583a | ||
|
|
ecc4586d02 | ||
|
|
ce4fa5ff67 | ||
|
|
649506b56a |
No files matched your search
@@ -40,6 +40,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 +88,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
|
||||
@@ -104,9 +112,11 @@ jobs:
|
||||
NEXT_VERSION: ${{ needs.release.outputs.version }}
|
||||
DEPLOY_LATEST: ${{ github.ref_name == 'main' }}
|
||||
DEPLOY_BETA: ${{ github.ref_name == 'beta' }}
|
||||
PUSH_IMAGE: ${{ github.event_name != 'workflow_dispatch' || github.events.inputs.push-image == 'true' }}
|
||||
PUSH_IMAGE: ${{ github.event_name != 'workflow_dispatch' || github.events.inputs.push-image == true }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.release.outputs.git_ref }}
|
||||
- name: Discord notification
|
||||
if: ${{ github.events.inputs.send-notifications != false }}
|
||||
env:
|
||||
@@ -130,8 +140,8 @@ jobs:
|
||||
with:
|
||||
images: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
|
||||
tags: |
|
||||
${{ env.DEPLOY_LATEST == true && 'type=raw,value=latest' || null }}
|
||||
${{ env.DEPLOY_BETA == true && 'type=raw,value=beta' || 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
|
||||
id: buildPushAction
|
||||
@@ -150,4 +160,4 @@ jobs:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@master
|
||||
with:
|
||||
args: "Deployment of image has completed for branch ${{ github.ref_name }}. 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 }}'. ${{ env.PUSH_IMAGE == 'true' && '' || 'This was a dry run' }}"
|
||||
@@ -1,3 +1,49 @@
|
||||
## [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
|
||||
|
||||
+4
-3
@@ -26,7 +26,7 @@ FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
# gettext is required for envsubst
|
||||
RUN apk add --no-cache redis nginx bash gettext
|
||||
RUN apk add --no-cache redis nginx bash gettext su-exec
|
||||
RUN mkdir /appdata
|
||||
VOLUME /appdata
|
||||
RUN mkdir /secrets
|
||||
@@ -43,14 +43,12 @@ RUN echo $'#!/bin/bash\ncd /app/apps/cli && node ./cli.cjs "$@"' > /usr/bin/homa
|
||||
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
|
||||
|
||||
COPY --from=builder /app/apps/nextjs/next.config.mjs .
|
||||
COPY --from=builder /app/apps/nextjs/package.json .
|
||||
@@ -67,6 +65,8 @@ 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 scripts/entrypoint.sh ./entrypoint.sh
|
||||
RUN chmod +x ./entrypoint.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
|
||||
@@ -77,4 +77,5 @@ ENV DB_DIALECT='sqlite'
|
||||
ENV DB_DRIVER='better-sqlite3'
|
||||
ENV AUTH_PROVIDERS='credentials'
|
||||
|
||||
ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||
CMD ["sh", "run.sh"]
|
||||
@@ -1,5 +1,6 @@
|
||||
// Importing env files here to validate on build
|
||||
import "@homarr/auth/env.mjs";
|
||||
import "@homarr/db/env.mjs";
|
||||
|
||||
import MillionLint from "@million/lint";
|
||||
import createNextIntlPlugin from "next-intl/plugin";
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"glob": "^11.0.0",
|
||||
"jotai": "^2.10.4",
|
||||
"mantine-react-table": "2.0.0-beta.7",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"postcss-preset-mantine": "^1.17.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"react": "^19.0.0",
|
||||
@@ -84,7 +84,7 @@
|
||||
"@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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
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
|
||||
@@ -19,21 +15,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(),
|
||||
@@ -51,13 +32,6 @@ export const env = createEnv({
|
||||
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,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> => {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"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",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homarr",
|
||||
"version": "1.0.0-beta.2",
|
||||
"version": "1.0.0-beta.6",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "cross-env CI=true turbo build",
|
||||
@@ -52,7 +52,7 @@
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^2.1.8"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.0",
|
||||
"packageManager": "pnpm@9.15.1",
|
||||
"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";
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"@trpc/react-query": "next",
|
||||
"@trpc/server": "next",
|
||||
"dockerode": "^4.0.2",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"superjson": "2.2.2",
|
||||
"trpc-to-openapi": "^2.1.0"
|
||||
|
||||
@@ -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,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,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,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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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,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,19 @@ import {
|
||||
integrations,
|
||||
integrationSecrets,
|
||||
integrationUserPermissions,
|
||||
} from "@homarr/db/schema/sqlite";
|
||||
} from "@homarr/db/schema";
|
||||
import type { IntegrationSecretKind } from "@homarr/definitions";
|
||||
import {
|
||||
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 +91,7 @@ export const integrationRouter = createTRPCRouter({
|
||||
where: inArray(
|
||||
integrations.kind,
|
||||
objectEntries(integrationDefs)
|
||||
.filter(([_, integration]) => integration.supportsSearch)
|
||||
.filter(([_, integration]) => [...integration.category].includes("search"))
|
||||
.map(([kind, _]) => kind),
|
||||
),
|
||||
});
|
||||
@@ -383,31 +384,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));
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { and, createId, desc, eq, like } from "@homarr/db";
|
||||
import { medias } from "@homarr/db/schema/sqlite";
|
||||
import { medias } from "@homarr/db/schema";
|
||||
import { validation, z } from "@homarr/validation";
|
||||
|
||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
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 { validation } from "@homarr/validation";
|
||||
|
||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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,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,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,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";
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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.21",
|
||||
"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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
"dependencies": {
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"tldts": "^6.1.68"
|
||||
"tldts": "^6.1.69"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { env } from "@homarr/auth/env.mjs";
|
||||
import { NEVER } from "@homarr/cron-jobs-core/expressions";
|
||||
import { db, eq, inArray } from "@homarr/db";
|
||||
import { sessions, users } from "@homarr/db/schema/sqlite";
|
||||
import { sessions, users } from "@homarr/db/schema";
|
||||
import { supportedAuthProviders } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import * as dotenv from "dotenv";
|
||||
import type { Config } from "drizzle-kit";
|
||||
|
||||
dotenv.config({ path: "../../.env" });
|
||||
import { env } from "../env.mjs";
|
||||
|
||||
export default {
|
||||
dialect: "mysql",
|
||||
schema: "./schema",
|
||||
casing: "snake_case",
|
||||
dbCredentials: {
|
||||
host: process.env.DB_HOST!,
|
||||
user: process.env.DB_USER!,
|
||||
password: process.env.DB_PASSWORD!,
|
||||
database: process.env.DB_NAME!,
|
||||
port: parseInt(process.env.DB_PORT!),
|
||||
},
|
||||
dbCredentials: env.DB_URL
|
||||
? { url: env.DB_URL }
|
||||
: {
|
||||
host: env.DB_HOST,
|
||||
user: env.DB_USER,
|
||||
password: env.DB_PASSWORD,
|
||||
database: env.DB_NAME,
|
||||
port: env.DB_PORT,
|
||||
},
|
||||
out: "./migrations/mysql",
|
||||
} satisfies Config;
|
||||
@@ -1,13 +1,11 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import type { Config } from "drizzle-kit";
|
||||
|
||||
dotenv.config({ path: "../../.env" });
|
||||
import { env } from "../env.mjs";
|
||||
|
||||
export default {
|
||||
dialect: "sqlite",
|
||||
schema: "./schema",
|
||||
casing: "snake_case",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
dbCredentials: { url: process.env.DB_URL! },
|
||||
dbCredentials: { url: env.DB_URL },
|
||||
out: "./migrations/sqlite",
|
||||
} satisfies Config;
|
||||
+10
-10
@@ -7,6 +7,7 @@ import mysql from "mysql2";
|
||||
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import { env } from "./env.mjs";
|
||||
import * as mysqlSchema from "./schema/mysql";
|
||||
import * as sqliteSchema from "./schema/sqlite";
|
||||
|
||||
@@ -15,7 +16,7 @@ type HomarrDatabase = BetterSQLite3Database<typeof sqliteSchema>;
|
||||
const init = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!connection) {
|
||||
switch (process.env.DB_DRIVER) {
|
||||
switch (env.DB_DRIVER) {
|
||||
case "mysql2":
|
||||
initMySQL2();
|
||||
break;
|
||||
@@ -36,7 +37,7 @@ class WinstonDrizzleLogger implements Logger {
|
||||
}
|
||||
|
||||
const initBetterSqlite = () => {
|
||||
connection = new Database(process.env.DB_URL);
|
||||
connection = new Database(env.DB_URL);
|
||||
database = drizzleSqlite(connection, {
|
||||
schema: sqliteSchema,
|
||||
logger: new WinstonDrizzleLogger(),
|
||||
@@ -45,16 +46,15 @@ const initBetterSqlite = () => {
|
||||
};
|
||||
|
||||
const initMySQL2 = () => {
|
||||
if (!process.env.DB_HOST) {
|
||||
connection = mysql.createConnection({ uri: process.env.DB_URL });
|
||||
if (!env.DB_HOST) {
|
||||
connection = mysql.createConnection({ uri: env.DB_URL });
|
||||
} else {
|
||||
connection = mysql.createConnection({
|
||||
host: process.env.DB_HOST,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
database: process.env.DB_NAME!,
|
||||
port: Number(process.env.DB_PORT),
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
host: env.DB_HOST,
|
||||
database: env.DB_NAME,
|
||||
port: env.DB_PORT,
|
||||
user: env.DB_USER,
|
||||
password: env.DB_PASSWORD,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
const drivers = {
|
||||
betterSqlite3: "better-sqlite3",
|
||||
mysql2: "mysql2",
|
||||
};
|
||||
|
||||
const isDriver = (driver) => process.env.DB_DRIVER === driver;
|
||||
const isUsingDbHost = Boolean(process.env.DB_HOST);
|
||||
const onlyAllowUrl = isDriver(drivers.betterSqlite3);
|
||||
const urlRequired = onlyAllowUrl || !isUsingDbHost;
|
||||
const hostRequired = isUsingDbHost && !onlyAllowUrl;
|
||||
|
||||
export const env = createEnv({
|
||||
/**
|
||||
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
|
||||
* built with invalid env vars.
|
||||
*/
|
||||
server: {
|
||||
DB_DRIVER: z
|
||||
.union([z.literal(drivers.betterSqlite3), z.literal(drivers.mysql2)], {
|
||||
message: `Invalid database driver, supported are ${Object.keys(drivers).join(", ")}`,
|
||||
})
|
||||
.default(drivers.betterSqlite3),
|
||||
...(urlRequired
|
||||
? {
|
||||
DB_URL: z.string(),
|
||||
}
|
||||
: {}),
|
||||
...(hostRequired
|
||||
? {
|
||||
DB_HOST: z.string(),
|
||||
DB_PORT: z
|
||||
.string()
|
||||
.regex(/\d+/)
|
||||
.transform(Number)
|
||||
.refine((number) => number >= 1)
|
||||
.default("3306"),
|
||||
DB_USER: z.string(),
|
||||
DB_PASSWORD: z.string(),
|
||||
DB_NAME: z.string(),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
/**
|
||||
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
|
||||
*/
|
||||
runtimeEnv: {
|
||||
DB_DRIVER: process.env.DB_DRIVER,
|
||||
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,
|
||||
},
|
||||
skipValidation:
|
||||
Boolean(process.env.CI) || Boolean(process.env.SKIP_ENV_VALIDATION) || process.env.npm_lifecycle_event === "lint",
|
||||
});
|
||||
@@ -1,10 +1,6 @@
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
import { database } from "./driver";
|
||||
import * as sqliteSchema from "./schema/sqlite";
|
||||
|
||||
// Export only the types from the sqlite schema as we're using that.
|
||||
export const schema = sqliteSchema;
|
||||
|
||||
export * from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { drizzle } from "drizzle-orm/mysql2";
|
||||
import { migrate } from "drizzle-orm/mysql2/migrator";
|
||||
import mysql from "mysql2";
|
||||
|
||||
import type { Database } from "../..";
|
||||
import { env } from "../../env.mjs";
|
||||
import * as mysqlSchema from "../../schema/mysql";
|
||||
import { seedDataAsync } from "../seed";
|
||||
|
||||
@@ -11,15 +11,15 @@ const migrationsFolder = process.argv[2] ?? ".";
|
||||
|
||||
const migrateAsync = async () => {
|
||||
const mysql2 = mysql.createConnection(
|
||||
process.env.DB_HOST
|
||||
? {
|
||||
host: process.env.DB_HOST,
|
||||
database: process.env.DB_NAME!,
|
||||
port: Number(process.env.DB_PORT),
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
}
|
||||
: { uri: process.env.DB_URL },
|
||||
env.DB_URL
|
||||
? { uri: env.DB_URL }
|
||||
: {
|
||||
host: env.DB_HOST,
|
||||
database: env.DB_NAME,
|
||||
port: env.DB_PORT,
|
||||
user: env.DB_USER,
|
||||
password: env.DB_PASSWORD,
|
||||
},
|
||||
);
|
||||
|
||||
const db = drizzle(mysql2, {
|
||||
|
||||
@@ -6,8 +6,8 @@ import { defaultServerSettings, defaultServerSettingsKeys } from "@homarr/server
|
||||
|
||||
import { createId, eq } from "..";
|
||||
import type { Database } from "..";
|
||||
import { onboarding, serverSettings } from "../schema";
|
||||
import { groups } from "../schema/mysql";
|
||||
import { onboarding, serverSettings } from "../schema/sqlite";
|
||||
|
||||
export const seedDataAsync = async (db: Database) => {
|
||||
await seedEveryoneGroupAsync(db);
|
||||
|
||||
@@ -2,15 +2,16 @@ import Database from "better-sqlite3";
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||
|
||||
import { schema } from "../..";
|
||||
import { env } from "../../env.mjs";
|
||||
import * as sqliteSchema from "../../schema/sqlite";
|
||||
import { seedDataAsync } from "../seed";
|
||||
|
||||
const migrationsFolder = process.argv[2] ?? ".";
|
||||
|
||||
const migrateAsync = async () => {
|
||||
const sqlite = new Database(process.env.DB_URL?.replace("file:", ""));
|
||||
const sqlite = new Database(env.DB_URL.replace("file:", ""));
|
||||
|
||||
const db = drizzle(sqlite, { schema, casing: "snake_case" });
|
||||
const db = drizzle(sqlite, { schema: sqliteSchema, casing: "snake_case" });
|
||||
|
||||
migrate(db, { migrationsFolder });
|
||||
|
||||
|
||||
+13
-11
@@ -7,10 +7,11 @@
|
||||
"exports": {
|
||||
".": "./index.ts",
|
||||
"./client": "./client.ts",
|
||||
"./schema/sqlite": "./schema/sqlite.ts",
|
||||
"./schema": "./schema/index.ts",
|
||||
"./test": "./test/index.ts",
|
||||
"./queries": "./queries/index.ts",
|
||||
"./validationSchemas": "./validationSchemas.ts"
|
||||
"./validationSchemas": "./validationSchemas.ts",
|
||||
"./env.mjs": "./env.mjs"
|
||||
},
|
||||
"main": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
@@ -21,16 +22,16 @@
|
||||
"clean": "rm -rf .turbo node_modules",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint",
|
||||
"migration:mysql:drop": "drizzle-kit drop --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:generate": "drizzle-kit generate --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:run": "drizzle-kit migrate --config ./configs/mysql.config.ts && pnpm run seed",
|
||||
"migration:sqlite:drop": "drizzle-kit drop --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:generate": "drizzle-kit generate --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:run": "drizzle-kit migrate --config ./configs/sqlite.config.ts && pnpm run seed",
|
||||
"push:mysql": "drizzle-kit push --config ./configs/mysql.config.ts",
|
||||
"push:sqlite": "drizzle-kit push --config ./configs/sqlite.config.ts",
|
||||
"migration:mysql:drop": "pnpm with-env drizzle-kit drop --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:generate": "pnpm with-env drizzle-kit generate --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:run": "pnpm with-env drizzle-kit migrate --config ./configs/mysql.config.ts && pnpm run seed",
|
||||
"migration:sqlite:drop": "pnpm with-env drizzle-kit drop --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:generate": "pnpm with-env drizzle-kit generate --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:run": "pnpm with-env drizzle-kit migrate --config ./configs/sqlite.config.ts && pnpm run seed",
|
||||
"push:mysql": "pnpm with-env drizzle-kit push --config ./configs/mysql.config.ts",
|
||||
"push:sqlite": "pnpm with-env drizzle-kit push --config ./configs/sqlite.config.ts",
|
||||
"seed": "pnpm with-env tsx ./migrations/run-seed.ts",
|
||||
"studio": "drizzle-kit studio --config ./configs/sqlite.config.ts",
|
||||
"studio": "pnpm with-env drizzle-kit studio --config ./configs/sqlite.config.ts",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"with-env": "dotenv -e ../../.env --"
|
||||
},
|
||||
@@ -42,6 +43,7 @@
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"@homarr/server-settings": "workspace:^0.1.0",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@t3-oss/env-nextjs": "^0.11.1",
|
||||
"@testcontainers/mysql": "^10.16.0",
|
||||
"better-sqlite3": "^11.7.0",
|
||||
"dotenv": "^16.4.7",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { WidgetKind } from "@homarr/definitions";
|
||||
import type { Database } from "..";
|
||||
import { inArray } from "..";
|
||||
import type { inferSupportedIntegrations } from "../../widgets/src";
|
||||
import { items } from "../schema/sqlite";
|
||||
import { items } from "../schema";
|
||||
|
||||
export const getItemsWithIntegrationsAsync = async <TKind extends WidgetKind>(
|
||||
db: Database,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { defaultServerSettings, defaultServerSettingsKeys } from "@homarr/server
|
||||
|
||||
import type { Database } from "..";
|
||||
import { eq } from "..";
|
||||
import { serverSettings } from "../schema/sqlite";
|
||||
import { serverSettings } from "../schema";
|
||||
|
||||
export const getServerSettingsAsync = async (db: Database) => {
|
||||
const settings = await db.query.serverSettings.findMany();
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { InferSelectModel } from "drizzle-orm";
|
||||
|
||||
import * as mysqlSchema from "./mysql";
|
||||
import * as sqliteSchema from "./sqlite";
|
||||
|
||||
type Schema = typeof sqliteSchema;
|
||||
|
||||
const schema = process.env.DB_DRIVER === "mysql2" ? (mysqlSchema as unknown as Schema) : sqliteSchema;
|
||||
|
||||
// Sadly we can't use export * from here as we have multiple possible exports
|
||||
export const {
|
||||
accounts,
|
||||
apiKeys,
|
||||
apps,
|
||||
boardGroupPermissions,
|
||||
boardUserPermissions,
|
||||
boards,
|
||||
groupMembers,
|
||||
groupPermissions,
|
||||
groups,
|
||||
iconRepositories,
|
||||
icons,
|
||||
integrationGroupPermissions,
|
||||
integrationItems,
|
||||
integrationSecrets,
|
||||
integrationUserPermissions,
|
||||
integrations,
|
||||
invites,
|
||||
items,
|
||||
medias,
|
||||
onboarding,
|
||||
searchEngines,
|
||||
sections,
|
||||
serverSettings,
|
||||
sessions,
|
||||
users,
|
||||
verificationTokens,
|
||||
} = schema;
|
||||
|
||||
export type User = InferSelectModel<typeof schema.users>;
|
||||
export type Account = InferSelectModel<typeof schema.accounts>;
|
||||
export type Session = InferSelectModel<typeof schema.sessions>;
|
||||
export type VerificationToken = InferSelectModel<typeof schema.verificationTokens>;
|
||||
export type Integration = InferSelectModel<typeof schema.integrations>;
|
||||
export type IntegrationSecret = InferSelectModel<typeof schema.integrationSecrets>;
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { AdapterAccount } from "@auth/core/adapters";
|
||||
import type { DayOfWeek } from "@mantine/dates";
|
||||
import type { InferSelectModel } from "drizzle-orm";
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import type { AnySQLiteColumn } from "drizzle-orm/sqlite-core";
|
||||
import { blob, index, int, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
@@ -567,10 +566,3 @@ export const searchEngineRelations = relations(searchEngines, ({ one }) => ({
|
||||
references: [integrations.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export type User = InferSelectModel<typeof users>;
|
||||
export type Account = InferSelectModel<typeof accounts>;
|
||||
export type Session = InferSelectModel<typeof sessions>;
|
||||
export type VerificationToken = InferSelectModel<typeof verificationTokens>;
|
||||
export type Integration = InferSelectModel<typeof integrations>;
|
||||
export type IntegrationSecret = InferSelectModel<typeof integrationSecrets>;
|
||||
@@ -2,11 +2,11 @@ import Database from "better-sqlite3";
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||
|
||||
import { schema } from "..";
|
||||
import * as sqliteSchema from "../schema/sqlite";
|
||||
|
||||
export const createDb = (debug?: boolean) => {
|
||||
const sqlite = new Database(":memory:");
|
||||
const db = drizzle(sqlite, { schema, logger: debug, casing: "snake_case" });
|
||||
const db = drizzle(sqlite, { schema: sqliteSchema, logger: debug, casing: "snake_case" });
|
||||
migrate(db, {
|
||||
migrationsFolder: "./packages/db/migrations/sqlite",
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createSelectSchema } from "drizzle-zod";
|
||||
|
||||
import { apps, boards, groups, invites, searchEngines, serverSettings, users } from "./schema/sqlite";
|
||||
import { apps, boards, groups, invites, searchEngines, serverSettings, users } from "./schema";
|
||||
|
||||
export const selectAppSchema = createSelectSchema(apps);
|
||||
export const selectBoardSchema = createSelectSchema(boards);
|
||||
|
||||
@@ -8,6 +8,7 @@ export type HomarrDocumentationPath =
|
||||
| "/blog/2023/11/10/authentication"
|
||||
| "/blog/2023/12/22/updated-documentation"
|
||||
| "/blog/2024/09/23/version-1.0"
|
||||
| "/blog/2024/12/17/open-beta-1.0"
|
||||
| "/blog/archive"
|
||||
| "/blog/authors"
|
||||
| "/blog/authors/ajnart"
|
||||
@@ -33,6 +34,7 @@ export type HomarrDocumentationPath =
|
||||
| "/blog/tags/update"
|
||||
| "/blog/tags/version"
|
||||
| "/blog/translations"
|
||||
| "/search"
|
||||
| "/docs/tags"
|
||||
| "/docs/tags/active-directory"
|
||||
| "/docs/tags/ad-guard"
|
||||
@@ -44,7 +46,6 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/apps"
|
||||
| "/docs/tags/banner"
|
||||
| "/docs/tags/blocking"
|
||||
| "/docs/tags/board"
|
||||
| "/docs/tags/boards"
|
||||
| "/docs/tags/bookmark"
|
||||
| "/docs/tags/bookmarks"
|
||||
@@ -56,10 +57,12 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/connections"
|
||||
| "/docs/tags/customization"
|
||||
| "/docs/tags/data-sources"
|
||||
| "/docs/tags/database"
|
||||
| "/docs/tags/developer"
|
||||
| "/docs/tags/development"
|
||||
| "/docs/tags/dns"
|
||||
| "/docs/tags/docker"
|
||||
| "/docs/tags/donation"
|
||||
| "/docs/tags/edit-mode"
|
||||
| "/docs/tags/env"
|
||||
| "/docs/tags/environment-variables"
|
||||
@@ -71,6 +74,8 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/hardware"
|
||||
| "/docs/tags/health"
|
||||
| "/docs/tags/help"
|
||||
| "/docs/tags/icon-picker"
|
||||
| "/docs/tags/icon-repositories"
|
||||
| "/docs/tags/icons"
|
||||
| "/docs/tags/iframe"
|
||||
| "/docs/tags/images"
|
||||
@@ -84,17 +89,18 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/links"
|
||||
| "/docs/tags/lists"
|
||||
| "/docs/tags/management"
|
||||
| "/docs/tags/media"
|
||||
| "/docs/tags/monitoring"
|
||||
| "/docs/tags/news"
|
||||
| "/docs/tags/notebook"
|
||||
| "/docs/tags/notes"
|
||||
| "/docs/tags/oidc"
|
||||
| "/docs/tags/open-collective"
|
||||
| "/docs/tags/open-media-vault"
|
||||
| "/docs/tags/overseerr"
|
||||
| "/docs/tags/permissions"
|
||||
| "/docs/tags/pi-hole"
|
||||
| "/docs/tags/ping"
|
||||
| "/docs/tags/preferences"
|
||||
| "/docs/tags/programming"
|
||||
| "/docs/tags/proxmox"
|
||||
| "/docs/tags/proxy"
|
||||
@@ -112,39 +118,37 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/table"
|
||||
| "/docs/tags/technical-documentation"
|
||||
| "/docs/tags/text"
|
||||
| "/docs/tags/theming"
|
||||
| "/docs/tags/torrent"
|
||||
| "/docs/tags/traefik"
|
||||
| "/docs/tags/translations"
|
||||
| "/docs/tags/unraid"
|
||||
| "/docs/tags/user"
|
||||
| "/docs/tags/uploads"
|
||||
| "/docs/tags/usenet"
|
||||
| "/docs/tags/users"
|
||||
| "/docs/tags/variables"
|
||||
| "/docs/tags/widgets"
|
||||
| "/docs/advanced/command-line"
|
||||
| "/docs/advanced/command-line/password-recovery"
|
||||
| "/docs/advanced/configuration/environment-variables"
|
||||
| "/docs/advanced/configuration/keyboard-shortcuts"
|
||||
| "/docs/advanced/configuration/proxies-and-certificates"
|
||||
| "/docs/advanced/customizations/board-customization"
|
||||
| "/docs/advanced/customizations/dark-mode"
|
||||
| "/docs/advanced/customizations/icons"
|
||||
| "/docs/advanced/customizations/user-preferences"
|
||||
| "/docs/advanced/sso"
|
||||
| "/docs/advanced/development/getting-started"
|
||||
| "/docs/advanced/environment-variables"
|
||||
| "/docs/advanced/icons"
|
||||
| "/docs/advanced/keyboard-shortcuts"
|
||||
| "/docs/advanced/proxy"
|
||||
| "/docs/advanced/single-sign-on"
|
||||
| "/docs/category/advanced"
|
||||
| "/docs/category/developer-guide"
|
||||
| "/docs/category/community"
|
||||
| "/docs/category/developer-guides"
|
||||
| "/docs/category/getting-started"
|
||||
| "/docs/category/installation"
|
||||
| "/docs/category/installation-1"
|
||||
| "/docs/category/integrations"
|
||||
| "/docs/category/management"
|
||||
| "/docs/category/more"
|
||||
| "/docs/category/widgets"
|
||||
| "/docs/community/donate"
|
||||
| "/docs/community/faq"
|
||||
| "/docs/community/get-in-touch"
|
||||
| "/docs/community/license"
|
||||
| "/docs/community/translations"
|
||||
| "/docs/development/getting-started"
|
||||
| "/docs/getting-started"
|
||||
| "/docs/getting-started/after-the-installation"
|
||||
| "/docs/getting-started/glossary"
|
||||
@@ -152,7 +156,6 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/getting-started/installation/easy-panel"
|
||||
| "/docs/getting-started/installation/helm"
|
||||
| "/docs/getting-started/installation/home-assistant"
|
||||
| "/docs/getting-started/installation/kubernetes"
|
||||
| "/docs/getting-started/installation/portainer"
|
||||
| "/docs/getting-started/installation/qnap"
|
||||
| "/docs/getting-started/installation/saltbox"
|
||||
@@ -172,15 +175,15 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/management/apps"
|
||||
| "/docs/management/boards"
|
||||
| "/docs/management/integrations"
|
||||
| "/docs/management/media"
|
||||
| "/docs/management/search-engines"
|
||||
| "/docs/management/settings"
|
||||
| "/docs/management/users"
|
||||
| "/docs/widgets/bookmarks"
|
||||
| "/docs/widgets/calendar-widget"
|
||||
| "/docs/widgets/clock-widget"
|
||||
| "/docs/widgets/dashdot-widget"
|
||||
| "/docs/widgets/calendar"
|
||||
| "/docs/widgets/clock"
|
||||
| "/docs/widgets/dns-hole"
|
||||
| "/docs/widgets/download-speed-widget"
|
||||
| "/docs/widgets/downloads"
|
||||
| "/docs/widgets/health-monitoring"
|
||||
| "/docs/widgets/home-assistant"
|
||||
| "/docs/widgets/iframe"
|
||||
@@ -188,10 +191,8 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/media-requests"
|
||||
| "/docs/widgets/media-server"
|
||||
| "/docs/widgets/notebook"
|
||||
| "/docs/widgets/rss-widget"
|
||||
| "/docs/widgets/torrent-widget"
|
||||
| "/docs/widgets/usenet-widget"
|
||||
| "/docs/widgets/rss"
|
||||
| "/docs/widgets/video"
|
||||
| "/docs/widgets/weather-widget"
|
||||
| "/docs/widgets/weather"
|
||||
| ""
|
||||
| "/sitemap.xml";
|
||||
@@ -1,2 +1,2 @@
|
||||
export const everyoneGroup = "everyone";
|
||||
export const credentialsAdminGroup = "admin";
|
||||
export const credentialsAdminGroup = "credentials-admin";
|
||||
@@ -14,7 +14,6 @@ interface integrationDefinition {
|
||||
iconUrl: string;
|
||||
secretKinds: AtLeastOneOf<IntegrationSecretKind[]>; // at least one secret kind set is required
|
||||
category: AtLeastOneOf<IntegrationCategory>;
|
||||
supportsSearch: boolean;
|
||||
}
|
||||
|
||||
export const integrationDefs = {
|
||||
@@ -23,140 +22,120 @@ export const integrationDefs = {
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/sabnzbd.png",
|
||||
category: ["downloadClient", "usenet"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
nzbGet: {
|
||||
name: "NZBGet",
|
||||
secretKinds: [["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/nzbget.png",
|
||||
category: ["downloadClient", "usenet"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
deluge: {
|
||||
name: "Deluge",
|
||||
secretKinds: [["password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/deluge.png",
|
||||
category: ["downloadClient", "torrent"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
transmission: {
|
||||
name: "Transmission",
|
||||
secretKinds: [["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/transmission.png",
|
||||
category: ["downloadClient", "torrent"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
qBittorrent: {
|
||||
name: "qBittorrent",
|
||||
secretKinds: [["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/qbittorrent.png",
|
||||
category: ["downloadClient", "torrent"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
sonarr: {
|
||||
name: "Sonarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/sonarr.png",
|
||||
category: ["calendar"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
radarr: {
|
||||
name: "Radarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/radarr.png",
|
||||
category: ["calendar"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
lidarr: {
|
||||
name: "Lidarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/lidarr.png",
|
||||
category: ["calendar"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
readarr: {
|
||||
name: "Readarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/readarr.png",
|
||||
category: ["calendar"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
prowlarr: {
|
||||
name: "Prowlarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/prowlarr.png",
|
||||
category: ["indexerManager"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
jellyfin: {
|
||||
name: "Jellyfin",
|
||||
secretKinds: [["username", "password"], ["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyfin.png",
|
||||
category: ["mediaService"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
plex: {
|
||||
name: "Plex",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/plex.png",
|
||||
category: ["mediaService"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
jellyseerr: {
|
||||
name: "Jellyseerr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyseerr.png",
|
||||
category: ["mediaSearch", "mediaRequest"],
|
||||
supportsSearch: true,
|
||||
category: ["mediaSearch", "mediaRequest", "search"],
|
||||
},
|
||||
overseerr: {
|
||||
name: "Overseerr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/overseerr.png",
|
||||
category: ["mediaSearch", "mediaRequest"],
|
||||
supportsSearch: true,
|
||||
category: ["mediaSearch", "mediaRequest", "search"],
|
||||
},
|
||||
piHole: {
|
||||
name: "Pi-hole",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/pi-hole.png",
|
||||
category: ["dnsHole"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
adGuardHome: {
|
||||
name: "AdGuard Home",
|
||||
secretKinds: [["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/adguard-home.png",
|
||||
category: ["dnsHole"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
homeAssistant: {
|
||||
name: "Home Assistant",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/home-assistant.png",
|
||||
category: ["smartHomeServer"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
openmediavault: {
|
||||
name: "OpenMediaVault",
|
||||
secretKinds: [["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/openmediavault.png",
|
||||
category: ["healthMonitoring"],
|
||||
supportsSearch: false,
|
||||
},
|
||||
dashDot: {
|
||||
name: "Dash.",
|
||||
secretKinds: [[]],
|
||||
category: ["healthMonitoring"],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/dashdot.png",
|
||||
supportsSearch: false,
|
||||
},
|
||||
tdarr: {
|
||||
name: "Tdarr",
|
||||
secretKinds: [[]],
|
||||
category: ["mediaTranscoding"],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/tdarr.png",
|
||||
supportsSearch: false,
|
||||
},
|
||||
} as const satisfies Record<string, integrationDefinition>;
|
||||
|
||||
@@ -195,22 +174,6 @@ export type IntegrationKindByCategory<TCategory extends IntegrationCategory> = {
|
||||
U
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Checks if search is supported by the integration
|
||||
* Uses a typescript guard with is to allow only integrations with search support within if statement
|
||||
* @param integration integration with kind
|
||||
* @returns true if the integration supports search
|
||||
*/
|
||||
export const isIntegrationWithSearchSupport = (integration: {
|
||||
kind: IntegrationKind;
|
||||
}): integration is { kind: IntegrationWithSearchSupport } => {
|
||||
return integrationDefs[integration.kind].supportsSearch;
|
||||
};
|
||||
|
||||
type IntegrationWithSearchSupport = {
|
||||
[Key in keyof typeof integrationDefs]: true extends (typeof integrationDefs)[Key]["supportsSearch"] ? Key : never;
|
||||
}[keyof typeof integrationDefs];
|
||||
|
||||
export type IntegrationSecretKind = keyof typeof integrationSecretKindObject;
|
||||
export type IntegrationKind = keyof typeof integrationDefs;
|
||||
export type IntegrationCategory =
|
||||
@@ -225,4 +188,5 @@ export type IntegrationCategory =
|
||||
| "smartHomeServer"
|
||||
| "indexerManager"
|
||||
| "healthMonitoring"
|
||||
| "search"
|
||||
| "mediaTranscoding";
|
||||
@@ -1,6 +1,6 @@
|
||||
import { decryptSecret } from "@homarr/common/server";
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import type { Integration as DbIntegration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration as DbIntegration } from "@homarr/db/schema";
|
||||
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
|
||||
|
||||
import { AdGuardHomeIntegration } from "../adguard-home/adguard-home-integration";
|
||||
|
||||
@@ -29,6 +29,10 @@ export abstract class Integration {
|
||||
return secret.value;
|
||||
}
|
||||
|
||||
protected hasSecretValue(kind: IntegrationSecretKind) {
|
||||
return this.integration.decryptedSecrets.some((secret) => secret.kind === kind);
|
||||
}
|
||||
|
||||
protected url(path: `/${string}`, queryParams?: Record<string, string | Date | number | boolean>) {
|
||||
const baseUrl = removeTrailingSlash(this.integration.url);
|
||||
const url = new URL(`${baseUrl}${path}`);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
const usenetQueueState = ["downloading", "queued", "paused"] as const;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
|
||||
export interface DownloadClientStatus {
|
||||
/** If client is considered paused */
|
||||
|
||||
@@ -18,13 +18,13 @@ export class JellyfinIntegration extends Integration {
|
||||
});
|
||||
|
||||
public async testConnectionAsync(): Promise<void> {
|
||||
const api = this.getApi();
|
||||
const api = await this.getApiAsync();
|
||||
const systemApi = getSystemApi(api);
|
||||
await systemApi.getPingSystem();
|
||||
}
|
||||
|
||||
public async getCurrentSessionsAsync(): Promise<StreamSession[]> {
|
||||
const api = this.getApi();
|
||||
const api = await this.getApiAsync();
|
||||
const sessionApi = getSessionApi(api);
|
||||
const sessions = await sessionApi.getSessions();
|
||||
|
||||
@@ -59,8 +59,22 @@ export class JellyfinIntegration extends Integration {
|
||||
});
|
||||
}
|
||||
|
||||
private getApi() {
|
||||
const apiKey = this.getSecretValue("apiKey");
|
||||
return this.jellyfin.createApi(this.url("/").toString(), apiKey);
|
||||
/**
|
||||
* Constructs an ApiClient synchronously with an ApiKey or asynchronously
|
||||
* with a username and password.
|
||||
* @returns An instance of Api that has been authenticated
|
||||
*/
|
||||
private async getApiAsync() {
|
||||
if (this.hasSecretValue("apiKey")) {
|
||||
const apiKey = this.getSecretValue("apiKey");
|
||||
return this.jellyfin.createApi(this.url("/").toString(), apiKey);
|
||||
}
|
||||
|
||||
const apiClient = this.jellyfin.createApi(this.url("/").toString());
|
||||
// Authentication state is stored internally in the Api class, so now
|
||||
// requests that require authentication can be made normally.
|
||||
// see https://typescript-sdk.jellyfin.org/#usage
|
||||
await apiClient.authenticateUserByName(this.getSecretValue("username"), this.getSecretValue("password"));
|
||||
return apiClient;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"ioredis": "5.4.1",
|
||||
"ioredis": "5.4.2",
|
||||
"superjson": "2.2.2",
|
||||
"winston": "3.17.0"
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@mantine/core": "^7.15.1",
|
||||
"@tabler/icons-react": "^3.26.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
"@mantine/core": "^7.15.1",
|
||||
"@mantine/hooks": "^7.15.1",
|
||||
"adm-zip": "0.5.16",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"superjson": "2.2.2",
|
||||
"zod": "^3.24.1",
|
||||
"zod-form-data": "^2.0.2"
|
||||
"zod-form-data": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createId, inArray } from "@homarr/db";
|
||||
import type { Database, InferInsertModel, InferSelectModel } from "@homarr/db";
|
||||
import { apps as appsTable } from "@homarr/db/schema/sqlite";
|
||||
import { apps as appsTable } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrApp } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Database } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import { boards } from "@homarr/db/schema/sqlite";
|
||||
import { boards } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import SuperJSON from "superjson";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import { items } from "@homarr/db/schema/sqlite";
|
||||
import { items } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrApp, OldmarrWidget } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createId } from "@homarr/db";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { sections } from "@homarr/db/schema/sqlite";
|
||||
import { sections } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { Database, InferInsertModel } from "@homarr/db";
|
||||
import { schema } from "@homarr/db";
|
||||
import * as schema from "@homarr/db/schema";
|
||||
|
||||
type TableKey = {
|
||||
[K in keyof typeof schema]: (typeof schema)[K] extends { _: { brand: "Table" } } ? K : never;
|
||||
|
||||
Loaded 100 of 154 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user