- Added GameApiConfig interface and configuration resolver from environment variables. - Created GameApiContext for managing database and transport dependencies. - Implemented InMemoryTurnDaemonTransport for testing purposes. - Developed RedisTurnDaemonTransport for command and status handling via Redis streams. - Defined TurnDaemonStreamKeys for namespacing Redis streams by profile. - Established TRPC router with endpoints for health check, world state retrieval, and turn daemon commands (run, pause, resume, status). - Integrated Fastify server with TRPC and Redis transport. - Added unit tests for router functionality and stream key generation. - Configured Vitest for testing environment.
79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import fastify from 'fastify';
|
|
import cors from '@fastify/cors';
|
|
import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
|
|
import {
|
|
createPostgresConnector,
|
|
createRedisConnector,
|
|
resolvePostgresConfigFromEnv,
|
|
resolveRedisConfigFromEnv,
|
|
} from '@sammo-ts/infra';
|
|
|
|
import { resolveGameApiConfigFromEnv } from './config.js';
|
|
import { createGameApiContext } from './context.js';
|
|
import { buildTurnDaemonStreamKeys } from './daemon/streamKeys.js';
|
|
import { RedisTurnDaemonTransport } from './daemon/redisTransport.js';
|
|
import { appRouter } from './router.js';
|
|
|
|
export const createGameApiServer = async () => {
|
|
const config = resolveGameApiConfigFromEnv();
|
|
const postgres = createPostgresConnector(resolvePostgresConfigFromEnv());
|
|
const redis = createRedisConnector(resolveRedisConfigFromEnv());
|
|
|
|
await postgres.connect();
|
|
await redis.connect();
|
|
|
|
const turnDaemon = new RedisTurnDaemonTransport(redis.client, {
|
|
keys: buildTurnDaemonStreamKeys(config.profileName),
|
|
requestTimeoutMs: config.daemonRequestTimeoutMs,
|
|
});
|
|
|
|
const app = fastify({
|
|
logger: true,
|
|
});
|
|
|
|
await app.register(cors, {
|
|
origin: true,
|
|
credentials: true,
|
|
});
|
|
|
|
await app.register(fastifyTRPCPlugin, {
|
|
prefix: config.trpcPath,
|
|
trpcOptions: {
|
|
router: appRouter,
|
|
createContext: () =>
|
|
createGameApiContext({
|
|
db: postgres.prisma,
|
|
turnDaemon,
|
|
profile: {
|
|
id: config.profile,
|
|
scenario: config.scenario,
|
|
name: config.profileName,
|
|
},
|
|
}),
|
|
},
|
|
});
|
|
|
|
app.get('/healthz', async () => ({
|
|
ok: true,
|
|
profile: config.profileName,
|
|
}));
|
|
|
|
app.addHook('onClose', async () => {
|
|
await redis.disconnect();
|
|
await postgres.disconnect();
|
|
});
|
|
|
|
return {
|
|
app,
|
|
config,
|
|
};
|
|
};
|
|
|
|
export const runGameApiServer = async (): Promise<void> => {
|
|
const { app, config } = await createGameApiServer();
|
|
await app.listen({
|
|
host: config.host,
|
|
port: config.port,
|
|
});
|
|
};
|