Getting data
We’ve put some data into our database. Now we need to get it back out.
Create a new remote function in auth.remote.ts. This time we’ll create a query called getUser:
export const getUser = query(async () => {
const { cookies } = getRequestEvent();
const session_id = cookies.get('session_id');
if (!session_id) return null;
const [result] = await db
.select({
id: user.id,
handle: user.handle,
display_name: user.display_name,
avatar_url: user.avatar_url,
created_at: user.created_at,
updated_at: user.updated_at
})
.from(session)
.innerJoin(user, eq(session.user_id, user.id))
.where(eq(session.id, session_id))
.limit(1);
return result ?? null;
}); This will look for a session matching session_id, and return the data for the associated user.
We can handle our test user here as well:
export const getUser = query(async () => {
const { cookies } = getRequestEvent();
const session_id = cookies.get('session_id');
if (!session_id) return null;
+ if (dev && session_id === 'test') {
+ const [result] = await db.select().from(user).where(eq(user.id, 'test'));
+ return result;
+ }
const [result] = await db
.select({
id: user.id,
handle: user.handle,
display_name: user.display_name,
avatar_url: user.avatar_url,
created_at: user.created_at,
updated_at: user.updated_at
})
.from(session)
.innerJoin(user, eq(session.user_id, user.id))
.where(eq(session.id, session_id))
.limit(1);
return result ?? null;
}); But it’s not enough to get a user or null — on this page we need to guarantee that the user exists. We can do that by creating a companion query:
export const requireUser = query(async () => {
const user = await getUser();
if (!user) redirect(302, '/login');
return user;
}); If user is null, this will redirect to the /login page. We can use this anywhere we need to know that the user is logged in — because redirect throws, requireUser will always return a user object.
One our homepage, add some structure, and an avatar for the logged-in user:
<header></header>
<main></main>
<footer>
<div class="left">
<img alt="{user.display_name}'s avatar" src={user.avatar_url} />
</div>
<div class="right"></div>
</footer>
<style>
footer {
position: fixed;
bottom: 0;
height: 6rem;
padding: 1rem;
.left {
height: 100%;
display: flex;
gap: 1rem;
}
img {
height: 100%;
aspect-ratio: 1;
border-radius: 9999px;
}
}
</style> We need a way to log out. Add a logout form…
export const logout = form(async () => {
const { cookies } = getRequestEvent();
const session_id = cookies.get('session_id');
if (!session_id) return;
if (dev && session_id === 'test') {
cookies.delete('session_id', { path: '/' });
return;
}
const [data] = await db.select().from(session).where(eq(session.id, session_id));
if (!data) return;
const client = createClient();
await client.revoke(data.user_id);
await db.delete(session).where(eq(session.id, session_id));
cookies.delete('session_id', { path: '/' });
}); …and wire up a button:
<form {...logout}>
<button>log out</button>
</form>