From b47c9d75dfdff6580968ed1f28fd1d1607bf4777 Mon Sep 17 00:00:00 2001 From: Christian Georgi Date: Wed, 28 Oct 2020 10:55:35 +0100 Subject: [PATCH] Embed Swagger UI --- .gitignore | 2 ++ bookshop/package.json | 3 ++- bookshop/server.js | 48 +++++++++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 bookshop/server.js diff --git a/.gitignore b/.gitignore index 1951715e..f3283db5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ default-env.json packages/messageBox reviews/msg-box reviews/db/test.db + +*.openapi3.json diff --git a/bookshop/package.json b/bookshop/package.json index 6601ca5c..20294682 100644 --- a/bookshop/package.json +++ b/bookshop/package.json @@ -10,7 +10,8 @@ "scripts": { "genres": "cds serve test/genres.cds", "start": "cds run", - "watch": "cds watch" + "watch": "cds watch", + "to-openapi": "cds compile srv --to openapi -s CatalogService -o srv" }, "cds": { "requires": { diff --git a/bookshop/server.js b/bookshop/server.js new file mode 100644 index 00000000..819982b7 --- /dev/null +++ b/bookshop/server.js @@ -0,0 +1,48 @@ +const cds = require ('@sap/cds') +const {resolve} = require ('path') +const {promisify} = require('util') +const readFile = promisify(require('fs').readFile) +const swaggerUi = require ('swagger-ui-express') +const DEBUG = cds.debug('openapi') + +let app, host, docCache={} + +cds + .on ('bootstrap', _app => { app = _app }) + .on ('serving', service => { + const apiPath = '/api-docs'+service.path + console.log (`[Open API] - serving ${service.name} at ${apiPath}`) + app.use(apiPath, async (req, _, next) => { + req.swaggerDoc = await toOpenApiDoc(service, host, docCache) + next() + }, swaggerUi.serve, swaggerUi.setup()) + }) + .on ('listening', ({server})=> { host = 'localhost:'+server.address().port }) + +async function toOpenApiDoc(service, host, cache) { + if (!cache[service.name]) { + const spec = await openApiFromFile(service) + if (spec) { + cache[service.name] = spec + } + else if (cds.compile.to.openapi) { // on-the-fly exporter available? + DEBUG && DEBUG ('Compiling Open API spec for', service.name) + cache[service.name] = cds.compile.to.openapi (service.model, { + service: service.name, + scheme: 'http', host, basePath: service.path + }) + } + } + return cache[service.name] +} + +async function openApiFromFile(service) { + const fileName = resolve(`srv/${service.name}.openapi3.json`) + const file = await readFile(fileName).catch(()=>{/*no such file*/}) + if (file) { + DEBUG && DEBUG ('Using Open API spec from file', fileName) + return JSON.parse(file) + } +} + +module.exports = cds.server diff --git a/package.json b/package.json index f81fc148..7423acbb 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", - "sqlite3": "^5" + "sqlite3": "^5", + "swagger-ui-express": "^4.1.4" }, "scripts": { "bookshop": "cds watch bookshop",