mirror of
https://github.com/FranP-code/Reflecto.git
synced 2025-10-13 00:43:31 +00:00
83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
import type { Context as HonoContext } from "hono";
|
|
import { Account, Client } from "node-appwrite";
|
|
import { sanitizeModel } from "./ai-models";
|
|
|
|
// 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) {
|
|
// Capture selected AI model from client header (optional)
|
|
const aiModelHeader = context.req.header("x-ai-model");
|
|
const aiModel = sanitizeModel(aiModelHeader);
|
|
|
|
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, aiModel };
|
|
}
|
|
|
|
// 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, aiModel };
|
|
} catch {
|
|
return { user: null as AuthUser, aiModel };
|
|
}
|
|
}
|
|
|
|
export type Context = Awaited<ReturnType<typeof createContext>>;
|