From 92b595581e5988cd57ebeb982a70c85bfef498c3 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 6 Dec 2025 17:38:08 +0900 Subject: feat(client): initialize React + Vite frontend foundation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set up the client-side React application with Vite bundler: - Add React 19 and Vite 7 with the React plugin - Create index.html entry point and App component - Configure Vite with API proxy to backend server - Add client build scripts to package.json - Update tsconfig for React JSX and DOM types - Fix TypeScript errors in auth code (JWT_SECRET type narrowing) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/client/App.tsx | 8 ++++++++ src/client/index.tsx | 2 +- src/client/main.tsx | 14 ++++++++++++++ src/server/middleware/auth.ts | 14 ++++++++++---- src/server/routes/auth.ts | 13 ++++++++----- 5 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 src/client/App.tsx create mode 100644 src/client/main.tsx (limited to 'src') diff --git a/src/client/App.tsx b/src/client/App.tsx new file mode 100644 index 0000000..fa42302 --- /dev/null +++ b/src/client/App.tsx @@ -0,0 +1,8 @@ +export function App() { + return ( +
+

Kioku

+

Spaced repetition learning app

+
+ ); +} diff --git a/src/client/index.tsx b/src/client/index.tsx index cb0ff5c..713869c 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -1 +1 @@ -export {}; +export { App } from "./App"; diff --git a/src/client/main.tsx b/src/client/main.tsx new file mode 100644 index 0000000..1e185be --- /dev/null +++ b/src/client/main.tsx @@ -0,0 +1,14 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./App"; + +const rootElement = document.getElementById("root"); +if (!rootElement) { + throw new Error("Root element not found"); +} + +createRoot(rootElement).render( + + + , +); diff --git a/src/server/middleware/auth.ts b/src/server/middleware/auth.ts index 51b4d9d..bb85b35 100644 --- a/src/server/middleware/auth.ts +++ b/src/server/middleware/auth.ts @@ -2,9 +2,12 @@ import type { Context, Next } from "hono"; import { verify } from "hono/jwt"; import { Errors } from "./error-handler.js"; -const JWT_SECRET = process.env.JWT_SECRET; -if (!JWT_SECRET) { - throw new Error("JWT_SECRET environment variable is required"); +function getJwtSecret(): string { + const secret = process.env.JWT_SECRET; + if (!secret) { + throw new Error("JWT_SECRET environment variable is required"); + } + return secret; } export interface AuthUser { @@ -38,7 +41,10 @@ export async function authMiddleware(c: Context, next: Next) { const token = authHeader.slice(7); try { - const payload = (await verify(token, JWT_SECRET)) as unknown as JWTPayload; + const payload = (await verify( + token, + getJwtSecret(), + )) as unknown as JWTPayload; const user: AuthUser = { id: payload.sub, diff --git a/src/server/routes/auth.ts b/src/server/routes/auth.ts index 25c959b..f0c0428 100644 --- a/src/server/routes/auth.ts +++ b/src/server/routes/auth.ts @@ -15,9 +15,12 @@ import { refreshTokenSchema, } from "../schemas/index.js"; -const JWT_SECRET = process.env.JWT_SECRET; -if (!JWT_SECRET) { - throw new Error("JWT_SECRET environment variable is required"); +function getJwtSecret(): string { + const secret = process.env.JWT_SECRET; + if (!secret) { + throw new Error("JWT_SECRET environment variable is required"); + } + return secret; } const ACCESS_TOKEN_EXPIRES_IN = 60 * 15; // 15 minutes const REFRESH_TOKEN_EXPIRES_IN = 60 * 60 * 24 * 7; // 7 days @@ -101,7 +104,7 @@ export function createAuthRouter(deps: AuthDependencies) { iat: now, exp: now + ACCESS_TOKEN_EXPIRES_IN, }, - JWT_SECRET, + getJwtSecret(), ); // Generate refresh token @@ -165,7 +168,7 @@ export function createAuthRouter(deps: AuthDependencies) { iat: now, exp: now + ACCESS_TOKEN_EXPIRES_IN, }, - JWT_SECRET, + getJwtSecret(), ); // Generate new refresh token (rotation) -- cgit v1.2.3-70-g09d2