minor refactors to the adapter code

This commit is contained in:
2026-02-09 00:55:48 +05:30
parent 624b4d35e0
commit 4927be7206
7 changed files with 193 additions and 75 deletions

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ count.txt
.vinxi
todos.json
data.db
public/uploads

View File

@@ -1,10 +1,39 @@
import type { NextjsBkndConfig } from "bknd/adapter/nextjs";
import { type BkndConfig, em, entity, text, boolean } from "bknd";
// Unrelated to framework adapters
import { registerLocalMediaAdapter } from "bknd/adapter/node";
const local = registerLocalMediaAdapter();
// --------------------- SCHEMA -----------------------
// this just for testing
const schema = em({
todos: entity("todos", {
title: text(),
done: boolean(),
}),
post:entity("posts",{
title: text(),
content: text(),
})
});
// --------------------- SCHEMA END -----------------------
export default {
connection: {
url: "data.db",
},
options:{
}
} satisfies NextjsBkndConfig;
options: {},
config: {
data: schema.toJSON(),
auth: { enabled: true },
media: {
enabled: true,
adapter: local({
path: "./public/uploads",
}),
},
},
} satisfies BkndConfig;

View File

@@ -1,8 +1,8 @@
// Both work just fine
// import { getApp as getBkndApp } from "bknd/adapter/react-router";
import { getApp as getBkndApp } from "bknd/adapter/nextjs";
import config from "../bknd.config";
// import { headers } from "next/headers";
export async function getApi({
headers,
verify,
@@ -20,5 +20,3 @@ export async function getApi({
return app.getApi();
}
export { config };

View File

@@ -1,33 +1,34 @@
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
import { TanStackDevtools } from '@tanstack/react-devtools'
import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router";
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools";
import { TanStackDevtools } from "@tanstack/react-devtools";
import { ClientProvider } from "bknd/client";
import appCss from '../styles.css?url'
import appCss from "../styles.css?url";
export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: 'utf-8',
charSet: "utf-8",
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
name: "viewport",
content: "width=device-width, initial-scale=1",
},
{
title: 'TanStack Start Starter',
title: "TanStack Start Starter",
},
],
links: [
{
rel: 'stylesheet',
rel: "stylesheet",
href: appCss,
},
],
}),
shellComponent: RootDocument,
})
});
function RootDocument({ children }: { children: React.ReactNode }) {
return (
@@ -36,14 +37,16 @@ function RootDocument({ children }: { children: React.ReactNode }) {
<HeadContent />
</head>
<body>
{children}
<ClientProvider verbose baseUrl="http://localhost:3000">
{children}
</ClientProvider>
<TanStackDevtools
config={{
position: 'bottom-right',
position: "bottom-right",
}}
plugins={[
{
name: 'Tanstack Router',
name: "Tanstack Router",
render: <TanStackRouterDevtoolsPanel />,
},
]}
@@ -51,5 +54,5 @@ function RootDocument({ children }: { children: React.ReactNode }) {
<Scripts />
</body>
</html>
)
);
}

View File

@@ -1,41 +1,21 @@
import { getApi } from "@/bknd";
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { getRequestHeaders } from "@tanstack/react-start/server";
import { useAuth } from "bknd/client";
import "bknd/dist/styles.css";
import { Admin } from "bknd/ui";
export const getUser = createServerFn({ method: "GET" }).handler(async () => {
const headers = getRequestHeaders();
const api = await getApi({ verify: true, headers });
return { user: api.getUser() };
});
export const Route = createFileRoute("/admin/$")({
component: RouteComponent,
loader: async () => {
const user = await getUser();
return { user };
},
});
function RouteComponent() {
const { user } = Route.useLoaderData();
console.log(user);
const { user } = useAuth();
return (
<Admin
withProvider={{
user: {
email: "ada@example.com",
id: "",
strategy: "",
},
}}
withProvider={{ user: user }}
config={{
basepath: "/admin",
logo_return_path: "/../",
theme: "system",
}}
baseUrl="http://localhost:3000"
/>

View File

@@ -1,25 +1,17 @@
import { createFileRoute } from "@tanstack/react-router";
import { config } from "@/bknd";
import config from "../../bknd.config";
// Works fine
import { serve } from "bknd/adapter/nextjs";
const handler = serve({
...config,
// cleanRequest: {
// depending on what name you used for the catch-all route,
// you need to change this to clean it from the request.
// searchParams: ["$"],
// },
});
export const Route = createFileRoute("/api/$")({
server: {
handlers: {
ANY: async ({ request }) => {
const res = await handler(request);
// console.log("[API] ", res);
return res;
},
ANY: async ({ request }) => await handler(request),
},
},
});

View File

@@ -1,27 +1,142 @@
import { createFileRoute, Link } from "@tanstack/react-router";
import "../App.css";
import { useAuth } from "bknd/client";
import { useState } from "react";
export const Route = createFileRoute("/")({ component: App });
function App() {
const { user, verified, register, logout, login } = useAuth();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [mode, setMode] = useState<"login" | "register">("login");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
async function handleSubmit(e: React.SubmitEvent) {
e.preventDefault();
setLoading(true);
setError(null);
try {
if (mode === "login") {
// attempt login
await login({ email, password } as any);
} else {
// attempt register
await register({ email, password } as any);
}
setEmail("");
setPassword("");
} catch (err: any) {
setError(err?.message ?? String(err));
} finally {
setLoading(false);
}
}
async function handleLogout() {
setLoading(true);
try {
await logout();
} catch (err: any) {
setError(err?.message ?? String(err));
} finally {
setLoading(false);
}
}
return (
<div className="App">
<header className="App-header">
<img
src="/tanstack-circle-logo.png"
alt="TanStack Logo"
style={{
width: "100px",
height: "100px",
}}
/>
<Link
className="App-link"
to="/admin"
>
Admin Dashboard
</Link>
</header>
<div>
<main style={{ padding: 20 }} className="App-header">
<header>
<img
src="/tanstack-circle-logo.png"
alt="TanStack Logo"
style={{ width: "100px", height: "100px" }}
/>
</header>
<section>
</section>
<section style={{ maxWidth: 420, margin: "0 auto" }}>
<h2 style={{margin:"24px 0 "}}>Account</h2>
{user ? (
<div style={{ gap: 8, display: "flex", flexDirection: "column" }}>
<div>
<strong>Signed in as:</strong> {user?.email ?? "Unknown"}
</div>
<div>
<strong>Verified:</strong> {verified ? "Yes" : "No"}
</div>
<div style={{ display: "flex", gap: 8 }}>
<button onClick={handleLogout} disabled={loading}>
{loading ? "Signing out..." : "Sign out"}
</button>
<Link to={"/admin" as string}>
<button>Go to Admin</button>
</Link>
</div>
</div>
) : (
<form onSubmit={handleSubmit} style={{ display: "grid", gap: 8 }}>
<div style={{ display: "flex", gap: 8 }}>
<button
type="button"
onClick={() => setMode("login")}
style={{ textDecoration: mode === "login" ? "underline" : "none" }}
>
Log in
</button>
<button
type="button"
onClick={() => setMode("register")}
style={{ textDecoration: mode === "register" ? "underline" : "none" }}
>
Register
</button>
</div>
<input
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
style={{
border: "1px solid white",
padding: "4px",
borderRadius: "4px"
}}
type="email"
/>
<input
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
style={{
border: "1px solid white",
padding: "4px",
borderRadius: "4px"
}}
type="password"
/>
{error ? <div style={{ color: "#ff6b6b" }}>{error}</div> : null}
<button type="submit" disabled={loading}>
{loading
? "Please wait..."
: mode === "login"
? "Log in"
: "Create account"}
</button>
</form>
)}
</section>
</main>
</div>
);
}