feat: migrate authentication to Appwrite and remove Better-Auth references

This commit is contained in:
2025-09-03 20:03:13 -03:00
parent 7b0526ebee
commit 2dc472c60e
15 changed files with 380 additions and 317 deletions

View File

@@ -1,17 +1,77 @@
import type { Context as HonoContext } from "hono";
import { auth } from "./auth";
import { Account, Client } from "node-appwrite";
// Hoisted regex for performance and linting
const BEARER_REGEX = /^Bearer\s+(.+)$/i;
// Minimal user shape to avoid leaking node-appwrite model types
export type AuthUser = {
$id: string;
name?: string | null;
email?: string | null;
} | null;
export type CreateContextOptions = {
context: HonoContext;
};
export async function createContext({ context }: CreateContextOptions) {
const session = await auth.api.getSession({
headers: context.req.raw.headers,
});
return {
session,
};
const endpoint = process.env.APPWRITE_ENDPOINT;
const projectId = process.env.APPWRITE_PROJECT_ID;
if (!(endpoint && projectId)) {
// Appwrite not configured; treat as unauthenticated
return { user: null as AuthUser };
}
// Initialize client per request
const client = new Client().setEndpoint(endpoint).setProject(projectId);
// Prefer JWT from Authorization header if provided
const authHeader = context.req.header("Authorization");
const bearer = authHeader?.match(BEARER_REGEX)?.[1];
if (bearer) {
client.setJWT(bearer);
} else {
// Fallback: Appwrite session cookie from browser
// Cookie name format: a_session_<PROJECT_ID>
const cookieHeader =
context.req.header("Cookie") || context.req.header("cookie");
if (cookieHeader) {
const cookieName = `a_session_${projectId}`;
const cookies = Object.fromEntries(
cookieHeader.split("; ").map((c) => {
const idx = c.indexOf("=");
return idx === -1
? [c, ""]
: [c.substring(0, idx), decodeURIComponent(c.substring(idx + 1))];
})
);
const session = cookies[cookieName];
if (session) {
client.setSession(session);
}
}
}
const account = new Account(client);
try {
const user = (await account.get()) as unknown as {
$id: string;
name?: string | null;
email?: string | null;
};
const minimal: AuthUser = {
$id: user.$id,
name: user.name ?? null,
email: user.email ?? null,
};
return { user: minimal };
} catch {
return { user: null as AuthUser };
}
}
export type Context = Awaited<ReturnType<typeof createContext>>;