Address ESlint console statements
This commit is contained in:
@@ -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 },
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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,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",
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user