openvibers/openvibe.watch Commits

/openapi.json: the service's public API as OpenAPI 3.1 (SEO-3) (#198)

OP OpenVibers committed 10 days ago · 3319845d97 · 2 files, +32 −0

It answered 404. The route serves the contracts' generated document for this service
(openvibe-contracts), without the operations they mark internal-only.

Changes

ddiff --git a/server/app.js b/server/app.js
iindex fb1bbb4..f1492f1 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -61,6 +61,25 @@ const CSP = "default-src 'self'; script-src 'self' 'unsafe-inline' https://openv
function createApp({ config, db, registry, check, observations, scheduler, auth, outbox, actions = null, now, log = console, limitsNow = null, sessions, keyStore, siteLimits, fetchImpl = globalThis.fetch, accountData = null, accountSend = null, eventSources = null, webhookSources = null, billing = null }) {
const app = express();
++ // GET /openapi.json (SEO-3): this service's public API as OpenAPI 3.1, generated from the contracts
++ // (openvibe-contracts); the operations they mark internal-only are left out.
++ app.get('/openapi.json', (_req, res) => {
++ const doc = require('openvibe-contracts').openapi.document('watch');
++ if (!doc) return res.status(404).type('text/plain').send('No API document.');
++ const METHODS = new Set(['get', 'put', 'post', 'delete', 'patch', 'head', 'options']);
++ const paths = {};
++ for (const [p, item] of Object.entries(doc.paths || {})) {
++ const kept = {};
++ for (const [k, op] of Object.entries(item || {})) {
++ if (!METHODS.has(k)) { kept[k] = op; continue; }
++ const vis = [].concat((op && op['x-openvibe-visibility']) || []);
++ if (vis.length && vis.every((v) => v === 'internal')) continue;
++ kept[k] = op;
++ }
++ if (Object.keys(kept).some((k) => METHODS.has(k))) paths[p] = kept;
++ }
++ res.set('Cache-Control', 'public, max-age=3600').set('Access-Control-Allow-Origin', '*').json({ ...doc, paths });
++ });
app.disable('x-powered-by');
app.set('trust proxy', config.trustProxy != null ? config.trustProxy : 'loopback');
const release = createRelease({ service: 'watch', root: path.join(__dirname, '..') });
ddiff --git a/test/openapi-json.test.js b/test/openapi-json.test.js
nnew file mode 100644
iindex 0000000..c3bf4e5
---- /dev/null
++++ b/test/openapi-json.test.js
@@@ -0,0 +1,13 @@
++'use strict';
++// SEO-3: /openapi.json answered 404 here (11-03). It is the contracts' OpenAPI 3.1 document for this service
++// (openvibe-contracts), without the operations they mark internal-only.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++const doc = require('openvibe-contracts').openapi.document('watch');
++assert.ok(doc && doc.openapi && /^3\.1/.test(doc.openapi), 'the contracts carry an OpenAPI 3.1 document for watch');
++const src = fs.readFileSync(path.join(__dirname, '..', 'server/app.js'), 'utf8');
++assert.match(src, /app\.get\('\/openapi\.json'/, 'the route is mounted');
++assert.match(src, /openapi\.document\('watch'\)/);
++assert.match(src, /vis\.every\(\(v\) => v === 'internal'\)\) continue;/, 'internal-only operations are left out');
++console.log('openapi.json: ok');