diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-06 17:38:08 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-06 17:38:08 +0900 |
| commit | 92b595581e5988cd57ebeb982a70c85bfef498c3 (patch) | |
| tree | 5b95c2b0a277ff7670206cdb16638e2ac5143c92 /src | |
| parent | 811458427593a4172a2cd535cc768db375350dca (diff) | |
| download | kioku-92b595581e5988cd57ebeb982a70c85bfef498c3.tar.gz kioku-92b595581e5988cd57ebeb982a70c85bfef498c3.tar.zst kioku-92b595581e5988cd57ebeb982a70c85bfef498c3.zip | |
feat(client): initialize React + Vite frontend foundation
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 <noreply@anthropic.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/App.tsx | 8 | ||||
| -rw-r--r-- | src/client/index.tsx | 2 | ||||
| -rw-r--r-- | src/client/main.tsx | 14 | ||||
| -rw-r--r-- | src/server/middleware/auth.ts | 14 | ||||
| -rw-r--r-- | src/server/routes/auth.ts | 13 |
5 files changed, 41 insertions, 10 deletions
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 ( + <div> + <h1>Kioku</h1> + <p>Spaced repetition learning app</p> + </div> + ); +} 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( + <StrictMode> + <App /> + </StrictMode>, +); 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) |
