import { type FastifyInstance } from 'fastify'; import { getAllPlatformSettings, getPlatformSettings, upsertPlatformSettings, deletePlatformSettings, } from '../../db/repositories/platform-settings-repository'; import { Platform } from '../../types/index'; // ── JSON Schemas for Fastify Validation ── const VALID_PLATFORMS = [Platform.YouTube, Platform.SoundCloud, Platform.Generic] as const; const upsertPlatformSettingsBodySchema = { type: 'object' as const, properties: { defaultFormatProfileId: { type: 'integer' as const, nullable: true }, checkInterval: { type: 'integer' as const, minimum: 1 }, concurrencyLimit: { type: 'integer' as const, minimum: 1, maximum: 10 }, subtitleLanguages: { type: 'string' as const, nullable: true }, grabAllEnabled: { type: 'boolean' as const }, grabAllOrder: { type: 'string' as const, enum: ['newest', 'oldest'] }, scanLimit: { type: 'integer' as const, minimum: 10, maximum: 1000 }, rateLimitDelay: { type: 'integer' as const, minimum: 0, maximum: 10000 }, defaultMonitoringMode: { type: 'string' as const, enum: ['all', 'future', 'existing', 'none'] }, nfoEnabled: { type: 'boolean' as const }, defaultView: { type: 'string' as const, enum: ['list', 'poster', 'table'] }, }, additionalProperties: false, }; // ── Route Plugin ── /** * Platform settings CRUD route plugin. * * Registers: * GET /api/v1/platform-settings — list all platform settings * GET /api/v1/platform-settings/:platform — get settings for a specific platform * PUT /api/v1/platform-settings/:platform — upsert settings for a platform * DELETE /api/v1/platform-settings/:platform — delete settings for a platform */ export async function platformSettingsRoutes(fastify: FastifyInstance): Promise { // ── GET /api/v1/platform-settings ── fastify.get('/api/v1/platform-settings', async (_request, _reply) => { return getAllPlatformSettings(fastify.db); }); // ── GET /api/v1/platform-settings/:platform ── fastify.get<{ Params: { platform: string } }>( '/api/v1/platform-settings/:platform', async (request, reply) => { const { platform } = request.params; const settings = await getPlatformSettings(fastify.db, platform); if (!settings) { return reply.status(404).send({ statusCode: 404, error: 'Not Found', message: `Platform settings for '${platform}' not found`, }); } return settings; } ); // ── PUT /api/v1/platform-settings/:platform ── fastify.put<{ Params: { platform: string }; Body: { defaultFormatProfileId?: number | null; checkInterval?: number; concurrencyLimit?: number; subtitleLanguages?: string | null; grabAllEnabled?: boolean; grabAllOrder?: 'newest' | 'oldest'; scanLimit?: number; rateLimitDelay?: number; defaultMonitoringMode?: 'all' | 'future' | 'existing' | 'none'; nfoEnabled?: boolean; defaultView?: 'list' | 'poster' | 'table'; }; }>( '/api/v1/platform-settings/:platform', { schema: { body: upsertPlatformSettingsBodySchema }, }, async (request, reply) => { const { platform } = request.params; // Validate platform enum if (!VALID_PLATFORMS.includes(platform as typeof VALID_PLATFORMS[number])) { return reply.status(400).send({ statusCode: 400, error: 'Bad Request', message: `Invalid platform '${platform}'. Must be one of: ${VALID_PLATFORMS.join(', ')}`, }); } const settings = await upsertPlatformSettings(fastify.db, { platform: platform as typeof VALID_PLATFORMS[number], ...request.body, }); return settings; } ); // ── DELETE /api/v1/platform-settings/:platform ── fastify.delete<{ Params: { platform: string } }>( '/api/v1/platform-settings/:platform', async (request, reply) => { const { platform } = request.params; const deleted = await deletePlatformSettings(fastify.db, platform); if (!deleted) { return reply.status(404).send({ statusCode: 404, error: 'Not Found', message: `Platform settings for '${platform}' not found`, }); } return reply.status(204).send(); } ); }