import { Router } from 'express'; import { areOpenApiDocsEnabled, setOpenApiDocsEnabled } from '../config/variables'; const router = Router(); function createOpenApiDocument(baseUrl: string) { return { openapi: '3.1.0', info: { title: 'Toju Plugin Support API', version: '1.0.0', description: 'Official HTTP endpoints for plugin install metadata and event definitions. ' + 'Plugin code is never executed by the signal server.' }, servers: [{ url: `${baseUrl}/api` }], paths: { '/servers/{serverId}/plugins': { get: { summary: 'Read plugin requirement snapshot', parameters: [{ name: 'serverId', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': { description: 'Plugin requirements and event definitions' } } } }, '/servers/{serverId}/plugins/{pluginId}/requirement': { put: { summary: 'Create or update a server plugin requirement', responses: { '200': { description: 'Requirement saved' }, '403': { description: 'Not authorized' } } }, delete: { summary: 'Delete a server plugin requirement', responses: { '200': { description: 'Requirement deleted' }, '403': { description: 'Not authorized' } } } }, '/servers/{serverId}/plugins/{pluginId}/events/{eventName}': { put: { summary: 'Create or update a plugin event definition', responses: { '200': { description: 'Event definition saved' }, '403': { description: 'Not authorized' } } }, delete: { summary: 'Delete a plugin event definition', responses: { '200': { description: 'Event definition deleted' }, '403': { description: 'Not authorized' } } } }, '/servers/{serverId}/plugins/{pluginId}/data': { get: { summary: 'Plugin data persistence disabled', responses: { '410': { description: 'Plugin data persistence is disabled on the signal server' } } } }, '/servers/{serverId}/plugins/{pluginId}/data/{key}': { put: { summary: 'Plugin data persistence disabled', responses: { '410': { description: 'Plugin data persistence is disabled on the signal server' } } }, delete: { summary: 'Plugin data persistence disabled', responses: { '410': { description: 'Plugin data persistence is disabled on the signal server' } } } }, '/openapi/settings': { get: { summary: 'Read OpenAPI docs setting', responses: { '200': { description: 'Setting value' } } }, put: { summary: 'Toggle OpenAPI docs exposure', responses: { '200': { description: 'Setting value' } } } } } }; } function docsDisabledResponse() { return { error: 'OpenAPI docs are disabled', errorCode: 'OPENAPI_DOCS_DISABLED' }; } router.get('/openapi/settings', (_req, res) => { res.json({ enabled: areOpenApiDocsEnabled() }); }); router.put('/openapi/settings', (req, res) => { res.json(setOpenApiDocsEnabled(req.body?.enabled === true)); }); router.get('/openapi.json', (req, res) => { if (!areOpenApiDocsEnabled()) { res.status(404).json(docsDisabledResponse()); return; } res.json(createOpenApiDocument(`${req.protocol}://${req.get('host') ?? 'localhost'}`)); }); router.get('/docs', (_req, res) => { if (!areOpenApiDocsEnabled()) { res.status(404).json(docsDisabledResponse()); return; } res.type('html').send(` Toju Plugin API Docs

Toju Plugin Support API

Plugin support endpoints are available at /api/openapi.json.

The signal server stores plugin install metadata and event definitions only. It never executes plugin code or stores arbitrary plugin data.

`); }); export default router;