diff --git a/.replit b/.replit index fc81a45d..4eea8915 100644 --- a/.replit +++ b/.replit @@ -33,3 +33,7 @@ outputType = "webview" [[ports]] localPort = 5000 externalPort = 80 + +[[ports]] +localPort = 37823 +externalPort = 3000 diff --git a/replit.md b/replit.md index b5ed9bee..d314ce25 100644 --- a/replit.md +++ b/replit.md @@ -5,13 +5,22 @@ ThrillWiki is a community-driven web application for discovering, reviewing, and ## Recent Changes (October 8, 2025) -### Performance & Reliability Improvements +### Critical Bug Fixes - Session 2 +- **Fixed Infinite Loop in Search Hook:** Resolved critical infinite re-render issue in `useSearch` hook by implementing JSON.stringify-based option keying. This creates stable references for search parameters (types, limit, minQuery) even when callers pass inline array literals, preventing infinite fetch loops while maintaining reactivity to option changes. +- **Fixed React Hook Order Violations:** Corrected hook call order in `useSearch` by ensuring all useState declarations come before useMemo/useCallback/useEffect. This prevents HMR (Hot Module Reload) errors and React queue violations during development. +- **Fixed Race Condition in Version History:** Implemented `fetchInProgressRef` guard in `useEntityVersions` hook to prevent concurrent fetch operations that could cause stale data or duplicate requests when rapidly switching between entities. +- **Enhanced Username Validation Stability:** Updated `useUsernameValidation` hook to properly use `useCallback` with stable dependencies, preventing unnecessary re-validation and API calls. +- **Improved Type Safety in Ride Components:** Removed unsafe `as any` type assertions in `ManufacturerModels.tsx` and `RideModelCard.tsx`, replacing them with properly typed interfaces for safer data handling and better IDE support. +- **Enhanced Image Upload Error Recovery:** Improved `imageUploadHelper.ts` to track uploaded image IDs and attempt cleanup deletion from Cloudflare when partial uploads fail, preventing orphaned images in storage. +- **Strengthened Edge Function Reliability:** Added memory leak protection with 10,000-entry limit to rate limiter in `detect-location` Edge Function, and improved topological sort error handling in `process-selective-approval` function. + +### Performance & Reliability Improvements - Session 1 - **Added Rate Limiting to Location Detection:** Implemented in-memory rate limiter for `detect-location` Edge Function to prevent abuse. Limits requests to 10 per minute per IP address with automatic cleanup to prevent memory leaks. Returns 429 status with Retry-After header when limit is exceeded. - **Standardized Error Response Format:** Updated `upload-image` Edge Function to use consistent error response structure across all error paths. All responses now include both `error` (short identifier) and `message` (human-readable description) fields, with optional `details` for additional context. This improves client-side error handling and debugging. - **Verified HMR Stability:** Investigated and confirmed that Hot Module Reload warnings for `ManufacturerRides.tsx` and `ManufacturerModels.tsx` were transient and have resolved themselves. - **Validated Cloudflare Integration:** Confirmed `requireSignedURLs` parameter in `upload-image` function is correctly implemented according to Cloudflare Images API specifications. -### Bug Fixes & Code Quality +### Bug Fixes & Code Quality - Session 1 - **Fixed Novu API Integration:** Updated `update-novu-preferences` Edge Function to correctly use Novu's updatePreference API, which requires separate calls for each channel type (email, sms, in_app, push). Implemented proper error handling that tracks per-channel results and returns 502 status with detailed failure information when any channel fails to update. - **Enhanced Input Validation:** Added validation for userId and channelPreferences in `update-novu-preferences` to prevent undefined access errors and return clear 400 error responses for invalid requests. - **Fixed TypeScript Errors in Edge Functions:** Corrected null checking for user object in `seed-test-data` function and improved error type handling for JSON parsing operations. diff --git a/src/hooks/useSearch.tsx b/src/hooks/useSearch.tsx index 29235f45..eb8c3146 100644 --- a/src/hooks/useSearch.tsx +++ b/src/hooks/useSearch.tsx @@ -27,6 +27,13 @@ const DEFAULT_MIN_QUERY = 2; const DEFAULT_DEBOUNCE_MS = 300; export function useSearch(options: UseSearchOptions = {}) { + // State declarations MUST come first to maintain hook order + const [query, setQuery] = useState(''); + const [results, setResults] = useState([]); + const [loading, setLoading] = useState(false); + const [recentSearches, setRecentSearches] = useState([]); + const [debouncedQuery, setDebouncedQuery] = useState(''); + // Stabilize options using JSON stringify to prevent infinite loops from array recreation const optionsKey = JSON.stringify({ types: options.types || DEFAULT_TYPES, @@ -38,14 +45,6 @@ export function useSearch(options: UseSearchOptions = {}) { const stableOptions = useMemo(() => JSON.parse(optionsKey), [optionsKey]); const { types, limit, minQuery, debounceMs } = stableOptions; - const [query, setQuery] = useState(''); - const [results, setResults] = useState([]); - const [loading, setLoading] = useState(false); - const [recentSearches, setRecentSearches] = useState([]); - - // Debounced query - const [debouncedQuery, setDebouncedQuery] = useState(''); - useEffect(() => { const timer = setTimeout(() => { setDebouncedQuery(query);