import type { Config } from "./config.js"; import { NocoDBClient } from "./services/nocodb.js"; import { Mailer } from "./services/mailer.js"; import { RedeemQueue } from "./services/redeemQueue.js"; import { AuditLogger } from "./services/audit.js"; import { DonorService } from "./services/donors.js"; import { loadActiveTables } from "./services/state.js"; /** Shared services wired once at startup and hung off the Fastify instance. */ export interface AppContext { config: Config; nocodb: NocoDBClient; mailer: Mailer; queue: RedeemQueue; audit: AuditLogger; donors: DonorService; } export function buildContext(config: Config): AppContext { const nocodb = new NocoDBClient(config); const audit = new AuditLogger(config); // Apply a persisted "active event table" override (set from the admin area), // so switching the event survives redeploys without editing .env. const override = loadActiveTables(config.STATE_DIR); if (override) { nocodb.setTableId(override.ticketsTableId); audit.setTableId(override.auditTableId ?? null); } return { config, nocodb, mailer: new Mailer(config), queue: new RedeemQueue(), audit, donors: new DonorService(config), }; } // Ambient module augmentation so `fastify.ctx` and `request.user` are typed. declare module "fastify" { interface FastifyInstance { ctx: AppContext; } } declare module "@fastify/jwt" { interface FastifyJWT { payload: { role: "staff" }; user: { role: "staff" }; } }