From ed80131a9be7756686c24b01522ce4e66be7dd1e Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Sat, 14 Feb 2026 00:12:41 +0100 Subject: [PATCH] refactor: server constants --- app/client/lib/constants.ts | 2 -- .../components/create-repository-form.tsx | 20 ++++++++++++++----- .../local-repository-form.tsx | 18 ++++++++++++----- app/client/modules/repositories/tabs/info.tsx | 1 - app/server/core/constants.ts | 11 ++++++++++ .../lib/auth-middlewares/only-one-user.ts | 2 +- .../migrations/00004-concat-path-name.ts | 5 ++--- app/server/modules/system/system.service.ts | 2 +- 8 files changed, 43 insertions(+), 18 deletions(-) delete mode 100644 app/client/lib/constants.ts diff --git a/app/client/lib/constants.ts b/app/client/lib/constants.ts deleted file mode 100644 index fc2c499a..00000000 --- a/app/client/lib/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const REPOSITORY_BASE = "/var/lib/zerobyte/repositories"; -export const REGISTRATION_ENABLED_KEY = "registrations_enabled"; diff --git a/app/client/modules/repositories/components/create-repository-form.tsx b/app/client/modules/repositories/components/create-repository-form.tsx index 7561423b..93165770 100644 --- a/app/client/modules/repositories/components/create-repository-form.tsx +++ b/app/client/modules/repositories/components/create-repository-form.tsx @@ -33,7 +33,9 @@ import { SftpRepositoryForm, AdvancedForm, } from "./repository-forms"; -import { REPOSITORY_BASE } from "~/client/lib/constants"; +import { useServerFn } from "@tanstack/react-start"; +import { getServerConstants } from "~/server/core/constants"; +import { useSuspenseQuery } from "@tanstack/react-query"; export const formSchema = type({ name: "2<=string<=32", @@ -52,8 +54,8 @@ type Props = { className?: string; }; -const defaultValuesForType = { - local: { backend: "local" as const, compressionMode: "auto" as const, path: REPOSITORY_BASE }, +const defaultValuesForType = (repoBase: string) => ({ + local: { backend: "local" as const, compressionMode: "auto" as const, path: repoBase }, s3: { backend: "s3" as const, compressionMode: "auto" as const }, r2: { backend: "r2" as const, compressionMode: "auto" as const }, gcs: { backend: "gcs" as const, compressionMode: "auto" as const }, @@ -61,7 +63,7 @@ const defaultValuesForType = { rclone: { backend: "rclone" as const, compressionMode: "auto" as const }, rest: { backend: "rest" as const, compressionMode: "auto" as const }, sftp: { backend: "sftp" as const, compressionMode: "auto" as const, port: 22, skipHostKeyCheck: false }, -}; +}); export const CreateRepositoryForm = ({ onSubmit, @@ -71,6 +73,12 @@ export const CreateRepositoryForm = ({ loading, className, }: Props) => { + const getConstants = useServerFn(getServerConstants); + const { data: constants } = useSuspenseQuery({ + queryKey: ["server-constants"], + queryFn: getConstants, + }); + const form = useForm({ resolver: arktypeResolver(cleanSchema as unknown as typeof formSchema), defaultValues: initialValues, @@ -125,7 +133,9 @@ export const CreateRepositoryForm = ({ name: form.getValues().name, isExistingRepository: form.getValues().isExistingRepository, customPassword: form.getValues().customPassword, - ...defaultValuesForType[value as keyof typeof defaultValuesForType], + ...defaultValuesForType(constants.REPOSITORY_BASE)[ + value as keyof ReturnType + ], }); }} value={field.value} diff --git a/app/client/modules/repositories/components/repository-forms/local-repository-form.tsx b/app/client/modules/repositories/components/repository-forms/local-repository-form.tsx index b310c8eb..5f993550 100644 --- a/app/client/modules/repositories/components/repository-forms/local-repository-form.tsx +++ b/app/client/modules/repositories/components/repository-forms/local-repository-form.tsx @@ -1,7 +1,6 @@ import { useState } from "react"; import type { UseFormReturn } from "react-hook-form"; import { Check, Pencil, X, AlertTriangle } from "lucide-react"; -import { REPOSITORY_BASE } from "~/client/lib/constants"; import { Button } from "../../../../components/ui/button"; import { FormItem, FormLabel, FormDescription, FormField, FormControl } from "../../../../components/ui/form"; import { DirectoryBrowser } from "../../../../components/directory-browser"; @@ -16,6 +15,9 @@ import { AlertDialogTitle, } from "../../../../components/ui/alert-dialog"; import type { RepositoryFormValues } from "../create-repository-form"; +import { useServerFn } from "@tanstack/react-start"; +import { getServerConstants } from "~/server/core/constants"; +import { useSuspenseQuery } from "@tanstack/react-query"; type Props = { form: UseFormReturn; @@ -25,6 +27,12 @@ export const LocalRepositoryForm = ({ form }: Props) => { const [showPathBrowser, setShowPathBrowser] = useState(false); const [showPathWarning, setShowPathWarning] = useState(false); + const getConstants = useServerFn(getServerConstants); + const { data: constants } = useSuspenseQuery({ + queryKey: ["server-constants"], + queryFn: getConstants, + }); + return ( {
- {field.value || REPOSITORY_BASE} + {field.value || constants.REPOSITORY_BASE}
diff --git a/app/client/modules/repositories/tabs/info.tsx b/app/client/modules/repositories/tabs/info.tsx index 26eefee9..b19170c3 100644 --- a/app/client/modules/repositories/tabs/info.tsx +++ b/app/client/modules/repositories/tabs/info.tsx @@ -14,7 +14,6 @@ import { AlertDialogTitle, } from "~/client/components/ui/alert-dialog"; import type { Repository } from "~/client/lib/types"; -import { REPOSITORY_BASE } from "~/client/lib/constants"; import { formatDateTime, formatTimeAgo } from "~/client/lib/datetime"; import { cancelDoctorMutation, diff --git a/app/server/core/constants.ts b/app/server/core/constants.ts index 0eff834f..c22e676f 100644 --- a/app/server/core/constants.ts +++ b/app/server/core/constants.ts @@ -1,3 +1,5 @@ +import { createServerFn } from "@tanstack/react-start"; + export const OPERATION_TIMEOUT = 5000; export const VOLUME_MOUNT_BASE = process.env.ZEROBYTE_VOLUMES_DIR || "/var/lib/zerobyte/volumes"; @@ -11,3 +13,12 @@ export const RESTIC_PASS_FILE = process.env.RESTIC_PASS_FILE || "/var/lib/zeroby export const RCLONE_CONFIG_DIR = process.env.RCLONE_CONFIG_DIR || "/root/.config/rclone"; export const DEFAULT_EXCLUDES = [DATABASE_URL, RESTIC_PASS_FILE, REPOSITORY_BASE]; + +export const REGISTRATION_ENABLED_KEY = "registrations_enabled"; + +export const getServerConstants = createServerFn({ method: "GET" }).handler(() => { + return { + REPOSITORY_BASE, + REGISTRATION_ENABLED_KEY, + }; +}); diff --git a/app/server/lib/auth-middlewares/only-one-user.ts b/app/server/lib/auth-middlewares/only-one-user.ts index 6f013f35..67b5bc55 100644 --- a/app/server/lib/auth-middlewares/only-one-user.ts +++ b/app/server/lib/auth-middlewares/only-one-user.ts @@ -2,7 +2,7 @@ import { db } from "~/server/db/db"; import type { AuthMiddlewareContext } from "../auth"; import { logger } from "~/server/utils/logger"; import { ForbiddenError } from "http-errors-enhanced"; -import { REGISTRATION_ENABLED_KEY } from "~/client/lib/constants"; +import { REGISTRATION_ENABLED_KEY } from "~/server/core/constants"; export const ensureOnlyOneUser = async (ctx: AuthMiddlewareContext) => { const { path } = ctx; diff --git a/app/server/modules/lifecycle/migrations/00004-concat-path-name.ts b/app/server/modules/lifecycle/migrations/00004-concat-path-name.ts index 82504e66..633aa698 100644 --- a/app/server/modules/lifecycle/migrations/00004-concat-path-name.ts +++ b/app/server/modules/lifecycle/migrations/00004-concat-path-name.ts @@ -3,8 +3,7 @@ import { db } from "../../../db/db"; import { repositoriesTable } from "../../../db/schema"; import { logger } from "../../../utils/logger"; import { toMessage } from "~/server/utils/errors"; - -const DEFAULT_LOCAL_REPOSITORY_ROOT = "/var/lib/zerobyte/repositories"; +import { REPOSITORY_BASE } from "~/server/core/constants"; type MigrationError = { name: string; error: string }; @@ -31,7 +30,7 @@ const isPathAlreadyMigrated = (path: string, name: string): boolean => { const buildPath = (path: string | null, name: string): string => { if (path === null || path.trim() === "") { - return `${DEFAULT_LOCAL_REPOSITORY_ROOT}/${name}`; + return `${REPOSITORY_BASE}/${name}`; } return `${trimTrailingSlashes(path)}/${name}`; diff --git a/app/server/modules/system/system.service.ts b/app/server/modules/system/system.service.ts index c04c83df..17260f00 100644 --- a/app/server/modules/system/system.service.ts +++ b/app/server/modules/system/system.service.ts @@ -6,7 +6,7 @@ import { cache } from "../../utils/cache"; import { logger } from "~/server/utils/logger"; import { db } from "../../db/db"; import { appMetadataTable } from "../../db/schema"; -import { REGISTRATION_ENABLED_KEY } from "~/client/lib/constants"; +import { REGISTRATION_ENABLED_KEY } from "~/server/core/constants"; const CACHE_TTL = 60 * 60;