chore: add a pre-commit hook to format files (#336)

chore: add a pre-commit hook to format files
This commit is contained in:
Nico 2026-01-10 11:57:24 +01:00 committed by Nicolas Meienberger
parent 2989e1c3e8
commit b9f92f7430
7 changed files with 35 additions and 55 deletions

View file

@ -113,7 +113,8 @@
"unicorn/no-useless-spread": "warn", "unicorn/no-useless-spread": "warn",
"unicorn/prefer-set-size": "warn", "unicorn/prefer-set-size": "warn",
"unicorn/prefer-string-starts-ends-with": "warn", "unicorn/prefer-string-starts-ends-with": "warn",
"import/no-cycle": "error" "import/no-cycle": "error",
"eslint/no-console": ["warn", { "allow": ["warn", "error", "info"] }]
}, },
"settings": { "settings": {
"jsx-a11y": { "jsx-a11y": {

View file

@ -61,14 +61,14 @@ export function useServerEvents() {
eventSourceRef.current = eventSource; eventSourceRef.current = eventSource;
eventSource.addEventListener("connected", () => { eventSource.addEventListener("connected", () => {
console.log("[SSE] Connected to server events"); console.info("[SSE] Connected to server events");
}); });
eventSource.addEventListener("heartbeat", () => {}); eventSource.addEventListener("heartbeat", () => {});
eventSource.addEventListener("backup:started", (e) => { eventSource.addEventListener("backup:started", (e) => {
const data = JSON.parse(e.data) as BackupEvent; const data = JSON.parse(e.data) as BackupEvent;
console.log("[SSE] Backup started:", data); console.info("[SSE] Backup started:", data);
handlersRef.current.get("backup:started")?.forEach((handler) => { handlersRef.current.get("backup:started")?.forEach((handler) => {
handler(data); handler(data);
@ -85,7 +85,7 @@ export function useServerEvents() {
eventSource.addEventListener("backup:completed", (e) => { eventSource.addEventListener("backup:completed", (e) => {
const data = JSON.parse(e.data) as BackupEvent; const data = JSON.parse(e.data) as BackupEvent;
console.log("[SSE] Backup completed:", data); console.info("[SSE] Backup completed:", data);
void queryClient.invalidateQueries(); void queryClient.invalidateQueries();
void queryClient.refetchQueries(); void queryClient.refetchQueries();
@ -97,7 +97,7 @@ export function useServerEvents() {
eventSource.addEventListener("volume:mounted", (e) => { eventSource.addEventListener("volume:mounted", (e) => {
const data = JSON.parse(e.data) as VolumeEvent; const data = JSON.parse(e.data) as VolumeEvent;
console.log("[SSE] Volume mounted:", data); console.info("[SSE] Volume mounted:", data);
handlersRef.current.get("volume:mounted")?.forEach((handler) => { handlersRef.current.get("volume:mounted")?.forEach((handler) => {
handler(data); handler(data);
@ -106,7 +106,7 @@ export function useServerEvents() {
eventSource.addEventListener("volume:unmounted", (e) => { eventSource.addEventListener("volume:unmounted", (e) => {
const data = JSON.parse(e.data) as VolumeEvent; const data = JSON.parse(e.data) as VolumeEvent;
console.log("[SSE] Volume unmounted:", data); console.info("[SSE] Volume unmounted:", data);
handlersRef.current.get("volume:unmounted")?.forEach((handler) => { handlersRef.current.get("volume:unmounted")?.forEach((handler) => {
handler(data); handler(data);
@ -115,7 +115,7 @@ export function useServerEvents() {
eventSource.addEventListener("volume:updated", (e) => { eventSource.addEventListener("volume:updated", (e) => {
const data = JSON.parse(e.data) as VolumeEvent; const data = JSON.parse(e.data) as VolumeEvent;
console.log("[SSE] Volume updated:", data); console.info("[SSE] Volume updated:", data);
void queryClient.invalidateQueries(); void queryClient.invalidateQueries();
@ -126,7 +126,7 @@ export function useServerEvents() {
eventSource.addEventListener("volume:status_updated", (e) => { eventSource.addEventListener("volume:status_updated", (e) => {
const data = JSON.parse(e.data) as VolumeEvent; const data = JSON.parse(e.data) as VolumeEvent;
console.log("[SSE] Volume status updated:", data); console.info("[SSE] Volume status updated:", data);
void queryClient.invalidateQueries(); void queryClient.invalidateQueries();
@ -137,7 +137,7 @@ export function useServerEvents() {
eventSource.addEventListener("mirror:started", (e) => { eventSource.addEventListener("mirror:started", (e) => {
const data = JSON.parse(e.data) as MirrorEvent; const data = JSON.parse(e.data) as MirrorEvent;
console.log("[SSE] Mirror copy started:", data); console.info("[SSE] Mirror copy started:", data);
handlersRef.current.get("mirror:started")?.forEach((handler) => { handlersRef.current.get("mirror:started")?.forEach((handler) => {
handler(data); handler(data);
@ -146,7 +146,7 @@ export function useServerEvents() {
eventSource.addEventListener("mirror:completed", (e) => { eventSource.addEventListener("mirror:completed", (e) => {
const data = JSON.parse(e.data) as MirrorEvent; const data = JSON.parse(e.data) as MirrorEvent;
console.log("[SSE] Mirror copy completed:", data); console.info("[SSE] Mirror copy completed:", data);
// Invalidate queries to refresh mirror status in the UI // Invalidate queries to refresh mirror status in the UI
void queryClient.invalidateQueries(); void queryClient.invalidateQueries();
@ -161,7 +161,7 @@ export function useServerEvents() {
}; };
return () => { return () => {
console.log("[SSE] Disconnecting from server events"); console.info("[SSE] Disconnecting from server events");
eventSource.close(); eventSource.close();
eventSourceRef.current = null; eventSourceRef.current = null;
}; };

View file

@ -6,16 +6,11 @@ import { db } from "../../db/db";
import { twoFactor, usersTable } from "../../db/schema"; import { twoFactor, usersTable } from "../../db/schema";
const listUsers = () => { const listUsers = () => {
return db return db.select({ id: usersTable.id, username: usersTable.username }).from(usersTable);
.select({ id: usersTable.id, username: usersTable.username })
.from(usersTable);
}; };
const disable2FA = async (username: string) => { const disable2FA = async (username: string) => {
const [user] = await db const [user] = await db.select().from(usersTable).where(eq(usersTable.username, username));
.select()
.from(usersTable)
.where(eq(usersTable.username, username));
if (!user) { if (!user) {
throw new Error(`User "${username}" not found`); throw new Error(`User "${username}" not found`);
@ -26,10 +21,7 @@ const disable2FA = async (username: string) => {
} }
await db.transaction(async (tx) => { await db.transaction(async (tx) => {
await tx await tx.update(usersTable).set({ twoFactorEnabled: false }).where(eq(usersTable.id, user.id));
.update(usersTable)
.set({ twoFactorEnabled: false })
.where(eq(usersTable.id, user.id));
await tx.delete(twoFactor).where(eq(twoFactor.userId, user.id)); await tx.delete(twoFactor).where(eq(twoFactor.userId, user.id));
}); });
}; };
@ -38,7 +30,7 @@ export const disable2FACommand = new Command("disable-2fa")
.description("Disable two-factor authentication for a user") .description("Disable two-factor authentication for a user")
.option("-u, --username <username>", "Username of the account") .option("-u, --username <username>", "Username of the account")
.action(async (options) => { .action(async (options) => {
console.log("\n🔐 Zerobyte 2FA Disable\n"); console.info("\n🔐 Zerobyte 2FA Disable\n");
let username = options.username; let username = options.username;
@ -47,9 +39,7 @@ export const disable2FACommand = new Command("disable-2fa")
if (users.length === 0) { if (users.length === 0) {
console.error("❌ No users found in the database."); console.error("❌ No users found in the database.");
console.log( console.info(" Please create a user first by starting the application.");
" Please create a user first by starting the application.",
);
process.exit(1); process.exit(1);
} }
@ -61,10 +51,8 @@ export const disable2FACommand = new Command("disable-2fa")
try { try {
await disable2FA(username); await disable2FA(username);
console.log( console.info(`\n✅ Two-factor authentication has been disabled for user "${username}".`);
`\n✅ Two-factor authentication has been disabled for user "${username}".`, console.info(" The user can re-enable 2FA from their account settings.");
);
console.log(" The user can re-enable 2FA from their account settings.");
} catch (error) { } catch (error) {
console.error(`\n❌ Failed to disable 2FA: ${toMessage(error)}`); console.error(`\n❌ Failed to disable 2FA: ${toMessage(error)}`);
process.exit(1); process.exit(1);

View file

@ -7,16 +7,11 @@ import { db } from "../../db/db";
import { account, sessionsTable, usersTable } from "../../db/schema"; import { account, sessionsTable, usersTable } from "../../db/schema";
const listUsers = () => { const listUsers = () => {
return db return db.select({ id: usersTable.id, username: usersTable.username }).from(usersTable);
.select({ id: usersTable.id, username: usersTable.username })
.from(usersTable);
}; };
const resetPassword = async (username: string, newPassword: string) => { const resetPassword = async (username: string, newPassword: string) => {
const [user] = await db const [user] = await db.select().from(usersTable).where(eq(usersTable.username, username));
.select()
.from(usersTable)
.where(eq(usersTable.username, username));
if (!user) { if (!user) {
throw new Error(`User "${username}" not found`); throw new Error(`User "${username}" not found`);
@ -28,16 +23,11 @@ const resetPassword = async (username: string, newPassword: string) => {
await tx await tx
.update(account) .update(account)
.set({ password: newPasswordHash }) .set({ password: newPasswordHash })
.where( .where(and(eq(account.userId, user.id), eq(account.providerId, "credential")));
and(eq(account.userId, user.id), eq(account.providerId, "credential")),
);
if (user.passwordHash) { if (user.passwordHash) {
const legacyHash = await Bun.password.hash(newPassword); const legacyHash = await Bun.password.hash(newPassword);
await tx await tx.update(usersTable).set({ passwordHash: legacyHash }).where(eq(usersTable.id, user.id));
.update(usersTable)
.set({ passwordHash: legacyHash })
.where(eq(usersTable.id, user.id));
} }
await tx.delete(sessionsTable).where(eq(sessionsTable.userId, user.id)); await tx.delete(sessionsTable).where(eq(sessionsTable.userId, user.id));
@ -49,7 +39,7 @@ export const resetPasswordCommand = new Command("reset-password")
.option("-u, --username <username>", "Username of the account") .option("-u, --username <username>", "Username of the account")
.option("-p, --password <password>", "New password for the account") .option("-p, --password <password>", "New password for the account")
.action(async (options) => { .action(async (options) => {
console.log("\n🔐 Zerobyte Password Reset\n"); console.info("\n🔐 Zerobyte Password Reset\n");
let username = options.username; let username = options.username;
let newPassword = options.password; let newPassword = options.password;
@ -59,9 +49,7 @@ export const resetPasswordCommand = new Command("reset-password")
if (users.length === 0) { if (users.length === 0) {
console.error("❌ No users found in the database."); console.error("❌ No users found in the database.");
console.log( console.info(" Please create a user first by starting the application.");
" Please create a user first by starting the application.",
);
process.exit(1); process.exit(1);
} }
@ -99,10 +87,8 @@ export const resetPasswordCommand = new Command("reset-password")
try { try {
await resetPassword(username, newPassword); await resetPassword(username, newPassword);
console.log( console.info(`\n✅ Password for user "${username}" has been reset successfully.`);
`\n✅ Password for user "${username}" has been reset successfully.`, console.info(" All existing sessions have been invalidated.");
);
console.log(" All existing sessions have been invalidated.");
} catch (error) { } catch (error) {
console.error(`\n❌ Failed to reset password: ${toMessage(error)}`); console.error(`\n❌ Failed to reset password: ${toMessage(error)}`);
process.exit(1); process.exit(1);

View file

@ -1,6 +1,4 @@
import * as fs from "node:fs/promises"; import * as fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
export type SystemCapabilities = { export type SystemCapabilities = {

View file

@ -229,7 +229,7 @@ const testDestination = async (id: number) => {
const shoutrrrUrl = buildShoutrrrUrl(decryptedConfig); const shoutrrrUrl = buildShoutrrrUrl(decryptedConfig);
console.log("Testing notification with Shoutrrr URL:", shoutrrrUrl); logger.debug("Testing notification with Shoutrrr URL:", shoutrrrUrl);
const result = await sendNotification({ const result = await sendNotification({
shoutrrrUrl, shoutrrrUrl,

7
lefthook.yml Normal file
View file

@ -0,0 +1,7 @@
pre-commit:
commands:
oxfmt:
glob: '*.{js,jsx,ts,tsx,json,jsonc}'
run: bunx oxfmt --write {staged_files}
stage_fixed: true