Address ESlint console statements

This commit is contained in:
adilallo
2026-01-28 11:49:56 -07:00
parent 6b8d646f8a
commit 29a3bd3824
10 changed files with 73 additions and 18 deletions
+5 -4
View File
@@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import fs from "fs";
import path from "path";
import { logger } from "../../../lib/logger";
const WEB_VITALS_DIR = path.join(process.cwd(), ".next", "web-vitals");
@@ -65,7 +66,7 @@ export async function POST(request: NextRequest) {
existingData = JSON.parse(fileContent) as WebVitalData[];
} catch (error) {
const err = error as Error;
console.warn("Could not parse existing vitals data:", err.message);
logger.warn("Could not parse existing vitals data:", err.message);
}
}
@@ -79,13 +80,13 @@ export async function POST(request: NextRequest) {
fs.writeFileSync(filePath, JSON.stringify(existingData, null, 2));
// Log for monitoring
console.log(
logger.info(
`Web Vital received: ${metric} = ${data.value}ms (${data.rating})`,
);
return NextResponse.json({ success: true });
} catch (error) {
console.error("Error processing web vital:", error);
logger.error("Error processing web vital:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
@@ -141,7 +142,7 @@ export async function GET() {
return NextResponse.json({ metrics });
} catch (error) {
console.error("Error fetching web vitals:", error);
logger.error("Error fetching web vitals:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
+3 -2
View File
@@ -6,6 +6,7 @@ import {
getAllBlogPosts as getAllPosts,
type BlogPost,
} from "../../../lib/content";
import { logger } from "../../../lib/logger";
import ContentBanner from "../../components/ContentBanner";
import AskOrganizer from "../../components/AskOrganizer";
import { getAssetPath, ASSETS } from "../../../lib/assetUtils";
@@ -44,7 +45,7 @@ export async function generateStaticParams() {
slug: post.slug,
}));
} catch (error) {
console.error("Error generating static params:", error);
logger.error("Error generating static params:", error);
return [];
}
}
@@ -87,7 +88,7 @@ export async function generateMetadata({
},
};
} catch (error) {
console.error("Error generating metadata:", error);
logger.error("Error generating metadata:", error);
return {
title: "Blog Post",
description: "A blog post from our community.",
+2 -1
View File
@@ -1,6 +1,7 @@
"use client";
import React, { Component, type ReactNode } from "react";
import { logger } from "../../lib/logger";
interface ErrorBoundaryProps {
children: ReactNode;
@@ -24,7 +25,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
// Log the error to an error reporting service
console.error("ErrorBoundary caught an error:", error, errorInfo);
logger.error("ErrorBoundary caught an error:", error, errorInfo);
}
render() {
+3 -2
View File
@@ -3,6 +3,7 @@
import { useState, memo } from "react";
import Image from "next/image";
import QuoteDecor from "./QuoteDecor";
import { logger } from "../../lib/logger";
interface QuoteBlockProps {
variant?: "compact" | "standard" | "extended";
@@ -109,7 +110,7 @@ const QuoteBlock = memo<QuoteBlockProps>(
// Error handling functions
const handleImageError = (error: unknown) => {
console.warn(
logger.warn(
`QuoteBlock: Failed to load avatar image for ${author}:`,
error,
);
@@ -135,7 +136,7 @@ const QuoteBlock = memo<QuoteBlockProps>(
// Validate required props
if (!quote || !author) {
console.error("QuoteBlock: Missing required props (quote or author)");
logger.error("QuoteBlock: Missing required props (quote or author)");
if (onError) {
onError({
type: "missing_props",
+2 -1
View File
@@ -5,6 +5,7 @@ import Image from "next/image";
import RuleCard from "./RuleCard";
import Button from "./Button";
import { getAssetPath } from "../../lib/assetUtils";
import { logger } from "../../lib/logger";
interface RuleStackProps {
className?: string;
@@ -38,7 +39,7 @@ const RuleStack = memo<RuleStackProps>(({ className = "" }) => {
});
}
}
console.log(`${templateName} template clicked`);
logger.debug(`${templateName} template clicked`);
};
return (
+2 -1
View File
@@ -1,6 +1,7 @@
"use client";
import { useState, useEffect, memo } from "react";
import { logger } from "../../lib/logger";
interface VitalData {
value: number;
@@ -50,7 +51,7 @@ const WebVitalsDashboard = memo(() => {
const data = (await response.json()) as { metrics?: Metrics };
setMetrics(data.metrics || {});
} catch (error) {
console.error("Error fetching web vitals:", error);
logger.error("Error fetching web vitals:", error);
} finally {
setLoading(false);
}
+20 -1
View File
@@ -129,7 +129,26 @@ const eslintConfig = [
rules: {
// Basic rules
"react/no-unescaped-entities": "off",
"no-console": "warn",
// Default: discourage console usage, but allow warn/error as "standard practice"
"no-console": ["warn", { allow: ["warn", "error"] }],
},
},
// App/lib code: no console.* (enforced)
{
files: ["app/**/*.{ts,tsx,js,jsx}", "lib/**/*.{ts,tsx,js,jsx}"],
rules: {
"no-console": "error",
},
},
// Tests/Storybook/scripts: console is acceptable
{
files: [
"tests/**/*.{ts,tsx,js,jsx}",
"stories/**/*.{ts,tsx,js,jsx}",
"scripts/**/*.{ts,js}",
],
rules: {
"no-console": "off",
},
},
// Config files - allow Node.js globals
+5 -3
View File
@@ -2,6 +2,8 @@
* Content caching utilities for improved performance
*/
import { logger } from "./logger";
// In-memory cache for blog posts
const blogPostCache = new Map<string, CacheEntry<unknown>>();
const blogListCache = new Map<string, CacheEntry<unknown[]>>();
@@ -243,9 +245,9 @@ export async function warmCache<T>(
cacheBlogPost(postWithSlug.slug, post);
});
console.log("Cache warmed up successfully");
logger.info("Cache warmed up successfully");
} catch (error) {
console.error("Error warming up cache:", error);
logger.error("Error warming up cache:", error);
}
}
@@ -258,7 +260,7 @@ export function isCacheHealthy(): boolean {
clearExpiredCache();
return blogPostCache.size < MAX_CACHE_SIZE;
} catch (error) {
console.error("Cache health check failed:", error);
logger.error("Cache health check failed:", error);
return false;
}
}
+4 -3
View File
@@ -3,6 +3,7 @@ import path from "path";
import matter from "gray-matter";
import { validateBlogPost, sanitizeBlogPost } from "./validation";
import type { BlogPostFrontmatter } from "./validation";
import { logger } from "./logger";
/**
* Content processing utilities for blog posts
@@ -73,7 +74,7 @@ export function getBlogPostFiles(): string[] {
(file) => file.endsWith(".md") || file.endsWith(".mdx"),
);
} catch (error) {
console.error("Error reading blog content directory:", error);
logger.error("Error reading blog content directory:", error);
return [];
}
}
@@ -92,7 +93,7 @@ export function parseBlogPost(filePath: string): BlogPost | null {
const validationResult = validateBlogPost(data);
if (!validationResult.isValid) {
console.error(
logger.error(
`Validation errors for ${filePath}:`,
validationResult.errors,
);
@@ -111,7 +112,7 @@ export function parseBlogPost(filePath: string): BlogPost | null {
lastModified: fs.statSync(fullPath).mtime,
};
} catch (error) {
console.error(`Error parsing blog post file ${filePath}:`, error);
logger.error(`Error parsing blog post file ${filePath}:`, error);
return null;
}
}
+27
View File
@@ -0,0 +1,27 @@
/* eslint-disable no-console */
/**
* Minimal logger wrapper.
*
* - Centralizes logging so we can swap implementations later (e.g. pino/sentry).
* - Avoids sprinkling `console.*` throughout app code.
*/
type LoggerArgs = unknown[];
const isProd = process.env.NODE_ENV === "production";
export const logger = {
debug: (...args: LoggerArgs) => {
if (!isProd) console.debug(...args);
},
info: (...args: LoggerArgs) => {
console.info(...args);
},
warn: (...args: LoggerArgs) => {
console.warn(...args);
},
error: (...args: LoggerArgs) => {
console.error(...args);
},
};