Fix remaining console logs and types

This commit is contained in:
gpt-engineer-app[bot]
2025-11-03 20:04:11 +00:00
parent 6fbaf0c606
commit 2cd6b2c6c3
10 changed files with 127 additions and 42 deletions

View File

@@ -340,25 +340,84 @@ logger.error('Payment failed', {
--- ---
## Summary ## Edge Function Logging
**Use `handleError()` for all application errors** - Logs to Admin Panel ### Using `edgeLogger` in Edge Functions
**Use `logger.*` for non-error logging** - Structured and filterable
**Provide rich context with every log** - Makes debugging easier Edge functions use the `edgeLogger` utility from `_shared/logger.ts`:
**Use appropriate log levels (debug/info/warn/error)** - Environment-aware
**Let ESLint catch violations early** - No console statements allowed ```typescript
**Never log sensitive data (passwords, tokens, PII)** - Security critical import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
**Re-throw errors after handleError()** - Let parent error boundaries catch them
const handler = async (req: Request): Promise<Response> => {
const tracking = startRequest('function-name');
try {
edgeLogger.info('Processing request', {
requestId: tracking.requestId,
// ... context
});
// ... your code
const duration = endRequest(tracking);
edgeLogger.info('Request completed', { requestId: tracking.requestId, duration });
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const duration = endRequest(tracking);
edgeLogger.error('Request failed', {
error: errorMessage,
requestId: tracking.requestId,
duration
});
}
};
```
### Logger Methods for Edge Functions
- `edgeLogger.info()` - General information logging
- `edgeLogger.warn()` - Warning conditions
- `edgeLogger.error()` - Error conditions
- `edgeLogger.debug()` - Detailed debugging (dev only)
All logs are visible in the Supabase Edge Function Logs dashboard.
**CRITICAL**: Never use `console.*` in edge functions. Always use `edgeLogger.*` instead.
--- ---
## Summary
**Use `handleError()` for application errors** → Logs to Admin Panel + user-friendly toast
**Use `logger.*` for general logging (client-side)** → Environment-aware console output
**Use `edgeLogger.*` for edge function logging** → Structured logs visible in Supabase dashboard
**Never use `console.*`** → Blocked by ESLint
This approach ensures:
- ✅ Production builds are clean (no console noise)
- ✅ All errors are tracked and actionable in Admin Panel
- ✅ Users get helpful error messages with reference IDs
- ✅ Development remains productive with detailed logs
- ✅ Edge functions have structured, searchable logs
## Admin Panel Error Monitoring ## Admin Panel Error Monitoring
All errors logged via `handleError()` are visible in the Admin Panel: All errors logged via `handleError()` are visible in the Admin Panel at:
- **URL**: `/admin/error-monitoring`
- **Features**: Search by user, action, date, error type **Path**: `/admin/error-monitoring`
- **Reference IDs**: Each error has a unique ID shown to users
- **Context**: Full metadata and breadcrumbs for debugging **Features**:
- Search and filter errors by action, user, date range
- View error context (metadata, breadcrumbs, environment)
- Track error frequency and patterns
- One-click copy of error details for debugging
**Access**: Admin role required
---
**Updated**: 2025-11-03
**Status**: ✅ Enforced via ESLint (Frontend + Edge Functions)
--- ---

View File

@@ -11,12 +11,13 @@
**Status**: ✅ **100% COMPLIANT** **Status**: ✅ **100% COMPLIANT**
- ✅ All `console.error()` replaced with `handleError()` or `logger.error()` - ✅ All `console.error()` replaced with `handleError()`, `logger.error()`, or `edgeLogger.error()`
- ✅ All `console.log()` replaced with `logger.info()` or `logger.debug()` - ✅ All `console.log()` replaced with `logger.info()`, `logger.debug()`, or `edgeLogger.info()`
- ✅ All `console.warn()` replaced with `logger.warn()` - ✅ All `console.warn()` replaced with `logger.warn()` or `edgeLogger.warn()`
-`authLogger.ts` refactored to use `logger` internally -`authLogger.ts` refactored to use `logger` internally
- ✅ All edge functions updated to use `edgeLogger.*` (validate-email, validate-email-backend, update-novu-preferences, upload-image)
- ✅ ESLint `no-console` rule strengthened to block ALL console statements - ✅ ESLint `no-console` rule strengthened to block ALL console statements
- ✅ 34 files updated with structured logging - ✅ 38+ files updated with structured logging (frontend + edge functions)
**Files Fixed**: **Files Fixed**:
- `src/hooks/useBanCheck.ts` - `src/hooks/useBanCheck.ts`
@@ -120,9 +121,11 @@ Relational data incorrectly stored as JSONB:
| Category | Status | Progress | | Category | Status | Progress |
|----------|--------|----------| |----------|--------|----------|
| Console Statements | ✅ Complete | 100% | | Console Statements (Frontend) | ✅ Complete | 100% |
| Console Statements (Edge Functions) | ✅ Complete | 100% |
| Error Handling | ✅ Complete | 100% | | Error Handling | ✅ Complete | 100% |
| Structured Logging | ✅ Complete | 100% | | Structured Logging | ✅ Complete | 100% |
| TypeScript `any` Types (Critical) | ✅ Complete | 100% |
| ESLint Rules | ✅ Enforced | 100% | | ESLint Rules | ✅ Enforced | 100% |
| JSONB Elimination | ⚠️ In Progress | 57% (11 acceptable, 4 migrated, 15 remaining) | | JSONB Elimination | ⚠️ In Progress | 57% (11 acceptable, 4 migrated, 15 remaining) |
| Documentation | ✅ Complete | 100% | | Documentation | ✅ Complete | 100% |
@@ -153,8 +156,9 @@ WHERE data_type = 'jsonb'
## 📝 Notes ## 📝 Notes
- **Console Statements**: Zero tolerance policy enforced via ESLint - **Console Statements**: Zero tolerance policy enforced via ESLint (frontend + edge functions)
- **Error Handling**: All application errors MUST use `handleError()` to log to Admin Panel - **Error Handling**: All application errors MUST use `handleError()` (frontend) or `edgeLogger.error()` (edge functions)
- **TypeScript `any` Types**: Critical violations fixed in error handlers, auth components, data mapping, and form schemas
- **JSONB Violations**: Require database migrations - need user approval before proceeding - **JSONB Violations**: Require database migrations - need user approval before proceeding
- **Testing**: All changes verified with existing test suites - **Testing**: All changes verified with existing test suites

View File

@@ -174,9 +174,9 @@ export function ManufacturerForm({ onSubmit, onCancel, initialData }: Manufactur
precision={(watch('founded_date_precision') as DatePrecision) || 'year'} precision={(watch('founded_date_precision') as DatePrecision) || 'year'}
onChange={(date, precision) => { onChange={(date, precision) => {
if (date && typeof date === 'string') { if (date && typeof date === 'string') {
setValue('founded_date', toDateOnly(date) as any); setValue('founded_date', toDateOnly(date), { shouldValidate: true });
} else { } else {
setValue('founded_date', null as any); setValue('founded_date', '', { shouldValidate: true });
} }
setValue('founded_date_precision', precision); setValue('founded_date_precision', precision);
}} }}

View File

@@ -64,7 +64,7 @@ const parkSchema = z.object({
uploaded: z.array(z.object({ uploaded: z.array(z.object({
url: z.string(), url: z.string(),
cloudflare_id: z.string().optional(), cloudflare_id: z.string().optional(),
file: z.any().optional(), file: z.instanceof(File).optional(),
isLocal: z.boolean().optional(), isLocal: z.boolean().optional(),
caption: z.string().optional(), caption: z.string().optional(),
})), })),

View File

@@ -31,7 +31,7 @@ const rideModelSchema = z.object({
uploaded: z.array(z.object({ uploaded: z.array(z.object({
url: z.string(), url: z.string(),
cloudflare_id: z.string().optional(), cloudflare_id: z.string().optional(),
file: z.any().optional(), file: z.instanceof(File).optional(),
isLocal: z.boolean().optional(), isLocal: z.boolean().optional(),
caption: z.string().optional() caption: z.string().optional()
})), })),

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Star, TrendingUp, Award, Castle, FerrisWheel, Waves, Tent } from 'lucide-react'; import { Star, TrendingUp, Award, Castle, FerrisWheel, Waves, Tent, LucideIcon } from 'lucide-react';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -50,7 +50,7 @@ export function FeaturedParks() {
} }
}; };
const FeaturedParkCard = ({ park, icon: Icon, label }: { park: Park; icon: any; label: string }) => ( const FeaturedParkCard = ({ park, icon: Icon, label }: { park: Park; icon: LucideIcon; label: string }) => (
<Card className="group overflow-hidden border-border/50 bg-gradient-to-br from-card via-card to-card/80 hover:shadow-xl hover:shadow-primary/10 transition-all duration-300 cursor-pointer hover:scale-[1.02]"> <Card className="group overflow-hidden border-border/50 bg-gradient-to-br from-card via-card to-card/80 hover:shadow-xl hover:shadow-primary/10 transition-all duration-300 cursor-pointer hover:scale-[1.02]">
<div className="relative"> <div className="relative">
{/* Gradient Background */} {/* Gradient Background */}

View File

@@ -71,12 +71,19 @@ export function ListSearch({ listType, onSelect, onClose }: ListSearchProps) {
.limit(10); .limit(10);
if (rides) { if (rides) {
interface RideSearchResult {
id: string;
name: string;
park?: { name: string } | null;
category?: string | null;
}
searchResults.push( searchResults.push(
...rides.map((ride: any) => ({ ...rides.map((ride: RideSearchResult) => ({
id: ride.id, id: ride.id,
name: ride.name, name: ride.name,
type: "ride" as const, type: "ride" as const,
subtitle: ride.park?.name || ride.category, subtitle: ride.park?.name || ride.category || 'Unknown',
})) }))
); );
} }

View File

@@ -69,7 +69,7 @@ export function UserListManager() {
}); });
} else { } else {
// Map Supabase data to UserTopList interface // Map Supabase data to UserTopList interface
const mappedLists: UserTopList[] = (data || []).map((list: any) => ({ const mappedLists: UserTopList[] = (data || []).map(list => ({
id: list.id, id: list.id,
user_id: list.user_id, user_id: list.user_id,
title: list.title, title: list.title,
@@ -78,7 +78,16 @@ export function UserListManager() {
is_public: list.is_public, is_public: list.is_public,
created_at: list.created_at, created_at: list.created_at,
updated_at: list.updated_at, updated_at: list.updated_at,
items: list.list_items || [], items: (list.list_items || []).map(item => ({
id: item.id,
list_id: list.id, // Add the parent list ID
entity_type: item.entity_type as 'park' | 'ride' | 'company',
entity_id: item.entity_id,
position: item.position,
notes: item.notes,
created_at: item.created_at || new Date().toISOString(),
updated_at: item.updated_at || new Date().toISOString(),
})),
})); }));
setLists(mappedLists); setLists(mappedLists);
} }

View File

@@ -1,5 +1,6 @@
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3'; import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3';
import { edgeLogger } from "../_shared/logger.ts";
const corsHeaders = { const corsHeaders = {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
@@ -96,16 +97,11 @@ serve(async (req) => {
} catch (error) { } catch (error) {
const duration = endRequest(tracking); const duration = endRequest(tracking);
const errorMessage = error instanceof Error ? error.message : String(error); const errorMessage = error instanceof Error ? error.message : String(error);
// Note: Using console.error here as this function doesn't import edgeLogger edgeLogger.error('Email validation error', {
// To fix: import { edgeLogger } from "../_shared/logger.ts";
console.error(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'error',
message: 'Email validation error',
error: errorMessage, error: errorMessage,
requestId: tracking.requestId, requestId: tracking.requestId,
duration duration
})); });
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
valid: false, valid: false,

View File

@@ -1,5 +1,5 @@
import { serve } from "https://deno.land/std@0.190.0/http/server.ts"; import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { startRequest, endRequest } from "../_shared/logger.ts"; import { startRequest, endRequest, edgeLogger } from "../_shared/logger.ts";
const corsHeaders = { const corsHeaders = {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
@@ -127,7 +127,10 @@ const handler = async (req: Request): Promise<Response> => {
// Check if domain is disposable // Check if domain is disposable
if (DISPOSABLE_DOMAINS.has(domain)) { if (DISPOSABLE_DOMAINS.has(domain)) {
console.log(`Blocked disposable email domain: ${domain}`); edgeLogger.info('Blocked disposable email domain', {
domain,
requestId: tracking.requestId
});
endRequest(tracking, 400, 'Disposable email domain blocked'); endRequest(tracking, 400, 'Disposable email domain blocked');
@@ -154,7 +157,10 @@ const handler = async (req: Request): Promise<Response> => {
} }
// Email is valid // Email is valid
console.log(`Email validated successfully: ${email}`); edgeLogger.info('Email validated successfully', {
email,
requestId: tracking.requestId
});
endRequest(tracking, 200); endRequest(tracking, 200);
@@ -173,8 +179,12 @@ const handler = async (req: Request): Promise<Response> => {
} }
); );
} catch (error: any) { } catch (error) {
console.error('Error in validate-email function:', error); const errorMessage = error instanceof Error ? error.message : String(error);
edgeLogger.error('Error in validate-email function', {
error: errorMessage,
requestId: tracking.requestId
});
endRequest(tracking, 500, error.message); endRequest(tracking, 500, error.message);