Skip to content
Closed
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
41 changes: 21 additions & 20 deletions examples/better-auth/src/backend/auth.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
// import { betterAuth } from "better-auth";
// import { sqliteAdapter } from "@better-auth/sqlite";
// import Database from "better-sqlite3";
//
// const db = new Database("./auth.db");
//
// export const auth = betterAuth({
// database: sqliteAdapter(db),
// emailAndPassword: {
// enabled: true,
// },
// session: {
// expiresIn: 60 * 60 * 24 * 7, // 7 days
// updateAge: 60 * 60 * 24, // 1 day (every day the session expiry is updated)
// },
// plugins: [],
// });
//
// export type Session = typeof auth.$Infer.Session;
// export type User = typeof auth.$Infer.User;
import { betterAuth } from "better-auth";
import { sqliteAdapter } from "@better-auth/sqlite";
import Database from "better-sqlite3";

const db = new Database("./auth.db");

export const auth = betterAuth({
// IMPORTANT: Connect your own database here
database: sqliteAdapter(db),
emailAndPassword: {
enabled: true,
},
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24, // 1 day (every day the session expiry is updated)
},
plugins: [],
});

export type Session = typeof auth.$Infer.Session;
export type User = typeof auth.$Infer.User;
94 changes: 47 additions & 47 deletions examples/better-auth/src/backend/registry.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
// import { actor, setup } from "@rivetkit/actor";
// import { auth, type Session, type User } from "./auth";
//
// export const chatRoom = actor({
// onAuth: async (c) => {
// const authResult = await auth.api.getSession({
// headers: c.req.headers,
// });
//
// if (!authResult?.session || !authResult?.user) {
// throw new Error("Unauthorized");
// }
//
// return {
// userId: authResult.user.id,
// user: authResult.user,
// session: authResult.session,
// };
// },
// state: {
// messages: [] as Array<{ id: string; userId: string; username: string; message: string; timestamp: number }>
// },
// actions: {
// sendMessage: (c, message: string) => {
// const newMessage = {
// id: crypto.randomUUID(),
// userId: c.auth.userId,
// username: c.auth.user.email,
// message,
// timestamp: Date.now(),
// };
//
// c.state.messages.push(newMessage);
// c.broadcast("newMessage", newMessage);
//
// return newMessage;
// },
// getMessages: (c) => {
// return c.state.messages;
// },
// },
// });
//
// export const registry = setup({
// use: { chatRoom },
// });
//
import { actor, setup } from "@rivetkit/actor";
import { auth, type Session, type User } from "./auth";

export const chatRoom = actor({
onAuth: async (c) => {
const authResult = await auth.api.getSession({
headers: c.req.headers,
});

if (!authResult?.session || !authResult?.user) {
throw new Error("Unauthorized");
}

return {
userId: authResult.user.id,
user: authResult.user,
session: authResult.session,
};
},
state: {
messages: [] as Array<{ id: string; userId: string; username: string; message: string; timestamp: number }>
},
actions: {
sendMessage: (c, message: string) => {
const newMessage = {
id: crypto.randomUUID(),
userId: c.auth.userId,
username: c.auth.user.email,
message,
timestamp: Date.now(),
};

c.state.messages.push(newMessage);
c.broadcast("newMessage", newMessage);

return newMessage;
},
getMessages: (c) => {
return c.state.messages;
},
},
});

export const registry = setup({
use: { chatRoom },
});

108 changes: 54 additions & 54 deletions examples/better-auth/src/backend/server.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
// import { registry } from "./registry";
// import { auth } from "./auth";
// import { Hono } from "hono";
// import { serve } from "@hono/node-server";
//
// // Setup router
// const app = new Hono();
//
// // Start RivetKit
// const { client, hono } = registry.run({
// driver: createMemoryDriver(),
// cors: {
// // IMPORTANT: Configure origins in production
// origin: "*",
// },
// });
//
// // Mount Better Auth routes
// app.on(["GET", "POST"], "/api/auth/**", (c) => auth.handler(c.req.raw));
//
// // Expose RivetKit to the frontend
// app.route("/registry", hono);
//
// // Example HTTP endpoint to join chat room
// app.post("/api/join-room/:roomId", async (c) => {
// const roomId = c.req.param("roomId");
//
// // Verify authentication
// const authResult = await auth.api.getSession({
// headers: c.req.header(),
// });
//
// if (!authResult?.session || !authResult?.user) {
// return c.json({ error: "Unauthorized" }, 401);
// }
//
// try {
// const room = client.chatRoom.getOrCreate(roomId);
// const messages = await room.getMessages();
//
// return c.json({
// success: true,
// roomId,
// messages,
// user: authResult.user
// });
// } catch (error) {
// return c.json({ error: "Failed to join room" }, 500);
// }
// });
//
// serve({ fetch: app.fetch, port: 8080 }, () =>
// console.log("Listening at http://localhost:8080"),
// );
import { registry } from "./registry";
import { auth } from "./auth";
import { Hono } from "hono";
import { serve } from "@hono/node-server";

