Files
Toju/server/src/routes/openapi-docs.ts
Myx ee293d7daf
Some checks failed
Deploy Web Apps / deploy (push) Successful in 5m52s
Build Android APK / build-android-apk (push) Failing after 23m15s
Queue Release Build / prepare (push) Successful in 1m42s
Queue Release Build / build-linux (push) Failing after 9m33s
Queue Release Build / build-windows (push) Successful in 26m5s
Queue Release Build / finalize (push) Has been skipped
feat: Rename to Toju and add translation
2026-06-05 17:17:29 +02:00

107 lines
3.9 KiB
TypeScript

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(`<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Toju Plugin API Docs</title></head>
<body style="font-family:system-ui;margin:2rem;line-height:1.5">
<h1>Toju Plugin Support API</h1>
<p>Plugin support endpoints are available at <a href="/api/openapi.json">/api/openapi.json</a>.</p>
<p>The signal server stores plugin install metadata and event definitions only. It never executes plugin code or stores arbitrary plugin data.</p>
</body>
</html>`);
});
export default router;