refactor: pr feedbacks
This commit is contained in:
parent
0da4b45d67
commit
b7e98deca1
9 changed files with 44 additions and 31 deletions
|
|
@ -14,7 +14,6 @@ import { useState, useEffect } from "react";
|
||||||
import { EmptyState } from "~/client/components/empty-state";
|
import { EmptyState } from "~/client/components/empty-state";
|
||||||
import { Button } from "~/client/components/ui/button";
|
import { Button } from "~/client/components/ui/button";
|
||||||
import { Card, CardContent } from "~/client/components/ui/card";
|
import { Card, CardContent } from "~/client/components/ui/card";
|
||||||
import { listBackupSchedules } from "~/client/api-client";
|
|
||||||
import {
|
import {
|
||||||
listBackupSchedulesOptions,
|
listBackupSchedulesOptions,
|
||||||
reorderBackupSchedulesMutation,
|
reorderBackupSchedulesMutation,
|
||||||
|
|
@ -23,12 +22,6 @@ import { SortableCard } from "~/client/components/sortable-card";
|
||||||
import { BackupCard } from "../components/backup-card";
|
import { BackupCard } from "../components/backup-card";
|
||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
|
|
||||||
export const clientLoader = async () => {
|
|
||||||
const jobs = await listBackupSchedules();
|
|
||||||
if (jobs.data) return jobs.data;
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function BackupsPage() {
|
export function BackupsPage() {
|
||||||
const { data: schedules } = useSuspenseQuery({
|
const { data: schedules } = useSuspenseQuery({
|
||||||
...listBackupSchedulesOptions(),
|
...listBackupSchedulesOptions(),
|
||||||
|
|
|
||||||
|
|
@ -110,10 +110,6 @@ export function SnapshotDetailsPage({ repositoryId, snapshotId }: { repositoryId
|
||||||
<span className="text-muted-foreground">Snapshot ID:</span>
|
<span className="text-muted-foreground">Snapshot ID:</span>
|
||||||
<p className="font-mono break-all">{data.short_id}</p>
|
<p className="font-mono break-all">{data.short_id}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<span className="text-muted-foreground">Short ID:</span>
|
|
||||||
<p className="font-mono break-all">{data.short_id}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<span className="text-muted-foreground">Hostname:</span>
|
<span className="text-muted-foreground">Hostname:</span>
|
||||||
<p>{data.hostname}</p>
|
<p>{data.hostname}</p>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ type AsyncLocalStorageConstructor = new <T>() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
let requestClientStore: RequestClientStore | undefined;
|
let requestClientStore: RequestClientStore | undefined;
|
||||||
|
let requestClientStorePromise: Promise<RequestClientStore | undefined> | undefined;
|
||||||
|
|
||||||
const ASYNC_HOOKS_MODULE = "node:async_hooks";
|
const ASYNC_HOOKS_MODULE = "node:async_hooks";
|
||||||
|
|
||||||
|
|
@ -22,14 +23,17 @@ const loadRequestClientStore = async (): Promise<RequestClientStore | undefined>
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requestClientStore) {
|
if (!requestClientStorePromise) {
|
||||||
const asyncHooksModule = (await import(/* @vite-ignore */ ASYNC_HOOKS_MODULE)) as {
|
requestClientStorePromise = (async () => {
|
||||||
AsyncLocalStorage: AsyncLocalStorageConstructor;
|
const asyncHooksModule = (await import(/* @vite-ignore */ ASYNC_HOOKS_MODULE)) as {
|
||||||
};
|
AsyncLocalStorage: AsyncLocalStorageConstructor;
|
||||||
requestClientStore = new asyncHooksModule.AsyncLocalStorage<RequestClient>();
|
};
|
||||||
|
requestClientStore = new asyncHooksModule.AsyncLocalStorage<RequestClient>();
|
||||||
|
return requestClientStore;
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestClientStore;
|
return requestClientStorePromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getRequestClient(): RequestClient {
|
export function getRequestClient(): RequestClient {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { getStatus } from "~/client/api-client";
|
|
||||||
import { createMiddleware } from "@tanstack/react-start";
|
import { createMiddleware } from "@tanstack/react-start";
|
||||||
import { redirect } from "@tanstack/react-router";
|
import { redirect } from "@tanstack/react-router";
|
||||||
import { auth } from "~/server/lib/auth";
|
import { auth } from "~/server/lib/auth";
|
||||||
import { getRequestHeaders } from "@tanstack/react-start/server";
|
import { getRequestHeaders } from "@tanstack/react-start/server";
|
||||||
|
import { authService } from "~/server/modules/auth/auth.service";
|
||||||
|
|
||||||
export const authMiddleware = createMiddleware().server(async ({ next, request }) => {
|
export const authMiddleware = createMiddleware().server(async ({ next, request }) => {
|
||||||
const headers = getRequestHeaders();
|
const headers = getRequestHeaders();
|
||||||
|
|
@ -11,8 +11,8 @@ export const authMiddleware = createMiddleware().server(async ({ next, request }
|
||||||
const isAuthRoute = ["/login", "/onboarding"].includes(new URL(request.url).pathname);
|
const isAuthRoute = ["/login", "/onboarding"].includes(new URL(request.url).pathname);
|
||||||
|
|
||||||
if (!session?.user?.id && !isAuthRoute) {
|
if (!session?.user?.id && !isAuthRoute) {
|
||||||
const status = await getStatus().catch(() => ({ data: { hasUsers: false } }));
|
const hasUsers = await authService.hasUsers();
|
||||||
if (!status.data?.hasUsers) {
|
if (!hasUsers) {
|
||||||
throw redirect({ to: "/onboarding" });
|
throw redirect({ to: "/onboarding" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,15 @@ export const Route = createFileRoute("/(dashboard)/backups/$backupId/$snapshotId
|
||||||
|
|
||||||
return { snapshot, repository, schedule: schedule.data };
|
return { snapshot, repository, schedule: schedule.data };
|
||||||
},
|
},
|
||||||
|
head: ({ params }) => ({
|
||||||
|
meta: [
|
||||||
|
{ title: `Zerobyte - Restore Snapshot ${params.snapshotId}` },
|
||||||
|
{
|
||||||
|
name: "description",
|
||||||
|
content: "Restore files from a backup snapshot.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
staticData: {
|
staticData: {
|
||||||
breadcrumb: (match) => [
|
breadcrumb: (match) => [
|
||||||
{ label: "Backup Jobs", href: "/backups" },
|
{ label: "Backup Jobs", href: "/backups" },
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,7 @@ export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()(
|
||||||
middleware: [apiClientMiddleware],
|
middleware: [apiClientMiddleware],
|
||||||
},
|
},
|
||||||
head: () => ({
|
head: () => ({
|
||||||
meta: [
|
meta: [{ title: "Zerobyte - Open Source Backup Solution" }],
|
||||||
{ charSet: "utf-8" },
|
|
||||||
{ name: "viewport", content: "width=device-width, initial-scale=1" },
|
|
||||||
{ title: "Zerobyte - Open Source Backup Solution" },
|
|
||||||
],
|
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
rel: "stylesheet",
|
rel: "stylesheet",
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,22 @@ export default createServerEntry({
|
||||||
|
|
||||||
process.on("SIGTERM", async () => {
|
process.on("SIGTERM", async () => {
|
||||||
logger.info("SIGTERM received, starting graceful shutdown...");
|
logger.info("SIGTERM received, starting graceful shutdown...");
|
||||||
await shutdown();
|
try {
|
||||||
process.exit(0);
|
await shutdown();
|
||||||
|
} catch (err) {
|
||||||
|
logger.error("Error during shutdown", err);
|
||||||
|
} finally {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("SIGINT", async () => {
|
process.on("SIGINT", async () => {
|
||||||
logger.info("SIGINT received, starting graceful shutdown...");
|
logger.info("SIGINT received, starting graceful shutdown...");
|
||||||
await shutdown();
|
try {
|
||||||
process.exit(0);
|
await shutdown();
|
||||||
|
} catch (err) {
|
||||||
|
logger.error("Error during shutdown", err);
|
||||||
|
} finally {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { format } from "date-fns";
|
||||||
import { createConsola, type ConsolaReporter } from "consola";
|
import { createConsola, type ConsolaReporter } from "consola";
|
||||||
import { formatWithOptions } from "node:util";
|
import { formatWithOptions } from "node:util";
|
||||||
import { sanitizeSensitiveData } from "./sanitize";
|
import { sanitizeSensitiveData } from "./sanitize";
|
||||||
|
|
@ -50,17 +51,18 @@ const reporter: ConsolaReporter = {
|
||||||
log(logObj, ctx) {
|
log(logObj, ctx) {
|
||||||
const level = resolveLevel(logObj.type);
|
const level = resolveLevel(logObj.type);
|
||||||
|
|
||||||
|
const timestamp = colorize("\x1b[90m", format(new Date(), "HH:mm:ss"));
|
||||||
const style = levelStyles[level];
|
const style = levelStyles[level];
|
||||||
const prefix = colorize(style.color, style.label);
|
const prefix = colorize(style.color, style.label);
|
||||||
const tag = logObj.tag ? `[${logObj.tag}]` : "";
|
const tag = logObj.tag ? `[${logObj.tag}]` : "";
|
||||||
const message = formatWithOptions(
|
const message = formatWithOptions(
|
||||||
{
|
{
|
||||||
colors: useColor,
|
|
||||||
...ctx.options.formatOptions,
|
...ctx.options.formatOptions,
|
||||||
|
colors: useColor,
|
||||||
},
|
},
|
||||||
...logObj.args,
|
...logObj.args,
|
||||||
);
|
);
|
||||||
const line = [prefix, tag, message].filter(Boolean).join(" ");
|
const line = [timestamp, prefix, tag, message].filter(Boolean).join(" ");
|
||||||
const stream = logObj.level < 2 ? (ctx.options.stderr ?? process.stderr) : (ctx.options.stdout ?? process.stdout);
|
const stream = logObj.level < 2 ? (ctx.options.stderr ?? process.stderr) : (ctx.options.stdout ?? process.stdout);
|
||||||
stream.write(line + "\n");
|
stream.write(line + "\n");
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
import viteReact from "@vitejs/plugin-react";
|
import viteReact from "@vitejs/plugin-react";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
define: {
|
||||||
|
"process.env.NODE_ENV": "production",
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
tsconfigPaths(),
|
tsconfigPaths(),
|
||||||
tanstackStart({
|
tanstackStart({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue