Enable auth-service/api-gateway on production, build their images in CI

This commit is contained in:
2026-08-18 14:11:00 +07:00
parent e5afedfa2f
commit b68005be1c
70 changed files with 6781 additions and 263 deletions
+36
View File
@@ -0,0 +1,36 @@
import type { AuthUser, LoginRequest } from "@duoc-thu/shared-types";
export class AuthError extends Error {
constructor(readonly status: number) {
super(`Auth request failed (${status})`);
this.name = "AuthError";
}
}
/** Calls the app's own `/api/auth/login` route (which holds the gateway URL
* and sets the httpOnly session cookie) — mirrors `sendChatMessage`'s
* BFF-first pattern rather than calling api-gateway from the browser. */
export async function login(credentials: LoginRequest): Promise<AuthUser> {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(credentials),
});
if (!response.ok) throw new AuthError(response.status);
const data = (await response.json()) as { user: AuthUser };
return data.user;
}
export async function logout(): Promise<void> {
const response = await fetch("/api/auth/logout", { method: "POST" });
if (!response.ok) throw new AuthError(response.status);
}
/** Returns `null` on 401 (no/expired session) rather than throwing — "not
* logged in" is an expected, common state for this page, not an error. */
export async function me(): Promise<AuthUser | null> {
const response = await fetch("/api/auth/me");
if (response.status === 401) return null;
if (!response.ok) throw new AuthError(response.status);
return (await response.json()) as AuthUser;
}
+1
View File
@@ -1,3 +1,4 @@
export * from "./sendChatMessage";
export * from "./getDrugSuggestions";
export * from "./auth";
+6
View File
@@ -17,9 +17,15 @@ export function buildMockResponse(userContent: string): SendMessageResponse {
`dùng để tra cứu. Câu hỏi nhận được: "${userContent}".`,
citations: [
{
chunkId: "mock-paracetamol-lieu_dung-1",
drugName: "PARACETAMOL",
sectionType: "lieu_dung",
sourcePageRange: [412, 413],
physicalPage: 411,
// Deliberately empty, same reasoning as `content` above — a
// plausible-looking mock snippet is a plausible-looking mock dose.
snippet: "",
isQuarantined: false,
},
],
disclaimer: