// src/controllers/api/v1/provider.ts // Copyright (C) 2026 Robert Colbert // All Rights Reserved import { Request, Response } from "express"; import { DtpController } from "../../../lib/controller.js"; import AiProvider from "../../../models/ai-provider.js"; class ProviderController extends DtpController { get name(): string { return "ProviderController"; } get slug(): string { return "ctrl:api:v1:provider"; } get route(): string { return "/providers"; } async start(): Promise { this.router.get("/", this.requireUser(), this.listProviders.bind(this)); this.router.get("/:id", this.requireUser(), this.getProvider.bind(this)); } /** * GET /api/v1/providers * List all AI providers. */ private async listProviders(_req: Request, res: Response): Promise { try { const providers = await AiProvider.find({}) .select("-apiKey") // Never expose API keys .sort({ name: 1 }) .lean(); res.json({ success: true, data: providers, }); } catch (error) { const err = error as Error; this.log.error("failed to list providers", { error: err.message }); res.status(500).json({ success: false, message: err.message, }); } } /** * GET /api/v1/providers/:id * Get a specific provider by ID. */ private async getProvider(req: Request, res: Response): Promise { try { const id = Array.isArray(req.params.id) ? req.params.id[0] : req.params.id; const provider = await AiProvider.findById(id) .select("-apiKey") // Never expose API keys .lean(); if (!provider) { res.status(404).json({ success: false, message: "Provider not found", }); return; } res.json({ success: true, data: provider, }); } catch (error) { const err = error as Error; this.log.error("failed to get provider", { error: err.message }); if (err.message.includes("Cast to ObjectId failed")) { res.status(400).json({ success: false, message: "Invalid provider ID", }); } else { res.status(500).json({ success: false, message: err.message, }); } } } } export default ProviderController;