refactor: remove console logs from file upload and notification handling

This commit is contained in:
Daniel Luiz Alves 2025-10-24 18:02:43 -03:00
parent 965ef244f3
commit d0d5d012f0
12 changed files with 3 additions and 279 deletions

View File

@ -46,8 +46,6 @@ export class FileController {
const objectName = `${userId}/${Date.now()}-${Math.random().toString(36).substring(7)}-${filename}.${extension}`;
const expires = parseInt(env.PRESIGNED_URL_EXPIRATION);
console.log(`[PRESIGNED] Generating upload URL using STORAGE_URL: ${env.STORAGE_URL || "from S3 config"}`);
const url = await this.fileService.getPresignedPutUrl(objectName, expires);
return reply.status(200).send({ url, objectName });
@ -665,12 +663,8 @@ export class FileController {
// Generate unique object name (same pattern as simple upload)
const objectName = `${userId}/${Date.now()}-${Math.random().toString(36).substring(7)}-${filename}.${extension}`;
console.log(`[Multipart] Creating multipart upload for: ${objectName}`);
const uploadId = await this.fileService.createMultipartUpload(objectName);
console.log(`[Multipart] Created uploadId: ${uploadId}`);
return reply.status(200).send({
uploadId,
objectName,
@ -706,8 +700,6 @@ export class FileController {
const expires = parseInt(env.PRESIGNED_URL_EXPIRATION);
console.log(`[Multipart] Getting presigned URL for part ${partNum} of ${objectName}`);
const url = await this.fileService.getPresignedPartUrl(objectName, uploadId, partNum, expires);
return reply.status(200).send({ url });
@ -734,12 +726,8 @@ export class FileController {
return reply.status(400).send({ error: "uploadId, objectName, and parts are required" });
}
console.log(`[Multipart] Completing multipart upload for ${objectName} with ${parts.length} parts`);
await this.fileService.completeMultipartUpload(objectName, uploadId, parts);
console.log(`[Multipart] Completed successfully: ${objectName}`);
return reply.status(200).send({
message: "Multipart upload completed successfully",
objectName,
@ -766,12 +754,8 @@ export class FileController {
return reply.status(400).send({ error: "uploadId and objectName are required" });
}
console.log(`[Multipart] Aborting multipart upload for ${objectName}`);
await this.fileService.abortMultipartUpload(objectName, uploadId);
console.log(`[Multipart] Aborted successfully: ${objectName}`);
return reply.status(200).send({
message: "Multipart upload aborted successfully",
});

View File

@ -37,7 +37,6 @@ export class FileService {
// Multipart upload methods
async createMultipartUpload(objectName: string): Promise<string> {
console.log(`[FileService] Creating multipart upload for: ${objectName}`);
return await this.storageProvider.createMultipartUpload(objectName);
}
@ -47,7 +46,6 @@ export class FileService {
partNumber: number,
expires: number = 3600
): Promise<string> {
console.log(`[FileService] Getting presigned URL for part ${partNumber} of ${objectName}`);
return await this.storageProvider.getPresignedPartUrl(objectName, uploadId, partNumber, expires);
}
@ -56,12 +54,10 @@ export class FileService {
uploadId: string,
parts: Array<{ PartNumber: number; ETag: string }>
): Promise<void> {
console.log(`[FileService] Completing multipart upload for ${objectName}`);
await this.storageProvider.completeMultipartUpload(objectName, uploadId, parts);
}
async abortMultipartUpload(objectName: string, uploadId: string): Promise<void> {
console.log(`[FileService] Aborting multipart upload for ${objectName}`);
await this.storageProvider.abortMultipartUpload(objectName, uploadId);
}
}

View File

@ -466,12 +466,8 @@ export class ReverseShareController {
return reply.status(401).send({ error: "Unauthorized" });
}
console.log(`Copy to my files: User ${userId} copying file ${fileId}`);
const file = await this.reverseShareService.copyReverseShareFileToUserFiles(fileId, userId);
console.log(`Copy to my files: Successfully copied file ${fileId}`);
return reply.send({ file, message: "File copied to your files successfully" });
} catch (error: any) {
console.error(`Copy to my files: Error:`, error.message);

View File

@ -179,7 +179,6 @@ export class S3StorageProvider implements StorageProvider {
* Returns uploadId for subsequent part uploads
*/
async createMultipartUpload(objectName: string): Promise<string> {
console.log(`[S3] Creating multipart upload for: ${objectName}`);
const client = createPublicS3Client();
if (!client) {
throw new Error("S3 client could not be created");
@ -196,7 +195,6 @@ export class S3StorageProvider implements StorageProvider {
throw new Error("Failed to create multipart upload - no UploadId returned");
}
console.log(`[S3] Multipart upload created - uploadId: ${response.UploadId}`);
return response.UploadId;
}
@ -209,7 +207,6 @@ export class S3StorageProvider implements StorageProvider {
partNumber: number,
expires: number
): Promise<string> {
console.log(`[S3] Getting presigned URL for part ${partNumber} of ${objectName}`);
const client = createPublicS3Client();
if (!client) {
throw new Error("S3 client could not be created");
@ -223,7 +220,6 @@ export class S3StorageProvider implements StorageProvider {
});
const url = await getSignedUrl(client, command, { expiresIn: expires });
console.log(`[S3] Presigned URL generated for part ${partNumber}`);
return url;
}
@ -235,7 +231,6 @@ export class S3StorageProvider implements StorageProvider {
uploadId: string,
parts: Array<{ PartNumber: number; ETag: string }>
): Promise<void> {
console.log(`[S3] Completing multipart upload for ${objectName} with ${parts.length} parts`);
const client = this.ensureClient();
const command = new CompleteMultipartUploadCommand({
@ -251,14 +246,12 @@ export class S3StorageProvider implements StorageProvider {
});
await client.send(command);
console.log(`[S3] Multipart upload completed successfully for ${objectName}`);
}
/**
* Abort a multipart upload
*/
async abortMultipartUpload(objectName: string, uploadId: string): Promise<void> {
console.log(`[S3] Aborting multipart upload for ${objectName} - uploadId: ${uploadId}`);
const client = this.ensureClient();
const command = new AbortMultipartUploadCommand({
@ -268,6 +261,5 @@ export class S3StorageProvider implements StorageProvider {
});
await client.send(command);
console.log(`[S3] Multipart upload aborted for ${objectName}`);
}
}

View File

@ -1,11 +1,9 @@
import * as fs from "fs/promises";
import crypto from "node:crypto";
import path from "path";
import fastifyMultipart from "@fastify/multipart";
import { buildApp } from "./app";
import { directoriesConfig } from "./config/directories.config";
import { env } from "./env";
import { appRoutes } from "./modules/app/routes";
import { authProvidersRoutes } from "./modules/auth-providers/routes";
import { authRoutes } from "./modules/auth/routes";
@ -18,7 +16,6 @@ import { shareRoutes } from "./modules/share/routes";
import { storageRoutes } from "./modules/storage/routes";
import { twoFactorRoutes } from "./modules/two-factor/routes";
import { userRoutes } from "./modules/user/routes";
import { IS_RUNNING_IN_CONTAINER } from "./utils/container-detection";
if (typeof globalThis.crypto === "undefined") {
globalThis.crypto = crypto.webcrypto as any;
@ -88,7 +85,7 @@ async function startServer() {
if (isInternalStorage) {
console.log("📦 Using internal storage (auto-configured)");
} else if (isExternalS3) {
console.log("📦 Using external S3 storage (AWS/S3-compatible/etc)");
console.log("📦 Using external S3 storage (AWS/S3-compatible)");
} else {
console.log("⚠️ WARNING: Storage not configured! Storage may not work.");
}
@ -98,10 +95,7 @@ async function startServer() {
host: "0.0.0.0",
});
const storageMode = isInternalStorage ? "Internal Storage" : isExternalS3 ? "External S3" : "Not Configured";
console.log(`🌴 Palmr server running on port 3333 🌴`);
console.log(`📦 Storage: ${storageMode}`);
console.log(`🌴 Palmr server running on port 3333`);
// Cleanup on shutdown
process.on("SIGINT", () => process.exit(0));

View File

@ -34,8 +34,6 @@ export function BackgroundPickerForm() {
const applyBackground = useCallback((backgroundValues: { light: string; dark: string }) => {
document.documentElement.style.setProperty("--custom-background-light", backgroundValues.light);
document.documentElement.style.setProperty("--custom-background-dark", backgroundValues.dark);
console.log("Applied background:", backgroundValues);
}, []);
useEffect(() => {

View File

@ -36,8 +36,6 @@ export function FontPickerForm() {
document.documentElement.style.setProperty("--font-serif", fontValue);
document.body.style.fontFamily = fontValue;
console.log("Applied font:", fontValue);
}, []);
useEffect(() => {

View File

@ -26,7 +26,6 @@ export function RadiusPickerForm() {
const [isCollapsed, setIsCollapsed] = useState(true);
const applyRadius = useCallback((radiusValue: string) => {
document.documentElement.style.setProperty("--radius", radiusValue);
console.log("Applied radius:", radiusValue);
}, []);
useEffect(() => {

View File

@ -204,7 +204,6 @@ export function useFileBrowser() {
const loadFiles = useCallback(async () => {
try {
console.log("loadFiles called - starting to load files...");
setIsLoading(true);
const [filesResponse, foldersResponse] = await Promise.all([listFiles(), listFolders()]);
@ -239,12 +238,6 @@ export function useFileBrowser() {
} else {
setCurrentPath([]);
}
console.log("Files and folders updated:", {
filesCount: sortedFiles.length,
foldersCount: sortedFolders.length,
currentFolderId: resolvedFolderId,
});
} catch {
toast.error(t("files.loadError"));
} finally {

View File

@ -96,8 +96,6 @@ export function GlobalDropZone({ onSuccess, children, currentFolderId }: GlobalD
// All uploads are done (no pending/uploading)
if (pendingCount === 0 && successCount > 0) {
console.log("[GlobalDropZone] All uploads complete, showing toast");
toast.success(
errorCount > 0
? t("uploadFile.partialSuccess", { success: successCount, error: errorCount })

View File

@ -1,185 +0,0 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslations } from "next-intl";
import { toast } from "sonner";
interface NotificationOptions {
title: string;
body: string;
icon?: string;
badge?: string;
tag?: string;
requireInteraction?: boolean;
silent?: boolean;
data?: any;
}
export function usePushNotifications() {
const t = useTranslations();
const [permissionGranted, setPermissionGranted] = useState(false);
const isSupported = useRef(typeof window !== "undefined" && "Notification" in window);
const requestPermission = useCallback(async (): Promise<boolean> => {
if (!isSupported.current) {
console.warn("Push notifications are not supported in this browser");
return false;
}
try {
const permission = await Notification.requestPermission();
const granted = permission === "granted";
setPermissionGranted(granted);
if (permission === "granted") {
console.log("🔔 Push notifications enabled");
toast.success(t("notifications.permissionGranted"));
} else if (permission === "denied") {
console.warn("🚫 Push notifications denied");
toast.warning(t("notifications.permissionDenied"));
} else {
console.info("⏸️ Push notifications dismissed");
}
return granted;
} catch (error) {
console.error("Error requesting notification permission:", error);
return false;
}
}, [t]);
const sendNotification = useCallback(
async (options: NotificationOptions): Promise<boolean> => {
if (!isSupported.current) {
console.warn("Push notifications not supported");
return false;
}
if (Notification.permission !== "granted") {
const granted = await requestPermission();
if (!granted) return false;
}
try {
const notification = new Notification(options.title, {
body: options.body,
icon: options.icon || "/favicon.ico",
badge: options.badge,
tag: options.tag,
requireInteraction: options.requireInteraction ?? false,
silent: options.silent ?? false,
data: options.data,
});
if (!options.requireInteraction) {
setTimeout(() => {
notification.close();
}, 5000);
}
notification.onclick = (event) => {
event.preventDefault();
window.focus();
notification.close();
if (options.data?.action === "focus-downloads") {
const downloadIndicator = document.querySelector("[data-download-indicator]");
if (downloadIndicator) {
downloadIndicator.scrollIntoView({ behavior: "smooth" });
}
}
};
return true;
} catch (error) {
console.error("Error sending notification:", error);
return false;
}
},
[requestPermission]
);
useEffect(() => {
if (isSupported.current) {
setPermissionGranted(Notification.permission === "granted");
}
}, []);
const notifyDownloadComplete = useCallback(
async (fileName: string, fileSize?: number) => {
const sizeText = fileSize ? ` (${(fileSize / 1024 / 1024).toFixed(1)}MB)` : "";
return sendNotification({
title: t("notifications.downloadComplete.title"),
body: t("notifications.downloadComplete.body", {
fileName: fileName + sizeText,
}),
icon: "/favicon.ico",
tag: `download-complete-${Date.now()}`,
requireInteraction: false,
data: {
action: "focus-downloads",
type: "download-complete",
fileName,
fileSize,
},
});
},
[sendNotification, t]
);
const notifyDownloadFailed = useCallback(
async (fileName: string, error?: string) => {
return sendNotification({
title: t("notifications.downloadFailed.title"),
body: t("notifications.downloadFailed.body", {
fileName,
error: error || t("notifications.downloadFailed.unknownError"),
}),
icon: "/favicon.ico",
tag: `download-failed-${Date.now()}`,
requireInteraction: true,
data: {
action: "focus-downloads",
type: "download-failed",
fileName,
error,
},
});
},
[sendNotification, t]
);
const notifyQueueProcessing = useCallback(
async (fileName: string, position?: number) => {
const positionText = position ? t("notifications.queueProcessing.position", { position }) : "";
return sendNotification({
title: t("notifications.queueProcessing.title"),
body: t("notifications.queueProcessing.body", {
fileName,
position: positionText,
}),
icon: "/favicon.ico",
tag: `queue-processing-${Date.now()}`,
requireInteraction: false,
silent: true,
data: {
action: "focus-downloads",
type: "queue-processing",
fileName,
position,
},
});
},
[sendNotification, t]
);
return {
isSupported: isSupported.current,
hasPermission: permissionGranted,
requestPermission,
sendNotification,
notifyDownloadComplete,
notifyDownloadFailed,
notifyQueueProcessing,
};
}

View File

@ -115,16 +115,11 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
shouldUseMultipart: (file: any) => {
const fileSize = file.size || 0;
const useMultipart = fileSize >= UPLOAD_CONFIG.MULTIPART_THRESHOLD;
console.log(
`[Upload] File ${file.name} (${(fileSize / 1024 / 1024).toFixed(2)}MB) - Using ${useMultipart ? "MULTIPART" : "SIMPLE PUT"}`
);
return useMultipart;
},
// For simple uploads (<100MB)
async getUploadParameters(file: UppyFile<any, any>): Promise<AwsS3UploadParameters> {
console.log(`[Upload] Getting upload parameters for simple upload: ${file.name}`);
try {
// 1. Validate file if validation callback is provided
if (onValidateRef.current) {
@ -157,8 +152,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
// Store the FINAL object name in file metadata
uppy.setFileMeta(file.id, { objectName: finalObjectName });
console.log(`[Upload] Simple upload URL obtained for: ${finalObjectName}`);
return {
method: "PUT" as const,
url: result.url,
@ -175,10 +168,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
// For multipart uploads (≥100MB)
async createMultipartUpload(file: UppyFile<any, any>) {
const fileSize = file.size || 0;
console.log(
`[Upload:Multipart] Creating multipart upload for: ${file.name} (${(fileSize / 1024 / 1024).toFixed(2)}MB)`
);
try {
// 1. Validate file
if (onValidateRef.current) {
@ -210,8 +199,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
uploadId,
});
console.log(`[Upload:Multipart] Created - uploadId: ${uploadId}, objectName: ${actualObjectName}`);
return {
uploadId,
key: actualObjectName,
@ -222,7 +209,7 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
}
},
// List parts (for resuming multipart uploads)
//TODO: List parts (for resuming multipart uploads)
async listParts(file: UppyFile<any, any>, { uploadId, key }: any) {
console.log(`[Upload:Multipart] Listing parts for: ${file.name}`);
// Para simplificar, não vamos implementar resumo de upload por enquanto
@ -233,7 +220,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
// Sign individual parts for multipart upload
async signPart(file: UppyFile<any, any>, partData: any) {
const { uploadId, key, partNumber, signal } = partData;
console.log(`[Upload:Multipart] Signing part ${partNumber} for: ${file.name}`);
try {
const response = await getMultipartPartUrl({
@ -242,8 +228,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
partNumber: partNumber.toString(),
});
console.log(`[Upload:Multipart] Got signed URL for part ${partNumber}`);
// Return the signed URL object directly - Uppy expects { url, headers }
return {
url: response.data.url,
@ -257,7 +241,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
// Complete multipart upload
async completeMultipartUpload(file: UppyFile<any, any>, data: any) {
console.log(`[Upload:Multipart] Completing multipart upload for: ${file.name}`);
const { uploadId, key, parts } = data;
const meta = file.meta as { objectName: string };
@ -268,8 +251,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
parts,
});
console.log(`[Upload:Multipart] Completed successfully: ${meta.objectName}`);
return {};
} catch (error) {
console.error("[Upload:Multipart] Failed to complete multipart upload:", error);
@ -278,7 +259,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
},
async abortMultipartUpload(file: UppyFile<any, any>, data: any) {
console.log(`[Upload:Multipart] Aborting multipart upload for: ${file.name}`);
const { uploadId, key } = data;
const meta = file.meta as { objectName: string };
@ -287,8 +267,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
uploadId,
objectName: meta.objectName || key,
});
console.log(`[Upload:Multipart] Aborted: ${meta.objectName}`);
} catch (error) {
console.error("[Upload:Multipart] Failed to abort multipart upload:", error);
// Don't throw - abort is cleanup, shouldn't fail the operation
@ -337,15 +315,10 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
// Upload success
const handleSuccess = async (file: any, response: any) => {
const objectName = file.meta.objectName;
console.log("[Upload] Upload complete:", file.name, objectName);
console.log("[Upload] Response:", response);
console.log("[Upload] Response status:", response?.status);
console.log("[Upload] Response body:", response?.body);
try {
// Call registration callback
if (onAfterUploadRef.current) {
console.log("[Upload] Registering file:", file.name);
await onAfterUploadRef.current(file.id, file.data, objectName);
}
@ -370,7 +343,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
// All uploads complete
const handleComplete = (result: any) => {
console.log("[Upload] All uploads complete");
setIsUploading(false);
};
@ -396,8 +368,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
const uppy = uppyRef.current;
if (!uppy) return;
console.log(`[Upload] Adding ${files.length} files to upload queue`);
files.forEach((file) => {
try {
uppy.addFile({
@ -422,7 +392,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
const uppy = uppyRef.current;
if (!uppy) return;
console.log("[Upload] Starting upload");
setIsUploading(true);
uppy.upload();
}, []);
@ -434,8 +403,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
const uppy = uppyRef.current;
if (!uppy) return;
console.log("[Upload] Cancelling upload:", fileId);
uppy.removeFile(fileId);
setFileUploads((prev) => prev.map((f) => (f.id === fileId ? { ...f, status: "cancelled" } : f)));
}, []);
@ -451,8 +418,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
const file = fileUploads.find((f) => f.id === fileId);
if (!file) return;
console.log("[Upload] Retrying upload:", fileId);
// Reset status to pending
setFileUploads((prev) => prev.map((f) => (f.id === fileId ? { ...f, status: "pending", error: undefined } : f)));
@ -470,8 +435,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
const uppy = uppyRef.current;
if (!uppy) return;
console.log("[Upload] Removing file:", fileId);
// Revoke preview URL if exists
const file = fileUploads.find((f) => f.id === fileId);
if (file?.previewUrl) {
@ -491,8 +454,6 @@ export function useUppyUpload(options: UseUppyUploadOptions) {
const uppy = uppyRef.current;
if (!uppy) return;
console.log("[Upload] Clearing all files");
// Revoke all preview URLs from current state
setFileUploads((prev) => {
prev.forEach((file) => {