diff --git a/.nvmrc b/.nvmrc
index 2a393af59..7af24b7dd 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-20.18.0
+22.11.0
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 0263499bb..28d5f189e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -27,7 +27,7 @@
"Umami"
],
"i18n-ally.dirStructure": "auto",
- "i18n-ally.enabledFrameworks": ["next-international"],
+ "i18n-ally.enabledFrameworks": ["next-intl"],
"i18n-ally.localesPaths": ["./packages/translation/src/lang/"],
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.extract.keyMaxLength": 0,
diff --git a/Dockerfile b/Dockerfile
index 7a2eca66e..468e189e1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:20.18.0-alpine AS base
+FROM node:22.11.0-alpine AS base
FROM base AS builder
RUN apk add --no-cache libc6-compat
diff --git a/apps/nextjs/next.config.mjs b/apps/nextjs/next.config.mjs
index 7d53a70db..2467471d8 100644
--- a/apps/nextjs/next.config.mjs
+++ b/apps/nextjs/next.config.mjs
@@ -2,11 +2,15 @@
import "@homarr/auth/env.mjs";
import MillionLint from "@million/lint";
+import createNextIntlPlugin from "next-intl/plugin";
import "./src/env.mjs";
+// Package path does not work... so we need to use relative path
+const withNextIntl = createNextIntlPlugin("../../packages/translation/src/request.ts");
+
/** @type {import("next").NextConfig} */
-const config = {
+const nextConfig = {
output: "standalone",
reactStrictMode: true,
/** We already do linting and typechecking as separate tasks in CI */
@@ -34,4 +38,4 @@ const config = {
// Skip transform is used because of webpack loader, without it for example 'Tooltip.Floating' will not work and show an error
const withMillionLint = MillionLint.next({ rsc: true, skipTransform: true, telemetry: false });
-export default config;
+export default withNextIntl(nextConfig);
diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json
index 22ae92ba7..69e896d1f 100644
--- a/apps/nextjs/package.json
+++ b/apps/nextjs/package.json
@@ -44,7 +44,7 @@
"@mantine/tiptap": "^7.13.4",
"@million/lint": "1.0.11",
"@t3-oss/env-nextjs": "^0.11.1",
- "@tabler/icons-react": "^3.20.0",
+ "@tabler/icons-react": "^3.21.0",
"@tanstack/react-query": "^5.59.16",
"@tanstack/react-query-devtools": "^5.59.16",
"@tanstack/react-query-next-experimental": "5.59.16",
@@ -70,7 +70,7 @@
"react-dom": "^18.3.1",
"react-error-boundary": "^4.1.2",
"react-simple-code-editor": "^0.14.1",
- "sass": "^1.80.4",
+ "sass": "^1.80.5",
"superjson": "2.2.1",
"swagger-ui-react": "^5.17.14",
"use-deep-compare-effect": "^1.8.1"
@@ -80,7 +80,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/chroma-js": "2.4.4",
- "@types/node": "^20.17.1",
+ "@types/node": "^22.8.6",
"@types/prismjs": "^1.26.5",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
diff --git a/apps/nextjs/src/app/[locale]/_client-providers/next-international.tsx b/apps/nextjs/src/app/[locale]/_client-providers/next-international.tsx
deleted file mode 100644
index 8297a73bb..000000000
--- a/apps/nextjs/src/app/[locale]/_client-providers/next-international.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { PropsWithChildren } from "react";
-
-import { defaultLocale } from "@homarr/translation";
-import { I18nProviderClient } from "@homarr/translation/client";
-
-export const NextInternationalProvider = ({ children, locale }: PropsWithChildren<{ locale: string }>) => {
- return (
-
- {children}
-
- );
-};
diff --git a/apps/nextjs/src/app/[locale]/layout.tsx b/apps/nextjs/src/app/[locale]/layout.tsx
index 22888ea0b..765eae8d7 100644
--- a/apps/nextjs/src/app/[locale]/layout.tsx
+++ b/apps/nextjs/src/app/[locale]/layout.tsx
@@ -7,18 +7,20 @@ import "@homarr/ui/styles.css";
import "~/styles/scroll-area.scss";
import { cookies } from "next/headers";
+import { notFound } from "next/navigation";
+import { NextIntlClientProvider } from "next-intl";
import { env } from "@homarr/auth/env.mjs";
import { auth } from "@homarr/auth/next";
import { ModalProvider } from "@homarr/modals";
import { Notifications } from "@homarr/notifications";
-import { getScopedI18n } from "@homarr/translation/server";
+import { isLocaleSupported } from "@homarr/translation";
+import { getI18nMessages, getScopedI18n } from "@homarr/translation/server";
import { Analytics } from "~/components/layout/analytics";
import { SearchEngineOptimization } from "~/components/layout/search-engine-optimization";
import { JotaiProvider } from "./_client-providers/jotai";
import { CustomMantineProvider } from "./_client-providers/mantine";
-import { NextInternationalProvider } from "./_client-providers/next-international";
import { AuthProvider } from "./_client-providers/session";
import { TRPCReactProvider } from "./_client-providers/trpc";
import { composeWrappers } from "./compose";
@@ -59,10 +61,15 @@ export const viewport: Viewport = {
};
export default async function Layout(props: { children: React.ReactNode; params: { locale: string } }) {
+ if (!isLocaleSupported(props.params.locale)) {
+ notFound();
+ }
+
const session = await auth();
const colorScheme = getColorScheme();
const tCommon = await getScopedI18n("common");
const direction = tCommon("direction");
+ const i18nMessages = await getI18nMessages();
const StackedProvider = composeWrappers([
(innerProps) => {
@@ -70,7 +77,7 @@ export default async function Layout(props: { children: React.ReactNode; params:
},
(innerProps) => ,
(innerProps) => ,
- (innerProps) => ,
+ (innerProps) => ,
(innerProps) => ,
(innerProps) => ,
]);
@@ -78,7 +85,7 @@ export default async function Layout(props: { children: React.ReactNode; params:
return (
// Instead of ColorSchemScript we use data-mantine-color-scheme to prevent flickering
{
+ const t = useI18n();
+
+ const url =
+ typeof window !== "undefined"
+ ? `${window.location.protocol}://${window.location.hostname}:${window.location.port}/api/user-medias/${media.id}`
+ : "";
+
+ return (
+
+ {({ copy, copied }) => (
+
+
+ {copied ? : }
+
+
+ )}
+
+ );
+};
diff --git a/apps/nextjs/src/app/[locale]/manage/medias/_actions/delete-media.tsx b/apps/nextjs/src/app/[locale]/manage/medias/_actions/delete-media.tsx
new file mode 100644
index 000000000..b38d1422d
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/medias/_actions/delete-media.tsx
@@ -0,0 +1,40 @@
+"use client";
+
+import { ActionIcon, Tooltip } from "@mantine/core";
+import { IconTrash } from "@tabler/icons-react";
+
+import type { RouterOutputs } from "@homarr/api";
+import { clientApi } from "@homarr/api/client";
+import { revalidatePathActionAsync } from "@homarr/common/client";
+import { useConfirmModal } from "@homarr/modals";
+import { useI18n } from "@homarr/translation/client";
+
+interface DeleteMediaProps {
+ media: RouterOutputs["media"]["getPaginated"]["items"][number];
+}
+
+export const DeleteMedia = ({ media }: DeleteMediaProps) => {
+ const { openConfirmModal } = useConfirmModal();
+ const t = useI18n();
+ const { mutateAsync, isPending } = clientApi.media.deleteMedia.useMutation();
+
+ const onClick = () => {
+ openConfirmModal({
+ title: t("media.action.delete.label"),
+ children: t.rich("media.action.delete.description", { bName: () => {media.name} }),
+ // eslint-disable-next-line no-restricted-syntax
+ onConfirm: async () => {
+ await mutateAsync({ id: media.id });
+ await revalidatePathActionAsync("/manage/medias");
+ },
+ });
+ };
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/apps/nextjs/src/app/[locale]/manage/medias/_actions/show-all.tsx b/apps/nextjs/src/app/[locale]/manage/medias/_actions/show-all.tsx
new file mode 100644
index 000000000..fb5c13a32
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/medias/_actions/show-all.tsx
@@ -0,0 +1,36 @@
+"use client";
+
+import { useState } from "react";
+import type { ChangeEvent } from "react";
+import { usePathname, useRouter, useSearchParams } from "next/navigation";
+import { Switch } from "@mantine/core";
+import type { SwitchProps } from "@mantine/core";
+
+import { useI18n } from "@homarr/translation/client";
+
+type ShowAllSwitchProps = Pick;
+
+export const IncludeFromAllUsersSwitch = ({ defaultChecked }: ShowAllSwitchProps) => {
+ const router = useRouter();
+ const pathName = usePathname();
+ const searchParams = useSearchParams();
+ const [checked, setChecked] = useState(defaultChecked);
+ const t = useI18n();
+
+ const onChange = (event: ChangeEvent) => {
+ setChecked(event.target.checked);
+ const params = new URLSearchParams(searchParams);
+ params.set("includeFromAllUsers", event.target.checked.toString());
+ if (params.has("page")) params.set("page", "1"); // Reset page to 1
+ router.replace(`${pathName}?${params.toString()}`);
+ };
+
+ return (
+
+ );
+};
diff --git a/apps/nextjs/src/app/[locale]/manage/medias/_actions/upload-media.tsx b/apps/nextjs/src/app/[locale]/manage/medias/_actions/upload-media.tsx
new file mode 100644
index 000000000..72b880fc9
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/medias/_actions/upload-media.tsx
@@ -0,0 +1,46 @@
+"use client";
+
+import { Button, FileButton } from "@mantine/core";
+import { IconUpload } from "@tabler/icons-react";
+
+import { clientApi } from "@homarr/api/client";
+import { revalidatePathActionAsync } from "@homarr/common/client";
+import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
+import { useI18n } from "@homarr/translation/client";
+import { supportedMediaUploadFormats } from "@homarr/validation";
+
+export const UploadMedia = () => {
+ const t = useI18n();
+ const { mutateAsync, isPending } = clientApi.media.uploadMedia.useMutation();
+
+ const handleFileUploadAsync = async (file: File | null) => {
+ if (!file) return;
+ const formData = new FormData();
+ formData.append("file", file);
+ await mutateAsync(formData, {
+ onSuccess() {
+ showSuccessNotification({
+ message: t("media.action.upload.notification.success.message"),
+ });
+ },
+ onError() {
+ showErrorNotification({
+ message: t("media.action.upload.notification.error.message"),
+ });
+ },
+ async onSettled() {
+ await revalidatePathActionAsync("/manage/medias");
+ },
+ });
+ };
+
+ return (
+
+ {({ onClick }) => (
+ }>
+ {t("media.action.upload.label")}
+
+ )}
+
+ );
+};
diff --git a/apps/nextjs/src/app/[locale]/manage/medias/page.tsx b/apps/nextjs/src/app/[locale]/manage/medias/page.tsx
new file mode 100644
index 000000000..c46701935
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/medias/page.tsx
@@ -0,0 +1,128 @@
+import Image from "next/image";
+import Link from "next/link";
+import { notFound } from "next/navigation";
+import { Anchor, Group, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from "@mantine/core";
+
+import type { RouterOutputs } from "@homarr/api";
+import { api } from "@homarr/api/server";
+import { auth } from "@homarr/auth/next";
+import { humanFileSize } from "@homarr/common";
+import { getI18n } from "@homarr/translation/server";
+import { SearchInput, TablePagination, UserAvatar } from "@homarr/ui";
+import { z } from "@homarr/validation";
+
+import { ManageContainer } from "~/components/manage/manage-container";
+import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
+import { CopyMedia } from "./_actions/copy-media";
+import { DeleteMedia } from "./_actions/delete-media";
+import { IncludeFromAllUsersSwitch } from "./_actions/show-all";
+import { UploadMedia } from "./_actions/upload-media";
+
+const searchParamsSchema = z.object({
+ search: z.string().optional(),
+ includeFromAllUsers: z
+ .string()
+ .regex(/true|false/)
+ .catch("false")
+ .transform((value) => value === "true"),
+ pageSize: z.string().regex(/\d+/).transform(Number).catch(10),
+ page: z.string().regex(/\d+/).transform(Number).catch(1),
+});
+
+type SearchParamsSchemaInputFromSchema> = Partial<{
+ [K in keyof TSchema]: Exclude extends unknown[] ? string[] : string;
+}>;
+
+interface MediaListPageProps {
+ searchParams: SearchParamsSchemaInputFromSchema>;
+}
+
+export default async function GroupsListPage(props: MediaListPageProps) {
+ const session = await auth();
+
+ if (!session) {
+ return notFound();
+ }
+
+ const t = await getI18n();
+ const searchParams = searchParamsSchema.parse(props.searchParams);
+ const { items: medias, totalCount } = await api.media.getPaginated(searchParams);
+ const isAdmin = session.user.permissions.includes("admin");
+
+ return (
+
+
+
+ {t("media.plural")}
+
+
+
+ {isAdmin && }
+
+
+
+
+
+
+
+
+ {t("media.field.name")}
+ {t("media.field.size")}
+ {t("media.field.creator")}
+
+
+
+
+ {medias.map((media) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
+
+interface RowProps {
+ media: RouterOutputs["media"]["getPaginated"]["items"][number];
+}
+
+const Row = ({ media }: RowProps) => {
+ return (
+
+
+
+
+ {media.name}
+ {humanFileSize(media.size)}
+
+ {media.creator ? (
+
+
+
+ {media.creator.name}
+
+
+ ) : (
+ "-"
+ )}
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx b/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx
index 978f13144..fc1425f21 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx
@@ -60,7 +60,10 @@ export const UserCreateStepperComponent = () => {
})
.refine((data) => data.password === data.confirmPassword, {
path: ["confirmPassword"],
- params: createCustomErrorParams("passwordsDoNotMatch"),
+ params: createCustomErrorParams({
+ key: "passwordsDoNotMatch",
+ params: {},
+ }),
}),
{
initialValues: {
diff --git a/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_rename-group-form.tsx b/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_rename-group-form.tsx
index 5f71808d4..407ee2429 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_rename-group-form.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_rename-group-form.tsx
@@ -58,7 +58,7 @@ export const RenameGroupForm = ({ group, disabled }: RenameGroupFormProps) => {
},
);
},
- [group.id, mutate, t],
+ [group.id, mutate, t, disabled],
);
return (
diff --git a/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_reserved-group-alert.tsx b/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_reserved-group-alert.tsx
index bd6920792..a777ce73d 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_reserved-group-alert.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/_reserved-group-alert.tsx
@@ -10,8 +10,8 @@ export const ReservedGroupAlert = async () => {
return (
}>
- {t("group.reservedNotice.message", {
- checkoutDocs: (
+ {t.rich("group.reservedNotice.message", {
+ checkoutDocs: () => (
;
export const PermissionSwitch = ({ name }: { name: GroupPermissionKey }) => {
const form = useFormContext();
diff --git a/apps/nextjs/src/app/api/user-medias/[id]/route.ts b/apps/nextjs/src/app/api/user-medias/[id]/route.ts
new file mode 100644
index 000000000..5f3fb36e3
--- /dev/null
+++ b/apps/nextjs/src/app/api/user-medias/[id]/route.ts
@@ -0,0 +1,29 @@
+import { notFound } from "next/navigation";
+import { NextResponse } from "next/server";
+import type { NextRequest } from "next/server";
+
+import { db, eq } from "@homarr/db";
+import { medias } from "@homarr/db/schema/sqlite";
+
+export async function GET(_req: NextRequest, { params }: { params: { id: string } }) {
+ const image = await db.query.medias.findFirst({
+ where: eq(medias.id, params.id),
+ columns: {
+ content: true,
+ contentType: true,
+ },
+ });
+
+ if (!image) {
+ notFound();
+ }
+
+ const headers = new Headers();
+ headers.set("Content-Type", image.contentType);
+ headers.set("Content-Length", image.content.length.toString());
+
+ return new NextResponse(image.content, {
+ status: 200,
+ headers,
+ });
+}
diff --git a/apps/nextjs/src/components/language/language-combobox.tsx b/apps/nextjs/src/components/language/language-combobox.tsx
index 6bd362591..b60e3a4fe 100644
--- a/apps/nextjs/src/components/language/language-combobox.tsx
+++ b/apps/nextjs/src/components/language/language-combobox.tsx
@@ -1,11 +1,11 @@
"use client";
import React from "react";
-import { Combobox, Group, InputBase, Text, useCombobox } from "@mantine/core";
+import { Combobox, Group, InputBase, Loader, Text, useCombobox } from "@mantine/core";
import { IconCheck } from "@tabler/icons-react";
import type { SupportedLanguage } from "@homarr/translation";
-import { localeAttributes, supportedLanguages } from "@homarr/translation";
+import { localeConfigurations, supportedLanguages } from "@homarr/translation";
import { useChangeLocale, useCurrentLocale } from "@homarr/translation/client";
import classes from "./language-combobox.module.css";
@@ -15,7 +15,7 @@ export const LanguageCombobox = () => {
onDropdownClose: () => combobox.resetSelectedOption(),
});
const currentLocale = useCurrentLocale();
- const changeLocale = useChangeLocale();
+ const { changeLocale, isPending } = useChangeLocale();
const handleOnOptionSubmit = React.useCallback(
(value: string) => {
@@ -39,6 +39,7 @@ export const LanguageCombobox = () => {
component="button"
type="button"
pointer
+ leftSection={isPending ? : null}
rightSection={}
rightSectionPointerEvents="none"
onClick={handleOnClick}
@@ -72,11 +73,11 @@ const OptionItem = ({
return (
-
+
- {localeAttributes[localeKey].name}
+ {localeConfigurations[localeKey].name}
- ({localeAttributes[localeKey].translatedName})
+ ({localeConfigurations[localeKey].translatedName})
diff --git a/apps/nextjs/src/versions/package-reader.ts b/apps/nextjs/src/versions/package-reader.ts
index c61da286b..25976619e 100644
--- a/apps/nextjs/src/versions/package-reader.ts
+++ b/apps/nextjs/src/versions/package-reader.ts
@@ -29,7 +29,7 @@ export const getPackageAttributesAsync = async () => {
};
};
-type PackageJsonDependencies = { [key in string]: string };
+type PackageJsonDependencies = Record;
interface PackageJson {
dependencies: PackageJsonDependencies | undefined;
}
diff --git a/apps/tasks/package.json b/apps/tasks/package.json
index 669d2c988..19c30327f 100644
--- a/apps/tasks/package.json
+++ b/apps/tasks/package.json
@@ -44,11 +44,11 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "@types/node": "^20.17.1",
+ "@types/node": "^22.8.6",
"dotenv-cli": "^7.4.2",
"eslint": "^9.13.0",
"prettier": "^3.3.3",
- "tsx": "4.19.1",
+ "tsx": "4.19.2",
"typescript": "^5.6.3"
}
}
diff --git a/apps/websocket/package.json b/apps/websocket/package.json
index bf522cfdf..826e1267e 100644
--- a/apps/websocket/package.json
+++ b/apps/websocket/package.json
@@ -26,7 +26,7 @@
"@homarr/redis": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"dotenv": "^16.4.5",
- "tsx": "4.19.1",
+ "tsx": "4.19.2",
"ws": "^8.18.0"
},
"devDependencies": {
diff --git a/package.json b/package.json
index 9410bd747..da7a4723e 100644
--- a/package.json
+++ b/package.json
@@ -29,8 +29,8 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@turbo/gen": "^2.2.3",
"@vitejs/plugin-react": "^4.3.3",
- "@vitest/coverage-v8": "^2.1.3",
- "@vitest/ui": "^2.1.3",
+ "@vitest/coverage-v8": "^2.1.4",
+ "@vitest/ui": "^2.1.4",
"cross-env": "^7.0.3",
"jsdom": "^25.0.1",
"prettier": "^3.3.3",
@@ -38,11 +38,11 @@
"turbo": "^2.2.3",
"typescript": "^5.6.3",
"vite-tsconfig-paths": "^5.0.1",
- "vitest": "^2.1.3"
+ "vitest": "^2.1.4"
},
- "packageManager": "pnpm@9.12.2",
+ "packageManager": "pnpm@9.12.3",
"engines": {
- "node": ">=20.18.0"
+ "node": ">=22.11.0"
},
"pnpm": {
"patchedDependencies": {
diff --git a/packages/api/src/root.ts b/packages/api/src/root.ts
index cd528106f..1f414de47 100644
--- a/packages/api/src/root.ts
+++ b/packages/api/src/root.ts
@@ -10,6 +10,7 @@ import { integrationRouter } from "./router/integration/integration-router";
import { inviteRouter } from "./router/invite";
import { locationRouter } from "./router/location";
import { logRouter } from "./router/log";
+import { mediaRouter } from "./router/medias/media-router";
import { searchEngineRouter } from "./router/search-engine/search-engine-router";
import { serverSettingsRouter } from "./router/serverSettings";
import { userRouter } from "./router/user";
@@ -33,6 +34,7 @@ export const appRouter = createTRPCRouter({
serverSettings: serverSettingsRouter,
cronJobs: cronJobsRouter,
apiKeys: apiKeysRouter,
+ media: mediaRouter,
});
// export type definition of API
diff --git a/packages/api/src/router/medias/media-router.ts b/packages/api/src/router/medias/media-router.ts
new file mode 100644
index 000000000..ebf8d256c
--- /dev/null
+++ b/packages/api/src/router/medias/media-router.ts
@@ -0,0 +1,88 @@
+import { TRPCError } from "@trpc/server";
+
+import { and, createId, desc, eq, like } from "@homarr/db";
+import { medias } from "@homarr/db/schema/sqlite";
+import { validation, z } from "@homarr/validation";
+
+import { createTRPCRouter, protectedProcedure } from "../../trpc";
+
+export const mediaRouter = createTRPCRouter({
+ getPaginated: protectedProcedure
+ .input(
+ validation.common.paginated.and(
+ z.object({ includeFromAllUsers: z.boolean().default(false), search: z.string().trim().default("") }),
+ ),
+ )
+ .query(async ({ ctx, input }) => {
+ const includeFromAllUsers = ctx.session.user.permissions.includes("admin") && input.includeFromAllUsers;
+
+ const where = and(
+ input.search.length >= 1 ? like(medias.name, `%${input.search}%`) : undefined,
+ includeFromAllUsers ? undefined : eq(medias.creatorId, ctx.session.user.id),
+ );
+ const dbMedias = await ctx.db.query.medias.findMany({
+ where,
+ orderBy: desc(medias.createdAt),
+ limit: input.pageSize,
+ offset: (input.page - 1) * input.pageSize,
+ columns: {
+ content: false,
+ },
+ with: {
+ creator: {
+ columns: {
+ id: true,
+ name: true,
+ image: true,
+ },
+ },
+ },
+ });
+
+ const totalCount = await ctx.db.$count(medias, where);
+
+ return {
+ items: dbMedias,
+ totalCount,
+ };
+ }),
+ uploadMedia: protectedProcedure.input(validation.media.uploadMedia).mutation(async ({ ctx, input }) => {
+ const content = Buffer.from(await input.file.arrayBuffer());
+ const id = createId();
+ await ctx.db.insert(medias).values({
+ id,
+ creatorId: ctx.session.user.id,
+ content,
+ size: input.file.size,
+ contentType: input.file.type,
+ name: input.file.name,
+ });
+
+ return id;
+ }),
+ deleteMedia: protectedProcedure.input(validation.common.byId).mutation(async ({ ctx, input }) => {
+ const dbMedia = await ctx.db.query.medias.findFirst({
+ where: eq(medias.id, input.id),
+ columns: {
+ creatorId: true,
+ },
+ });
+
+ if (!dbMedia) {
+ throw new TRPCError({
+ code: "NOT_FOUND",
+ message: "Media not found",
+ });
+ }
+
+ // Only allow admins and the creator of the media to delete it
+ if (!ctx.session.user.permissions.includes("admin") && ctx.session.user.id !== dbMedia.creatorId) {
+ throw new TRPCError({
+ code: "FORBIDDEN",
+ message: "You don't have permission to delete this media",
+ });
+ }
+
+ await ctx.db.delete(medias).where(eq(medias.id, input.id));
+ }),
+});
diff --git a/packages/cli/package.json b/packages/cli/package.json
index bba9ee6b4..c4188f83b 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -23,7 +23,7 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
- "@drizzle-team/brocli": "^0.10.1",
+ "@drizzle-team/brocli": "^0.10.2",
"@homarr/auth": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
diff --git a/packages/common/package.json b/packages/common/package.json
index 26fd7b577..b8958f043 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -29,7 +29,7 @@
"dayjs": "^1.11.13",
"next": "^14.2.16",
"react": "^18.3.1",
- "tldts": "^6.1.55"
+ "tldts": "^6.1.57"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts
index e29902783..45c9ad902 100644
--- a/packages/common/src/types.ts
+++ b/packages/common/src/types.ts
@@ -5,3 +5,7 @@ export type AtLeastOneOf = [T, ...T[]];
export type Modify>> = {
[P in keyof (Omit & R)]: (Omit & R)[P];
};
+
+export type RemoveReadonly = {
+ -readonly [P in keyof T]: T[P] extends Record ? RemoveReadonly : T[P];
+};
diff --git a/packages/db/migrations/mysql/0014_bizarre_red_shift.sql b/packages/db/migrations/mysql/0014_bizarre_red_shift.sql
new file mode 100644
index 000000000..42ff3c8f1
--- /dev/null
+++ b/packages/db/migrations/mysql/0014_bizarre_red_shift.sql
@@ -0,0 +1,12 @@
+CREATE TABLE `media` (
+ `id` varchar(64) NOT NULL,
+ `name` varchar(512) NOT NULL,
+ `content` BLOB NOT NULL,
+ `content_type` text NOT NULL,
+ `size` int NOT NULL,
+ `created_at` timestamp NOT NULL DEFAULT (now()),
+ `creator_id` varchar(64),
+ CONSTRAINT `media_id` PRIMARY KEY(`id`)
+);
+--> statement-breakpoint
+ALTER TABLE `media` ADD CONSTRAINT `media_creator_id_user_id_fk` FOREIGN KEY (`creator_id`) REFERENCES `user`(`id`) ON DELETE set null ON UPDATE no action;
\ No newline at end of file
diff --git a/packages/db/migrations/mysql/meta/0014_snapshot.json b/packages/db/migrations/mysql/meta/0014_snapshot.json
new file mode 100644
index 000000000..2ed1db552
--- /dev/null
+++ b/packages/db/migrations/mysql/meta/0014_snapshot.json
@@ -0,0 +1,1602 @@
+{
+ "version": "5",
+ "dialect": "mysql",
+ "id": "a7bb5792-ebee-46d2-a962-5795ba0d1465",
+ "prevId": "aa507e60-8e16-4546-b7a5-86304be877ab",
+ "tables": {
+ "account": {
+ "name": "account",
+ "columns": {
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "providerAccountId": {
+ "name": "providerAccountId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "token_type": {
+ "name": "token_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "session_state": {
+ "name": "session_state",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "userId_idx": {
+ "name": "userId_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "account_userId_user_id_fk": {
+ "name": "account_userId_user_id_fk",
+ "tableFrom": "account",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "account_provider_providerAccountId_pk": {
+ "name": "account_provider_providerAccountId_pk",
+ "columns": ["provider", "providerAccountId"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "apiKey_userId_user_id_fk": {
+ "name": "apiKey_userId_user_id_fk",
+ "tableFrom": "apiKey",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "apiKey_id": {
+ "name": "apiKey_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "app": {
+ "name": "app",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "href": {
+ "name": "href",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "app_id": {
+ "name": "app_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "boardGroupPermission": {
+ "name": "boardGroupPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardGroupPermission_board_id_board_id_fk": {
+ "name": "boardGroupPermission_board_id_board_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardGroupPermission_group_id_group_id_fk": {
+ "name": "boardGroupPermission_group_id_group_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardGroupPermission_board_id_group_id_permission_pk": {
+ "name": "boardGroupPermission_board_id_group_id_permission_pk",
+ "columns": ["board_id", "group_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "boardUserPermission": {
+ "name": "boardUserPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardUserPermission_board_id_board_id_fk": {
+ "name": "boardUserPermission_board_id_board_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardUserPermission_user_id_user_id_fk": {
+ "name": "boardUserPermission_user_id_user_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardUserPermission_board_id_user_id_permission_pk": {
+ "name": "boardUserPermission_board_id_user_id_permission_pk",
+ "columns": ["board_id", "user_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "board": {
+ "name": "board",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(256)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "page_title": {
+ "name": "page_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "meta_title": {
+ "name": "meta_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "logo_image_url": {
+ "name": "logo_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "favicon_image_url": {
+ "name": "favicon_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_url": {
+ "name": "background_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_attachment": {
+ "name": "background_image_attachment",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('fixed')"
+ },
+ "background_image_repeat": {
+ "name": "background_image_repeat",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('no-repeat')"
+ },
+ "background_image_size": {
+ "name": "background_image_size",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('cover')"
+ },
+ "primary_color": {
+ "name": "primary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('#fa5252')"
+ },
+ "secondary_color": {
+ "name": "secondary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('#fd7e14')"
+ },
+ "opacity": {
+ "name": "opacity",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 100
+ },
+ "custom_css": {
+ "name": "custom_css",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "column_count": {
+ "name": "column_count",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 10
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "board_creator_id_user_id_fk": {
+ "name": "board_creator_id_user_id_fk",
+ "tableFrom": "board",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "board_id": {
+ "name": "board_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {
+ "board_name_unique": {
+ "name": "board_name_unique",
+ "columns": ["name"]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "groupMember": {
+ "name": "groupMember",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupMember_groupId_group_id_fk": {
+ "name": "groupMember_groupId_group_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "groupMember_userId_user_id_fk": {
+ "name": "groupMember_userId_user_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "groupMember_groupId_userId_pk": {
+ "name": "groupMember_groupId_userId_pk",
+ "columns": ["groupId", "userId"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "groupPermission": {
+ "name": "groupPermission",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupPermission_groupId_group_id_fk": {
+ "name": "groupPermission_groupId_group_id_fk",
+ "tableFrom": "groupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "group": {
+ "name": "group",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "owner_id": {
+ "name": "owner_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "group_owner_id_user_id_fk": {
+ "name": "group_owner_id_user_id_fk",
+ "tableFrom": "group",
+ "tableTo": "user",
+ "columnsFrom": ["owner_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "group_id": {
+ "name": "group_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {
+ "group_name_unique": {
+ "name": "group_name_unique",
+ "columns": ["name"]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "iconRepository": {
+ "name": "iconRepository",
+ "columns": {
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_slug": {
+ "name": "iconRepository_slug",
+ "type": "varchar(150)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "iconRepository_iconRepository_id": {
+ "name": "iconRepository_iconRepository_id",
+ "columns": ["iconRepository_id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "icon": {
+ "name": "icon",
+ "columns": {
+ "icon_id": {
+ "name": "icon_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_name": {
+ "name": "icon_name",
+ "type": "varchar(250)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_checksum": {
+ "name": "icon_checksum",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "icon_iconRepository_id_iconRepository_iconRepository_id_fk": {
+ "name": "icon_iconRepository_id_iconRepository_iconRepository_id_fk",
+ "tableFrom": "icon",
+ "tableTo": "iconRepository",
+ "columnsFrom": ["iconRepository_id"],
+ "columnsTo": ["iconRepository_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "icon_icon_id": {
+ "name": "icon_icon_id",
+ "columns": ["icon_id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "integrationGroupPermissions": {
+ "name": "integrationGroupPermissions",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationGroupPermissions_integration_id_integration_id_fk": {
+ "name": "integrationGroupPermissions_integration_id_integration_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationGroupPermissions_group_id_group_id_fk": {
+ "name": "integrationGroupPermissions_group_id_group_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integration_group_permission__pk": {
+ "name": "integration_group_permission__pk",
+ "columns": ["integration_id", "group_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "integration_item": {
+ "name": "integration_item",
+ "columns": {
+ "item_id": {
+ "name": "item_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integration_item_item_id_item_id_fk": {
+ "name": "integration_item_item_id_item_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "item",
+ "columnsFrom": ["item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_item_integration_id_integration_id_fk": {
+ "name": "integration_item_integration_id_integration_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integration_item_item_id_integration_id_pk": {
+ "name": "integration_item_item_id_integration_id_pk",
+ "columns": ["item_id", "integration_id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "integrationSecret": {
+ "name": "integrationSecret",
+ "columns": {
+ "kind": {
+ "name": "kind",
+ "type": "varchar(16)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration_secret__kind_idx": {
+ "name": "integration_secret__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ },
+ "integration_secret__updated_at_idx": {
+ "name": "integration_secret__updated_at_idx",
+ "columns": ["updated_at"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "integrationSecret_integration_id_integration_id_fk": {
+ "name": "integrationSecret_integration_id_integration_id_fk",
+ "tableFrom": "integrationSecret",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationSecret_integration_id_kind_pk": {
+ "name": "integrationSecret_integration_id_kind_pk",
+ "columns": ["integration_id", "kind"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "integrationUserPermission": {
+ "name": "integrationUserPermission",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationUserPermission_integration_id_integration_id_fk": {
+ "name": "integrationUserPermission_integration_id_integration_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationUserPermission_user_id_user_id_fk": {
+ "name": "integrationUserPermission_user_id_user_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationUserPermission_integration_id_user_id_permission_pk": {
+ "name": "integrationUserPermission_integration_id_user_id_permission_pk",
+ "columns": ["integration_id", "user_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "integration": {
+ "name": "integration",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration__kind_idx": {
+ "name": "integration__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "integration_id": {
+ "name": "integration_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "invite": {
+ "name": "invite",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expiration_date": {
+ "name": "expiration_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "invite_creator_id_user_id_fk": {
+ "name": "invite_creator_id_user_id_fk",
+ "tableFrom": "invite",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "invite_id": {
+ "name": "invite_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {
+ "invite_token_unique": {
+ "name": "invite_token_unique",
+ "columns": ["token"]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "item": {
+ "name": "item",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "section_id": {
+ "name": "section_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "options": {
+ "name": "options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('{\"json\": {}}')"
+ },
+ "advanced_options": {
+ "name": "advanced_options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('{\"json\": {}}')"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "item_section_id_section_id_fk": {
+ "name": "item_section_id_section_id_fk",
+ "tableFrom": "item",
+ "tableTo": "section",
+ "columnsFrom": ["section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "item_id": {
+ "name": "item_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "media": {
+ "name": "media",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "content": {
+ "name": "content",
+ "type": "BLOB",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "content_type": {
+ "name": "content_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "size": {
+ "name": "size",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "media_creator_id_user_id_fk": {
+ "name": "media_creator_id_user_id_fk",
+ "tableFrom": "media",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "media_id": {
+ "name": "media_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "search_engine": {
+ "name": "search_engine",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "short": {
+ "name": "short",
+ "type": "varchar(8)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "url_template": {
+ "name": "url_template",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "search_engine_id": {
+ "name": "search_engine_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "section": {
+ "name": "section",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "board_id": {
+ "name": "board_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "parent_section_id": {
+ "name": "parent_section_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "section_board_id_board_id_fk": {
+ "name": "section_board_id_board_id_fk",
+ "tableFrom": "section",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "section_parent_section_id_section_id_fk": {
+ "name": "section_parent_section_id_section_id_fk",
+ "tableFrom": "section",
+ "tableTo": "section",
+ "columnsFrom": ["parent_section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "section_id": {
+ "name": "section_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "serverSetting": {
+ "name": "serverSetting",
+ "columns": {
+ "key": {
+ "name": "key",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('{\"json\": {}}')"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "serverSetting_key": {
+ "name": "serverSetting_key",
+ "columns": ["key"]
+ }
+ },
+ "uniqueConstraints": {
+ "serverSetting_key_unique": {
+ "name": "serverSetting_key_unique",
+ "columns": ["key"]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "session": {
+ "name": "session",
+ "columns": {
+ "sessionToken": {
+ "name": "sessionToken",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "user_id_idx": {
+ "name": "user_id_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "session_userId_user_id_fk": {
+ "name": "session_userId_user_id_fk",
+ "tableFrom": "session",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "session_sessionToken": {
+ "name": "session_sessionToken",
+ "columns": ["sessionToken"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "user": {
+ "name": "user",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailVerified": {
+ "name": "emailVerified",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'credentials'"
+ },
+ "homeBoardId": {
+ "name": "homeBoardId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "colorScheme": {
+ "name": "colorScheme",
+ "type": "varchar(5)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'dark'"
+ },
+ "firstDayOfWeek": {
+ "name": "firstDayOfWeek",
+ "type": "tinyint",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "pingIconsEnabled": {
+ "name": "pingIconsEnabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "user_homeBoardId_board_id_fk": {
+ "name": "user_homeBoardId_board_id_fk",
+ "tableFrom": "user",
+ "tableTo": "board",
+ "columnsFrom": ["homeBoardId"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "user_id": {
+ "name": "user_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "verificationToken": {
+ "name": "verificationToken",
+ "columns": {
+ "identifier": {
+ "name": "identifier",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "verificationToken_identifier_token_pk": {
+ "name": "verificationToken_identifier_token_pk",
+ "columns": ["identifier", "token"]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ }
+ },
+ "views": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "tables": {},
+ "indexes": {}
+ }
+}
diff --git a/packages/db/migrations/mysql/meta/_journal.json b/packages/db/migrations/mysql/meta/_journal.json
index 7ac6a43d8..1c201d874 100644
--- a/packages/db/migrations/mysql/meta/_journal.json
+++ b/packages/db/migrations/mysql/meta/_journal.json
@@ -99,6 +99,13 @@
"when": 1729369383739,
"tag": "0013_youthful_vulture",
"breakpoints": true
+ },
+ {
+ "idx": 14,
+ "version": "5",
+ "when": 1729524382483,
+ "tag": "0014_bizarre_red_shift",
+ "breakpoints": true
}
]
}
diff --git a/packages/db/migrations/sqlite/0014_colorful_cargill.sql b/packages/db/migrations/sqlite/0014_colorful_cargill.sql
new file mode 100644
index 000000000..56c92817f
--- /dev/null
+++ b/packages/db/migrations/sqlite/0014_colorful_cargill.sql
@@ -0,0 +1,10 @@
+CREATE TABLE `media` (
+ `id` text PRIMARY KEY NOT NULL,
+ `name` text NOT NULL,
+ `content` blob NOT NULL,
+ `content_type` text NOT NULL,
+ `size` integer NOT NULL,
+ `created_at` integer DEFAULT (unixepoch()) NOT NULL,
+ `creator_id` text,
+ FOREIGN KEY (`creator_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE set null
+);
diff --git a/packages/db/migrations/sqlite/meta/0014_snapshot.json b/packages/db/migrations/sqlite/meta/0014_snapshot.json
new file mode 100644
index 000000000..1566912f7
--- /dev/null
+++ b/packages/db/migrations/sqlite/meta/0014_snapshot.json
@@ -0,0 +1,1531 @@
+{
+ "version": "6",
+ "dialect": "sqlite",
+ "id": "f76c21f2-0fbd-4107-a029-e05e917b9428",
+ "prevId": "767f5db4-59ab-46c7-a154-4fcd9474c358",
+ "tables": {
+ "account": {
+ "name": "account",
+ "columns": {
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "providerAccountId": {
+ "name": "providerAccountId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "token_type": {
+ "name": "token_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "session_state": {
+ "name": "session_state",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "userId_idx": {
+ "name": "userId_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "account_userId_user_id_fk": {
+ "name": "account_userId_user_id_fk",
+ "tableFrom": "account",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "account_provider_providerAccountId_pk": {
+ "columns": ["provider", "providerAccountId"],
+ "name": "account_provider_providerAccountId_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "apiKey_userId_user_id_fk": {
+ "name": "apiKey_userId_user_id_fk",
+ "tableFrom": "apiKey",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "app": {
+ "name": "app",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "href": {
+ "name": "href",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "boardGroupPermission": {
+ "name": "boardGroupPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardGroupPermission_board_id_board_id_fk": {
+ "name": "boardGroupPermission_board_id_board_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardGroupPermission_group_id_group_id_fk": {
+ "name": "boardGroupPermission_group_id_group_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardGroupPermission_board_id_group_id_permission_pk": {
+ "columns": ["board_id", "group_id", "permission"],
+ "name": "boardGroupPermission_board_id_group_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "boardUserPermission": {
+ "name": "boardUserPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardUserPermission_board_id_board_id_fk": {
+ "name": "boardUserPermission_board_id_board_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardUserPermission_user_id_user_id_fk": {
+ "name": "boardUserPermission_user_id_user_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardUserPermission_board_id_user_id_permission_pk": {
+ "columns": ["board_id", "user_id", "permission"],
+ "name": "boardUserPermission_board_id_user_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "board": {
+ "name": "board",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "page_title": {
+ "name": "page_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "meta_title": {
+ "name": "meta_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "logo_image_url": {
+ "name": "logo_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "favicon_image_url": {
+ "name": "favicon_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_url": {
+ "name": "background_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_attachment": {
+ "name": "background_image_attachment",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'fixed'"
+ },
+ "background_image_repeat": {
+ "name": "background_image_repeat",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'no-repeat'"
+ },
+ "background_image_size": {
+ "name": "background_image_size",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'cover'"
+ },
+ "primary_color": {
+ "name": "primary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'#fa5252'"
+ },
+ "secondary_color": {
+ "name": "secondary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'#fd7e14'"
+ },
+ "opacity": {
+ "name": "opacity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 100
+ },
+ "custom_css": {
+ "name": "custom_css",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "column_count": {
+ "name": "column_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 10
+ }
+ },
+ "indexes": {
+ "board_name_unique": {
+ "name": "board_name_unique",
+ "columns": ["name"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "board_creator_id_user_id_fk": {
+ "name": "board_creator_id_user_id_fk",
+ "tableFrom": "board",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "groupMember": {
+ "name": "groupMember",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupMember_groupId_group_id_fk": {
+ "name": "groupMember_groupId_group_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "groupMember_userId_user_id_fk": {
+ "name": "groupMember_userId_user_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "groupMember_groupId_userId_pk": {
+ "columns": ["groupId", "userId"],
+ "name": "groupMember_groupId_userId_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "groupPermission": {
+ "name": "groupPermission",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupPermission_groupId_group_id_fk": {
+ "name": "groupPermission_groupId_group_id_fk",
+ "tableFrom": "groupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "group": {
+ "name": "group",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "owner_id": {
+ "name": "owner_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "group_name_unique": {
+ "name": "group_name_unique",
+ "columns": ["name"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "group_owner_id_user_id_fk": {
+ "name": "group_owner_id_user_id_fk",
+ "tableFrom": "group",
+ "tableTo": "user",
+ "columnsFrom": ["owner_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "iconRepository": {
+ "name": "iconRepository",
+ "columns": {
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_slug": {
+ "name": "iconRepository_slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "icon": {
+ "name": "icon",
+ "columns": {
+ "icon_id": {
+ "name": "icon_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_name": {
+ "name": "icon_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_checksum": {
+ "name": "icon_checksum",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "icon_iconRepository_id_iconRepository_iconRepository_id_fk": {
+ "name": "icon_iconRepository_id_iconRepository_iconRepository_id_fk",
+ "tableFrom": "icon",
+ "tableTo": "iconRepository",
+ "columnsFrom": ["iconRepository_id"],
+ "columnsTo": ["iconRepository_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "integrationGroupPermissions": {
+ "name": "integrationGroupPermissions",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationGroupPermissions_integration_id_integration_id_fk": {
+ "name": "integrationGroupPermissions_integration_id_integration_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationGroupPermissions_group_id_group_id_fk": {
+ "name": "integrationGroupPermissions_group_id_group_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationGroupPermissions_integration_id_group_id_permission_pk": {
+ "columns": ["integration_id", "group_id", "permission"],
+ "name": "integrationGroupPermissions_integration_id_group_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "integration_item": {
+ "name": "integration_item",
+ "columns": {
+ "item_id": {
+ "name": "item_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integration_item_item_id_item_id_fk": {
+ "name": "integration_item_item_id_item_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "item",
+ "columnsFrom": ["item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_item_integration_id_integration_id_fk": {
+ "name": "integration_item_integration_id_integration_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integration_item_item_id_integration_id_pk": {
+ "columns": ["item_id", "integration_id"],
+ "name": "integration_item_item_id_integration_id_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "integrationSecret": {
+ "name": "integrationSecret",
+ "columns": {
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration_secret__kind_idx": {
+ "name": "integration_secret__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ },
+ "integration_secret__updated_at_idx": {
+ "name": "integration_secret__updated_at_idx",
+ "columns": ["updated_at"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "integrationSecret_integration_id_integration_id_fk": {
+ "name": "integrationSecret_integration_id_integration_id_fk",
+ "tableFrom": "integrationSecret",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationSecret_integration_id_kind_pk": {
+ "columns": ["integration_id", "kind"],
+ "name": "integrationSecret_integration_id_kind_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "integrationUserPermission": {
+ "name": "integrationUserPermission",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationUserPermission_integration_id_integration_id_fk": {
+ "name": "integrationUserPermission_integration_id_integration_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationUserPermission_user_id_user_id_fk": {
+ "name": "integrationUserPermission_user_id_user_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationUserPermission_integration_id_user_id_permission_pk": {
+ "columns": ["integration_id", "user_id", "permission"],
+ "name": "integrationUserPermission_integration_id_user_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "integration": {
+ "name": "integration",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration__kind_idx": {
+ "name": "integration__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "invite": {
+ "name": "invite",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expiration_date": {
+ "name": "expiration_date",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "invite_token_unique": {
+ "name": "invite_token_unique",
+ "columns": ["token"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "invite_creator_id_user_id_fk": {
+ "name": "invite_creator_id_user_id_fk",
+ "tableFrom": "invite",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "item": {
+ "name": "item",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "section_id": {
+ "name": "section_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "options": {
+ "name": "options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'{\"json\": {}}'"
+ },
+ "advanced_options": {
+ "name": "advanced_options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'{\"json\": {}}'"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "item_section_id_section_id_fk": {
+ "name": "item_section_id_section_id_fk",
+ "tableFrom": "item",
+ "tableTo": "section",
+ "columnsFrom": ["section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "media": {
+ "name": "media",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "content": {
+ "name": "content",
+ "type": "blob",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "content_type": {
+ "name": "content_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "size": {
+ "name": "size",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(unixepoch())"
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "media_creator_id_user_id_fk": {
+ "name": "media_creator_id_user_id_fk",
+ "tableFrom": "media",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "search_engine": {
+ "name": "search_engine",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "short": {
+ "name": "short",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "url_template": {
+ "name": "url_template",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "section": {
+ "name": "section",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "board_id": {
+ "name": "board_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "parent_section_id": {
+ "name": "parent_section_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "section_board_id_board_id_fk": {
+ "name": "section_board_id_board_id_fk",
+ "tableFrom": "section",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "section_parent_section_id_section_id_fk": {
+ "name": "section_parent_section_id_section_id_fk",
+ "tableFrom": "section",
+ "tableTo": "section",
+ "columnsFrom": ["parent_section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "serverSetting": {
+ "name": "serverSetting",
+ "columns": {
+ "key": {
+ "name": "key",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'{\"json\": {}}'"
+ }
+ },
+ "indexes": {
+ "serverSetting_key_unique": {
+ "name": "serverSetting_key_unique",
+ "columns": ["key"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "session": {
+ "name": "session",
+ "columns": {
+ "sessionToken": {
+ "name": "sessionToken",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "user_id_idx": {
+ "name": "user_id_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "session_userId_user_id_fk": {
+ "name": "session_userId_user_id_fk",
+ "tableFrom": "session",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "user": {
+ "name": "user",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailVerified": {
+ "name": "emailVerified",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'credentials'"
+ },
+ "homeBoardId": {
+ "name": "homeBoardId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "colorScheme": {
+ "name": "colorScheme",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'dark'"
+ },
+ "firstDayOfWeek": {
+ "name": "firstDayOfWeek",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "pingIconsEnabled": {
+ "name": "pingIconsEnabled",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "user_homeBoardId_board_id_fk": {
+ "name": "user_homeBoardId_board_id_fk",
+ "tableFrom": "user",
+ "tableTo": "board",
+ "columnsFrom": ["homeBoardId"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "verificationToken": {
+ "name": "verificationToken",
+ "columns": {
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "verificationToken_identifier_token_pk": {
+ "columns": ["identifier", "token"],
+ "name": "verificationToken_identifier_token_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ }
+ },
+ "views": {},
+ "enums": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "indexes": {}
+ }
+}
diff --git a/packages/db/migrations/sqlite/meta/_journal.json b/packages/db/migrations/sqlite/meta/_journal.json
index e88a243de..36d590465 100644
--- a/packages/db/migrations/sqlite/meta/_journal.json
+++ b/packages/db/migrations/sqlite/meta/_journal.json
@@ -99,6 +99,13 @@
"when": 1729369389386,
"tag": "0013_faithful_hex",
"breakpoints": true
+ },
+ {
+ "idx": 14,
+ "version": "6",
+ "when": 1729524387583,
+ "tag": "0014_colorful_cargill",
+ "breakpoints": true
}
]
}
diff --git a/packages/db/package.json b/packages/db/package.json
index 122226edc..d586d18c3 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -44,8 +44,8 @@
"@testcontainers/mysql": "^10.13.2",
"better-sqlite3": "^11.5.0",
"dotenv": "^16.4.5",
- "drizzle-kit": "^0.26.2",
- "drizzle-orm": "^0.35.3",
+ "drizzle-kit": "^0.27.1",
+ "drizzle-orm": "^0.36.0",
"mysql2": "3.11.3"
},
"devDependencies": {
@@ -56,7 +56,7 @@
"dotenv-cli": "^7.4.2",
"eslint": "^9.13.0",
"prettier": "^3.3.3",
- "tsx": "4.19.1",
+ "tsx": "4.19.2",
"typescript": "^5.6.3"
}
}
diff --git a/packages/db/schema/mysql.ts b/packages/db/schema/mysql.ts
index e5b2b050f..0bbbbbe8d 100644
--- a/packages/db/schema/mysql.ts
+++ b/packages/db/schema/mysql.ts
@@ -2,7 +2,18 @@ import type { AdapterAccount } from "@auth/core/adapters";
import type { DayOfWeek } from "@mantine/dates";
import { relations } from "drizzle-orm";
import type { AnyMySqlColumn } from "drizzle-orm/mysql-core";
-import { boolean, index, int, mysqlTable, primaryKey, text, timestamp, tinyint, varchar } from "drizzle-orm/mysql-core";
+import {
+ boolean,
+ customType,
+ index,
+ int,
+ mysqlTable,
+ primaryKey,
+ text,
+ timestamp,
+ tinyint,
+ varchar,
+} from "drizzle-orm/mysql-core";
import type {
BackgroundImageAttachment,
@@ -20,6 +31,12 @@ import type {
} from "@homarr/definitions";
import { backgroundImageAttachments, backgroundImageRepeats, backgroundImageSizes } from "@homarr/definitions";
+const customBlob = customType<{ data: Buffer }>({
+ dataType() {
+ return "BLOB";
+ },
+});
+
export const apiKeys = mysqlTable("apiKey", {
id: varchar("id", { length: 64 }).notNull().primaryKey(),
apiKey: text("apiKey").notNull(),
@@ -142,6 +159,16 @@ export const invites = mysqlTable("invite", {
.references(() => users.id, { onDelete: "cascade" }),
});
+export const medias = mysqlTable("media", {
+ id: varchar("id", { length: 64 }).notNull().primaryKey(),
+ name: varchar("name", { length: 512 }).notNull(),
+ content: customBlob("content").notNull(),
+ contentType: text("content_type").notNull(),
+ size: int("size").notNull(),
+ createdAt: timestamp("created_at", { mode: "date" }).notNull().defaultNow(),
+ creatorId: varchar("creator_id", { length: 64 }).references(() => users.id, { onDelete: "set null" }),
+});
+
export const integrations = mysqlTable(
"integration",
{
@@ -387,6 +414,13 @@ export const userRelations = relations(users, ({ many }) => ({
invites: many(invites),
}));
+export const mediaRelations = relations(medias, ({ one }) => ({
+ creator: one(users, {
+ fields: [medias.creatorId],
+ references: [users.id],
+ }),
+}));
+
export const iconRelations = relations(icons, ({ one }) => ({
repository: one(iconRepositories, {
fields: [icons.iconRepositoryId],
diff --git a/packages/db/schema/sqlite.ts b/packages/db/schema/sqlite.ts
index 08a8b8c44..a66b5f72a 100644
--- a/packages/db/schema/sqlite.ts
+++ b/packages/db/schema/sqlite.ts
@@ -1,9 +1,9 @@
import type { AdapterAccount } from "@auth/core/adapters";
import type { DayOfWeek } from "@mantine/dates";
import type { InferSelectModel } from "drizzle-orm";
-import { relations } from "drizzle-orm";
+import { relations, sql } from "drizzle-orm";
import type { AnySQLiteColumn } from "drizzle-orm/sqlite-core";
-import { index, int, integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
+import { blob, index, int, integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
import { backgroundImageAttachments, backgroundImageRepeats, backgroundImageSizes } from "@homarr/definitions";
import type {
@@ -145,6 +145,18 @@ export const invites = sqliteTable("invite", {
.references(() => users.id, { onDelete: "cascade" }),
});
+export const medias = sqliteTable("media", {
+ id: text("id").notNull().primaryKey(),
+ name: text("name").notNull(),
+ content: blob("content", { mode: "buffer" }).$type().notNull(),
+ contentType: text("content_type").notNull(),
+ size: int("size").notNull(),
+ createdAt: integer("created_at", { mode: "timestamp" })
+ .notNull()
+ .default(sql`(unixepoch())`),
+ creatorId: text("creator_id").references(() => users.id, { onDelete: "set null" }),
+});
+
export const integrations = sqliteTable(
"integration",
{
@@ -387,6 +399,14 @@ export const userRelations = relations(users, ({ many }) => ({
groups: many(groupMembers),
ownedGroups: many(groups),
invites: many(invites),
+ medias: many(medias),
+}));
+
+export const mediaRelations = relations(medias, ({ one }) => ({
+ creator: one(users, {
+ fields: [medias.creatorId],
+ references: [users.id],
+ }),
}));
export const iconRelations = relations(icons, ({ one }) => ({
diff --git a/packages/db/test/schema.spec.ts b/packages/db/test/schema.spec.ts
index 1d379763a..3de1cd5a9 100644
--- a/packages/db/test/schema.spec.ts
+++ b/packages/db/test/schema.spec.ts
@@ -9,11 +9,35 @@ import { objectEntries } from "@homarr/common";
import * as mysqlSchema from "../schema/mysql";
import * as sqliteSchema from "../schema/sqlite";
+// We need the following two types as there is currently no support for Buffer in mysql and
+// so we use a custom type which results in the config beeing different
+type FixedMysqlConfig = {
+ [key in keyof MysqlConfig]: {
+ [column in keyof MysqlConfig[key]]: {
+ [property in Exclude]: MysqlConfig[key][column][property];
+ } & {
+ dataType: MysqlConfig[key][column]["data"] extends Buffer ? "buffer" : MysqlConfig[key][column]["dataType"];
+ data: MysqlConfig[key][column]["data"] extends Buffer ? Buffer : MysqlConfig[key][column]["data"];
+ };
+ };
+};
+
+type FixedSqliteConfig = {
+ [key in keyof SqliteConfig]: {
+ [column in keyof SqliteConfig[key]]: {
+ [property in Exclude]: SqliteConfig[key][column][property];
+ } & {
+ dataType: SqliteConfig[key][column]["dataType"] extends Buffer ? "buffer" : SqliteConfig[key][column]["dataType"];
+ data: SqliteConfig[key][column]["data"] extends Buffer ? Buffer : SqliteConfig[key][column]["data"];
+ };
+ };
+};
+
test("schemas should match", () => {
expectTypeOf().toEqualTypeOf();
expectTypeOf().toEqualTypeOf();
- expectTypeOf().toEqualTypeOf();
- expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
objectEntries(sqliteSchema).forEach(([tableName, sqliteTable]) => {
Object.entries(sqliteTable).forEach(([columnName, sqliteColumn]: [string, object]) => {
diff --git a/packages/integrations/package.json b/packages/integrations/package.json
index a3d944fa8..9025fd682 100644
--- a/packages/integrations/package.json
+++ b/packages/integrations/package.json
@@ -33,7 +33,7 @@
"@homarr/log": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
- "@jellyfin/sdk": "^0.10.0",
+ "@jellyfin/sdk": "^0.11.0",
"xml2js": "^0.6.2"
},
"devDependencies": {
diff --git a/packages/modals-collection/package.json b/packages/modals-collection/package.json
index c18486717..e2a30ce32 100644
--- a/packages/modals-collection/package.json
+++ b/packages/modals-collection/package.json
@@ -31,7 +31,7 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^7.13.4",
- "@tabler/icons-react": "^3.20.0",
+ "@tabler/icons-react": "^3.21.0",
"dayjs": "^1.11.13",
"next": "^14.2.16",
"react": "^18.3.1"
diff --git a/packages/modals-collection/src/invites/invite-copy-modal.tsx b/packages/modals-collection/src/invites/invite-copy-modal.tsx
index 2fa3890a3..08136af34 100644
--- a/packages/modals-collection/src/invites/invite-copy-modal.tsx
+++ b/packages/modals-collection/src/invites/invite-copy-modal.tsx
@@ -12,8 +12,11 @@ export const InviteCopyModal = createModal
- {t("action.copy.description")}
- {/* TODO: When next-international v2 is released the descriptions bold element can be implemented, see https://github.com/QuiiBz/next-international/pull/361 for progress */}
+
+ {t.rich("action.copy.description", {
+ b: (children) => {children},
+ })}
+
{t("action.copy.link")}
{t("field.id.label")}:
diff --git a/packages/notifications/package.json b/packages/notifications/package.json
index 985ef3853..eb9eaf1f3 100644
--- a/packages/notifications/package.json
+++ b/packages/notifications/package.json
@@ -25,7 +25,7 @@
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^7.13.4",
- "@tabler/icons-react": "^3.20.0"
+ "@tabler/icons-react": "^3.21.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
diff --git a/packages/server-settings/src/index.ts b/packages/server-settings/src/index.ts
index ee5a6ade8..7934dc0da 100644
--- a/packages/server-settings/src/index.ts
+++ b/packages/server-settings/src/index.ts
@@ -1,8 +1,6 @@
export const defaultServerSettingsKeys = ["analytics", "crawlingAndIndexing"] as const;
-export type ServerSettingsRecord = {
- [key in (typeof defaultServerSettingsKeys)[number]]: Record;
-};
+export type ServerSettingsRecord = Record<(typeof defaultServerSettingsKeys)[number], Record>;
export const defaultServerSettings = {
analytics: {
diff --git a/packages/spotlight/package.json b/packages/spotlight/package.json
index 22e4fa28e..22f2f8df8 100644
--- a/packages/spotlight/package.json
+++ b/packages/spotlight/package.json
@@ -33,7 +33,7 @@
"@mantine/core": "^7.13.4",
"@mantine/hooks": "^7.13.4",
"@mantine/spotlight": "^7.13.4",
- "@tabler/icons-react": "^3.20.0",
+ "@tabler/icons-react": "^3.21.0",
"jotai": "^2.10.1",
"next": "^14.2.16",
"react": "^18.3.1",
diff --git a/packages/spotlight/src/modes/command/children/language.tsx b/packages/spotlight/src/modes/command/children/language.tsx
index 848139b68..f861746dd 100644
--- a/packages/spotlight/src/modes/command/children/language.tsx
+++ b/packages/spotlight/src/modes/command/children/language.tsx
@@ -1,7 +1,7 @@
import { Group, Stack, Text } from "@mantine/core";
import { IconCheck } from "@tabler/icons-react";
-import { localeAttributes, supportedLanguages } from "@homarr/translation";
+import { localeConfigurations, supportedLanguages } from "@homarr/translation";
import { useChangeLocale, useCurrentLocale, useI18n } from "@homarr/translation/client";
import { createChildrenOptions } from "../../../lib/children";
@@ -11,34 +11,34 @@ export const languageChildrenOptions = createChildrenOptions ({ localeKey, attributes: localeAttributes[localeKey] }))
+ .map((localeKey) => ({ localeKey, configuration: localeConfigurations[localeKey] }))
.filter(
- ({ attributes }) =>
- attributes.name.toLowerCase().includes(normalizedQuery) ||
- attributes.translatedName.toLowerCase().includes(normalizedQuery),
+ ({ configuration }) =>
+ configuration.name.toLowerCase().includes(normalizedQuery) ||
+ configuration.translatedName.toLowerCase().includes(normalizedQuery),
)
.sort(
(languageA, languageB) =>
Math.min(
- languageA.attributes.name.toLowerCase().indexOf(normalizedQuery),
- languageA.attributes.translatedName.toLowerCase().indexOf(normalizedQuery),
+ languageA.configuration.name.toLowerCase().indexOf(normalizedQuery),
+ languageA.configuration.translatedName.toLowerCase().indexOf(normalizedQuery),
) -
Math.min(
- languageB.attributes.name.toLowerCase().indexOf(normalizedQuery),
- languageB.attributes.translatedName.toLowerCase().indexOf(normalizedQuery),
+ languageB.configuration.name.toLowerCase().indexOf(normalizedQuery),
+ languageB.configuration.translatedName.toLowerCase().indexOf(normalizedQuery),
),
)
- .map(({ localeKey, attributes }) => ({
+ .map(({ localeKey, configuration }) => ({
key: localeKey,
Component() {
return (
-
+
- {attributes.name}
+ {configuration.name}
- ({attributes.translatedName})
+ ({configuration.translatedName})
@@ -47,7 +47,7 @@ export const languageChildrenOptions = createChildrenOptions changeLocale(localeKey) };
},
diff --git a/packages/spotlight/src/modes/page/pages-search-group.tsx b/packages/spotlight/src/modes/page/pages-search-group.tsx
index 698f6166c..9383631ef 100644
--- a/packages/spotlight/src/modes/page/pages-search-group.tsx
+++ b/packages/spotlight/src/modes/page/pages-search-group.tsx
@@ -7,6 +7,7 @@ import {
IconLayoutDashboard,
IconLogs,
IconMailForward,
+ IconPhoto,
IconPlug,
IconReport,
IconSearch,
@@ -89,6 +90,12 @@ export const pagesSearchGroup = createGroup<{
name: t("manageSearchEngine.label"),
hidden: !session,
},
+ {
+ icon: IconPhoto,
+ path: "/manage/medias",
+ name: t("manageMedia.label"),
+ hidden: !session,
+ },
{
icon: IconUsers,
path: "/manage/users",
diff --git a/packages/translation/package.json b/packages/translation/package.json
index 0f4f728d3..cb0478444 100644
--- a/packages/translation/package.json
+++ b/packages/translation/package.json
@@ -6,9 +6,10 @@
"type": "module",
"exports": {
".": "./index.ts",
- "./client": "./src/client.ts",
+ "./client": "./src/client/index.ts",
"./server": "./src/server.ts",
- "./middleware": "./src/middleware.ts"
+ "./middleware": "./src/middleware.ts",
+ "./request": "./src/request.ts"
},
"typesVersions": {
"*": {
@@ -25,9 +26,12 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
+ "@homarr/common": "workspace:^0.1.0",
"dayjs": "^1.11.13",
"mantine-react-table": "2.0.0-beta.7",
- "next-international": "^1.2.4"
+ "next": "^14.2.16",
+ "next-intl": "3.24.0",
+ "react": "^18.3.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
diff --git a/packages/translation/src/client.ts b/packages/translation/src/client.ts
deleted file mode 100644
index 8cbb49e73..000000000
--- a/packages/translation/src/client.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-"use client";
-
-import { createI18nClient } from "next-international/client";
-
-import { languageMapping } from "./lang";
-import enTranslation from "./lang/en";
-
-export const { useI18n, useScopedI18n, useCurrentLocale, useChangeLocale, I18nProviderClient } = createI18nClient(
- languageMapping(),
- {
- fallbackLocale: enTranslation,
- },
-);
diff --git a/packages/translation/src/client/index.ts b/packages/translation/src/client/index.ts
new file mode 100644
index 000000000..16d73330b
--- /dev/null
+++ b/packages/translation/src/client/index.ts
@@ -0,0 +1,19 @@
+"use client";
+
+import { useMessages, useTranslations } from "next-intl";
+
+import type { TranslationObject } from "../type";
+
+export { useChangeLocale } from "./use-change-locale";
+export { useCurrentLocale } from "./use-current-locale";
+
+export const { useI18n, useScopedI18n } = {
+ useI18n: useTranslations,
+ useScopedI18n: useTranslations,
+};
+
+export const { useI18nMessages } = {
+ useI18nMessages: () => useMessages() as TranslationObject,
+};
+
+export { useTranslations };
diff --git a/packages/translation/src/client/use-change-locale.ts b/packages/translation/src/client/use-change-locale.ts
new file mode 100644
index 000000000..7d5ce06e1
--- /dev/null
+++ b/packages/translation/src/client/use-change-locale.ts
@@ -0,0 +1,25 @@
+import { useTransition } from "react";
+import { usePathname, useRouter } from "next/navigation";
+
+import type { SupportedLanguage } from "../config";
+import { useCurrentLocale } from "./use-current-locale";
+
+export const useChangeLocale = () => {
+ const currentLocale = useCurrentLocale();
+ const router = useRouter();
+ const pathname = usePathname();
+ const [isPending, startTransition] = useTransition();
+
+ return {
+ changeLocale: (newLocale: SupportedLanguage) => {
+ if (newLocale === currentLocale) {
+ return;
+ }
+
+ startTransition(() => {
+ router.replace(`/${newLocale}/${pathname}`);
+ });
+ },
+ isPending,
+ };
+};
diff --git a/packages/translation/src/client/use-current-locale.ts b/packages/translation/src/client/use-current-locale.ts
new file mode 100644
index 000000000..f05eff7e5
--- /dev/null
+++ b/packages/translation/src/client/use-current-locale.ts
@@ -0,0 +1,5 @@
+import { useLocale } from "next-intl";
+
+import type { SupportedLanguage } from "../config";
+
+export const useCurrentLocale = () => useLocale() as SupportedLanguage;
diff --git a/packages/translation/src/config.ts b/packages/translation/src/config.ts
new file mode 100644
index 000000000..6a88e640d
--- /dev/null
+++ b/packages/translation/src/config.ts
@@ -0,0 +1,26 @@
+import { objectKeys } from "@homarr/common";
+
+export const localeConfigurations = {
+ de: {
+ name: "Deutsch",
+ translatedName: "German",
+ flagIcon: "de",
+ },
+ en: {
+ name: "English",
+ translatedName: "English",
+ flagIcon: "us",
+ },
+} satisfies Record<
+ string,
+ {
+ name: string;
+ translatedName: string;
+ flagIcon: string;
+ }
+>;
+
+export const supportedLanguages = objectKeys(localeConfigurations);
+export type SupportedLanguage = (typeof supportedLanguages)[number];
+
+export const defaultLocale = "en" satisfies SupportedLanguage;
diff --git a/packages/translation/src/index.ts b/packages/translation/src/index.ts
index 89f14b401..fff1e95aa 100644
--- a/packages/translation/src/index.ts
+++ b/packages/translation/src/index.ts
@@ -1,14 +1,11 @@
+import type { SupportedLanguage } from "./config";
+import { supportedLanguages } from "./config";
import type { stringOrTranslation, TranslationFunction } from "./type";
export * from "./type";
-export * from "./locale-attributes";
-
-export const supportedLanguages = ["en", "de"] as const;
-export type SupportedLanguage = (typeof supportedLanguages)[number];
-
-export const defaultLocale = "en";
-export { languageMapping } from "./lang";
-export type { TranslationKeys } from "./lang";
+export * from "./config";
+export { createLanguageMapping } from "./mapping";
+export type { TranslationKeys } from "./mapping";
export const translateIfNecessary = (t: TranslationFunction, value: stringOrTranslation | undefined) => {
if (typeof value === "function") {
@@ -16,3 +13,7 @@ export const translateIfNecessary = (t: TranslationFunction, value: stringOrTran
}
return value;
};
+
+export const isLocaleSupported = (locale: string): locale is SupportedLanguage => {
+ return supportedLanguages.includes(locale as SupportedLanguage);
+};
diff --git a/packages/translation/src/lang/en.ts b/packages/translation/src/lang/en.ts
index 670be6712..0a87bbb6b 100644
--- a/packages/translation/src/lang/en.ts
+++ b/packages/translation/src/lang/en.ts
@@ -552,6 +552,44 @@ export default {
full: "Full integration access",
},
},
+ media: {
+ plural: "Medias",
+ search: "Find a media",
+ field: {
+ name: "Name",
+ size: "Size",
+ creator: "Creator",
+ },
+ action: {
+ upload: {
+ label: "Upload media",
+ file: "Select file",
+ notification: {
+ success: {
+ message: "The media was successfully uploaded",
+ },
+ error: {
+ message: "The media could not be uploaded",
+ },
+ },
+ },
+ delete: {
+ label: "Delete media",
+ description: "Are you sure you want to delete the media ?",
+ notification: {
+ success: {
+ message: "The media was successfully deleted",
+ },
+ error: {
+ message: "The media could not be deleted",
+ },
+ },
+ },
+ copy: {
+ label: "Copy URL",
+ },
+ },
+ },
common: {
// Either "ltr" or "rtl"
direction: "ltr",
@@ -668,7 +706,7 @@ export default {
},
},
},
- mantineReactTable: MRT_Localization_EN,
+ mantineReactTable: MRT_Localization_EN as Readonly>,
},
section: {
dynamic: {
@@ -1167,11 +1205,11 @@ export default {
},
integration: {
noData: "No integration found",
- description: "Click {here} to create a new integration",
+ description: "Click to create a new integration",
},
app: {
noData: "No app found",
- description: "Click {here} to create a new app",
+ description: "Click to create a new app",
},
error: {
action: {
@@ -1644,6 +1682,7 @@ export default {
apps: "Apps",
integrations: "Integrations",
searchEngies: "Search engines",
+ medias: "Medias",
users: {
label: "Users",
items: {
@@ -1732,6 +1771,9 @@ export default {
},
},
},
+ media: {
+ includeFromAllUsers: "Include media from all users",
+ },
user: {
back: "Back to users",
fieldsDisabledExternalProvider:
@@ -1800,7 +1842,7 @@ export default {
copy: {
title: "Copy invite",
description:
- "Your invitation has been generated. After this modal closes, you'll not be able to copy this link anymore. If you do no longer wish to invite said person, you can delete this invitation any time.",
+ "Your invitation has been generated. After this modal closes, you'll not be able to copy this link anymore. If you do no longer wish to invite said person, you can delete this invitation any time.",
link: "Invitation link",
button: "Copy & close",
},
@@ -2138,6 +2180,9 @@ export default {
label: "Edit",
},
},
+ medias: {
+ label: "Medias",
+ },
apps: {
label: "Apps",
new: {
@@ -2359,6 +2404,9 @@ export default {
manageSearchEngine: {
label: "Manage search engines",
},
+ manageMedia: {
+ label: "Manage medias",
+ },
manageUser: {
label: "Manage users",
},
diff --git a/packages/translation/src/locale-attributes.ts b/packages/translation/src/locale-attributes.ts
deleted file mode 100644
index 69967c003..000000000
--- a/packages/translation/src/locale-attributes.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { SupportedLanguage } from ".";
-
-export const localeAttributes: Record<
- SupportedLanguage,
- {
- name: string;
- translatedName: string;
- flagIcon: string;
- }
-> = {
- de: {
- name: "Deutsch",
- translatedName: "German",
- flagIcon: "de",
- },
- en: {
- name: "English",
- translatedName: "English",
- flagIcon: "us",
- },
-};
diff --git a/packages/translation/src/lang.ts b/packages/translation/src/mapping.ts
similarity index 88%
rename from packages/translation/src/lang.ts
rename to packages/translation/src/mapping.ts
index 5874d7918..b65d7e7bb 100644
--- a/packages/translation/src/lang.ts
+++ b/packages/translation/src/mapping.ts
@@ -1,9 +1,9 @@
-import { supportedLanguages } from ".";
+import { supportedLanguages } from "./config";
const _enTranslations = () => import("./lang/en");
type EnTranslation = typeof _enTranslations;
-export const languageMapping = () => {
+export const createLanguageMapping = () => {
const mapping: Record = {};
for (const language of supportedLanguages) {
diff --git a/packages/translation/src/middleware.ts b/packages/translation/src/middleware.ts
index 77d2a138d..636c1c5ca 100644
--- a/packages/translation/src/middleware.ts
+++ b/packages/translation/src/middleware.ts
@@ -1,9 +1,10 @@
-import { createI18nMiddleware } from "next-international/middleware";
+import createMiddleware from "next-intl/middleware";
-import { defaultLocale, supportedLanguages } from ".";
+import { routing } from "./routing";
-export const I18nMiddleware = createI18nMiddleware({
- locales: supportedLanguages,
- defaultLocale,
- urlMappingStrategy: "rewrite",
-});
+export const I18nMiddleware = createMiddleware(routing);
+
+export const config = {
+ // Match only internationalized pathnames
+ matcher: ["/", "/(de|en)/:path*"],
+};
diff --git a/packages/translation/src/request.ts b/packages/translation/src/request.ts
new file mode 100644
index 000000000..4436d7443
--- /dev/null
+++ b/packages/translation/src/request.ts
@@ -0,0 +1,34 @@
+import deepmerge from "deepmerge";
+import { getRequestConfig } from "next-intl/server";
+
+import { isLocaleSupported } from ".";
+import type { SupportedLanguage } from "./config";
+import { createLanguageMapping } from "./mapping";
+import { routing } from "./routing";
+
+// This file is referenced in the `next.config.js` file. See https://next-intl-docs.vercel.app/docs/usage/configuration
+export default getRequestConfig(async ({ requestLocale }) => {
+ let currentLocale = await requestLocale;
+
+ if (!currentLocale || !isLocaleSupported(currentLocale)) {
+ currentLocale = routing.defaultLocale;
+ }
+ const typedLocale = currentLocale as SupportedLanguage;
+
+ const languageMap = createLanguageMapping();
+ const currentMessages = (await languageMap[typedLocale]()).default;
+
+ // Fallback to default locale if the current locales messages if not all messages are present
+ if (currentLocale !== routing.defaultLocale) {
+ const fallbackMessages = (await languageMap[routing.defaultLocale]()).default;
+ return {
+ locale: currentLocale,
+ messages: deepmerge(fallbackMessages, currentMessages),
+ };
+ }
+
+ return {
+ locale: currentLocale,
+ messages: currentMessages,
+ };
+});
diff --git a/packages/translation/src/routing.ts b/packages/translation/src/routing.ts
new file mode 100644
index 000000000..a7e171bc5
--- /dev/null
+++ b/packages/translation/src/routing.ts
@@ -0,0 +1,11 @@
+import { defineRouting } from "next-intl/routing";
+
+import { defaultLocale, supportedLanguages } from "./config";
+
+export const routing = defineRouting({
+ locales: supportedLanguages,
+ defaultLocale,
+ localePrefix: {
+ mode: "never", // Rewrite the URL with locale parameter but without shown in url
+ },
+});
diff --git a/packages/translation/src/server.ts b/packages/translation/src/server.ts
index c7b32793a..bfab90719 100644
--- a/packages/translation/src/server.ts
+++ b/packages/translation/src/server.ts
@@ -1,8 +1,8 @@
-import { createI18nServer } from "next-international/server";
+import { getTranslations } from "next-intl/server";
-import { languageMapping } from "./lang";
-import enTranslation from "./lang/en";
+export const { getI18n, getScopedI18n } = {
+ getI18n: getTranslations,
+ getScopedI18n: getTranslations,
+};
-export const { getI18n, getScopedI18n, getStaticParams } = createI18nServer(languageMapping(), {
- fallbackLocale: enTranslation,
-});
+export { getMessages as getI18nMessages } from "next-intl/server";
diff --git a/packages/translation/src/type.ts b/packages/translation/src/type.ts
index e2baf031f..6057069f0 100644
--- a/packages/translation/src/type.ts
+++ b/packages/translation/src/type.ts
@@ -1,9 +1,19 @@
+import type { NamespaceKeys, NestedKeyOf } from "next-intl";
+
+import type { RemoveReadonly } from "@homarr/common/types";
+
import type { useI18n, useScopedI18n } from "./client";
import type enTranslation from "./lang/en";
-export type TranslationFunction = ReturnType;
-export type ScopedTranslationFunction[0]> = ReturnType<
- typeof useScopedI18n
->;
+export type TranslationFunction = ReturnType>;
+export type ScopedTranslationFunction<
+ NestedKey extends NamespaceKeys> = never,
+> = ReturnType>;
export type TranslationObject = typeof enTranslation;
export type stringOrTranslation = string | ((t: TranslationFunction) => string);
+
+declare global {
+ // Use type safe message keys with `next-intl`
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
+ interface IntlMessages extends RemoveReadonly {}
+}
diff --git a/packages/ui/package.json b/packages/ui/package.json
index e7c275d94..5399b0f18 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -31,7 +31,7 @@
"@mantine/core": "^7.13.4",
"@mantine/dates": "^7.13.4",
"@mantine/hooks": "^7.13.4",
- "@tabler/icons-react": "^3.20.0",
+ "@tabler/icons-react": "^3.21.0",
"mantine-react-table": "2.0.0-beta.7",
"next": "^14.2.16",
"react": "^18.3.1"
diff --git a/packages/ui/src/components/beta-badge.tsx b/packages/ui/src/components/beta-badge.tsx
index 4c7381196..8d9d36615 100644
--- a/packages/ui/src/components/beta-badge.tsx
+++ b/packages/ui/src/components/beta-badge.tsx
@@ -1,14 +1,16 @@
+"use client";
+
import type { BadgeProps } from "@mantine/core";
import { Badge } from "@mantine/core";
-import { useI18n } from "@homarr/translation/client";
+import { useTranslations } from "@homarr/translation/client";
interface BetaBadgeProps {
size: BadgeProps["size"];
}
export const BetaBadge = ({ size }: BetaBadgeProps) => {
- const t = useI18n();
+ const t = useTranslations();
return (
{t("common.beta")}
diff --git a/packages/ui/src/hooks/use-translated-mantine-react-table.ts b/packages/ui/src/hooks/use-translated-mantine-react-table.ts
index 1be41a63b..275f48b75 100644
--- a/packages/ui/src/hooks/use-translated-mantine-react-table.ts
+++ b/packages/ui/src/hooks/use-translated-mantine-react-table.ts
@@ -1,22 +1,14 @@
import type { MRT_RowData, MRT_TableOptions } from "mantine-react-table";
import { useMantineReactTable } from "mantine-react-table";
-import { MRT_Localization_EN } from "mantine-react-table/locales/en/index.cjs";
-import { objectKeys } from "@homarr/common";
-import { useScopedI18n } from "@homarr/translation/client";
+import { useI18nMessages } from "@homarr/translation/client";
export const useTranslatedMantineReactTable = (
tableOptions: Omit, "localization">,
) => {
- const t = useScopedI18n("common.mantineReactTable");
+ const messages = useI18nMessages();
return useMantineReactTable({
...tableOptions,
- localization: objectKeys(MRT_Localization_EN).reduce(
- (acc, key) => {
- acc[key] = t(key);
- return acc;
- },
- {} as typeof MRT_Localization_EN,
- ),
+ localization: messages.common.mantineReactTable,
});
};
diff --git a/packages/validation/src/form/i18n.ts b/packages/validation/src/form/i18n.ts
index c057fad57..db53d1e95 100644
--- a/packages/validation/src/form/i18n.ts
+++ b/packages/validation/src/form/i18n.ts
@@ -1,15 +1,9 @@
-import type { ParamsObject } from "international-types";
import type { ErrorMapCtx, z, ZodTooBigIssue, ZodTooSmallIssue } from "zod";
import { ZodIssueCode } from "zod";
-import type { TranslationObject } from "@homarr/translation";
+import type { TranslationFunction, TranslationObject } from "@homarr/translation";
-export const zodErrorMap = <
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- TFunction extends (key: string, ...params: any[]) => string,
->(
- t: TFunction,
-) => {
+export const zodErrorMap = (t: TFunction) => {
return (issue: z.ZodIssueOptionalMessage, ctx: ErrorMapCtx) => {
const error = handleZodError(issue, ctx);
if ("message" in error && error.message) {
@@ -139,7 +133,7 @@ type CustomErrorKey = keyof TranslationObject["common"]["zod"]["errors"]["custom
export interface CustomErrorParams {
i18n: {
key: TKey;
- params: ParamsObject;
+ params: Record;
};
}
diff --git a/packages/validation/src/index.ts b/packages/validation/src/index.ts
index 2cd11284d..dd218ff7c 100644
--- a/packages/validation/src/index.ts
+++ b/packages/validation/src/index.ts
@@ -5,6 +5,7 @@ import { groupSchemas } from "./group";
import { iconsSchemas } from "./icons";
import { integrationSchemas } from "./integration";
import { locationSchemas } from "./location";
+import { mediaSchemas } from "./media";
import { searchEngineSchemas } from "./search-engine";
import { userSchemas } from "./user";
import { widgetSchemas } from "./widgets";
@@ -19,6 +20,7 @@ export const validation = {
location: locationSchemas,
icons: iconsSchemas,
searchEngine: searchEngineSchemas,
+ media: mediaSchemas,
common: commonSchemas,
};
@@ -32,3 +34,4 @@ export {
type BoardItemIntegration,
} from "./shared";
export { passwordRequirements } from "./user";
+export { supportedMediaUploadFormats } from "./media";
diff --git a/packages/validation/src/media.ts b/packages/validation/src/media.ts
new file mode 100644
index 000000000..d18e87589
--- /dev/null
+++ b/packages/validation/src/media.ts
@@ -0,0 +1,44 @@
+import type { z } from "zod";
+import { zfd } from "zod-form-data";
+
+import { createCustomErrorParams } from "./form/i18n";
+
+export const supportedMediaUploadFormats = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"];
+
+export const uploadMediaSchema = zfd.formData({
+ file: zfd.file().superRefine((value: File | null, context: z.RefinementCtx) => {
+ if (!value) {
+ return context.addIssue({
+ code: "invalid_type",
+ expected: "object",
+ received: "null",
+ });
+ }
+
+ if (!supportedMediaUploadFormats.includes(value.type)) {
+ return context.addIssue({
+ code: "custom",
+ params: createCustomErrorParams({
+ key: "invalidFileType",
+ params: { expected: `one of ${supportedMediaUploadFormats.join(", ")}` },
+ }),
+ });
+ }
+
+ if (value.size > 1024 * 1024 * 32) {
+ return context.addIssue({
+ code: "custom",
+ params: createCustomErrorParams({
+ key: "fileTooLarge",
+ params: { maxSize: "32 MB" },
+ }),
+ });
+ }
+
+ return null;
+ }),
+});
+
+export const mediaSchemas = {
+ uploadMedia: uploadMediaSchema,
+};
diff --git a/packages/validation/src/user.ts b/packages/validation/src/user.ts
index 566e43363..65bac9500 100644
--- a/packages/validation/src/user.ts
+++ b/packages/validation/src/user.ts
@@ -30,7 +30,10 @@ const passwordSchema = z
return passwordRequirements.every((requirement) => requirement.check(value));
},
{
- params: createCustomErrorParams("passwordRequirements"),
+ params: createCustomErrorParams({
+ key: "passwordRequirements",
+ params: {},
+ }),
},
);
@@ -38,7 +41,10 @@ const confirmPasswordRefine = [
(data: { password: string; confirmPassword: string }) => data.password === data.confirmPassword,
{
path: ["confirmPassword"],
- params: createCustomErrorParams("passwordsDoNotMatch"),
+ params: createCustomErrorParams({
+ key: "passwordsDoNotMatch",
+ params: {},
+ }),
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
] satisfies [(args: any) => boolean, unknown];
diff --git a/packages/widgets/package.json b/packages/widgets/package.json
index 4716fc5e5..76cabdb3a 100644
--- a/packages/widgets/package.json
+++ b/packages/widgets/package.json
@@ -40,7 +40,7 @@
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^7.13.4",
"@mantine/hooks": "^7.13.4",
- "@tabler/icons-react": "^3.20.0",
+ "@tabler/icons-react": "^3.21.0",
"@tiptap/extension-color": "2.9.1",
"@tiptap/extension-highlight": "2.9.1",
"@tiptap/extension-image": "2.9.1",
diff --git a/packages/widgets/src/_inputs/widget-app-input.tsx b/packages/widgets/src/_inputs/widget-app-input.tsx
index ee22b08da..fd3cc0599 100644
--- a/packages/widgets/src/_inputs/widget-app-input.tsx
+++ b/packages/widgets/src/_inputs/widget-app-input.tsx
@@ -43,8 +43,8 @@ export const WidgetAppInput = ({ property, kind }: CommonWidgetInputProps<"app">
inputWrapperOrder={["label", "input", "description", "error"]}
description={
- {t("widget.common.app.description", {
- here: (
+ {t.rich("widget.common.app.description", {
+ here: () => (
{t("common.here")}
diff --git a/packages/widgets/src/import.ts b/packages/widgets/src/import.ts
index 2868bb32e..911871a38 100644
--- a/packages/widgets/src/import.ts
+++ b/packages/widgets/src/import.ts
@@ -1,5 +1,3 @@
import type { WidgetKind } from "@homarr/definitions";
-export type WidgetImportRecord = {
- [K in WidgetKind]: unknown;
-};
+export type WidgetImportRecord = Record;
diff --git a/packages/widgets/src/test/translation.spec.ts b/packages/widgets/src/test/translation.spec.ts
index 5415fefcc..967c5de85 100644
--- a/packages/widgets/src/test/translation.spec.ts
+++ b/packages/widgets/src/test/translation.spec.ts
@@ -1,12 +1,12 @@
import { describe, expect, it } from "vitest";
import { objectEntries } from "@homarr/common";
-import { languageMapping } from "@homarr/translation";
+import { createLanguageMapping } from "@homarr/translation";
import { widgetImports } from "..";
describe("Widget properties with description should have matching translations", async () => {
- const enTranslation = await languageMapping().en();
+ const enTranslation = await createLanguageMapping().en();
objectEntries(widgetImports).forEach(([key, value]) => {
Object.entries(value.definition.options).forEach(
([optionKey, optionValue]: [string, { withDescription?: boolean }]) => {
@@ -25,7 +25,7 @@ describe("Widget properties with description should have matching translations",
});
describe("Widget properties should have matching name translations", async () => {
- const enTranslation = await languageMapping().en();
+ const enTranslation = await createLanguageMapping().en();
objectEntries(widgetImports).forEach(([key, value]) => {
Object.keys(value.definition.options).forEach((optionKey) => {
it(`should have matching translations for ${optionKey} option name of ${key} widget`, () => {
diff --git a/packages/widgets/src/widget-integration-select.tsx b/packages/widgets/src/widget-integration-select.tsx
index 3aa27fcd6..215b1ccf2 100644
--- a/packages/widgets/src/widget-integration-select.tsx
+++ b/packages/widgets/src/widget-integration-select.tsx
@@ -92,8 +92,8 @@ export const WidgetIntegrationSelect = ({
inputWrapperOrder={["label", "input", "description", "error"]}
description={
- {t("widget.common.integration.description", {
- here: (
+ {t.rich("widget.common.integration.description", {
+ here: () => (
{t("common.here")}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 92e2f6f9a..58225a680 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -18,16 +18,16 @@ importers:
version: link:tooling/prettier
'@turbo/gen':
specifier: ^2.2.3
- version: 2.2.3(@types/node@20.17.1)(typescript@5.6.3)
+ version: 2.2.3(@types/node@22.8.6)(typescript@5.6.3)
'@vitejs/plugin-react':
specifier: ^4.3.3
- version: 4.3.3(vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))
+ version: 4.3.3(vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))
'@vitest/coverage-v8':
- specifier: ^2.1.3
- version: 2.1.3(vitest@2.1.3)
+ specifier: ^2.1.4
+ version: 2.1.4(vitest@2.1.4)
'@vitest/ui':
- specifier: ^2.1.3
- version: 2.1.3(vitest@2.1.3)
+ specifier: ^2.1.4
+ version: 2.1.4(vitest@2.1.4)
cross-env:
specifier: ^7.0.3
version: 7.0.3
@@ -48,10 +48,10 @@ importers:
version: 5.6.3
vite-tsconfig-paths:
specifier: ^5.0.1
- version: 5.0.1(typescript@5.6.3)(vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))
+ version: 5.0.1(typescript@5.6.3)(vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))
vitest:
- specifier: ^2.1.3
- version: 2.1.3(@types/node@20.17.1)(@vitest/ui@2.1.3)(jsdom@25.0.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ specifier: ^2.1.4
+ version: 2.1.4(@types/node@22.8.6)(@vitest/ui@2.1.4)(jsdom@25.0.1)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
apps/nextjs:
dependencies:
@@ -143,8 +143,8 @@ importers:
specifier: ^0.11.1
version: 0.11.1(typescript@5.6.3)(zod@3.23.8)
'@tabler/icons-react':
- specifier: ^3.20.0
- version: 3.20.0(react@18.3.1)
+ specifier: ^3.21.0
+ version: 3.21.0(react@18.3.1)
'@tanstack/react-query':
specifier: ^5.59.16
version: 5.59.16(react@18.3.1)
@@ -153,19 +153,19 @@ importers:
version: 5.59.16(@tanstack/react-query@5.59.16(react@18.3.1))(react@18.3.1)
'@tanstack/react-query-next-experimental':
specifier: 5.59.16
- version: 5.59.16(@tanstack/react-query@5.59.16(react@18.3.1))(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4))(react@18.3.1)
+ version: 5.59.16(@tanstack/react-query@5.59.16(react@18.3.1))(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react@18.3.1)
'@trpc/client':
specifier: next
- version: 11.0.0-rc.593(@trpc/server@11.0.0-rc.593)
+ version: 11.0.0-rc.608(@trpc/server@11.0.0-rc.608)
'@trpc/next':
specifier: next
- version: 11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/react-query@11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@trpc/server@11.0.0-rc.593)(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/react-query@11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@trpc/server@11.0.0-rc.608)(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@trpc/react-query':
specifier: next
- version: 11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@trpc/server':
specifier: next
- version: 11.0.0-rc.593
+ version: 11.0.0-rc.608
'@xterm/addon-canvas':
specifier: ^0.7.0
version: 0.7.0(@xterm/xterm@5.5.0)
@@ -198,10 +198,10 @@ importers:
version: 2.10.1(@types/react@18.3.12)(react@18.3.1)
mantine-react-table:
specifier: 2.0.0-beta.7
- version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.20.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.21.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
postcss-preset-mantine:
specifier: ^1.17.0
version: 1.17.0(postcss@8.4.47)
@@ -221,8 +221,8 @@ importers:
specifier: ^0.14.1
version: 0.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
sass:
- specifier: ^1.80.4
- version: 1.80.4
+ specifier: ^1.80.5
+ version: 1.80.5
superjson:
specifier: 2.2.1
version: 2.2.1
@@ -246,8 +246,8 @@ importers:
specifier: 2.4.4
version: 2.4.4
'@types/node':
- specifier: ^20.17.1
- version: 20.17.1
+ specifier: ^22.8.6
+ version: 22.8.6
'@types/prismjs':
specifier: ^1.26.5
version: 1.26.5
@@ -346,8 +346,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
'@types/node':
- specifier: ^20.17.1
- version: 20.17.1
+ specifier: ^22.8.6
+ version: 22.8.6
dotenv-cli:
specifier: ^7.4.2
version: 7.4.2
@@ -358,8 +358,8 @@ importers:
specifier: ^3.3.3
version: 3.3.3
tsx:
- specifier: 4.19.1
- version: 4.19.1
+ specifier: 4.19.2
+ version: 4.19.2
typescript:
specifier: ^5.6.3
version: 5.6.3
@@ -394,8 +394,8 @@ importers:
specifier: ^16.4.5
version: 16.4.5
tsx:
- specifier: 4.19.1
- version: 4.19.1
+ specifier: 4.19.2
+ version: 4.19.2
ws:
specifier: ^8.18.0
version: 8.18.0
@@ -505,19 +505,19 @@ importers:
version: link:../validation
'@trpc/client':
specifier: next
- version: 11.0.0-rc.593(@trpc/server@11.0.0-rc.593)
+ version: 11.0.0-rc.608(@trpc/server@11.0.0-rc.608)
'@trpc/react-query':
specifier: next
- version: 11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@trpc/server':
specifier: next
- version: 11.0.0-rc.593
+ version: 11.0.0-rc.608
dockerode:
specifier: ^4.0.2
version: 4.0.2
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -526,7 +526,7 @@ importers:
version: 2.2.1
trpc-swagger:
specifier: ^1.2.6
- version: 1.2.6(patch_hash=6s72z7zx33c52iesv5sewipn6i)(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(zod@3.23.8)
+ version: 1.2.6(patch_hash=6s72z7zx33c52iesv5sewipn6i)(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(zod@3.23.8)
devDependencies:
'@homarr/eslint-config':
specifier: workspace:^0.2.0
@@ -587,10 +587,10 @@ importers:
version: 7.2.1
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
next-auth:
specifier: 5.0.0-beta.25
- version: 5.0.0-beta.25(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4))(react@18.3.1)
+ version: 5.0.0-beta.25(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react@18.3.1)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -626,8 +626,8 @@ importers:
packages/cli:
dependencies:
'@drizzle-team/brocli':
- specifier: ^0.10.1
- version: 0.10.1
+ specifier: ^0.10.2
+ version: 0.10.2
'@homarr/auth':
specifier: workspace:^0.1.0
version: link:../auth
@@ -667,13 +667,13 @@ importers:
version: 1.11.13
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react:
specifier: ^18.3.1
version: 18.3.1
tldts:
- specifier: ^6.1.55
- version: 6.1.55
+ specifier: ^6.1.57
+ version: 6.1.57
devDependencies:
'@homarr/eslint-config':
specifier: workspace:^0.2.0
@@ -860,11 +860,11 @@ importers:
specifier: ^16.4.5
version: 16.4.5
drizzle-kit:
- specifier: ^0.26.2
- version: 0.26.2
+ specifier: ^0.27.1
+ version: 0.27.1
drizzle-orm:
- specifier: ^0.35.3
- version: 0.35.3(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.11)(@types/react@18.3.12)(better-sqlite3@11.5.0)(mysql2@3.11.3)(react@18.3.1)
+ specifier: ^0.36.0
+ version: 0.36.0(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.11)(@types/react@18.3.12)(better-sqlite3@11.5.0)(mysql2@3.11.3)(react@18.3.1)
mysql2:
specifier: 3.11.3
version: 3.11.3
@@ -891,8 +891,8 @@ importers:
specifier: ^3.3.3
version: 3.3.3
tsx:
- specifier: 4.19.1
- version: 4.19.1
+ specifier: 4.19.2
+ version: 4.19.2
typescript:
specifier: ^5.6.3
version: 5.6.3
@@ -1002,8 +1002,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../validation
'@jellyfin/sdk':
- specifier: ^0.10.0
- version: 0.10.0(axios@1.7.7)
+ specifier: ^0.11.0
+ version: 0.11.0(axios@1.7.7)
xml2js:
specifier: ^0.6.2
version: 0.6.2
@@ -1122,14 +1122,14 @@ importers:
specifier: ^7.13.4
version: 7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@tabler/icons-react':
- specifier: ^3.20.0
- version: 3.20.0(react@18.3.1)
+ specifier: ^3.21.0
+ version: 3.21.0(react@18.3.1)
dayjs:
specifier: ^1.11.13
version: 1.11.13
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -1159,8 +1159,8 @@ importers:
specifier: ^7.13.4
version: 7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@tabler/icons-react':
- specifier: ^3.20.0
- version: 3.20.0(react@18.3.1)
+ specifier: ^3.21.0
+ version: 3.21.0(react@18.3.1)
devDependencies:
'@homarr/eslint-config':
specifier: workspace:^0.2.0
@@ -1356,14 +1356,14 @@ importers:
specifier: ^7.13.4
version: 7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@tabler/icons-react':
- specifier: ^3.20.0
- version: 3.20.0(react@18.3.1)
+ specifier: ^3.21.0
+ version: 3.21.0(react@18.3.1)
jotai:
specifier: ^2.10.1
version: 2.10.1(@types/react@18.3.12)(react@18.3.1)
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -1389,15 +1389,24 @@ importers:
packages/translation:
dependencies:
+ '@homarr/common':
+ specifier: workspace:^0.1.0
+ version: link:../common
dayjs:
specifier: ^1.11.13
version: 1.11.13
mantine-react-table:
specifier: 2.0.0-beta.7
- version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.20.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- next-international:
- specifier: ^1.2.4
- version: 1.2.4
+ version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.21.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ next:
+ specifier: ^14.2.16
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
+ next-intl:
+ specifier: 3.24.0
+ version: 3.24.0(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react@18.3.1)
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
devDependencies:
'@homarr/eslint-config':
specifier: workspace:^0.2.0
@@ -1442,14 +1451,14 @@ importers:
specifier: ^7.13.4
version: 7.13.4(react@18.3.1)
'@tabler/icons-react':
- specifier: ^3.20.0
- version: 3.20.0(react@18.3.1)
+ specifier: ^3.21.0
+ version: 3.21.0(react@18.3.1)
mantine-react-table:
specifier: 2.0.0-beta.7
- version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.20.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.21.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -1561,8 +1570,8 @@ importers:
specifier: ^7.13.4
version: 7.13.4(react@18.3.1)
'@tabler/icons-react':
- specifier: ^3.20.0
- version: 3.20.0(react@18.3.1)
+ specifier: ^3.21.0
+ version: 3.21.0(react@18.3.1)
'@tiptap/extension-color':
specifier: 2.9.1
version: 2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))(@tiptap/extension-text-style@2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1)))
@@ -1616,10 +1625,10 @@ importers:
version: 1.11.13
mantine-react-table:
specifier: 2.0.0-beta.7
- version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.20.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.21.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next:
specifier: ^14.2.16
- version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ version: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -1659,10 +1668,10 @@ importers:
version: 2.2.3(eslint@9.13.0)
eslint-plugin-import:
specifier: ^2.31.0
- version: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0)
+ version: 2.31.0(@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0)
eslint-plugin-jsx-a11y:
- specifier: ^6.10.1
- version: 6.10.1(eslint@9.13.0)
+ specifier: ^6.10.2
+ version: 6.10.2(eslint@9.13.0)
eslint-plugin-react:
specifier: ^7.37.2
version: 7.37.2(eslint@9.13.0)
@@ -1670,8 +1679,8 @@ importers:
specifier: ^5.0.0
version: 5.0.0(eslint@9.13.0)
typescript-eslint:
- specifier: ^8.11.0
- version: 8.11.0(eslint@9.13.0)(typescript@5.6.3)
+ specifier: ^8.12.2
+ version: 8.12.2(eslint@9.13.0)(typescript@5.6.3)
devDependencies:
'@homarr/prettier-config':
specifier: workspace:^0.1.0
@@ -1890,8 +1899,8 @@ packages:
'@dabh/diagnostics@2.0.3':
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
- '@drizzle-team/brocli@0.10.1':
- resolution: {integrity: sha512-AHy0vjc+n/4w/8Mif+w86qpppHuF3AyXbcWW+R/W7GNA3F5/p2nuhlkCJaTXSLZheB4l1rtHzOfr9A7NwoR/Zg==}
+ '@drizzle-team/brocli@0.10.2':
+ resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
'@esbuild-kit/core-utils@3.3.2':
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
@@ -2654,6 +2663,21 @@ packages:
'@floating-ui/utils@0.2.8':
resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==}
+ '@formatjs/ecma402-abstract@2.2.0':
+ resolution: {integrity: sha512-IpM+ev1E4QLtstniOE29W1rqH9eTdx5hQdNL8pzrflMj/gogfaoONZqL83LUeQScHAvyMbpqP5C9MzNf+fFwhQ==}
+
+ '@formatjs/fast-memoize@2.2.1':
+ resolution: {integrity: sha512-XS2RcOSyWxmUB7BUjj3mlPH0exsUzlf6QfhhijgI941WaJhVxXQ6mEWkdUFIdnKi3TuTYxRdelsgv3mjieIGIA==}
+
+ '@formatjs/icu-messageformat-parser@2.8.0':
+ resolution: {integrity: sha512-r2un3fmF9oJv3mOkH+wwQZ037VpqmdfahbcCZ9Lh+p6Sx+sNsonI7Zcr6jNMm1s+Si7ejQORS4Ezlh05mMPAXA==}
+
+ '@formatjs/icu-skeleton-parser@1.8.4':
+ resolution: {integrity: sha512-LMQ1+Wk1QSzU4zpd5aSu7+w5oeYhupRwZnMQckLPRYhSjf2/8JWQ882BauY9NyHxs5igpuQIXZDgfkaH3PoATg==}
+
+ '@formatjs/intl-localematcher@0.5.5':
+ resolution: {integrity: sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==}
+
'@hapi/bourne@3.0.0':
resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
@@ -2702,8 +2726,8 @@ packages:
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
engines: {node: '>=8'}
- '@jellyfin/sdk@0.10.0':
- resolution: {integrity: sha512-fUUwiPOGQEFYxnS9olYkv7GXIX5N9JYdRBR8bapN86OhbHWzL1JHgWf/sAUcNTQGlCWMKTJqve4KFOQB1FlMAQ==}
+ '@jellyfin/sdk@0.11.0':
+ resolution: {integrity: sha512-WmM4as9ptqH+CvC2YsUefNWQDmu2aWIamwAoj7h2BFR6l019pcRFG5FT22egwbdizR6DfdpmsoAWB4x9QCzcEQ==}
peerDependencies:
axios: ^1.3.4
@@ -3210,13 +3234,13 @@ packages:
typescript:
optional: true
- '@tabler/icons-react@3.20.0':
- resolution: {integrity: sha512-a47oaL48bb5Cx/WUVfg/NZrsWwFExrcDQO8thUZ7S6h/OQYFu7sm4E5pZsmUtGCjikB3lRzjtmMD+C4s7mr9yw==}
+ '@tabler/icons-react@3.21.0':
+ resolution: {integrity: sha512-Qq0GnZzzccbv/zuMyXAUUPlogNAqx9KsF8cr/ev3bxs+GMObqNEjXv1eZl9GFzxyQTS435siJNU8A1BaIYhX8g==}
peerDependencies:
react: '>= 16'
- '@tabler/icons@3.20.0':
- resolution: {integrity: sha512-nXSeUzsCOxX/Of+kdUVQfxL9bG+ck8XCWNf9dGSpE+nhVexRwk/4HiDQDxFDysfT7vfgSut6GXnrZsU5M5dSlA==}
+ '@tabler/icons@3.21.0':
+ resolution: {integrity: sha512-5+GkkmWCr1wgMor5cOF1/YYflTQdc15y10FUikJ3HW8hDiFjfbuoAHJi17FT1vwsr1sA78rkJMn+fDoOOjnnPA==}
'@tanstack/match-sorter-utils@8.19.4':
resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==}
@@ -3467,19 +3491,19 @@ packages:
'@tootallnate/quickjs-emscripten@0.23.0':
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
- '@trpc/client@11.0.0-rc.593':
- resolution: {integrity: sha512-uQORhYMwUeY4TluQmhl6N183BiLZz5mgIzBynkSWKxtQ7TIHt+3iRzTSiJH1jTl3SEOtCacRHS6b1yvFP2RJXw==}
+ '@trpc/client@11.0.0-rc.608':
+ resolution: {integrity: sha512-ZvhYhewiXXo3Kfy7JazVShsJUJTyqgkEV1rjhioJ6r3aIGw0ZS6zyyjcq1w99DTIzRP//FgB239NG5c66Ki9sw==}
peerDependencies:
- '@trpc/server': 11.0.0-rc.593+f73cd3fd9
+ '@trpc/server': 11.0.0-rc.608+f75de97b3
- '@trpc/next@11.0.0-rc.593':
- resolution: {integrity: sha512-uNaDYBwf69OfcKcgebezKdQoWgG3uF2iLyZbEAtkYCgQXbRmvkRpHxvJbR6oBYdEiJRxJhDXx9sm4kKcoOqK6w==}
+ '@trpc/next@11.0.0-rc.608':
+ resolution: {integrity: sha512-dL+ifSaJIl+21P3LZ1JEl1uzqDD7pZ3iCs9uEnf3tjyZhbCuavnTL7faRDV6wZ6+L6opzKxIzeVNC4e490Ys0Q==}
peerDependencies:
'@tanstack/react-query': ^5.59.15
- '@trpc/client': 11.0.0-rc.593+f73cd3fd9
- '@trpc/react-query': 11.0.0-rc.593+f73cd3fd9
- '@trpc/server': 11.0.0-rc.593+f73cd3fd9
- next: '*'
+ '@trpc/client': 11.0.0-rc.608+f75de97b3
+ '@trpc/react-query': 11.0.0-rc.608+f75de97b3
+ '@trpc/server': 11.0.0-rc.608+f75de97b3
+ next: 15.0.2
react: '>=16.8.0'
react-dom: '>=16.8.0'
peerDependenciesMeta:
@@ -3488,17 +3512,17 @@ packages:
'@trpc/react-query':
optional: true
- '@trpc/react-query@11.0.0-rc.593':
- resolution: {integrity: sha512-T5abZpWKW+Ndk3SAGwXqRLnIXTpdiQd0OF5TqTGbE1RuAWVf6rOZJWSjxp0M16aypkc0uEDAUia912VnKhrOqA==}
+ '@trpc/react-query@11.0.0-rc.608':
+ resolution: {integrity: sha512-V0UJltzCfdn3PqePqbB8TK64aNXVBpdoLEC4OdMtTYiZTsAnH1jTwrNOBji3Xwm8Q0n4jaUDrIz5M/5IPjYrGg==}
peerDependencies:
'@tanstack/react-query': ^5.59.15
- '@trpc/client': 11.0.0-rc.593+f73cd3fd9
- '@trpc/server': 11.0.0-rc.593+f73cd3fd9
+ '@trpc/client': 11.0.0-rc.608+f75de97b3
+ '@trpc/server': 11.0.0-rc.608+f75de97b3
react: '>=18.2.0'
react-dom: '>=18.2.0'
- '@trpc/server@11.0.0-rc.593':
- resolution: {integrity: sha512-ihZNf7nM3OriZkkuOUFjuB51FJdtCXZUUj8FIXkq0VXF9VmMOD7j4QTl5YojIzMTJBMGUK9VADcO0shgELEmyw==}
+ '@trpc/server@11.0.0-rc.608':
+ resolution: {integrity: sha512-+qxeyWlS+1zlTbekG7C+khDGZn788kLJG+ufO8mH/kgbRC+/a0OZSk7tyQI2Pf+UWeKc6KzrTi7TRBOOEBBE1A==}
'@tsconfig/node10@1.0.11':
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
@@ -3616,8 +3640,8 @@ packages:
'@types/node@18.19.50':
resolution: {integrity: sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==}
- '@types/node@20.17.1':
- resolution: {integrity: sha512-j2VlPv1NnwPJbaCNv69FO/1z4lId0QmGvpT41YxitRtWlg96g/j8qcv2RKsLKe2F6OJgyXhupN1Xo17b2m139Q==}
+ '@types/node@22.8.6':
+ resolution: {integrity: sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==}
'@types/prismjs@1.26.5':
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
@@ -3685,8 +3709,8 @@ packages:
'@types/xml2js@0.4.14':
resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==}
- '@typescript-eslint/eslint-plugin@8.11.0':
- resolution: {integrity: sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==}
+ '@typescript-eslint/eslint-plugin@8.12.2':
+ resolution: {integrity: sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
@@ -3696,8 +3720,8 @@ packages:
typescript:
optional: true
- '@typescript-eslint/parser@8.11.0':
- resolution: {integrity: sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==}
+ '@typescript-eslint/parser@8.12.2':
+ resolution: {integrity: sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -3706,12 +3730,12 @@ packages:
typescript:
optional: true
- '@typescript-eslint/scope-manager@8.11.0':
- resolution: {integrity: sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==}
+ '@typescript-eslint/scope-manager@8.12.2':
+ resolution: {integrity: sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/type-utils@8.11.0':
- resolution: {integrity: sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==}
+ '@typescript-eslint/type-utils@8.12.2':
+ resolution: {integrity: sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '*'
@@ -3719,12 +3743,12 @@ packages:
typescript:
optional: true
- '@typescript-eslint/types@8.11.0':
- resolution: {integrity: sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==}
+ '@typescript-eslint/types@8.12.2':
+ resolution: {integrity: sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.11.0':
- resolution: {integrity: sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==}
+ '@typescript-eslint/typescript-estree@8.12.2':
+ resolution: {integrity: sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '*'
@@ -3732,14 +3756,14 @@ packages:
typescript:
optional: true
- '@typescript-eslint/utils@8.11.0':
- resolution: {integrity: sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==}
+ '@typescript-eslint/utils@8.12.2':
+ resolution: {integrity: sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
- '@typescript-eslint/visitor-keys@8.11.0':
- resolution: {integrity: sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==}
+ '@typescript-eslint/visitor-keys@8.12.2':
+ resolution: {integrity: sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@umami/node@0.4.0':
@@ -3768,23 +3792,22 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0
- '@vitest/coverage-v8@2.1.3':
- resolution: {integrity: sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==}
+ '@vitest/coverage-v8@2.1.4':
+ resolution: {integrity: sha512-FPKQuJfR6VTfcNMcGpqInmtJuVXFSCd9HQltYncfR01AzXhLucMEtQ5SinPdZxsT5x/5BK7I5qFJ5/ApGCmyTQ==}
peerDependencies:
- '@vitest/browser': 2.1.3
- vitest: 2.1.3
+ '@vitest/browser': 2.1.4
+ vitest: 2.1.4
peerDependenciesMeta:
'@vitest/browser':
optional: true
- '@vitest/expect@2.1.3':
- resolution: {integrity: sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==}
+ '@vitest/expect@2.1.4':
+ resolution: {integrity: sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==}
- '@vitest/mocker@2.1.3':
- resolution: {integrity: sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==}
+ '@vitest/mocker@2.1.4':
+ resolution: {integrity: sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==}
peerDependencies:
- '@vitest/spy': 2.1.3
- msw: ^2.3.5
+ msw: ^2.4.9
vite: ^5.0.0
peerDependenciesMeta:
msw:
@@ -3792,25 +3815,25 @@ packages:
vite:
optional: true
- '@vitest/pretty-format@2.1.3':
- resolution: {integrity: sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==}
+ '@vitest/pretty-format@2.1.4':
+ resolution: {integrity: sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==}
- '@vitest/runner@2.1.3':
- resolution: {integrity: sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==}
+ '@vitest/runner@2.1.4':
+ resolution: {integrity: sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==}
- '@vitest/snapshot@2.1.3':
- resolution: {integrity: sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==}
+ '@vitest/snapshot@2.1.4':
+ resolution: {integrity: sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==}
- '@vitest/spy@2.1.3':
- resolution: {integrity: sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==}
+ '@vitest/spy@2.1.4':
+ resolution: {integrity: sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==}
- '@vitest/ui@2.1.3':
- resolution: {integrity: sha512-2XwTrHVJw3t9NYES26LQUYy51ZB8W4bRPgqUH2Eyda3kIuOlYw1ZdPNU22qcVlUVx4WKgECFQOSXuopsczuVjQ==}
+ '@vitest/ui@2.1.4':
+ resolution: {integrity: sha512-Zd9e5oU063c+j9N9XzGJagCLNvG71x/2tOme3Js4JEZKX55zsgxhJwUgLI8hkN6NjMLpdJO8d7nVUUuPGAA58Q==}
peerDependencies:
- vitest: 2.1.3
+ vitest: 2.1.4
- '@vitest/utils@2.1.3':
- resolution: {integrity: sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==}
+ '@vitest/utils@2.1.4':
+ resolution: {integrity: sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==}
'@webassemblyjs/ast@1.12.1':
resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==}
@@ -4216,8 +4239,8 @@ packages:
caniuse-lite@1.0.30001660:
resolution: {integrity: sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==}
- chai@5.1.1:
- resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==}
+ chai@5.1.2:
+ resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==}
engines: {node: '>=12'}
chalk-scripts@1.2.8:
@@ -4674,16 +4697,16 @@ packages:
resolution: {integrity: sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==}
engines: {node: '>=4'}
- drizzle-kit@0.26.2:
- resolution: {integrity: sha512-cMq8omEKywjIy5KcqUo6LvEFxkl8/zYHsgYjFVXjmPWWtuW4blcz+YW9+oIhoaALgs2ebRjzXwsJgN9i6P49Dw==}
+ drizzle-kit@0.27.1:
+ resolution: {integrity: sha512-4BNA0T2blN+jW5wSwhtc+FIlCMuxYSMWCnYYdOBi5rttwq8aVXRUid0d0NCzcBKtZQSPZGAUxy+TXr7Q1OgEug==}
hasBin: true
- drizzle-orm@0.35.3:
- resolution: {integrity: sha512-Uv6N+b36x4BaZlxc96e+ag7RnMapBLGhc4SSi2F7RDwqYJipWjaU/P68RUp1FbW9r+mxoDp8nMz2Eece8PJxfA==}
+ drizzle-orm@0.36.0:
+ resolution: {integrity: sha512-6BETYPdKSR7cDHC0ZfqZk2VrKJ8n/Rfd3ajFPsAbc69gi87nwZ6oBA2wUGMELHA0tQE4kUKN0Ds00LUZQ6Z69A==}
peerDependencies:
'@aws-sdk/client-rds-data': '>=3'
'@cloudflare/workers-types': '>=3'
- '@electric-sql/pglite': '>=0.1.1'
+ '@electric-sql/pglite': '>=0.2.0'
'@libsql/client': '>=0.10.0'
'@libsql/client-wasm': '>=0.10.0'
'@neondatabase/serverless': '>=0.1'
@@ -4719,6 +4742,8 @@ packages:
optional: true
'@libsql/client':
optional: true
+ '@libsql/client-wasm':
+ optional: true
'@neondatabase/serverless':
optional: true
'@op-engineering/op-sqlite':
@@ -4938,8 +4963,8 @@ packages:
'@typescript-eslint/parser':
optional: true
- eslint-plugin-jsx-a11y@6.10.1:
- resolution: {integrity: sha512-zHByM9WTUMnfsDTafGXRiqxp6lFtNoSOWBY6FonVRn3A+BUwN1L/tdBXT40BcBJi0cZjOGTXZ0eD/rTG9fEJ0g==}
+ eslint-plugin-jsx-a11y@6.10.2:
+ resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
engines: {node: '>=4.0'}
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
@@ -5038,6 +5063,10 @@ packages:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
+ expect-type@1.1.0:
+ resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==}
+ engines: {node: '>=12.0.0'}
+
external-editor@3.1.0:
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
engines: {node: '>=4'}
@@ -5077,8 +5106,8 @@ packages:
fault@1.0.4:
resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==}
- fdir@6.3.0:
- resolution: {integrity: sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==}
+ fdir@6.4.2:
+ resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==}
peerDependencies:
picomatch: ^3 || ^4
peerDependenciesMeta:
@@ -5472,8 +5501,8 @@ packages:
resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
engines: {node: '>= 0.4'}
- international-types@0.8.1:
- resolution: {integrity: sha512-tajBCAHo4I0LIFlmQ9ZWfjMWVyRffzuvfbXCd6ssFt5u1Zw15DN0UBpVTItXdNa1ls+cpQt3Yw8+TxsfGF8JcA==}
+ intl-messageformat@10.7.1:
+ resolution: {integrity: sha512-xQuJW2WcyzNJZWUu5xTVPOmNSA1Sowuu/NKFdUid5Fxx/Yl6/s4DefTU/y7zy+irZLDmFGmTLtnM8FqpN05wlA==}
invariant@2.2.4:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
@@ -5881,6 +5910,9 @@ packages:
loupe@3.1.1:
resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==}
+ loupe@3.1.2:
+ resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
+
lower-case-first@1.0.2:
resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==}
@@ -5911,8 +5943,8 @@ packages:
m3u8-parser@7.2.0:
resolution: {integrity: sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==}
- magic-string@0.30.11:
- resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
+ magic-string@0.30.12:
+ resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==}
magicast@0.3.5:
resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
@@ -6101,6 +6133,10 @@ packages:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
+ negotiator@1.0.0:
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
+ engines: {node: '>= 0.6'}
+
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
@@ -6128,8 +6164,11 @@ packages:
nodemailer:
optional: true
- next-international@1.2.4:
- resolution: {integrity: sha512-JQvp+h2iSgA/t8hu5S/Lwow1ZErJutQRdpnplxjv4VTlCiND8T95fYih8BjkHcVhQbtM+Wu9Mb1CM32wD9hlWQ==}
+ next-intl@3.24.0:
+ resolution: {integrity: sha512-48X68QsI92grir2dH1W15yhyVnEjW4c9qmwNt+du+k6mI1QtlE6GyANWHoL4/leTixHv8knZ1y9B/Ys06gmKLg==}
+ peerDependencies:
+ next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0
next@14.2.16:
resolution: {integrity: sha512-LcO7WnFu6lYSvCzZoo1dB+IO0xXz5uEv52HF1IUN0IqVTUIZGHuuR10I5efiLadGt+4oZqTcNZyVVEem/TM5nA==}
@@ -6963,8 +7002,8 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- sass@1.80.4:
- resolution: {integrity: sha512-rhMQ2tSF5CsuuspvC94nPM9rToiAFw2h3JTrLlgmNw1MH79v8Cr3DH6KF6o6r+8oofY3iYVPUf66KzC8yuVN1w==}
+ sass@1.80.5:
+ resolution: {integrity: sha512-TQd2aoQl/+zsxRMEDSxVdpPIqeq9UFc6pr7PzkugiTx3VYCFPUaa3P4RrBQsqok4PO200Vkz0vXQBNlg7W907g==}
engines: {node: '>=14.0.0'}
hasBin: true
@@ -7008,9 +7047,6 @@ packages:
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
- server-only@0.0.1:
- resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
-
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
@@ -7067,9 +7103,9 @@ packages:
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
- sirv@2.0.4:
- resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
- engines: {node: '>= 10'}
+ sirv@3.0.0:
+ resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
+ engines: {node: '>=18'}
sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
@@ -7357,11 +7393,11 @@ packages:
tinycolor2@1.6.0:
resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==}
- tinyexec@0.3.0:
- resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==}
+ tinyexec@0.3.1:
+ resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==}
- tinyglobby@0.2.6:
- resolution: {integrity: sha512-NbBoFBpqfcgd1tCiO8Lkfdk+xrA7mlLR9zgvZcZWQQwU63XAfUePyd6wZBaU93Hqw347lHnwFzttAkemHzzz4g==}
+ tinyglobby@0.2.10:
+ resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==}
engines: {node: '>=12.0.0'}
tinygradient@1.1.5:
@@ -7385,11 +7421,11 @@ packages:
title-case@2.1.1:
resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==}
- tldts-core@6.1.55:
- resolution: {integrity: sha512-BL+BuKHHaOpntE5BGI6naXjULU6aRlgaYdfDHR3T/hdbNTWkWUZ9yuc11wGnwgpvRwlyUiIK+QohYK3olaVU6Q==}
+ tldts-core@6.1.57:
+ resolution: {integrity: sha512-lXnRhuQpx3zU9EONF9F7HfcRLvN1uRYUBIiKL+C/gehC/77XTU+Jye6ui86GA3rU6FjlJ0triD1Tkjt2F/2lEg==}
- tldts@6.1.55:
- resolution: {integrity: sha512-HxQR/9roQ07Pwc8RyyrJMAxRz5/ssoF3qIPPUiIo3zUt6yMdmYZjM2OZIFMiZ3jHyz9jrGHEHuQZrUhoc1LkDw==}
+ tldts@6.1.57:
+ resolution: {integrity: sha512-Oy7yDXK8meJl8vPMOldzA+MtueAJ5BrH4l4HXwZuj2AtfoQbLjmTJmjNWPUcAo+E/ibHn7QlqMS0BOcXJFJyHQ==}
hasBin: true
tmp@0.0.33:
@@ -7507,8 +7543,8 @@ packages:
resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==}
engines: {node: '>=0.6.x'}
- tsx@4.19.1:
- resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==}
+ tsx@4.19.2:
+ resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==}
engines: {node: '>=18.0.0'}
hasBin: true
@@ -7594,8 +7630,8 @@ packages:
types-ramda@0.30.1:
resolution: {integrity: sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA==}
- typescript-eslint@8.11.0:
- resolution: {integrity: sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA==}
+ typescript-eslint@8.12.2:
+ resolution: {integrity: sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '*'
@@ -7717,6 +7753,11 @@ packages:
peerDependencies:
react: '>=16.13'
+ use-intl@3.24.0:
+ resolution: {integrity: sha512-lmrARod7yjMYehbyY9xBLjjgnlNcJsl1UAltAPlgspRG7RH6H0JYaGo4C3PZW/BTy0Dgmcvcl8rH/VemzGIhgQ==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0
+
use-isomorphic-layout-effect@1.1.2:
resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==}
peerDependencies:
@@ -7787,8 +7828,8 @@ packages:
videojs-vtt.js@0.15.5:
resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==}
- vite-node@2.1.3:
- resolution: {integrity: sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==}
+ vite-node@2.1.4:
+ resolution: {integrity: sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
@@ -7831,15 +7872,15 @@ packages:
terser:
optional: true
- vitest@2.1.3:
- resolution: {integrity: sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==}
+ vitest@2.1.4:
+ resolution: {integrity: sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/node': ^18.0.0 || >=20.0.0
- '@vitest/browser': 2.1.3
- '@vitest/ui': 2.1.3
+ '@vitest/browser': 2.1.4
+ '@vitest/ui': 2.1.4
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -8335,7 +8376,7 @@ snapshots:
enabled: 2.0.0
kuler: 2.0.0
- '@drizzle-team/brocli@0.10.1': {}
+ '@drizzle-team/brocli@0.10.2': {}
'@esbuild-kit/core-utils@3.3.2':
dependencies:
@@ -8767,6 +8808,31 @@ snapshots:
'@floating-ui/utils@0.2.8': {}
+ '@formatjs/ecma402-abstract@2.2.0':
+ dependencies:
+ '@formatjs/fast-memoize': 2.2.1
+ '@formatjs/intl-localematcher': 0.5.5
+ tslib: 2.7.0
+
+ '@formatjs/fast-memoize@2.2.1':
+ dependencies:
+ tslib: 2.7.0
+
+ '@formatjs/icu-messageformat-parser@2.8.0':
+ dependencies:
+ '@formatjs/ecma402-abstract': 2.2.0
+ '@formatjs/icu-skeleton-parser': 1.8.4
+ tslib: 2.7.0
+
+ '@formatjs/icu-skeleton-parser@1.8.4':
+ dependencies:
+ '@formatjs/ecma402-abstract': 2.2.0
+ tslib: 2.7.0
+
+ '@formatjs/intl-localematcher@0.5.5':
+ dependencies:
+ tslib: 2.7.0
+
'@hapi/bourne@3.0.0': {}
'@homarr/gridstack@1.0.3': {}
@@ -8811,7 +8877,7 @@ snapshots:
'@istanbuljs/schema@0.1.3': {}
- '@jellyfin/sdk@0.10.0(axios@1.7.7)':
+ '@jellyfin/sdk@0.11.0(axios@1.7.7)':
dependencies:
axios: 1.7.7
@@ -8846,10 +8912,12 @@ snapshots:
dependencies:
'@libsql/core': 0.14.0
js-base64: 3.7.7
+ optional: true
'@libsql/core@0.14.0':
dependencies:
js-base64: 3.7.7
+ optional: true
'@mantine/colors-generator@7.13.4(chroma-js@3.1.2)':
dependencies:
@@ -9536,12 +9604,12 @@ snapshots:
optionalDependencies:
typescript: 5.6.3
- '@tabler/icons-react@3.20.0(react@18.3.1)':
+ '@tabler/icons-react@3.21.0(react@18.3.1)':
dependencies:
- '@tabler/icons': 3.20.0
+ '@tabler/icons': 3.21.0
react: 18.3.1
- '@tabler/icons@3.20.0': {}
+ '@tabler/icons@3.21.0': {}
'@tanstack/match-sorter-utils@8.19.4':
dependencies:
@@ -9557,10 +9625,10 @@ snapshots:
'@tanstack/react-query': 5.59.16(react@18.3.1)
react: 18.3.1
- '@tanstack/react-query-next-experimental@5.59.16(@tanstack/react-query@5.59.16(react@18.3.1))(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4))(react@18.3.1)':
+ '@tanstack/react-query-next-experimental@5.59.16(@tanstack/react-query@5.59.16(react@18.3.1))(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react@18.3.1)':
dependencies:
'@tanstack/react-query': 5.59.16(react@18.3.1)
- next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react: 18.3.1
'@tanstack/react-query@5.59.16(react@18.3.1)':
@@ -9799,30 +9867,30 @@ snapshots:
'@tootallnate/quickjs-emscripten@0.23.0': {}
- '@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593)':
+ '@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608)':
dependencies:
- '@trpc/server': 11.0.0-rc.593
+ '@trpc/server': 11.0.0-rc.608
- '@trpc/next@11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/react-query@11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@trpc/server@11.0.0-rc.593)(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ '@trpc/next@11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/react-query@11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@trpc/server@11.0.0-rc.608)(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
- '@trpc/client': 11.0.0-rc.593(@trpc/server@11.0.0-rc.593)
- '@trpc/server': 11.0.0-rc.593
- next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ '@trpc/client': 11.0.0-rc.608(@trpc/server@11.0.0-rc.608)
+ '@trpc/server': 11.0.0-rc.608
+ next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@tanstack/react-query': 5.59.16(react@18.3.1)
- '@trpc/react-query': 11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@trpc/react-query': 11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@trpc/react-query@11.0.0-rc.593(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ '@trpc/react-query@11.0.0-rc.608(@tanstack/react-query@5.59.16(react@18.3.1))(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/react-query': 5.59.16(react@18.3.1)
- '@trpc/client': 11.0.0-rc.593(@trpc/server@11.0.0-rc.593)
- '@trpc/server': 11.0.0-rc.593
+ '@trpc/client': 11.0.0-rc.608(@trpc/server@11.0.0-rc.608)
+ '@trpc/server': 11.0.0-rc.608
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- '@trpc/server@11.0.0-rc.593': {}
+ '@trpc/server@11.0.0-rc.608': {}
'@tsconfig/node10@1.0.11': {}
@@ -9834,7 +9902,7 @@ snapshots:
'@tsconfig/svelte@1.0.13': {}
- '@turbo/gen@2.2.3(@types/node@20.17.1)(typescript@5.6.3)':
+ '@turbo/gen@2.2.3(@types/node@22.8.6)(typescript@5.6.3)':
dependencies:
'@turbo/workspaces': 2.2.3
commander: 10.0.1
@@ -9844,7 +9912,7 @@ snapshots:
node-plop: 0.26.3
picocolors: 1.0.1
proxy-agent: 6.4.0
- ts-node: 10.9.2(@types/node@20.17.1)(typescript@5.6.3)
+ ts-node: 10.9.2(@types/node@22.8.6)(typescript@5.6.3)
update-check: 1.5.4
validate-npm-package-name: 5.0.1
transitivePeerDependencies:
@@ -9871,7 +9939,7 @@ snapshots:
'@types/asn1@0.2.4':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/babel__core@7.20.5':
dependencies:
@@ -9896,22 +9964,22 @@ snapshots:
'@types/bcrypt@5.0.2':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/better-sqlite3@7.6.11':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/chroma-js@2.4.4': {}
'@types/connect@3.4.38':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/cookie@0.6.0': {}
@@ -9920,7 +9988,7 @@ snapshots:
'@types/connect': 3.4.38
'@types/express': 4.17.21
'@types/keygrip': 1.0.6
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/css-font-loading-module@0.0.7': {}
@@ -9928,13 +9996,13 @@ snapshots:
'@types/docker-modem@3.0.6':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/ssh2': 1.15.1
'@types/dockerode@3.3.31':
dependencies:
'@types/docker-modem': 3.0.6
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/ssh2': 1.15.1
'@types/estree@1.0.5': {}
@@ -9943,7 +10011,7 @@ snapshots:
'@types/express-serve-static-core@4.19.5':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/qs': 6.9.16
'@types/range-parser': 1.2.7
'@types/send': 0.17.4
@@ -9958,7 +10026,7 @@ snapshots:
'@types/glob@7.2.0':
dependencies:
'@types/minimatch': 5.1.2
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/hast@2.3.10':
dependencies:
@@ -9987,7 +10055,7 @@ snapshots:
dependencies:
undici-types: 5.26.5
- '@types/node@20.17.1':
+ '@types/node@22.8.6':
dependencies:
undici-types: 6.19.8
@@ -10015,21 +10083,21 @@ snapshots:
'@types/send@0.17.4':
dependencies:
'@types/mime': 1.3.5
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/serve-static@1.15.7':
dependencies:
'@types/http-errors': 2.0.4
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/send': 0.17.4
'@types/ssh2-streams@0.1.12':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/ssh2@0.5.52':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/ssh2-streams': 0.1.12
'@types/ssh2@1.15.1':
@@ -10042,7 +10110,7 @@ snapshots:
'@types/through@0.0.33':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/tinycolor2@1.4.6': {}
@@ -10058,20 +10126,20 @@ snapshots:
'@types/ws@8.5.12':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
'@types/xml2js@0.4.14':
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
- '@typescript-eslint/eslint-plugin@8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0)(typescript@5.6.3)':
+ '@typescript-eslint/eslint-plugin@8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0)(typescript@5.6.3)':
dependencies:
'@eslint-community/regexpp': 4.11.1
- '@typescript-eslint/parser': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
- '@typescript-eslint/scope-manager': 8.11.0
- '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
- '@typescript-eslint/utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
- '@typescript-eslint/visitor-keys': 8.11.0
+ '@typescript-eslint/parser': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/scope-manager': 8.12.2
+ '@typescript-eslint/type-utils': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 8.12.2
eslint: 9.13.0
graphemer: 1.4.0
ignore: 5.3.2
@@ -10082,12 +10150,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3)':
+ '@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3)':
dependencies:
- '@typescript-eslint/scope-manager': 8.11.0
- '@typescript-eslint/types': 8.11.0
- '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3)
- '@typescript-eslint/visitor-keys': 8.11.0
+ '@typescript-eslint/scope-manager': 8.12.2
+ '@typescript-eslint/types': 8.12.2
+ '@typescript-eslint/typescript-estree': 8.12.2(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 8.12.2
debug: 4.3.7
eslint: 9.13.0
optionalDependencies:
@@ -10095,15 +10163,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.11.0':
+ '@typescript-eslint/scope-manager@8.12.2':
dependencies:
- '@typescript-eslint/types': 8.11.0
- '@typescript-eslint/visitor-keys': 8.11.0
+ '@typescript-eslint/types': 8.12.2
+ '@typescript-eslint/visitor-keys': 8.12.2
- '@typescript-eslint/type-utils@8.11.0(eslint@9.13.0)(typescript@5.6.3)':
+ '@typescript-eslint/type-utils@8.12.2(eslint@9.13.0)(typescript@5.6.3)':
dependencies:
- '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3)
- '@typescript-eslint/utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/typescript-estree': 8.12.2(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
debug: 4.3.7
ts-api-utils: 1.3.0(typescript@5.6.3)
optionalDependencies:
@@ -10112,12 +10180,12 @@ snapshots:
- eslint
- supports-color
- '@typescript-eslint/types@8.11.0': {}
+ '@typescript-eslint/types@8.12.2': {}
- '@typescript-eslint/typescript-estree@8.11.0(typescript@5.6.3)':
+ '@typescript-eslint/typescript-estree@8.12.2(typescript@5.6.3)':
dependencies:
- '@typescript-eslint/types': 8.11.0
- '@typescript-eslint/visitor-keys': 8.11.0
+ '@typescript-eslint/types': 8.12.2
+ '@typescript-eslint/visitor-keys': 8.12.2
debug: 4.3.7
fast-glob: 3.3.2
is-glob: 4.0.3
@@ -10129,20 +10197,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.11.0(eslint@9.13.0)(typescript@5.6.3)':
+ '@typescript-eslint/utils@8.12.2(eslint@9.13.0)(typescript@5.6.3)':
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0)
- '@typescript-eslint/scope-manager': 8.11.0
- '@typescript-eslint/types': 8.11.0
- '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3)
+ '@typescript-eslint/scope-manager': 8.12.2
+ '@typescript-eslint/types': 8.12.2
+ '@typescript-eslint/typescript-estree': 8.12.2(typescript@5.6.3)
eslint: 9.13.0
transitivePeerDependencies:
- supports-color
- typescript
- '@typescript-eslint/visitor-keys@8.11.0':
+ '@typescript-eslint/visitor-keys@8.12.2':
dependencies:
- '@typescript-eslint/types': 8.11.0
+ '@typescript-eslint/types': 8.12.2
eslint-visitor-keys: 3.4.3
'@umami/node@0.4.0': {}
@@ -10175,18 +10243,18 @@ snapshots:
global: 4.4.0
is-function: 1.0.2
- '@vitejs/plugin-react@4.3.3(vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))':
+ '@vitejs/plugin-react@4.3.3(vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))':
dependencies:
'@babel/core': 7.25.2
'@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2)
'@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2)
'@types/babel__core': 7.20.5
react-refresh: 0.14.2
- vite: 5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vite: 5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
transitivePeerDependencies:
- supports-color
- '@vitest/coverage-v8@2.1.3(vitest@2.1.3)':
+ '@vitest/coverage-v8@2.1.4(vitest@2.1.4)':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 0.2.3
@@ -10195,64 +10263,64 @@ snapshots:
istanbul-lib-report: 3.0.1
istanbul-lib-source-maps: 5.0.6
istanbul-reports: 3.1.7
- magic-string: 0.30.11
+ magic-string: 0.30.12
magicast: 0.3.5
std-env: 3.7.0
test-exclude: 7.0.1
tinyrainbow: 1.2.0
- vitest: 2.1.3(@types/node@20.17.1)(@vitest/ui@2.1.3)(jsdom@25.0.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vitest: 2.1.4(@types/node@22.8.6)(@vitest/ui@2.1.4)(jsdom@25.0.1)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
transitivePeerDependencies:
- supports-color
- '@vitest/expect@2.1.3':
+ '@vitest/expect@2.1.4':
dependencies:
- '@vitest/spy': 2.1.3
- '@vitest/utils': 2.1.3
- chai: 5.1.1
+ '@vitest/spy': 2.1.4
+ '@vitest/utils': 2.1.4
+ chai: 5.1.2
tinyrainbow: 1.2.0
- '@vitest/mocker@2.1.3(@vitest/spy@2.1.3)(vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))':
+ '@vitest/mocker@2.1.4(vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))':
dependencies:
- '@vitest/spy': 2.1.3
+ '@vitest/spy': 2.1.4
estree-walker: 3.0.3
- magic-string: 0.30.11
+ magic-string: 0.30.12
optionalDependencies:
- vite: 5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vite: 5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
- '@vitest/pretty-format@2.1.3':
+ '@vitest/pretty-format@2.1.4':
dependencies:
tinyrainbow: 1.2.0
- '@vitest/runner@2.1.3':
+ '@vitest/runner@2.1.4':
dependencies:
- '@vitest/utils': 2.1.3
+ '@vitest/utils': 2.1.4
pathe: 1.1.2
- '@vitest/snapshot@2.1.3':
+ '@vitest/snapshot@2.1.4':
dependencies:
- '@vitest/pretty-format': 2.1.3
- magic-string: 0.30.11
+ '@vitest/pretty-format': 2.1.4
+ magic-string: 0.30.12
pathe: 1.1.2
- '@vitest/spy@2.1.3':
+ '@vitest/spy@2.1.4':
dependencies:
tinyspy: 3.0.2
- '@vitest/ui@2.1.3(vitest@2.1.3)':
+ '@vitest/ui@2.1.4(vitest@2.1.4)':
dependencies:
- '@vitest/utils': 2.1.3
+ '@vitest/utils': 2.1.4
fflate: 0.8.2
flatted: 3.3.1
pathe: 1.1.2
- sirv: 2.0.4
- tinyglobby: 0.2.6
+ sirv: 3.0.0
+ tinyglobby: 0.2.10
tinyrainbow: 1.2.0
- vitest: 2.1.3(@types/node@20.17.1)(@vitest/ui@2.1.3)(jsdom@25.0.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vitest: 2.1.4(@types/node@22.8.6)(@vitest/ui@2.1.4)(jsdom@25.0.1)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
- '@vitest/utils@2.1.3':
+ '@vitest/utils@2.1.4':
dependencies:
- '@vitest/pretty-format': 2.1.3
- loupe: 3.1.1
+ '@vitest/pretty-format': 2.1.4
+ loupe: 3.1.2
tinyrainbow: 1.2.0
'@webassemblyjs/ast@1.12.1':
@@ -10733,7 +10801,7 @@ snapshots:
caniuse-lite@1.0.30001660: {}
- chai@5.1.1:
+ chai@5.1.2:
dependencies:
assertion-error: 2.0.1
check-error: 2.1.1
@@ -11193,19 +11261,18 @@ snapshots:
drange@1.1.1: {}
- drizzle-kit@0.26.2:
+ drizzle-kit@0.27.1:
dependencies:
- '@drizzle-team/brocli': 0.10.1
+ '@drizzle-team/brocli': 0.10.2
'@esbuild-kit/esm-loader': 2.6.5
esbuild: 0.19.12
esbuild-register: 3.6.0(esbuild@0.19.12)
transitivePeerDependencies:
- supports-color
- drizzle-orm@0.35.3(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.11)(@types/react@18.3.12)(better-sqlite3@11.5.0)(mysql2@3.11.3)(react@18.3.1):
- dependencies:
- '@libsql/client-wasm': 0.14.0
+ drizzle-orm@0.36.0(@libsql/client-wasm@0.14.0)(@types/better-sqlite3@7.6.11)(@types/react@18.3.12)(better-sqlite3@11.5.0)(mysql2@3.11.3)(react@18.3.1):
optionalDependencies:
+ '@libsql/client-wasm': 0.14.0
'@types/better-sqlite3': 7.6.11
'@types/react': 18.3.12
better-sqlite3: 11.5.0
@@ -11515,17 +11582,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
eslint: 9.13.0
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0):
+ eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@@ -11536,7 +11603,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.13.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -11548,13 +11615,13 @@ snapshots:
string.prototype.trimend: 1.0.8
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jsx-a11y@6.10.1(eslint@9.13.0):
+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.13.0):
dependencies:
aria-query: 5.3.2
array-includes: 3.1.8
@@ -11564,7 +11631,6 @@ snapshots:
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
- es-iterator-helpers: 1.1.0
eslint: 9.13.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
@@ -11705,6 +11771,8 @@ snapshots:
expand-template@2.0.3: {}
+ expect-type@1.1.0: {}
+
external-editor@3.1.0:
dependencies:
chardet: 0.7.0
@@ -11745,7 +11813,7 @@ snapshots:
dependencies:
format: 0.2.2
- fdir@6.3.0(picomatch@4.0.2):
+ fdir@6.4.2(picomatch@4.0.2):
optionalDependencies:
picomatch: 4.0.2
@@ -12169,7 +12237,12 @@ snapshots:
hasown: 2.0.2
side-channel: 1.0.6
- international-types@0.8.1: {}
+ intl-messageformat@10.7.1:
+ dependencies:
+ '@formatjs/ecma402-abstract': 2.2.0
+ '@formatjs/fast-memoize': 2.2.1
+ '@formatjs/icu-messageformat-parser': 2.8.0
+ tslib: 2.7.0
invariant@2.2.4:
dependencies:
@@ -12406,7 +12479,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -12417,7 +12490,8 @@ snapshots:
'@types/react': 18.3.12
react: 18.3.1
- js-base64@3.7.7: {}
+ js-base64@3.7.7:
+ optional: true
js-file-download@0.4.12: {}
@@ -12584,6 +12658,8 @@ snapshots:
dependencies:
get-func-name: 2.0.2
+ loupe@3.1.2: {}
+
lower-case-first@1.0.2:
dependencies:
lower-case: 1.1.4
@@ -12613,7 +12689,7 @@ snapshots:
'@videojs/vhs-utils': 4.1.1
global: 4.4.0
- magic-string@0.30.11:
+ magic-string@0.30.12:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
@@ -12633,12 +12709,12 @@ snapshots:
make-error@1.3.6: {}
- mantine-react-table@2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.20.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ mantine-react-table@2.0.0-beta.7(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(@tabler/icons-react@3.21.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@mantine/core': 7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mantine/dates': 7.13.4(@mantine/core@7.13.4(@mantine/hooks@7.13.4(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.13.4(react@18.3.1))(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mantine/hooks': 7.13.4(react@18.3.1)
- '@tabler/icons-react': 3.20.0(react@18.3.1)
+ '@tabler/icons-react': 3.21.0(react@18.3.1)
'@tanstack/match-sorter-utils': 8.19.4
'@tanstack/react-table': 8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@tanstack/react-virtual': 3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -12785,25 +12861,29 @@ snapshots:
negotiator@0.6.3: {}
+ negotiator@1.0.0: {}
+
neo-async@2.6.2: {}
neotraverse@0.6.18: {}
netmask@2.0.2: {}
- next-auth@5.0.0-beta.25(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4))(react@18.3.1):
+ next-auth@5.0.0-beta.25(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react@18.3.1):
dependencies:
'@auth/core': 0.37.2
- next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)
+ next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
react: 18.3.1
- next-international@1.2.4:
+ next-intl@3.24.0(next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5))(react@18.3.1):
dependencies:
- client-only: 0.0.1
- international-types: 0.8.1
- server-only: 0.0.1
+ '@formatjs/intl-localematcher': 0.5.5
+ negotiator: 1.0.0
+ next: 14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5)
+ react: 18.3.1
+ use-intl: 3.24.0(react@18.3.1)
- next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4):
+ next@14.2.16(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.5):
dependencies:
'@next/env': 14.2.16
'@swc/helpers': 0.5.5
@@ -12824,7 +12904,7 @@ snapshots:
'@next/swc-win32-arm64-msvc': 14.2.16
'@next/swc-win32-ia32-msvc': 14.2.16
'@next/swc-win32-x64-msvc': 14.2.16
- sass: 1.80.4
+ sass: 1.80.5
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@@ -12880,7 +12960,7 @@ snapshots:
node-mocks-http@1.16.0:
dependencies:
'@types/express': 4.17.21
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
accepts: 1.3.8
content-disposition: 0.5.4
depd: 1.1.2
@@ -13770,7 +13850,7 @@ snapshots:
safer-buffer@2.1.2: {}
- sass@1.80.4:
+ sass@1.80.5:
dependencies:
'@parcel/watcher': 2.4.1
chokidar: 4.0.0
@@ -13816,8 +13896,6 @@ snapshots:
dependencies:
randombytes: 2.1.0
- server-only@0.0.1: {}
-
set-blocking@2.0.0: {}
set-function-length@1.2.2:
@@ -13878,7 +13956,7 @@ snapshots:
dependencies:
is-arrayish: 0.3.2
- sirv@2.0.4:
+ sirv@3.0.0:
dependencies:
'@polka/url': 1.0.0-next.25
mrmime: 2.0.0
@@ -14270,11 +14348,11 @@ snapshots:
tinycolor2@1.6.0: {}
- tinyexec@0.3.0: {}
+ tinyexec@0.3.1: {}
- tinyglobby@0.2.6:
+ tinyglobby@0.2.10:
dependencies:
- fdir: 6.3.0(picomatch@4.0.2)
+ fdir: 6.4.2(picomatch@4.0.2)
picomatch: 4.0.2
tinygradient@1.1.5:
@@ -14297,11 +14375,11 @@ snapshots:
no-case: 2.3.2
upper-case: 1.1.3
- tldts-core@6.1.55: {}
+ tldts-core@6.1.57: {}
- tldts@6.1.55:
+ tldts@6.1.57:
dependencies:
- tldts-core: 6.1.55
+ tldts-core: 6.1.57
tmp@0.0.33:
dependencies:
@@ -14330,7 +14408,7 @@ snapshots:
tough-cookie@5.0.0:
dependencies:
- tldts: 6.1.55
+ tldts: 6.1.57
tr46@0.0.3: {}
@@ -14358,10 +14436,10 @@ snapshots:
triple-beam@1.4.1: {}
- trpc-swagger@1.2.6(patch_hash=6s72z7zx33c52iesv5sewipn6i)(@trpc/client@11.0.0-rc.593(@trpc/server@11.0.0-rc.593))(@trpc/server@11.0.0-rc.593)(zod@3.23.8):
+ trpc-swagger@1.2.6(patch_hash=6s72z7zx33c52iesv5sewipn6i)(@trpc/client@11.0.0-rc.608(@trpc/server@11.0.0-rc.608))(@trpc/server@11.0.0-rc.608)(zod@3.23.8):
dependencies:
- '@trpc/client': 11.0.0-rc.593(@trpc/server@11.0.0-rc.593)
- '@trpc/server': 11.0.0-rc.593
+ '@trpc/client': 11.0.0-rc.608(@trpc/server@11.0.0-rc.608)
+ '@trpc/server': 11.0.0-rc.608
chalk-scripts: 1.2.8
co-body: 6.2.0
lodash.clonedeep: 4.5.0
@@ -14376,14 +14454,14 @@ snapshots:
ts-mixer@6.0.4: {}
- ts-node@10.9.2(@types/node@20.17.1)(typescript@5.6.3):
+ ts-node@10.9.2(@types/node@22.8.6)(typescript@5.6.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
acorn: 8.12.1
acorn-walk: 8.3.4
arg: 4.1.3
@@ -14413,7 +14491,7 @@ snapshots:
tsscmp@1.0.6: {}
- tsx@4.19.1:
+ tsx@4.19.2:
dependencies:
esbuild: 0.23.1
get-tsconfig: 4.8.1
@@ -14508,11 +14586,11 @@ snapshots:
dependencies:
ts-toolbelt: 9.6.0
- typescript-eslint@8.11.0(eslint@9.13.0)(typescript@5.6.3):
+ typescript-eslint@8.12.2(eslint@9.13.0)(typescript@5.6.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0)(typescript@5.6.3)
- '@typescript-eslint/parser': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
- '@typescript-eslint/utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/eslint-plugin': 8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.13.0)(typescript@5.6.3))(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.12.2(eslint@9.13.0)(typescript@5.6.3)
optionalDependencies:
typescript: 5.6.3
transitivePeerDependencies:
@@ -14632,6 +14710,12 @@ snapshots:
dequal: 2.0.3
react: 18.3.1
+ use-intl@3.24.0(react@18.3.1):
+ dependencies:
+ '@formatjs/fast-memoize': 2.2.1
+ intl-messageformat: 10.7.1
+ react: 18.3.1
+
use-isomorphic-layout-effect@1.1.2(@types/react@18.3.12)(react@18.3.1):
dependencies:
react: 18.3.1
@@ -14695,12 +14779,12 @@ snapshots:
dependencies:
global: 4.4.0
- vite-node@2.1.3(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0):
+ vite-node@2.1.4(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0):
dependencies:
cac: 6.7.14
debug: 4.3.7
pathe: 1.1.2
- vite: 5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vite: 5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -14712,53 +14796,54 @@ snapshots:
- supports-color
- terser
- vite-tsconfig-paths@5.0.1(typescript@5.6.3)(vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)):
+ vite-tsconfig-paths@5.0.1(typescript@5.6.3)(vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)):
dependencies:
debug: 4.3.7
globrex: 0.1.2
tsconfck: 3.1.3(typescript@5.6.3)
optionalDependencies:
- vite: 5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vite: 5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
transitivePeerDependencies:
- supports-color
- typescript
- vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0):
+ vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0):
dependencies:
esbuild: 0.21.5
postcss: 8.4.47
rollup: 4.21.3
optionalDependencies:
- '@types/node': 20.17.1
+ '@types/node': 22.8.6
fsevents: 2.3.3
- sass: 1.80.4
+ sass: 1.80.5
sugarss: 4.0.1(postcss@8.4.47)
terser: 5.32.0
- vitest@2.1.3(@types/node@20.17.1)(@vitest/ui@2.1.3)(jsdom@25.0.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0):
+ vitest@2.1.4(@types/node@22.8.6)(@vitest/ui@2.1.4)(jsdom@25.0.1)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0):
dependencies:
- '@vitest/expect': 2.1.3
- '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))
- '@vitest/pretty-format': 2.1.3
- '@vitest/runner': 2.1.3
- '@vitest/snapshot': 2.1.3
- '@vitest/spy': 2.1.3
- '@vitest/utils': 2.1.3
- chai: 5.1.1
+ '@vitest/expect': 2.1.4
+ '@vitest/mocker': 2.1.4(vite@5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0))
+ '@vitest/pretty-format': 2.1.4
+ '@vitest/runner': 2.1.4
+ '@vitest/snapshot': 2.1.4
+ '@vitest/spy': 2.1.4
+ '@vitest/utils': 2.1.4
+ chai: 5.1.2
debug: 4.3.7
- magic-string: 0.30.11
+ expect-type: 1.1.0
+ magic-string: 0.30.12
pathe: 1.1.2
std-env: 3.7.0
tinybench: 2.9.0
- tinyexec: 0.3.0
+ tinyexec: 0.3.1
tinypool: 1.0.1
tinyrainbow: 1.2.0
- vite: 5.4.5(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
- vite-node: 2.1.3(@types/node@20.17.1)(sass@1.80.4)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vite: 5.4.5(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
+ vite-node: 2.1.4(@types/node@22.8.6)(sass@1.80.5)(sugarss@4.0.1(postcss@8.4.47))(terser@5.32.0)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 20.17.1
- '@vitest/ui': 2.1.3(vitest@2.1.3)
+ '@types/node': 22.8.6
+ '@vitest/ui': 2.1.4(vitest@2.1.4)
jsdom: 25.0.1
transitivePeerDependencies:
- less
diff --git a/tooling/eslint/package.json b/tooling/eslint/package.json
index fcae5e533..b9d146c5a 100644
--- a/tooling/eslint/package.json
+++ b/tooling/eslint/package.json
@@ -20,10 +20,10 @@
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^2.2.3",
"eslint-plugin-import": "^2.31.0",
- "eslint-plugin-jsx-a11y": "^6.10.1",
+ "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
- "typescript-eslint": "^8.11.0"
+ "typescript-eslint": "^8.12.2"
},
"devDependencies": {
"@homarr/prettier-config": "workspace:^0.1.0",