Files
curriculum-project-hub/hub/src/admin/plugin.ts
T
hongjr03 4e2699d0a5 fix(admin): serve built SPA and include it in release builds
registerStaticSpa was never mounted, so production only exposed org-admin
APIs. Wire it after auth/API routes, fold admin:build into npm run build,
and install admin-web deps during deploy so admin-web/build ships with the
release for same-origin /admin/*.
2026-07-14 23:54:47 +08:00

70 lines
2.6 KiB
TypeScript

/**
* Registers org-admin HTTP surface: auth, org APIs, and the static SPA shell.
*/
import cookie from "@fastify/cookie";
import type { PrismaClient } from "@prisma/client";
import type { FastifyInstance } from "fastify";
import { registerAuthRoutes } from "./routes/authRoutes.js";
import { registerOrgRoutes } from "./routes/orgRoutes.js";
import { registerStaticSpa } from "./static.js";
import type { LocalSecretEnvelope } from "../security/secretEnvelope.js";
import type { ProviderReadinessProbe } from "../connections/providerReadiness.js";
import type { FeishuReadinessProbe } from "../connections/feishuReadiness.js";
export interface AdminPluginConfig {
readonly prisma: PrismaClient;
readonly sessionSecret: string;
readonly publicBaseUrl: string;
readonly feishuAppId: string;
readonly feishuAppSecret: string;
readonly projectWorkspaceRoot: string;
readonly secretEnvelope: LocalSecretEnvelope;
readonly providerReadinessProbe?: ProviderReadinessProbe;
readonly feishuConnectionReadinessProbe?: FeishuReadinessProbe;
readonly cookieSecure?: boolean;
readonly oauthScope?: string;
readonly fetchImpl?: typeof fetch;
readonly allowLegacyFeishuOAuth?: boolean;
}
export async function registerAdminPlugin(
app: FastifyInstance,
config: AdminPluginConfig,
): Promise<void> {
await app.register(cookie);
const cookieSecure =
config.cookieSecure ?? config.publicBaseUrl.startsWith("https://");
await registerAuthRoutes(app, {
prisma: config.prisma,
sessionSecret: config.sessionSecret,
publicBaseUrl: config.publicBaseUrl,
feishuAppId: config.feishuAppId,
feishuAppSecret: config.feishuAppSecret,
secretEnvelope: config.secretEnvelope,
cookieSecure,
...(config.oauthScope !== undefined ? { oauthScope: config.oauthScope } : {}),
...(config.fetchImpl !== undefined ? { fetchImpl: config.fetchImpl } : {}),
...(config.allowLegacyFeishuOAuth !== undefined
? { allowLegacyFeishuOAuth: config.allowLegacyFeishuOAuth }
: {}),
});
await registerOrgRoutes(app, {
prisma: config.prisma,
sessionSecret: config.sessionSecret,
projectWorkspaceRoot: config.projectWorkspaceRoot,
secretEnvelope: config.secretEnvelope,
...(config.providerReadinessProbe !== undefined
? { providerReadinessProbe: config.providerReadinessProbe }
: {}),
...(config.feishuConnectionReadinessProbe !== undefined
? { feishuConnectionReadinessProbe: config.feishuConnectionReadinessProbe }
: {}),
});
// After API + /admin/login so SPA fallback does not shadow auth routes.
await registerStaticSpa(app);
}