Sessions
The session arg is a signed cookie store, wired into every handler and middleware. Mutations commit before the response. There is no manual save.
import { redirect } from 'camelon';
import type { PostFunction } from 'camelon';
export type PostInput = { body: { email: string; password: string } };
export const post: PostFunction<PostInput> = async ({ body, session }) => {
const user = await authenticate(body);
session.set('userId', user.id);
session.flash('toast', 'Welcome back'); // read once on the next page
throw redirect('/dashboard');
};import { redirect } from 'camelon';
import type { PostFunction } from 'camelon';
export const post: PostFunction = async ({ session }) => {
session.destroy(); // clears state, expires the cookie
throw redirect('/');
};API
| Method | Effect |
|---|---|
get(key) |
read a value |
set(key, val) |
write a value |
has(key) |
check a key |
unset(key) |
remove a key |
flash(key, val) |
write a one-read value |
destroy() |
clear state, expire the cookie |
Type the store by declaring session on Register — get/set are then keyed and valued from it, with no per-call type argument:
declare module 'camelon' {
interface Register {
session: { userId: string };
}
}
session.set('userId', user.id); // value typed
const id = session.get('userId'); // string | undefined
Guarding a section
Check the session in a _middleware.ts:
import { redirect } from 'camelon';
import type { MiddlewareFunction } from 'camelon';
const requireAuth: MiddlewareFunction = ({ session }) => {
if (!session.has('userId')) throw redirect('/login');
};
export const middleware = [requireAuth];export default function Dashboard() {
return <h1>Welcome back</h1>;
}The secret
Set SESSION_SECRET to sign cookies. In dev without one, camelon uses an ephemeral per-boot secret and warns. In production without one, the first session use throws. There is no default secret.
Custom store
Pass your own store for max-age or key rotation. createSessionStore is on the camelon/session subpath.
import { createSessionStore } from 'camelon/session';
await createHandler({
routes: manifest,
session: createSessionStore({
secrets: [process.env.SESSION_SECRET!],
maxAge: 60 * 60 * 24,
}),
});
CSRF
camelon checks the Origin header on POST, PUT, PATCH, and DELETE in production, blocking cross-origin writes. Allow extra origins for third-party callbacks, or disable with ['*'].
await createHandler({
routes: manifest,
csrf: { trustedOrigins: ['https://pay.example.com'] },
});
There is no raw cookies arg. For a one-off cookie, read request.headers.get('cookie') or write response.header('set-cookie', ...).