Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions apps/react-app-router-fm/app/app-nav.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,47 @@
import { NavLink } from "react-router"
import { NavLink, useNavigate } from "react-router"
import { authClient } from "./lib/auth-client.js"

export function AppNav() {
const navigate = useNavigate()
return (
<nav>
<NavLink end to="/">
Home
</NavLink>
<NavLink end to="/about">
About
</NavLink>
<button onClick={() => authClient.signOut()}>Sign Out</button>
<nav
className="container-fluid"
style={{ position: "sticky", top: 0, zIndex: 10, backdropFilter: "saturate(180%) blur(6px)" }}
>
<ul>
<li>
<NavLink end to="/" style={{ fontWeight: 600 }}>
Effectify
</NavLink>
</li>
</ul>
<ul>
<li>
<NavLink end to="/">
Home
</NavLink>
</li>
<li>
<NavLink end to="/todo-app">
Todo App
</NavLink>
</li>
<li>
<button
type="button"
onClick={async () => {
try {
await authClient.signOut()
navigate("/login")
} catch {
navigate("/login")
}
}}
>
Sign Out
</button>
</li>
</ul>
</nav>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import { betterAuth } from "better-auth"
import { openAPI } from "better-auth/plugins"
import type { BetterAuthOptions } from "better-auth/types"
// import Database from 'better-sqlite3'
import { pool } from "./prisma.js"

// const __filename = fileURLToPath(import.meta.url)
Expand All @@ -16,7 +15,6 @@ export const authOptions = {
emailAndPassword: {
enabled: true,
},
// database: new Database(join(__dirname, '../sqlite.db')),
database: pool,

advanced: {
Expand Down
5 changes: 4 additions & 1 deletion apps/react-app-router-fm/app/lib/prisma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { PrismaPg } from "@prisma/adapter-pg"
import { Pool } from "pg"
import { PrismaClient } from "../../prisma/generated/client.js"

const connectionString = `${process.env.DATABASE_URL}`
const connectionString = process.env.DATABASE_URL
if (!connectionString || connectionString.trim().length === 0) {
throw new Error("Missing DATABASE_URL environment variable")
}
Comment on lines +6 to +9

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Trim DATABASE_URL before using it.

You validate .trim() but still pass the untrimmed value downstream. That can fail if the env var contains whitespace.

Proposed fix
-const connectionString = process.env.DATABASE_URL
-if (!connectionString || connectionString.trim().length === 0) {
+const connectionString = process.env.DATABASE_URL?.trim()
+if (!connectionString) {
   throw new Error("Missing DATABASE_URL environment variable")
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const connectionString = process.env.DATABASE_URL
if (!connectionString || connectionString.trim().length === 0) {
throw new Error("Missing DATABASE_URL environment variable")
}
const connectionString = process.env.DATABASE_URL?.trim()
if (!connectionString) {
throw new Error("Missing DATABASE_URL environment variable")
}
🤖 Prompt for AI Agents
In `@apps/react-app-router-fm/app/lib/prisma.ts` around lines 6 - 9, The code
reads process.env.DATABASE_URL into connectionString but only trims for the
check — change it to use a trimmed value everywhere: compute a trimmed variable
(e.g., const connectionString = process.env.DATABASE_URL?.trim();), validate
that trimmed value and throw the same error if empty, and then pass that trimmed
connectionString downstream wherever the current untrimmed value was used so no
leading/trailing whitespace can break connections.


export const pool = new Pool({ connectionString })
const adapter = new PrismaPg({ connectionString })
Expand Down
6 changes: 6 additions & 0 deletions apps/react-app-router-fm/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export const links: LinksFunction = () => [
href: "https://fonts.gstatic.com",
crossOrigin: "anonymous",
},
{
rel: "stylesheet",
href: "https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css",
integrity: "sha384-NZhm4G1I7BpEGdjDKnzEfy3d78xvy7ECKUwwnKTYi036z42IyF056PbHfpQLIYgL",
crossOrigin: "anonymous",
},
{
rel: "stylesheet",
href:
Expand Down
2 changes: 1 addition & 1 deletion apps/react-app-router-fm/app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default [
index("./app.tsx"),
route("api/*", "./routes/api.ts"),
route("api/auth/*", "./routes/api.auth.ts"),
route("about", "./routes/about.tsx"),
route("todo-app", "./routes/todo-app.tsx"),
route("login", "./routes/login.tsx"),
route("signup", "./routes/signup.tsx"),
] satisfies RouteConfig
98 changes: 0 additions & 98 deletions apps/react-app-router-fm/app/routes/about.tsx

This file was deleted.

95 changes: 37 additions & 58 deletions apps/react-app-router-fm/app/routes/login.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from "react"
import { authClient } from "./../lib/auth-client.js"
import { useNavigate } from "react-router"
import { Link, useNavigate } from "react-router"

export default function Login() {
const [email, setEmail] = useState("")
Expand Down Expand Up @@ -30,66 +30,45 @@ export default function Login() {
}

return (
<div className="flex min-h-screen flex-col items-center justify-center bg-gray-50 p-4">
<div className="w-full max-w-md space-y-8 rounded-lg bg-white p-6 shadow-md">
<div>
<h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900">
Sign in to your account
</h2>
</div>
<form className="mt-8 space-y-6" onSubmit={handleLogin}>
<div className="-space-y-px rounded-md shadow-sm">
<div>
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
id="email-address"
name="email"
type="email"
autoComplete="email"
required
className="relative block w-full rounded-t-md border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:z-10 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 px-3"
placeholder="Email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<label htmlFor="password" className="sr-only">
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="relative block w-full rounded-b-md border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:z-10 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 px-3"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<main className="container">
<article>
<h2>Sign in to your account</h2>
<form onSubmit={handleLogin}>
<div>
<label htmlFor="email-address">Email address</label>
<input
id="email-address"
name="email"
type="email"
autoComplete="email"
required
placeholder="Email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>

{error && <div className="text-red-500 text-sm text-center">{error}</div>}

<div>
<button
type="submit"
className="group relative flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Sign in
</button>
<label htmlFor="password">Password</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
{error && (
<small role="alert" aria-live="polite" style={{ color: "var(--pico-color-red-500)" }}>{error}</small>
)}
<button type="submit">Sign in</button>
</form>
<div className="text-center text-sm">
<a href="/signup" className="font-medium text-indigo-600 hover:text-indigo-500">
Don't have an account? Sign up
</a>
</div>
</div>
</div>
<p>
Don't have an account? <Link to="/signup">Sign up</Link>
</p>
</article>
</main>
)
}
Loading