Files
qipai/backend/src/routes/platform-bootstrap.ts
T

56 lines
1.7 KiB
TypeScript

import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import {
AmbiguousAppTenantError,
type PlatformBootstrap
} from '../tenancy/platform-config-repository.js';
const headerSchema = z.object({
'x-wechat-appid': z.string().trim().min(6).max(64),
'tenant-id': z.string().regex(/^[1-9]\d{0,19}$/).optional()
});
export interface PlatformConfigResolver {
resolveBootstrap(appId: string, tenantId?: string): Promise<PlatformBootstrap | null>;
}
export async function registerPlatformBootstrapRoutes(
app: FastifyInstance,
repository: PlatformConfigResolver
): Promise<void> {
app.get('/app-api/bootstrap', async (request, reply) => {
const parsed = headerSchema.safeParse(request.headers);
if (!parsed.success) {
return reply.status(400).send({
code: 'INVALID_APP_CONTEXT',
message: 'x-wechat-appid is required and tenant-id must be a positive integer.',
traceId: request.traceId
});
}
try {
const bootstrap = await repository.resolveBootstrap(
parsed.data['x-wechat-appid'],
parsed.data['tenant-id']
);
if (!bootstrap) {
return reply.status(404).send({
code: 'APP_TENANT_NOT_FOUND',
message: 'The application and tenant binding is not active.',
traceId: request.traceId
});
}
return { code: 0, data: bootstrap, traceId: request.traceId };
} catch (error) {
if (error instanceof AmbiguousAppTenantError) {
return reply.status(409).send({
code: 'TENANT_SELECTION_REQUIRED',
message: error.message,
traceId: request.traceId
});
}
throw error;
}
});
}