// Setup router
const app = new Hono();

// Start RivetKit
const { client, hono } = registry.run({
driver: createMemoryDriver(),
cors: {
// IMPORTANT: Configure origins in production
origin: "*",
},
});

// Mount Better Auth routes
app.on(["GET", "POST"], "/api/auth/**", (c) => auth.handler(c.req.raw));

// Expose RivetKit to the frontend
app.route("/registry", hono);

// Example HTTP endpoint to join chat room
app.post("/api/join-room/:roomId", async (c) => {
const roomId = c.req.param("roomId");

// Verify authentication
const authResult = await auth.api.getSession({
headers: c.req.header(),
});

if (!authResult?.session || !authResult?.user) {
return c.json({ error: "Unauthorized" }, 401);
}

try {
const room = client.chatRoom.getOrCreate(roomId);
const messages = await room.getMessages();

return c.json({
success: true,
roomId,
messages,
user: authResult.user
});
} catch (error) {
return c.json({ error: "Failed to join room" }, 500);
}
});

serve({ fetch: app.fetch, port: 8080 }, () =>
console.log("Listening at http://localhost:8080"),
);
146 changes: 73 additions & 73 deletions examples/better-auth/src/frontend/App.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,73 @@
// import { useState, useEffect } from "react";
// import { authClient } from "./auth-client";
// import { AuthForm } from "./components/AuthForm";
// import { ChatRoom } from "./components/ChatRoom";
//
// function App() {
// const [user, setUser] = useState<{ id: string; email: string } | null>(null);
// const [loading, setLoading] = useState(true);
//
// useEffect(() => {
// // Check if user is already authenticated
// const checkAuth = async () => {
// try {
// const session = await authClient.getSession();
// if (session.data?.user) {
// setUser(session.data.user);
// }
// } catch (error) {
// console.error("Auth check failed:", error);
// } finally {
// setLoading(false);
// }
// };
//
// checkAuth();
// }, []);
//
// const handleAuthSuccess = async () => {
// try {
// const session = await authClient.getSession();
// if (session.data?.user) {
// setUser(session.data.user);
// }
// } catch (error) {
// console.error("Failed to get user after auth:", error);
// }
// };
//
// const handleSignOut = () => {
// setUser(null);
// };
//
// if (loading) {
// return (
// <div style={{
// display: "flex",
// justifyContent: "center",
// alignItems: "center",
// height: "100vh"
// }}>
// Loading...
// </div>
// );
// }
//
// return (
// <div style={{ minHeight: "100vh", backgroundColor: "#f0f0f0" }}>
// <div style={{ padding: "20px 0" }}>
// <h1 style={{ textAlign: "center", marginBottom: "30px" }}>
// RivetKit with Better Auth
// </h1>
//
// {user ? (
// <ChatRoom user={user} onSignOut={handleSignOut} />
// ) : (
// <AuthForm onAuthSuccess={handleAuthSuccess} />
// )}
// </div>
// </div>
// );
// }
//
// export default App;
import { useState, useEffect } from "react";
import { authClient } from "./auth-client";
import { AuthForm } from "./components/AuthForm";
import { ChatRoom } from "./components/ChatRoom";

function App() {
const [user, setUser] = useState<{ id: string; email: string } | null>(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
// Check if user is already authenticated
const checkAuth = async () => {
try {
const session = await authClient.getSession();
if (session.data?.user) {
setUser(session.data.user);
}
} catch (error) {
console.error("Auth check failed:", error);
} finally {
setLoading(false);
}
};

checkAuth();
}, []);

const handleAuthSuccess = async () => {
try {
const session = await authClient.getSession();
if (session.data?.user) {
setUser(session.data.user);
}
} catch (error) {
console.error("Failed to get user after auth:", error);
}
};

const handleSignOut = () => {
setUser(null);
};

if (loading) {
return (
<div style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh"
}}>
Loading...
</div>
);
}

return (
<div style={{ minHeight: "100vh", backgroundColor: "#f0f0f0" }}>
<div style={{ padding: "20px 0" }}>
<h1 style={{ textAlign: "center", marginBottom: "30px" }}>
RivetKit with Better Auth
</h1>

{user ? (
<ChatRoom user={user} onSignOut={handleSignOut} />
) : (
<AuthForm onAuthSuccess={handleAuthSuccess} />
)}
</div>
</div>
);
}

export default App;
Loading
Loading