refactor: enforce strict linting rules, replace forEach with for...of loops, and remove console logging throughout the frontend.

This commit is contained in:
ramvignesh-b
2026-04-13 14:30:17 +05:30
parent 2776aac69a
commit 12763ab7ab
12 changed files with 38 additions and 37 deletions
+20 -1
View File
@@ -17,7 +17,26 @@
"linter": { "linter": {
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": true "recommended": true,
"complexity": {
"noForEach": "error",
"useLiteralKeys": "error"
},
"style": {
"useConst": "error",
"noNonNullAssertion": "warn"
},
"a11y": {
"useAltText": "error",
"noAutofocus": "warn"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsole": "warn"
},
"correctness": {
"noUnusedVariables": "error"
}
}, },
"includes": ["**", "!backend"] "includes": ["**", "!backend"]
}, },
-2
View File
@@ -48,8 +48,6 @@ api.interceptors.response.use(
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`; originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
return api(originalRequest); return api(originalRequest);
} catch (refreshError) { } catch (refreshError) {
// Refresh failed, perform logout to clear tokens
console.error("Session expired, logging out...");
useAuthStore.getState().clearAuth(); useAuthStore.getState().clearAuth();
return Promise.reject(refreshError); return Promise.reject(refreshError);
} }
+6 -6
View File
@@ -67,10 +67,10 @@ export const ComposeCanvas = forwardRef<
if (initialData) { if (initialData) {
await canvas.loadFromJSON(initialData); await canvas.loadFromJSON(initialData);
if (readOnly) { if (readOnly) {
canvas.getObjects().forEach((obj) => { for (const obj of canvas.getObjects()) {
obj.selectable = false; obj.selectable = false;
obj.evented = false; obj.evented = false;
}); }
} }
canvas.renderAll(); canvas.renderAll();
} else { } else {
@@ -119,11 +119,11 @@ export const ComposeCanvas = forwardRef<
const hiddenTextareas = document.querySelectorAll( const hiddenTextareas = document.querySelectorAll(
'textarea[data-fabric="textarea"]', 'textarea[data-fabric="textarea"]',
); );
hiddenTextareas.forEach((ta) => { for (const textArea of hiddenTextareas) {
if (!ta.getAttribute("aria-label")) { if (!textArea.getAttribute("aria-label")) {
ta.setAttribute("aria-label", "Canvas text input"); textArea.setAttribute("aria-label", "Canvas text input");
}
} }
});
}, 100); }, 100);
canvas.on("mouse:down", (opt) => { canvas.on("mouse:down", (opt) => {
+2 -2
View File
@@ -15,8 +15,8 @@ export const replacePathParams = (
params: Record<string, string>, params: Record<string, string>,
): string => { ): string => {
let result = url; let result = url;
Object.entries(params).forEach(([key, value]) => { for (const [key, value] of Object.entries(params)) {
result = result.replace(`:${key}`, value); result = result.replace(`:${key}`, value);
}); }
return result; return result;
}; };
+1 -2
View File
@@ -36,8 +36,7 @@ export const useAuth = () => {
const logout = async () => { const logout = async () => {
try { try {
await api.post(endpoints.LOGOUT); await api.post(endpoints.LOGOUT);
} catch (error) { } catch (_error) {
console.error("Logout failed:", error);
} finally { } finally {
clearAuth(); clearAuth();
setMasterKey(null); setMasterKey(null);
+2 -3
View File
@@ -43,8 +43,7 @@ async function decryptLetters(
)) as LetterMetadata; )) as LetterMetadata;
return { ...letter, metadata }; return { ...letter, metadata };
} catch (err) { } catch (_err) {
console.warn("Decryption failed for letter:", letter.public_id, err);
return { return {
...letter, ...letter,
metadata: { recipient: "Encrypted Letter" }, metadata: { recipient: "Encrypted Letter" },
@@ -67,7 +66,7 @@ export function useLetters() {
.get(endpoints.LETTERS) .get(endpoints.LETTERS)
.then((res) => decryptLetters(res.data, masterKey)) .then((res) => decryptLetters(res.data, masterKey))
.then(setLetters) .then(setLetters)
.catch((err) => console.error("Drawer load failed:", err)) .catch((_err) => {})
.finally(() => setLoading(false)); .finally(() => setLoading(false));
}, [masterKey]); }, [masterKey]);
+1 -2
View File
@@ -28,8 +28,7 @@ export default function Activate() {
}); });
await publicApi.get(url); await publicApi.get(url);
setStatus("success"); setStatus("success");
} catch (err) { } catch (_err) {
console.error("Activation error:", err);
setStatus("error"); setStatus("error");
} }
}; };
+3 -7
View File
@@ -79,8 +79,7 @@ export default function Editor() {
requestAnimationFrame(() => { requestAnimationFrame(() => {
canvasRef.current?.loadData(canvasData); canvasRef.current?.loadData(canvasData);
}); });
} catch (err) { } catch (_err) {
console.error("Failed to load existing letter:", err);
} finally { } finally {
setIsInitialLoading(false); setIsInitialLoading(false);
} }
@@ -158,8 +157,7 @@ export default function Editor() {
} }
setTimeout(() => setIsSaveSuccess(false), 5000); setTimeout(() => setIsSaveSuccess(false), 5000);
} catch (error) { } catch (_error) {
console.error("Save failed:", error);
} finally { } finally {
setIsSealing(false); setIsSealing(false);
} }
@@ -169,9 +167,7 @@ export default function Editor() {
if (!shareLink) return; if (!shareLink) return;
try { try {
await navigator.clipboard.writeText(shareLink); await navigator.clipboard.writeText(shareLink);
} catch (err) { } catch (_err) {}
console.error("Failed to copy:", err);
}
}; };
return ( return (
-1
View File
@@ -46,7 +46,6 @@ export default function Login() {
navigate(ROUTES.DRAWER); navigate(ROUTES.DRAWER);
} catch (err) { } catch (err) {
console.error("Login error:", err);
let message = let message =
"Sorry, we're experiencing technical issues.\nPlease try again later."; "Sorry, we're experiencing technical issues.\nPlease try again later.";
if (axios.isAxiosError(err) && err.response?.status !== 500) { if (axios.isAxiosError(err) && err.response?.status !== 500) {
-1
View File
@@ -52,7 +52,6 @@ export default function Reader() {
setCanvasData(json); setCanvasData(json);
setIsDecrypting(false); setIsDecrypting(false);
} catch (err: any) { } catch (err: any) {
console.error("Reader Error:", err);
setError(`Failed to load letter: ${err.message || "Unknown error"}`); setError(`Failed to load letter: ${err.message || "Unknown error"}`);
setIsDecrypting(false); setIsDecrypting(false);
} }
-1
View File
@@ -50,7 +50,6 @@ export default function Register() {
}); });
navigate(ROUTES.VERIFY_EMAIL); navigate(ROUTES.VERIFY_EMAIL);
} catch (err) { } catch (err) {
console.error("Registration error:", err);
let message = "Registration failed. Please try again."; let message = "Registration failed. Please try again.";
if (axios.isAxiosError(err)) { if (axios.isAxiosError(err)) {
message = err.response?.data?.message || message; message = err.response?.data?.message || message;
+3 -9
View File
@@ -39,9 +39,7 @@ export async function decryptCanvasImages(
// We need the raw file in the editor so we can re-encrypt it if the user saves again. // We need the raw file in the editor so we can re-encrypt it if the user saves again.
obj._customRawFile = await blobUrlToFile(blobUrl, obj.src); obj._customRawFile = await blobUrlToFile(blobUrl, obj.src);
} }
} catch (err) { } catch (_err) {}
console.error("Error decrypting image in canvas:", obj.src, err);
}
} }
} }
} }
@@ -66,9 +64,7 @@ export async function decryptCanvasImagesWithSharingKey(
try { try {
const res = await api.get(remoteUrl, { responseType: "blob" }); const res = await api.get(remoteUrl, { responseType: "blob" });
obj.src = await crypto.decryptImageWithSharingKey(res.data, sharingKey); obj.src = await crypto.decryptImageWithSharingKey(res.data, sharingKey);
} catch (err) { } catch (_err) {}
console.error("Guest decryption failed for canvas image:", err);
}
} }
} }
} }
@@ -96,9 +92,7 @@ export async function encryptCanvasImages(
); );
filenameMapping.set(img.src, filename); filenameMapping.set(img.src, filename);
encryptedFiles.set(filename, encryptedBlob); encryptedFiles.set(filename, encryptedBlob);
} catch (err) { } catch (_err) {}
console.error("Failed to encrypt new canvas image:", err);
}
} }
// Update the canvas JSON to use the new encrypted filenames instead of blob URLs. // Update the canvas JSON to use the new encrypted filenames instead of blob URLs.