From 81bed513696632368361000cb0288c766d863db8 Mon Sep 17 00:00:00 2001 From: varutasu <104105839+varutasu@users.noreply.github.com> Date: Tue, 2 Jun 2026 01:03:42 -0500 Subject: [PATCH] fix(lint): clear lib/config baseline and make CI lint blocking. (#63) Lazy-init theme from localStorage, hoist checkAuth with useCallback, named config exports for PostCSS/Tailwind, and remove the non-blocking || true wrapper from ci.yml (requires #61 + #62 merged first). Co-authored-by: Cursor --- .github/workflows/ci.yml | 14 +------ lib/theme-context.js | 14 ++++--- lib/use-auth.js | 83 +++++++++++++++++++++++----------------- postcss.config.js | 6 ++- tailwind.config.js | 6 ++- 5 files changed, 64 insertions(+), 59 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c99febe..28b5385 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,19 +36,7 @@ jobs: node-version: ${{ env.NODE_VERSION }} cache: npm - run: npm ci - # TODO(fix-lint-baseline): drop the `|| true` wrapper once .convoys/fix-lint-baseline - # lands. The codebase has ~100 pre-existing ESLint errors (conditional React - # hooks, unescaped entities, etc.). For now lint runs and posts output as a - # warning annotation so the PR check stays green while the debt is visible. - - name: Lint (non-blocking until fix-lint-baseline) - run: | - set +e - npm run lint --if-present - status=$? - if [ "$status" -ne 0 ]; then - echo "::warning title=Lint errors (non-blocking)::ESLint reported errors above. Tracked in .convoys/ship-readiness.md as P1 #11.5 (fix-lint-baseline). Remove the wrapper in .github/workflows/ci.yml after baseline is fixed." - fi - exit 0 + - run: npm run lint --if-present schema-map-fresh: name: Schema map up to date diff --git a/lib/theme-context.js b/lib/theme-context.js index 6dd2f60..5e4c371 100644 --- a/lib/theme-context.js +++ b/lib/theme-context.js @@ -2,15 +2,17 @@ import { createContext, useContext, useEffect, useState } from 'react'; const ThemeContext = createContext(); +function readThemeFromStorage() { + if (typeof window === 'undefined') return 'light'; + return localStorage.getItem('theme') || 'light'; +} + export function ThemeProvider({ children }) { - const [theme, setTheme] = useState('light'); + const [theme, setTheme] = useState(readThemeFromStorage); useEffect(() => { - // Check for saved theme preference or default to light - const savedTheme = localStorage.getItem('theme') || 'light'; - setTheme(savedTheme); - document.documentElement.setAttribute('data-theme', savedTheme); - }, []); + document.documentElement.setAttribute('data-theme', theme); + }, [theme]); const toggleTheme = () => { const newTheme = theme === 'light' ? 'dark' : 'light'; diff --git a/lib/use-auth.js b/lib/use-auth.js index 28512c5..e19ca72 100644 --- a/lib/use-auth.js +++ b/lib/use-auth.js @@ -1,45 +1,56 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useCallback } from 'react'; + +async function verifyAuthFromStorage() { + const token = localStorage.getItem('auth_token'); + + const headers = { + 'Content-Type': 'application/json', + }; + + if (token) { + headers.Authorization = `Bearer ${token}`; + } + + try { + const response = await fetch('/api/auth/verify', { headers }); + if (response.ok) { + return await response.json(); + } + + if (token) { + localStorage.removeItem('auth_token'); + } + return null; + } catch (error) { + console.error('Auth check failed:', error); + return null; + } +} export function useAuth() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { - checkAuth(); + let active = true; + + void (async () => { + const verifiedUser = await verifyAuthFromStorage(); + if (!active) return; + setUser(verifiedUser); + setLoading(false); + })(); + + return () => { + active = false; + }; }, []); - const checkAuth = async () => { - try { - // Get token from localStorage - const token = localStorage.getItem('auth_token'); - - const headers = { - 'Content-Type': 'application/json', - }; - - // Add authorization header if token exists - if (token) { - headers.Authorization = `Bearer ${token}`; - } - - const response = await fetch('/api/auth/verify', { headers }); - if (response.ok) { - const userData = await response.json(); - setUser(userData); - } else { - setUser(null); - // Clear invalid token - if (token) { - localStorage.removeItem('auth_token'); - } - } - } catch (error) { - console.error('Auth check failed:', error); - setUser(null); - } finally { - setLoading(false); - } - }; + const refreshAuth = useCallback(async () => { + const verifiedUser = await verifyAuthFromStorage(); + setUser(verifiedUser); + setLoading(false); + }, []); const logout = () => { localStorage.removeItem('auth_token'); @@ -50,6 +61,6 @@ export function useAuth() { user, loading, logout, - refreshAuth: checkAuth + refreshAuth, }; -} \ No newline at end of file +} diff --git a/postcss.config.js b/postcss.config.js index 387612e..a982c64 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,8 @@ -export default { +const config = { plugins: { tailwindcss: {}, autoprefixer: {}, }, -} \ No newline at end of file +}; + +export default config; diff --git a/tailwind.config.js b/tailwind.config.js index 7913239..8ecd520 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,5 +1,5 @@ /** @type {import('tailwindcss').Config} */ -export default { +const config = { content: [ './pages/**/*.{js,ts,jsx,tsx,mdx}', './components/**/*.{js,ts,jsx,tsx,mdx}', @@ -29,4 +29,6 @@ export default { }, }, plugins: [], -} \ No newline at end of file +}; + +export default config;