From aab47d68db50a6933edd6eba572fbc210862e98e Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Thu, 13 Nov 2025 18:42:03 +0100 Subject: [PATCH] refactor: unify backend and frontend servers --- .dockerignore | 10 +- .gitignore | 48 +- Dockerfile | 12 +- .../api-client/@tanstack/react-query.gen.ts | 0 .../app => app}/api-client/client.gen.ts | 0 .../api-client/client/client.gen.ts | 0 .../app => app}/api-client/client/index.ts | 0 .../api-client/client/types.gen.ts | 0 .../api-client/client/utils.gen.ts | 0 .../app => app}/api-client/core/auth.gen.ts | 0 .../api-client/core/bodySerializer.gen.ts | 0 .../app => app}/api-client/core/params.gen.ts | 0 .../api-client/core/pathSerializer.gen.ts | 0 .../app => app}/api-client/core/types.gen.ts | 0 {apps/client/app => app}/api-client/index.ts | 0 .../client/app => app}/api-client/sdk.gen.ts | 0 .../app => app}/api-client/types.gen.ts | 0 {apps/client/app => app}/app.css | 0 .../client}/components/app-breadcrumb.tsx | 4 +- .../client}/components/app-sidebar.tsx | 6 +- .../client}/components/auth-layout.tsx | 0 .../client}/components/bytes-size.tsx | 0 .../components/create-repository-dialog.tsx | 2 +- .../components/create-repository-form.tsx | 6 +- .../components/create-volume-dialog.tsx | 2 +- .../client}/components/create-volume-form.tsx | 4 +- .../client}/components/directory-browser.tsx | 0 .../client}/components/empty-state.tsx | 0 .../client}/components/file-tree.tsx | 4 +- .../client}/components/grid-background.tsx | 2 +- .../app => app/client}/components/layout.tsx | 0 .../app => app/client}/components/onoff.tsx | 2 +- .../client}/components/repository-icon.tsx | 2 +- .../client}/components/snapshots-table.tsx | 6 +- .../client}/components/status-dot.tsx | 4 +- .../client}/components/ui/alert-dialog.tsx | 4 +- .../client}/components/ui/alert.tsx | 2 +- .../client}/components/ui/badge.tsx | 0 app/client/components/ui/breadcrumb.tsx | 92 ++ .../client}/components/ui/button.tsx | 2 +- .../app => app/client}/components/ui/card.tsx | 2 +- .../client}/components/ui/chart.tsx | 2 +- app/client/components/ui/checkbox.tsx | 27 + .../client}/components/ui/code-block.tsx | 0 app/client/components/ui/dialog.tsx | 121 +++ .../app => app/client}/components/ui/form.tsx | 4 +- .../client}/components/ui/input.tsx | 2 +- app/client/components/ui/label.tsx | 21 + .../client}/components/ui/progress.tsx | 2 +- app/client/components/ui/scroll-area.tsx | 46 + .../client}/components/ui/select.tsx | 45 +- app/client/components/ui/separator.tsx | 26 + app/client/components/ui/sheet.tsx | 103 ++ .../client}/components/ui/sidebar.tsx | 16 +- app/client/components/ui/skeleton.tsx | 7 + .../client}/components/ui/sonner.tsx | 0 .../client}/components/ui/switch.tsx | 2 +- app/client/components/ui/table.tsx | 73 ++ .../app => app/client}/components/ui/tabs.tsx | 2 +- .../client}/components/ui/textarea.tsx | 2 +- app/client/components/ui/tooltip.tsx | 46 + .../components/volume-file-browser.tsx | 2 +- .../client}/components/volume-icon.tsx | 2 +- .../app => app/client}/hooks/use-mobile.ts | 0 .../client}/hooks/use-server-events.ts | 0 .../client}/hooks/use-system-info.ts | 0 .../app => app/client}/lib/breadcrumbs.ts | 0 {apps/client/app => app/client}/lib/errors.ts | 0 {apps/client/app => app/client}/lib/types.ts | 0 {apps/client/app => app/client}/lib/utils.ts | 0 .../auth/routes/download-recovery-key.tsx | 10 +- .../client}/modules/auth/routes/login.tsx | 8 +- .../modules/auth/routes/onboarding.tsx | 16 +- .../components/backup-progress-card.tsx | 8 +- .../backups/components/backup-status-dot.tsx | 10 +- .../components/create-schedule-form.tsx | 24 +- .../backups/components/schedule-summary.tsx | 10 +- .../components/snapshot-file-browser.tsx | 16 +- .../backups/components/snapshot-timeline.tsx | 6 +- .../modules/backups/routes/backup-details.tsx | 4 +- .../modules/backups/routes/backups.tsx | 6 +- .../modules/backups/routes/create-backup.tsx | 12 +- .../components/restore-snapshot-dialog.tsx | 8 +- .../components/restore-snapshot-form.tsx | 12 +- .../repositories/routes/repositories.tsx | 18 +- .../routes/repository-details.tsx | 10 +- .../repositories/routes/snapshot-details.tsx | 4 +- .../modules/repositories/tabs/info.tsx | 4 +- .../modules/repositories/tabs/snapshots.tsx | 12 +- .../modules/settings/routes/settings.tsx | 10 +- .../volumes/components/healthchecks-card.tsx | 8 +- .../volumes/components/storage-chart.tsx | 8 +- .../modules/volumes/routes/volume-details.tsx | 20 +- .../modules/volumes/routes/volumes.tsx | 18 +- .../client}/modules/volumes/tabs/docker.tsx | 10 +- .../client}/modules/volumes/tabs/files.tsx | 6 +- .../client}/modules/volumes/tabs/info.tsx | 8 +- .../client/app => app/client}/routes/root.tsx | 4 + {apps/client/app => app}/context.ts | 2 +- {apps/client/app => app}/middleware/auth.ts | 0 {apps/client/app => app}/root.tsx | 4 +- app/routes.ts | 19 + app/schemas/node_modules/arktype | 1 + .../schemas/src => app/schemas}/restic.ts | 0 .../src/index.ts => app/schemas/volumes.ts | 0 .../src => app/server}/core/capabilities.ts | 0 .../server/src => app/server}/core/config.ts | 0 .../src => app/server}/core/constants.ts | 0 .../server/src => app/server}/core/events.ts | 0 .../src => app/server}/core/scheduler.ts | 0 {apps/server/src => app/server}/db/db.ts | 2 +- {apps/server/src => app/server}/db/schema.ts | 9 +- {apps/server/src => app/server}/index.ts | 8 +- .../server}/jobs/backup-execution.ts | 0 .../server}/jobs/cleanup-dangling.ts | 0 .../server}/jobs/cleanup-sessions.ts | 0 .../src => app/server}/jobs/healthchecks.ts | 0 .../server}/jobs/repository-healthchecks.ts | 0 .../server}/modules/auth/auth.controller.ts | 0 .../server}/modules/auth/auth.dto.ts | 0 .../server}/modules/auth/auth.middleware.ts | 0 .../server}/modules/auth/auth.service.ts | 0 .../server}/modules/backends/backend.ts | 2 +- .../backends/directory/directory-backend.ts | 2 +- .../modules/backends/nfs/nfs-backend.ts | 2 +- .../modules/backends/smb/smb-backend.ts | 2 +- .../modules/backends/utils/backend-utils.ts | 0 .../modules/backends/webdav/webdav-backend.ts | 2 +- .../modules/backups/backups.controller.ts | 0 .../server}/modules/backups/backups.dto.ts | 0 .../modules/backups/backups.service.ts | 0 .../modules/driver/driver.controller.ts | 0 .../modules/events/events.controller.ts | 0 .../server}/modules/lifecycle/shutdown.ts | 0 .../server}/modules/lifecycle/startup.ts | 0 .../repositories/repositories.controller.ts | 0 .../modules/repositories/repositories.dto.ts | 7 +- .../repositories/repositories.service.ts | 2 +- .../modules/system/system.controller.ts | 0 .../server}/modules/system/system.dto.ts | 0 .../server}/modules/system/system.service.ts | 0 .../server}/modules/volumes/helpers.ts | 0 .../modules/volumes/volume.controller.ts | 0 .../server}/modules/volumes/volume.dto.ts | 2 +- .../server}/modules/volumes/volume.service.ts | 3 +- .../server/src => app/server}/utils/crypto.ts | 0 .../server/src => app/server}/utils/errors.ts | 0 .../server/src => app/server}/utils/logger.ts | 0 .../src => app/server}/utils/mountinfo.ts | 0 .../server/src => app/server}/utils/rclone.ts | 0 .../server/src => app/server}/utils/restic.ts | 2 +- .../src => app/server}/utils/sanitize.ts | 0 .../server/src => app/server}/utils/spawn.ts | 0 .../src => app/server}/utils/timeout.ts | 0 {apps/client/app => app}/utils/clipboard.ts | 0 {apps/client/app => app}/utils/object.ts | 0 {apps/client/app => app}/utils/utils.ts | 0 apps/client/.gitignore | 7 - apps/client/README.md | 87 -- apps/client/app/components/ui/breadcrumb.tsx | 109 --- apps/client/app/components/ui/checkbox.tsx | 30 - apps/client/app/components/ui/dialog.tsx | 141 --- apps/client/app/components/ui/label.tsx | 24 - apps/client/app/components/ui/scroll-area.tsx | 56 -- apps/client/app/components/ui/separator.tsx | 26 - apps/client/app/components/ui/sheet.tsx | 139 --- apps/client/app/components/ui/skeleton.tsx | 13 - apps/client/app/components/ui/table.tsx | 114 --- apps/client/app/components/ui/tooltip.tsx | 59 -- apps/client/app/routes.ts | 19 - apps/client/package.json | 64 -- apps/client/vite.config.ts | 34 - apps/server/.gitignore | 1 - apps/server/build.ts | 13 - apps/server/package.json | 32 - apps/server/tsconfig.json | 18 - bun.lock | 918 ++++-------------- .../client/components.json => components.json | 0 docker-compose.yml | 5 +- .../0000_known_madelyne_pryor.sql | 0 .../0001_far_frank_castle.sql | 0 .../0002_cheerful_randall.sql | 0 .../0003_mature_hellcat.sql | 0 .../0004_wealthy_tomas.sql | 0 .../drizzle => drizzle}/0005_simple_alice.sql | 0 .../0006_secret_micromacro.sql | 0 .../drizzle => drizzle}/0007_watery_sersi.sql | 0 .../0008_silent_lady_bullseye.sql | 0 .../0009_little_adam_warlock.sql | 0 .../0010_perfect_proemial_gods.sql | 0 .../meta/0000_snapshot.json | 0 .../meta/0001_snapshot.json | 0 .../meta/0002_snapshot.json | 0 .../meta/0003_snapshot.json | 0 .../meta/0004_snapshot.json | 0 .../meta/0005_snapshot.json | 0 .../meta/0006_snapshot.json | 0 .../meta/0007_snapshot.json | 0 .../meta/0008_snapshot.json | 0 .../meta/0009_snapshot.json | 0 .../meta/0010_snapshot.json | 0 .../drizzle => drizzle}/meta/_journal.json | 0 mutagen.yml.lock | 1 + package.json | 87 +- packages/schemas/package.json | 21 - packages/schemas/tsconfig.json | 19 - .../public => public}/images/background.jpg | Bin .../images/favicon/apple-touch-icon.png | Bin .../images/favicon/favicon-96x96.png | Bin .../images/favicon/favicon.ico | Bin .../images/favicon/favicon.svg | 0 .../images/favicon/site.webmanifest | 0 .../favicon/web-app-manifest-192x192.png | Bin .../favicon/web-app-manifest-512x512.png | Bin ...router.config.ts => react-router.config.ts | 2 +- apps/client/tsconfig.json => tsconfig.json | 0 turbo.json | 20 - vite.config.ts | 20 + 218 files changed, 1105 insertions(+), 2102 deletions(-) rename {apps/client/app => app}/api-client/@tanstack/react-query.gen.ts (100%) rename {apps/client/app => app}/api-client/client.gen.ts (100%) rename {apps/client/app => app}/api-client/client/client.gen.ts (100%) rename {apps/client/app => app}/api-client/client/index.ts (100%) rename {apps/client/app => app}/api-client/client/types.gen.ts (100%) rename {apps/client/app => app}/api-client/client/utils.gen.ts (100%) rename {apps/client/app => app}/api-client/core/auth.gen.ts (100%) rename {apps/client/app => app}/api-client/core/bodySerializer.gen.ts (100%) rename {apps/client/app => app}/api-client/core/params.gen.ts (100%) rename {apps/client/app => app}/api-client/core/pathSerializer.gen.ts (100%) rename {apps/client/app => app}/api-client/core/types.gen.ts (100%) rename {apps/client/app => app}/api-client/index.ts (100%) rename {apps/client/app => app}/api-client/sdk.gen.ts (100%) rename {apps/client/app => app}/api-client/types.gen.ts (100%) rename {apps/client/app => app}/app.css (100%) rename {apps/client/app => app/client}/components/app-breadcrumb.tsx (90%) rename {apps/client/app => app/client}/components/app-sidebar.tsx (94%) rename {apps/client/app => app/client}/components/auth-layout.tsx (100%) rename {apps/client/app => app/client}/components/bytes-size.tsx (100%) rename {apps/client/app => app/client}/components/create-repository-dialog.tsx (97%) rename {apps/client/app => app/client}/components/create-repository-form.tsx (98%) rename {apps/client/app => app/client}/components/create-volume-dialog.tsx (97%) rename {apps/client/app => app/client}/components/create-volume-form.tsx (99%) rename {apps/client/app => app/client}/components/directory-browser.tsx (100%) rename {apps/client/app => app/client}/components/empty-state.tsx (100%) rename {apps/client/app => app/client}/components/file-tree.tsx (99%) rename {apps/client/app => app/client}/components/grid-background.tsx (95%) rename {apps/client/app => app/client}/components/layout.tsx (100%) rename {apps/client/app => app/client}/components/onoff.tsx (95%) rename {apps/client/app => app/client}/components/repository-icon.tsx (87%) rename {apps/client/app => app/client}/components/snapshots-table.tsx (94%) rename {apps/client/app => app/client}/components/status-dot.tsx (92%) rename {apps/client/app => app/client}/components/ui/alert-dialog.tsx (97%) rename {apps/client/app => app/client}/components/ui/alert.tsx (97%) rename {apps/client/app => app/client}/components/ui/badge.tsx (100%) create mode 100644 app/client/components/ui/breadcrumb.tsx rename {apps/client/app => app/client}/components/ui/button.tsx (98%) rename {apps/client/app => app/client}/components/ui/card.tsx (98%) rename {apps/client/app => app/client}/components/ui/chart.tsx (99%) create mode 100644 app/client/components/ui/checkbox.tsx rename {apps/client/app => app/client}/components/ui/code-block.tsx (100%) create mode 100644 app/client/components/ui/dialog.tsx rename {apps/client/app => app/client}/components/ui/form.tsx (97%) rename {apps/client/app => app/client}/components/ui/input.tsx (95%) create mode 100644 app/client/components/ui/label.tsx rename {apps/client/app => app/client}/components/ui/progress.tsx (93%) create mode 100644 app/client/components/ui/scroll-area.tsx rename {apps/client/app => app/client}/components/ui/select.tsx (84%) create mode 100644 app/client/components/ui/separator.tsx create mode 100644 app/client/components/ui/sheet.tsx rename {apps/client/app => app/client}/components/ui/sidebar.tsx (97%) create mode 100644 app/client/components/ui/skeleton.tsx rename {apps/client/app => app/client}/components/ui/sonner.tsx (100%) rename {apps/client/app => app/client}/components/ui/switch.tsx (96%) create mode 100644 app/client/components/ui/table.tsx rename {apps/client/app => app/client}/components/ui/tabs.tsx (98%) rename {apps/client/app => app/client}/components/ui/textarea.tsx (94%) create mode 100644 app/client/components/ui/tooltip.tsx rename {apps/client/app => app/client}/components/volume-file-browser.tsx (98%) rename {apps/client/app => app/client}/components/volume-icon.tsx (95%) rename {apps/client/app => app/client}/hooks/use-mobile.ts (100%) rename {apps/client/app => app/client}/hooks/use-server-events.ts (100%) rename {apps/client/app => app/client}/hooks/use-system-info.ts (100%) rename {apps/client/app => app/client}/lib/breadcrumbs.ts (100%) rename {apps/client/app => app/client}/lib/errors.ts (100%) rename {apps/client/app => app/client}/lib/types.ts (100%) rename {apps/client/app => app/client}/lib/utils.ts (100%) rename {apps/client/app => app/client}/modules/auth/routes/download-recovery-key.tsx (90%) rename {apps/client/app => app/client}/modules/auth/routes/login.tsx (93%) rename {apps/client/app => app/client}/modules/auth/routes/onboarding.tsx (92%) rename {apps/client/app => app/client}/modules/backups/components/backup-progress-card.tsx (91%) rename {apps/client/app => app/client}/modules/backups/components/backup-status-dot.tsx (86%) rename {apps/client/app => app/client}/modules/backups/components/create-schedule-form.tsx (96%) rename {apps/client/app => app/client}/modules/backups/components/schedule-summary.tsx (96%) rename {apps/client/app => app/client}/modules/backups/components/snapshot-file-browser.tsx (95%) rename {apps/client/app => app/client}/modules/backups/components/snapshot-timeline.tsx (95%) rename {apps/client/app => app/client}/modules/backups/routes/backup-details.tsx (98%) rename {apps/client/app => app/client}/modules/backups/routes/backups.tsx (96%) rename {apps/client/app => app/client}/modules/backups/routes/create-backup.tsx (94%) rename {apps/client/app => app/client}/modules/repositories/components/restore-snapshot-dialog.tsx (92%) rename {apps/client/app => app/client}/modules/repositories/components/restore-snapshot-form.tsx (92%) rename {apps/client/app => app/client}/modules/repositories/routes/repositories.tsx (92%) rename {apps/client/app => app/client}/modules/repositories/routes/repository-details.tsx (96%) rename {apps/client/app => app/client}/modules/repositories/routes/snapshot-details.tsx (94%) rename {apps/client/app => app/client}/modules/repositories/tabs/info.tsx (95%) rename {apps/client/app => app/client}/modules/repositories/tabs/snapshots.tsx (92%) rename {apps/client/app => app/client}/modules/settings/routes/settings.tsx (97%) rename {apps/client/app => app/client}/modules/volumes/components/healthchecks-card.tsx (93%) rename {apps/client/app => app/client}/modules/volumes/components/storage-chart.tsx (94%) rename {apps/client/app => app/client}/modules/volumes/routes/volume-details.tsx (89%) rename {apps/client/app => app/client}/modules/volumes/routes/volumes.tsx (91%) rename {apps/client/app => app/client}/modules/volumes/tabs/docker.tsx (93%) rename {apps/client/app => app/client}/modules/volumes/tabs/files.tsx (88%) rename {apps/client/app => app/client}/modules/volumes/tabs/info.tsx (91%) rename {apps/client/app => app/client}/routes/root.tsx (62%) rename {apps/client/app => app}/context.ts (80%) rename {apps/client/app => app}/middleware/auth.ts (100%) rename {apps/client/app => app}/root.tsx (95%) create mode 100644 app/routes.ts create mode 120000 app/schemas/node_modules/arktype rename {packages/schemas/src => app/schemas}/restic.ts (100%) rename packages/schemas/src/index.ts => app/schemas/volumes.ts (100%) rename {apps/server/src => app/server}/core/capabilities.ts (100%) rename {apps/server/src => app/server}/core/config.ts (100%) rename {apps/server/src => app/server}/core/constants.ts (100%) rename {apps/server/src => app/server}/core/events.ts (100%) rename {apps/server/src => app/server}/core/scheduler.ts (100%) rename {apps/server/src => app/server}/db/db.ts (91%) rename {apps/server/src => app/server}/db/schema.ts (96%) rename {apps/server/src => app/server}/index.ts (96%) rename {apps/server/src => app/server}/jobs/backup-execution.ts (100%) rename {apps/server/src => app/server}/jobs/cleanup-dangling.ts (100%) rename {apps/server/src => app/server}/jobs/cleanup-sessions.ts (100%) rename {apps/server/src => app/server}/jobs/healthchecks.ts (100%) rename {apps/server/src => app/server}/jobs/repository-healthchecks.ts (100%) rename {apps/server/src => app/server}/modules/auth/auth.controller.ts (100%) rename {apps/server/src => app/server}/modules/auth/auth.dto.ts (100%) rename {apps/server/src => app/server}/modules/auth/auth.middleware.ts (100%) rename {apps/server/src => app/server}/modules/auth/auth.service.ts (100%) rename {apps/server/src => app/server}/modules/backends/backend.ts (94%) rename {apps/server/src => app/server}/modules/backends/directory/directory-backend.ts (96%) rename {apps/server/src => app/server}/modules/backends/nfs/nfs-backend.ts (98%) rename {apps/server/src => app/server}/modules/backends/smb/smb-backend.ts (98%) rename {apps/server/src => app/server}/modules/backends/utils/backend-utils.ts (100%) rename {apps/server/src => app/server}/modules/backends/webdav/webdav-backend.ts (98%) rename {apps/server/src => app/server}/modules/backups/backups.controller.ts (100%) rename {apps/server/src => app/server}/modules/backups/backups.dto.ts (100%) rename {apps/server/src => app/server}/modules/backups/backups.service.ts (100%) rename {apps/server/src => app/server}/modules/driver/driver.controller.ts (100%) rename {apps/server/src => app/server}/modules/events/events.controller.ts (100%) rename {apps/server/src => app/server}/modules/lifecycle/shutdown.ts (100%) rename {apps/server/src => app/server}/modules/lifecycle/startup.ts (100%) rename {apps/server/src => app/server}/modules/repositories/repositories.controller.ts (100%) rename {apps/server/src => app/server}/modules/repositories/repositories.dto.ts (98%) rename {apps/server/src => app/server}/modules/repositories/repositories.service.ts (99%) rename {apps/server/src => app/server}/modules/system/system.controller.ts (100%) rename {apps/server/src => app/server}/modules/system/system.dto.ts (100%) rename {apps/server/src => app/server}/modules/system/system.service.ts (100%) rename {apps/server/src => app/server}/modules/volumes/helpers.ts (100%) rename {apps/server/src => app/server}/modules/volumes/volume.controller.ts (100%) rename {apps/server/src => app/server}/modules/volumes/volume.dto.ts (99%) rename {apps/server/src => app/server}/modules/volumes/volume.service.ts (98%) rename {apps/server/src => app/server}/utils/crypto.ts (100%) rename {apps/server/src => app/server}/utils/errors.ts (100%) rename {apps/server/src => app/server}/utils/logger.ts (100%) rename {apps/server/src => app/server}/utils/mountinfo.ts (100%) rename {apps/server/src => app/server}/utils/rclone.ts (100%) rename {apps/server/src => app/server}/utils/restic.ts (99%) rename {apps/server/src => app/server}/utils/sanitize.ts (100%) rename {apps/server/src => app/server}/utils/spawn.ts (100%) rename {apps/server/src => app/server}/utils/timeout.ts (100%) rename {apps/client/app => app}/utils/clipboard.ts (100%) rename {apps/client/app => app}/utils/object.ts (100%) rename {apps/client/app => app}/utils/utils.ts (100%) delete mode 100644 apps/client/.gitignore delete mode 100644 apps/client/README.md delete mode 100644 apps/client/app/components/ui/breadcrumb.tsx delete mode 100644 apps/client/app/components/ui/checkbox.tsx delete mode 100644 apps/client/app/components/ui/dialog.tsx delete mode 100644 apps/client/app/components/ui/label.tsx delete mode 100644 apps/client/app/components/ui/scroll-area.tsx delete mode 100644 apps/client/app/components/ui/separator.tsx delete mode 100644 apps/client/app/components/ui/sheet.tsx delete mode 100644 apps/client/app/components/ui/skeleton.tsx delete mode 100644 apps/client/app/components/ui/table.tsx delete mode 100644 apps/client/app/components/ui/tooltip.tsx delete mode 100644 apps/client/app/routes.ts delete mode 100644 apps/client/package.json delete mode 100644 apps/client/vite.config.ts delete mode 100644 apps/server/.gitignore delete mode 100644 apps/server/build.ts delete mode 100644 apps/server/package.json delete mode 100644 apps/server/tsconfig.json rename apps/client/components.json => components.json (100%) rename {apps/server/drizzle => drizzle}/0000_known_madelyne_pryor.sql (100%) rename {apps/server/drizzle => drizzle}/0001_far_frank_castle.sql (100%) rename {apps/server/drizzle => drizzle}/0002_cheerful_randall.sql (100%) rename {apps/server/drizzle => drizzle}/0003_mature_hellcat.sql (100%) rename {apps/server/drizzle => drizzle}/0004_wealthy_tomas.sql (100%) rename {apps/server/drizzle => drizzle}/0005_simple_alice.sql (100%) rename {apps/server/drizzle => drizzle}/0006_secret_micromacro.sql (100%) rename {apps/server/drizzle => drizzle}/0007_watery_sersi.sql (100%) rename {apps/server/drizzle => drizzle}/0008_silent_lady_bullseye.sql (100%) rename {apps/server/drizzle => drizzle}/0009_little_adam_warlock.sql (100%) rename {apps/server/drizzle => drizzle}/0010_perfect_proemial_gods.sql (100%) rename {apps/server/drizzle => drizzle}/meta/0000_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0001_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0002_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0003_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0004_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0005_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0006_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0007_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0008_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0009_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/0010_snapshot.json (100%) rename {apps/server/drizzle => drizzle}/meta/_journal.json (100%) create mode 100644 mutagen.yml.lock delete mode 100644 packages/schemas/package.json delete mode 100644 packages/schemas/tsconfig.json rename {apps/client/public => public}/images/background.jpg (100%) rename {apps/client/public => public}/images/favicon/apple-touch-icon.png (100%) rename {apps/client/public => public}/images/favicon/favicon-96x96.png (100%) rename {apps/client/public => public}/images/favicon/favicon.ico (100%) rename {apps/client/public => public}/images/favicon/favicon.svg (100%) rename {apps/client/public => public}/images/favicon/site.webmanifest (100%) rename {apps/client/public => public}/images/favicon/web-app-manifest-192x192.png (100%) rename {apps/client/public => public}/images/favicon/web-app-manifest-512x512.png (100%) rename apps/client/react-router.config.ts => react-router.config.ts (92%) rename apps/client/tsconfig.json => tsconfig.json (100%) delete mode 100644 turbo.json create mode 100644 vite.config.ts diff --git a/.dockerignore b/.dockerignore index 7cac851b..7015b036 100644 --- a/.dockerignore +++ b/.dockerignore @@ -12,12 +12,10 @@ !**/build.ts !**/components.json -!apps/**/src/** -!apps/**/drizzle/** -!apps/**/app/** -!apps/**/public/** - -!packages/**/src/** +!src/** +!drizzle/** +!app/** +!public/** # License files and attributions !LICENSE diff --git a/.gitignore b/.gitignore index 2bd0209f..4addbfe3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,47 +1,11 @@ -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib +.DS_Store +/node_modules/ -# Test binary, built with `go test -c` -*.test +# React Router +/.react-router/ +/build/ +/dist/ -# Code coverage profiles and other test artifacts -*.out -coverage.* -*.coverprofile -profile.cov - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work -go.work.sum - -# env file .env - -# Editor/IDE -# .idea/ -# .vscode/ -ironmount -out/ -*.db -tmp/ - -node_modules/ -.env* - .turbo - -mutagen.yml.lock - -data/ - CLAUDE.md diff --git a/Dockerfile b/Dockerfile index 0a7ad18a..909077ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,9 +45,6 @@ WORKDIR /app COPY --from=deps /deps/restic /usr/local/bin/restic COPY --from=deps /deps/rclone /usr/local/bin/rclone COPY ./package.json ./bun.lock ./ -COPY ./packages/schemas/package.json ./packages/schemas/package.json -COPY ./apps/client/package.json ./apps/client/package.json -COPY ./apps/server/package.json ./apps/server/package.json RUN bun install --frozen-lockfile @@ -84,14 +81,15 @@ WORKDIR /app COPY --from=deps /deps/restic /usr/local/bin/restic COPY --from=deps /deps/rclone /usr/local/bin/rclone -COPY --from=builder /app/apps/server/dist ./ -COPY --from=builder /app/apps/server/drizzle ./assets/migrations -COPY --from=builder /app/apps/client/dist/client ./assets/frontend +COPY --from=builder /app/dist/client ./dist/client +COPY --from=builder /app/dist/server ./dist/server +COPY --from=builder /app/drizzle ./assets/migrations +COPY --from=builder /app/package.json ./ # Include third-party licenses and attribution COPY ./LICENSES ./LICENSES COPY ./NOTICES.md ./NOTICES.md COPY ./LICENSE ./LICENSE.md -CMD ["bun", "./index.js"] +CMD ["bun", "run", "start"] diff --git a/apps/client/app/api-client/@tanstack/react-query.gen.ts b/app/api-client/@tanstack/react-query.gen.ts similarity index 100% rename from apps/client/app/api-client/@tanstack/react-query.gen.ts rename to app/api-client/@tanstack/react-query.gen.ts diff --git a/apps/client/app/api-client/client.gen.ts b/app/api-client/client.gen.ts similarity index 100% rename from apps/client/app/api-client/client.gen.ts rename to app/api-client/client.gen.ts diff --git a/apps/client/app/api-client/client/client.gen.ts b/app/api-client/client/client.gen.ts similarity index 100% rename from apps/client/app/api-client/client/client.gen.ts rename to app/api-client/client/client.gen.ts diff --git a/apps/client/app/api-client/client/index.ts b/app/api-client/client/index.ts similarity index 100% rename from apps/client/app/api-client/client/index.ts rename to app/api-client/client/index.ts diff --git a/apps/client/app/api-client/client/types.gen.ts b/app/api-client/client/types.gen.ts similarity index 100% rename from apps/client/app/api-client/client/types.gen.ts rename to app/api-client/client/types.gen.ts diff --git a/apps/client/app/api-client/client/utils.gen.ts b/app/api-client/client/utils.gen.ts similarity index 100% rename from apps/client/app/api-client/client/utils.gen.ts rename to app/api-client/client/utils.gen.ts diff --git a/apps/client/app/api-client/core/auth.gen.ts b/app/api-client/core/auth.gen.ts similarity index 100% rename from apps/client/app/api-client/core/auth.gen.ts rename to app/api-client/core/auth.gen.ts diff --git a/apps/client/app/api-client/core/bodySerializer.gen.ts b/app/api-client/core/bodySerializer.gen.ts similarity index 100% rename from apps/client/app/api-client/core/bodySerializer.gen.ts rename to app/api-client/core/bodySerializer.gen.ts diff --git a/apps/client/app/api-client/core/params.gen.ts b/app/api-client/core/params.gen.ts similarity index 100% rename from apps/client/app/api-client/core/params.gen.ts rename to app/api-client/core/params.gen.ts diff --git a/apps/client/app/api-client/core/pathSerializer.gen.ts b/app/api-client/core/pathSerializer.gen.ts similarity index 100% rename from apps/client/app/api-client/core/pathSerializer.gen.ts rename to app/api-client/core/pathSerializer.gen.ts diff --git a/apps/client/app/api-client/core/types.gen.ts b/app/api-client/core/types.gen.ts similarity index 100% rename from apps/client/app/api-client/core/types.gen.ts rename to app/api-client/core/types.gen.ts diff --git a/apps/client/app/api-client/index.ts b/app/api-client/index.ts similarity index 100% rename from apps/client/app/api-client/index.ts rename to app/api-client/index.ts diff --git a/apps/client/app/api-client/sdk.gen.ts b/app/api-client/sdk.gen.ts similarity index 100% rename from apps/client/app/api-client/sdk.gen.ts rename to app/api-client/sdk.gen.ts diff --git a/apps/client/app/api-client/types.gen.ts b/app/api-client/types.gen.ts similarity index 100% rename from apps/client/app/api-client/types.gen.ts rename to app/api-client/types.gen.ts diff --git a/apps/client/app/app.css b/app/app.css similarity index 100% rename from apps/client/app/app.css rename to app/app.css diff --git a/apps/client/app/components/app-breadcrumb.tsx b/app/client/components/app-breadcrumb.tsx similarity index 90% rename from apps/client/app/components/app-breadcrumb.tsx rename to app/client/components/app-breadcrumb.tsx index ca215dc5..5918651f 100644 --- a/apps/client/app/components/app-breadcrumb.tsx +++ b/app/client/components/app-breadcrumb.tsx @@ -6,8 +6,8 @@ import { BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, -} from "~/components/ui/breadcrumb"; -import { useBreadcrumbs } from "~/lib/breadcrumbs"; +} from "~/client/components/ui/breadcrumb"; +import { useBreadcrumbs } from "~/client/lib/breadcrumbs"; export function AppBreadcrumb() { const breadcrumbs = useBreadcrumbs(); diff --git a/apps/client/app/components/app-sidebar.tsx b/app/client/components/app-sidebar.tsx similarity index 94% rename from apps/client/app/components/app-sidebar.tsx rename to app/client/components/app-sidebar.tsx index 78bc14c7..9995ee1b 100644 --- a/apps/client/app/components/app-sidebar.tsx +++ b/app/client/components/app-sidebar.tsx @@ -10,9 +10,9 @@ import { SidebarMenuButton, SidebarMenuItem, useSidebar, -} from "~/components/ui/sidebar"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/components/ui/tooltip"; -import { cn } from "~/lib/utils"; +} from "~/client/components/ui/sidebar"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/client/components/ui/tooltip"; +import { cn } from "~/client/lib/utils"; const items = [ { diff --git a/apps/client/app/components/auth-layout.tsx b/app/client/components/auth-layout.tsx similarity index 100% rename from apps/client/app/components/auth-layout.tsx rename to app/client/components/auth-layout.tsx diff --git a/apps/client/app/components/bytes-size.tsx b/app/client/components/bytes-size.tsx similarity index 100% rename from apps/client/app/components/bytes-size.tsx rename to app/client/components/bytes-size.tsx diff --git a/apps/client/app/components/create-repository-dialog.tsx b/app/client/components/create-repository-dialog.tsx similarity index 97% rename from apps/client/app/components/create-repository-dialog.tsx rename to app/client/components/create-repository-dialog.tsx index 88aa1dd8..972250ac 100644 --- a/apps/client/app/components/create-repository-dialog.tsx +++ b/app/client/components/create-repository-dialog.tsx @@ -3,7 +3,7 @@ import { Plus } from "lucide-react"; import { useId } from "react"; import { toast } from "sonner"; import { createRepositoryMutation } from "~/api-client/@tanstack/react-query.gen"; -import { parseError } from "~/lib/errors"; +import { parseError } from "~/client/lib/errors"; import { CreateRepositoryForm } from "./create-repository-form"; import { Button } from "./ui/button"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog"; diff --git a/apps/client/app/components/create-repository-form.tsx b/app/client/components/create-repository-form.tsx similarity index 98% rename from apps/client/app/components/create-repository-form.tsx rename to app/client/components/create-repository-form.tsx index d925ad3e..2a645cae 100644 --- a/apps/client/app/components/create-repository-form.tsx +++ b/app/client/components/create-repository-form.tsx @@ -1,9 +1,8 @@ import { arktypeResolver } from "@hookform/resolvers/arktype"; -import { COMPRESSION_MODES, repositoryConfigSchema } from "@ironmount/schemas/restic"; import { type } from "arktype"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; -import { cn, slugify } from "~/lib/utils"; +import { cn, slugify } from "~/client/lib/utils"; import { deepClean } from "~/utils/object"; import { Button } from "./ui/button"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "./ui/form"; @@ -14,7 +13,8 @@ import { useQuery } from "@tanstack/react-query"; import { Alert, AlertDescription } from "./ui/alert"; import { ExternalLink } from "lucide-react"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; -import { useSystemInfo } from "~/hooks/use-system-info"; +import { useSystemInfo } from "~/client/hooks/use-system-info"; +import { COMPRESSION_MODES, repositoryConfigSchema } from "~/schemas/restic"; export const formSchema = type({ name: "2<=string<=32", diff --git a/apps/client/app/components/create-volume-dialog.tsx b/app/client/components/create-volume-dialog.tsx similarity index 97% rename from apps/client/app/components/create-volume-dialog.tsx rename to app/client/components/create-volume-dialog.tsx index e4d8880a..0ed77aef 100644 --- a/apps/client/app/components/create-volume-dialog.tsx +++ b/app/client/components/create-volume-dialog.tsx @@ -3,7 +3,7 @@ import { Plus } from "lucide-react"; import { useId } from "react"; import { toast } from "sonner"; import { createVolumeMutation } from "~/api-client/@tanstack/react-query.gen"; -import { parseError } from "~/lib/errors"; +import { parseError } from "~/client/lib/errors"; import { CreateVolumeForm } from "./create-volume-form"; import { Button } from "./ui/button"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog"; diff --git a/apps/client/app/components/create-volume-form.tsx b/app/client/components/create-volume-form.tsx similarity index 99% rename from apps/client/app/components/create-volume-form.tsx rename to app/client/components/create-volume-form.tsx index 961fdc57..7b8114ee 100644 --- a/apps/client/app/components/create-volume-form.tsx +++ b/app/client/components/create-volume-form.tsx @@ -1,18 +1,18 @@ import { arktypeResolver } from "@hookform/resolvers/arktype"; -import { volumeConfigSchema } from "@ironmount/schemas"; import { useMutation } from "@tanstack/react-query"; import { type } from "arktype"; import { CheckCircle, Loader2, XCircle } from "lucide-react"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { testConnectionMutation } from "~/api-client/@tanstack/react-query.gen"; -import { cn, slugify } from "~/lib/utils"; +import { cn, slugify } from "~/client/lib/utils"; import { deepClean } from "~/utils/object"; import { DirectoryBrowser } from "./directory-browser"; import { Button } from "./ui/button"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "./ui/form"; import { Input } from "./ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select"; +import { volumeConfigSchema } from "~/schemas/volumes"; export const formSchema = type({ name: "2<=string<=32", diff --git a/apps/client/app/components/directory-browser.tsx b/app/client/components/directory-browser.tsx similarity index 100% rename from apps/client/app/components/directory-browser.tsx rename to app/client/components/directory-browser.tsx diff --git a/apps/client/app/components/empty-state.tsx b/app/client/components/empty-state.tsx similarity index 100% rename from apps/client/app/components/empty-state.tsx rename to app/client/components/empty-state.tsx diff --git a/apps/client/app/components/file-tree.tsx b/app/client/components/file-tree.tsx similarity index 99% rename from apps/client/app/components/file-tree.tsx rename to app/client/components/file-tree.tsx index 88c45c14..f7636629 100644 --- a/apps/client/app/components/file-tree.tsx +++ b/app/client/components/file-tree.tsx @@ -10,8 +10,8 @@ import { ChevronDown, ChevronRight, File as FileIcon, Folder as FolderIcon, FolderOpen, Loader2 } from "lucide-react"; import { memo, type ReactNode, useCallback, useEffect, useMemo, useState } from "react"; -import { cn } from "~/lib/utils"; -import { Checkbox } from "~/components/ui/checkbox"; +import { cn } from "~/client/lib/utils"; +import { Checkbox } from "~/client/components/ui/checkbox"; const NODE_PADDING_LEFT = 12; diff --git a/apps/client/app/components/grid-background.tsx b/app/client/components/grid-background.tsx similarity index 95% rename from apps/client/app/components/grid-background.tsx rename to app/client/components/grid-background.tsx index 945cedb7..5f8df115 100644 --- a/apps/client/app/components/grid-background.tsx +++ b/app/client/components/grid-background.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from "react"; -import { cn } from "~/lib/utils"; +import { cn } from "~/client/lib/utils"; interface GridBackgroundProps { children: ReactNode; diff --git a/apps/client/app/components/layout.tsx b/app/client/components/layout.tsx similarity index 100% rename from apps/client/app/components/layout.tsx rename to app/client/components/layout.tsx diff --git a/apps/client/app/components/onoff.tsx b/app/client/components/onoff.tsx similarity index 95% rename from apps/client/app/components/onoff.tsx rename to app/client/components/onoff.tsx index a5b690da..7fe95082 100644 --- a/apps/client/app/components/onoff.tsx +++ b/app/client/components/onoff.tsx @@ -1,4 +1,4 @@ -import { cn } from "~/lib/utils"; +import { cn } from "~/client/lib/utils"; import { Switch } from "./ui/switch"; type Props = { diff --git a/apps/client/app/components/repository-icon.tsx b/app/client/components/repository-icon.tsx similarity index 87% rename from apps/client/app/components/repository-icon.tsx rename to app/client/components/repository-icon.tsx index 40d41526..aaf9d579 100644 --- a/apps/client/app/components/repository-icon.tsx +++ b/app/client/components/repository-icon.tsx @@ -1,5 +1,5 @@ -import type { RepositoryBackend } from "@ironmount/schemas/restic"; import { Database, HardDrive, Cloud } from "lucide-react"; +import type { RepositoryBackend } from "~/schemas/restic"; type Props = { backend: RepositoryBackend; diff --git a/apps/client/app/components/snapshots-table.tsx b/app/client/components/snapshots-table.tsx similarity index 94% rename from apps/client/app/components/snapshots-table.tsx rename to app/client/components/snapshots-table.tsx index 922ddde5..564b5e4a 100644 --- a/apps/client/app/components/snapshots-table.tsx +++ b/app/client/components/snapshots-table.tsx @@ -1,9 +1,9 @@ import { Calendar, Clock, Database, FolderTree, HardDrive } from "lucide-react"; import { useNavigate } from "react-router"; import type { ListSnapshotsResponse } from "~/api-client/types.gen"; -import { ByteSize } from "~/components/bytes-size"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table"; -import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip"; +import { ByteSize } from "~/client/components/bytes-size"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/client/components/ui/table"; +import { Tooltip, TooltipContent, TooltipTrigger } from "~/client/components/ui/tooltip"; import { formatDuration } from "~/utils/utils"; type Snapshot = ListSnapshotsResponse[number]; diff --git a/apps/client/app/components/status-dot.tsx b/app/client/components/status-dot.tsx similarity index 92% rename from apps/client/app/components/status-dot.tsx rename to app/client/components/status-dot.tsx index 9206a33c..d28d1584 100644 --- a/apps/client/app/components/status-dot.tsx +++ b/app/client/components/status-dot.tsx @@ -1,5 +1,5 @@ -import type { VolumeStatus } from "~/lib/types"; -import { cn } from "~/lib/utils"; +import type { VolumeStatus } from "~/client/lib/types"; +import { cn } from "~/client/lib/utils"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; export const StatusDot = ({ status }: { status: VolumeStatus }) => { diff --git a/apps/client/app/components/ui/alert-dialog.tsx b/app/client/components/ui/alert-dialog.tsx similarity index 97% rename from apps/client/app/components/ui/alert-dialog.tsx rename to app/client/components/ui/alert-dialog.tsx index 6bbf718b..4105ce33 100644 --- a/apps/client/app/components/ui/alert-dialog.tsx +++ b/app/client/components/ui/alert-dialog.tsx @@ -1,7 +1,7 @@ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; import type * as React from "react"; -import { buttonVariants } from "~/components/ui/button"; -import { cn } from "~/lib/utils"; +import { buttonVariants } from "~/client/components/ui/button"; +import { cn } from "~/client/lib/utils"; function AlertDialog({ ...props }: React.ComponentProps) { return ; diff --git a/apps/client/app/components/ui/alert.tsx b/app/client/components/ui/alert.tsx similarity index 97% rename from apps/client/app/components/ui/alert.tsx rename to app/client/components/ui/alert.tsx index b33dad7a..1014ae72 100644 --- a/apps/client/app/components/ui/alert.tsx +++ b/app/client/components/ui/alert.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "~/lib/utils"; +import { cn } from "~/client/lib/utils"; const alertVariants = cva( "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", diff --git a/apps/client/app/components/ui/badge.tsx b/app/client/components/ui/badge.tsx similarity index 100% rename from apps/client/app/components/ui/badge.tsx rename to app/client/components/ui/badge.tsx diff --git a/app/client/components/ui/breadcrumb.tsx b/app/client/components/ui/breadcrumb.tsx new file mode 100644 index 00000000..138587d7 --- /dev/null +++ b/app/client/components/ui/breadcrumb.tsx @@ -0,0 +1,92 @@ +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { ChevronRight, MoreHorizontal } from "lucide-react"; + +import { cn } from "~/client/lib/utils"; + +function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { + return