refactor: remove central validation export to improve typescript performance (#2810)

* refactor: remove central validation export to improve typescript performance

* fix: missing package exports change in validation package

* chore: address pull request feedback
This commit is contained in:
Meier Lukas
2025-04-06 12:37:28 +02:00
committed by GitHub
parent c1cd563048
commit 75ba3f2ae7
81 changed files with 450 additions and 582 deletions

View File

@@ -9,7 +9,7 @@ import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useScopedI18n } from "@homarr/translation/client";
import { CustomPasswordInput } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { userRegistrationSchema } from "@homarr/validation/user";
interface RegistrationFormProps {
invite: {
@@ -22,7 +22,7 @@ export const RegistrationForm = ({ invite }: RegistrationFormProps) => {
const t = useScopedI18n("user");
const router = useRouter();
const { mutate, isPending } = clientApi.user.register.useMutation();
const form = useZodForm(validation.user.registration, {
const form = useZodForm(userRegistrationSchema, {
initialValues: {
username: "",
password: "",
@@ -30,7 +30,7 @@ export const RegistrationForm = ({ invite }: RegistrationFormProps) => {
},
});
const handleSubmit = (values: z.infer<typeof validation.user.registration>) => {
const handleSubmit = (values: z.infer<typeof userRegistrationSchema>) => {
mutate(
{
...values,

View File

@@ -13,7 +13,7 @@ import type { useForm } from "@homarr/form";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useScopedI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { userSignInSchema } from "@homarr/validation/user";
interface LoginFormProps {
providers: string[];
@@ -22,7 +22,7 @@ interface LoginFormProps {
callbackUrl: string;
}
const extendedValidation = validation.user.signIn.extend({ provider: z.enum(["credentials", "ldap"]) });
const extendedValidation = userSignInSchema.extend({ provider: z.enum(["credentials", "ldap"]) });
export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, callbackUrl }: LoginFormProps) => {
const t = useScopedI18n("user");

View File

@@ -20,7 +20,7 @@ import { useDisclosure } from "@mantine/hooks";
import { useZodForm } from "@homarr/form";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { boardSavePartialSettingsSchema } from "@homarr/validation/board";
import type { Board } from "../../_types";
import { generateColors } from "../../(content)/_theme";
@@ -35,7 +35,7 @@ const hexRegex = /^#[0-9a-fA-F]{6}$/;
const progressPercentageLabel = (value: number) => `${value}%`;
export const ColorSettingsContent = ({ board }: Props) => {
const form = useZodForm(validation.board.savePartialSettings, {
const form = useZodForm(boardSavePartialSettingsSchema, {
initialValues: {
primaryColor: board.primaryColor,
secondaryColor: board.secondaryColor,

View File

@@ -12,7 +12,7 @@ import type { TranslationObject } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
import type { SelectItemWithDescriptionBadge } from "@homarr/ui";
import { SelectWithDescriptionBadge } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { boardSavePartialSettingsSchema } from "@homarr/validation/board";
import type { Board } from "../../_types";
import { useSavePartialSettingsMutation } from "./_shared";
@@ -24,7 +24,7 @@ export const BackgroundSettingsContent = ({ board }: Props) => {
const t = useI18n();
const { data: session } = useSession();
const { mutate: savePartialSettings, isPending } = useSavePartialSettingsMutation(board);
const form = useZodForm(validation.board.savePartialSettings, {
const form = useZodForm(boardSavePartialSettingsSchema, {
initialValues: {
backgroundImageUrl: board.backgroundImageUrl ?? "",
backgroundImageAttachment: board.backgroundImageAttachment,

View File

@@ -8,7 +8,7 @@ import { useUpdateBoard } from "@homarr/boards/updater";
import { useZodForm } from "@homarr/form";
import { IconPicker } from "@homarr/forms-collection";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { boardSavePartialSettingsSchema } from "@homarr/validation/board";
import { createMetaTitle } from "~/metadata";
import type { Board } from "../../_types";
@@ -28,7 +28,7 @@ export const GeneralSettingsContent = ({ board }: Props) => {
const { mutate: savePartialSettings, isPending } = useSavePartialSettingsMutation(board);
const form = useZodForm(
validation.board.savePartialSettings
boardSavePartialSettingsSchema
.pick({
pageTitle: true,
logoImageUrl: true,

View File

@@ -6,7 +6,7 @@ import { clientApi } from "@homarr/api/client";
import { createId } from "@homarr/db/client";
import { useZodForm } from "@homarr/form";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { boardSaveLayoutsSchema } from "@homarr/validation/board";
import type { Board } from "../../_types";
@@ -22,7 +22,7 @@ export const LayoutSettingsContent = ({ board }: Props) => {
void utils.board.getHomeBoard.invalidate();
},
});
const form = useZodForm(validation.board.saveLayouts.omit({ id: true }).required(), {
const form = useZodForm(boardSaveLayoutsSchema.omit({ id: true }).required(), {
initialValues: {
layouts: board.layouts,
},

View File

@@ -8,18 +8,18 @@ import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { groupCreateSchema } from "@homarr/validation/group";
export const InitGroup = () => {
const t = useI18n();
const { mutateAsync } = clientApi.group.createInitialExternalGroup.useMutation();
const form = useZodForm(validation.group.create, {
const form = useZodForm(groupCreateSchema, {
initialValues: {
name: "",
},
});
const handleSubmitAsync = async (values: z.infer<typeof validation.group.create>) => {
const handleSubmitAsync = async (values: z.infer<typeof groupCreateSchema>) => {
await mutateAsync(values, {
async onSuccess() {
await revalidatePathActionAsync("/init");

View File

@@ -12,13 +12,13 @@ import type { CheckboxProps } from "@homarr/form/types";
import { defaultServerSettings } from "@homarr/server-settings";
import type { TranslationObject } from "@homarr/translation";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { settingsInitSchema } from "@homarr/validation/settings";
export const InitSettings = () => {
const tSection = useScopedI18n("management.page.settings.section");
const t = useI18n();
const { mutateAsync } = clientApi.serverSettings.initSettings.useMutation();
const form = useZodForm(validation.settings.init, { initialValues: defaultServerSettings });
const form = useZodForm(settingsInitSchema, { initialValues: defaultServerSettings });
form.watch("analytics.enableGeneral", ({ value }) => {
if (!value) {
@@ -30,7 +30,7 @@ export const InitSettings = () => {
}
});
const handleSubmitAsync = async (values: z.infer<typeof validation.settings.init>) => {
const handleSubmitAsync = async (values: z.infer<typeof settingsInitSchema>) => {
await mutateAsync(values, {
async onSuccess() {
await revalidatePathActionAsync("/init");

View File

@@ -10,13 +10,13 @@ import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useScopedI18n } from "@homarr/translation/client";
import { CustomPasswordInput } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { userInitSchema } from "@homarr/validation/user";
export const InitUserForm = () => {
const t = useScopedI18n("user");
const tUser = useScopedI18n("init.step.user");
const { mutateAsync, isPending } = clientApi.user.initUser.useMutation();
const form = useZodForm(validation.user.init, {
const form = useZodForm(userInitSchema, {
initialValues: {
username: "",
password: "",
@@ -74,4 +74,4 @@ export const InitUserForm = () => {
);
};
type FormType = z.infer<typeof validation.user.init>;
type FormType = z.infer<typeof userInitSchema>;

View File

@@ -10,7 +10,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { AppForm } from "@homarr/forms-collection";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import type { validation } from "@homarr/validation";
import type { appManageSchema } from "@homarr/validation/app";
interface AppEditFormProps {
app: RouterOutputs["app"]["byId"];
@@ -40,7 +40,7 @@ export const AppEditForm = ({ app }: AppEditFormProps) => {
});
const handleSubmit = useCallback(
(values: z.infer<typeof validation.app.manage>) => {
(values: z.infer<typeof appManageSchema>) => {
mutate({
id: app.id,
...values,

View File

@@ -14,7 +14,7 @@ import { convertIntegrationTestConnectionError } from "@homarr/integrations/clie
import { useConfirmModal } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { integrationUpdateSchema } from "@homarr/validation/integration";
import { SecretCard } from "../../_components/secrets/integration-secret-card";
import { IntegrationSecretInput } from "../../_components/secrets/integration-secret-inputs";
@@ -32,7 +32,7 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
) ?? getDefaultSecretKinds(integration.kind);
const router = useRouter();
const form = useZodForm(validation.integration.update.omit({ id: true }), {
const form = useZodForm(integrationUpdateSchema.omit({ id: true }), {
initialValues: {
name: integration.name,
url: integration.url,
@@ -141,4 +141,4 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
);
};
type FormType = Omit<z.infer<typeof validation.integration.update>, "id">;
type FormType = Omit<z.infer<typeof integrationUpdateSchema>, "id">;

View File

@@ -27,20 +27,21 @@ import { useZodForm } from "@homarr/form";
import { convertIntegrationTestConnectionError } from "@homarr/integrations/client";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { appHrefSchema } from "@homarr/validation/app";
import { integrationCreateSchema } from "@homarr/validation/integration";
import { IntegrationSecretInput } from "../_components/secrets/integration-secret-inputs";
interface NewIntegrationFormProps {
searchParams: Partial<z.infer<typeof validation.integration.create>> & {
searchParams: Partial<z.infer<typeof integrationCreateSchema>> & {
kind: IntegrationKind;
};
}
const formSchema = validation.integration.create.omit({ kind: true }).and(
const formSchema = integrationCreateSchema.omit({ kind: true }).and(
z.object({
createApp: z.boolean(),
appHref: validation.app.manage.shape.href,
appHref: appHrefSchema,
}),
);

View File

@@ -7,14 +7,14 @@ import type { IntegrationKind } from "@homarr/definitions";
import { getIntegrationName, integrationKinds } from "@homarr/definitions";
import { getScopedI18n } from "@homarr/translation/server";
import { IntegrationAvatar } from "@homarr/ui";
import type { validation } from "@homarr/validation";
import type { integrationCreateSchema } from "@homarr/validation/integration";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
import { NewIntegrationForm } from "./_integration-new-form";
interface NewIntegrationPageProps {
searchParams: Promise<
Partial<z.infer<typeof validation.integration.create>> & {
Partial<z.infer<typeof integrationCreateSchema>> & {
kind: IntegrationKind;
}
>;

View File

@@ -12,9 +12,9 @@ import { useZodForm } from "@homarr/form";
import { IconPicker } from "@homarr/forms-collection";
import type { TranslationFunction } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { searchEngineManageSchema } from "@homarr/validation/search-engine";
type FormType = z.infer<typeof validation.searchEngine.manage>;
type FormType = z.infer<typeof searchEngineManageSchema>;
interface SearchEngineFormProps {
submitButtonTranslation: (t: TranslationFunction) => string;
@@ -30,7 +30,7 @@ export const SearchEngineForm = (props: SearchEngineFormProps) => {
const [integrationData] = clientApi.integration.allThatSupportSearch.useSuspenseQuery();
const form = useZodForm(validation.searchEngine.manage, {
const form = useZodForm(searchEngineManageSchema, {
initialValues: initialValues ?? {
name: "",
short: "",

View File

@@ -10,7 +10,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import type { TranslationFunction } from "@homarr/translation";
import { useScopedI18n } from "@homarr/translation/client";
import type { validation } from "@homarr/validation";
import type { searchEngineManageSchema } from "@homarr/validation/search-engine";
import { SearchEngineForm } from "../../_form";
@@ -41,7 +41,7 @@ export const SearchEngineEditForm = ({ searchEngine }: SearchEngineEditFormProps
});
const handleSubmit = useCallback(
(values: z.infer<typeof validation.searchEngine.manage>) => {
(values: z.infer<typeof searchEngineManageSchema>) => {
mutate({
id: searchEngine.id,
...values,

View File

@@ -9,7 +9,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import type { TranslationFunction } from "@homarr/translation";
import { useScopedI18n } from "@homarr/translation/client";
import type { validation } from "@homarr/validation";
import type { searchEngineManageSchema } from "@homarr/validation/search-engine";
import { SearchEngineForm } from "../_form";
@@ -35,7 +35,7 @@ export const SearchEngineNewForm = () => {
});
const handleSubmit = useCallback(
(values: z.infer<typeof validation.searchEngine.manage>) => {
(values: z.infer<typeof searchEngineManageSchema>) => {
mutate(values);
},
[mutate],

View File

@@ -10,7 +10,7 @@ import { useZodForm } from "@homarr/form";
import { createModal, useModalAction } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { superRefineCertificateFile } from "@homarr/validation";
import { superRefineCertificateFile } from "@homarr/validation/certificates";
export const AddCertificateButton = () => {
const { openModal } = useModalAction(AddCertificateModal);

View File

@@ -9,7 +9,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { userChangeHomeBoardsSchema } from "@homarr/validation/user";
import type { Board } from "~/app/[locale]/boards/_types";
import { BoardSelect } from "~/components/board/board-select";
@@ -40,7 +40,7 @@ export const ChangeHomeBoardForm = ({ user, boardsData }: ChangeHomeBoardFormPro
});
},
});
const form = useZodForm(validation.user.changeHomeBoards, {
const form = useZodForm(userChangeHomeBoardsSchema, {
initialValues: {
homeBoardId: user.homeBoardId,
mobileHomeBoardId: user.mobileHomeBoardId,
@@ -82,4 +82,4 @@ export const ChangeHomeBoardForm = ({ user, boardsData }: ChangeHomeBoardFormPro
);
};
type FormType = z.infer<typeof validation.user.changeHomeBoards>;
type FormType = z.infer<typeof userChangeHomeBoardsSchema>;

View File

@@ -9,7 +9,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { userChangeSearchPreferencesSchema } from "@homarr/validation/user";
interface ChangeSearchPreferencesFormProps {
user: RouterOutputs["user"]["getById"];
@@ -37,7 +37,7 @@ export const ChangeSearchPreferencesForm = ({ user, searchEnginesData }: ChangeS
});
},
});
const form = useZodForm(validation.user.changeSearchPreferences, {
const form = useZodForm(userChangeSearchPreferencesSchema, {
initialValues: {
defaultSearchEngineId: user.defaultSearchEngineId,
openInNewTab: user.openSearchInNewTab,
@@ -75,4 +75,4 @@ export const ChangeSearchPreferencesForm = ({ user, searchEnginesData }: ChangeS
);
};
type FormType = z.infer<typeof validation.user.changeSearchPreferences>;
type FormType = z.infer<typeof userChangeSearchPreferencesSchema>;

View File

@@ -12,7 +12,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { userFirstDayOfWeekSchema } from "@homarr/validation/user";
dayjs.extend(localeData);
@@ -42,7 +42,7 @@ export const FirstDayOfWeek = ({ user }: FirstDayOfWeekProps) => {
});
},
});
const form = useZodForm(validation.user.firstDayOfWeek, {
const form = useZodForm(userFirstDayOfWeekSchema, {
initialValues: {
firstDayOfWeek: user.firstDayOfWeek as DayOfWeek,
},
@@ -80,4 +80,4 @@ export const FirstDayOfWeek = ({ user }: FirstDayOfWeekProps) => {
);
};
type FormType = z.infer<typeof validation.user.firstDayOfWeek>;
type FormType = z.infer<typeof userFirstDayOfWeekSchema>;

View File

@@ -9,7 +9,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { userPingIconsEnabledSchema } from "@homarr/validation/user";
interface PingIconsEnabledProps {
user: RouterOutputs["user"]["getById"];
@@ -35,7 +35,7 @@ export const PingIconsEnabled = ({ user }: PingIconsEnabledProps) => {
});
},
});
const form = useZodForm(validation.user.pingIconsEnabled, {
const form = useZodForm(userPingIconsEnabledSchema, {
initialValues: {
pingIconsEnabled: user.pingIconsEnabled,
},
@@ -66,4 +66,4 @@ export const PingIconsEnabled = ({ user }: PingIconsEnabledProps) => {
);
};
type FormType = z.infer<typeof validation.user.pingIconsEnabled>;
type FormType = z.infer<typeof userPingIconsEnabledSchema>;

View File

@@ -9,7 +9,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { userEditProfileSchema } from "@homarr/validation/user";
interface UserProfileFormProps {
user: RouterOutputs["user"]["getById"];
@@ -43,7 +43,7 @@ export const UserProfileForm = ({ user }: UserProfileFormProps) => {
});
},
});
const form = useZodForm(validation.user.editProfile.omit({ id: true }), {
const form = useZodForm(userEditProfileSchema.omit({ id: true }), {
initialValues: {
name: user.name ?? "",
email: user.email ?? "",

View File

@@ -10,7 +10,7 @@ import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { CustomPasswordInput } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { userChangePasswordSchema } from "@homarr/validation/user";
interface ChangePasswordFormProps {
user: RouterOutputs["user"]["getById"];
@@ -34,7 +34,7 @@ export const ChangePasswordForm = ({ user }: ChangePasswordFormProps) => {
});
},
});
const form = useZodForm(validation.user.changePassword, {
const form = useZodForm(userChangePasswordSchema, {
initialValues: {
/* Require previous password if the current user want's to change his password */
previousPassword: session?.user.id === user.id ? "" : "_",

View File

@@ -27,8 +27,8 @@ import { useModalAction } from "@homarr/modals";
import { showErrorNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { CustomPasswordInput, UserAvatar } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { createCustomErrorParams } from "@homarr/validation/form";
import { createCustomErrorParams } from "@homarr/validation/form/i18n";
import { userPasswordSchema } from "@homarr/validation/user";
import { GroupSelectModal } from "~/components/access/group-select-modal";
import { StepperNavigationComponent } from "./stepper-navigation";
@@ -84,7 +84,7 @@ export const UserCreateStepperComponent = ({ initialGroups }: UserCreateStepperC
const securityForm = useZodForm(
z
.object({
password: validation.user.password,
password: userPasswordSchema,
confirmPassword: z.string(),
})
.refine((data) => data.password === data.confirmPassword, {

View File

@@ -8,7 +8,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { groupUpdateSchema } from "@homarr/validation/group";
interface RenameGroupFormProps {
group: {
@@ -21,7 +21,7 @@ interface RenameGroupFormProps {
export const RenameGroupForm = ({ group, disabled }: RenameGroupFormProps) => {
const t = useI18n();
const { mutate, isPending } = clientApi.group.updateGroup.useMutation();
const form = useZodForm(validation.group.update.pick({ name: true }), {
const form = useZodForm(groupUpdateSchema.pick({ name: true }), {
initialValues: {
name: group.name,
},

View File

@@ -6,7 +6,7 @@ import { clientApi } from "@homarr/api/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { groupSettingsSchema } from "@homarr/validation/group";
import { BoardSelect } from "~/components/board/board-select";
@@ -19,7 +19,7 @@ interface GroupHomeBoardsProps {
export const GroupHomeBoards = ({ homeBoardId, mobileHomeBoardId, groupId }: GroupHomeBoardsProps) => {
const t = useI18n();
const [availableBoards] = clientApi.board.getBoardsForGroup.useSuspenseQuery({ groupId });
const form = useZodForm(validation.group.settings.pick({ homeBoardId: true, mobileHomeBoardId: true }), {
const form = useZodForm(groupSettingsSchema.pick({ homeBoardId: true, mobileHomeBoardId: true }), {
initialValues: {
homeBoardId,
mobileHomeBoardId,

View File

@@ -11,7 +11,7 @@ import { useModalAction } from "@homarr/modals";
import { showSuccessNotification } from "@homarr/notifications";
import { useSettings } from "@homarr/settings";
import { useScopedI18n } from "@homarr/translation/client";
import type { BoardItemAdvancedOptions } from "@homarr/validation";
import type { BoardItemAdvancedOptions } from "@homarr/validation/shared";
import { loadWidgetDynamic, reduceWidgetOptionsWithDefaultValues, widgetImports } from "@homarr/widgets";
import { WidgetError } from "@homarr/widgets/errors";
import { WidgetEditModal } from "@homarr/widgets/modals";