Swagger UI with cds-swagger-ui-express
Moved from `bookshop` to `fiori`, as that one already has a `server.js`
This commit is contained in:
@@ -5,15 +5,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capire/common": "*",
|
"@capire/common": "*",
|
||||||
"@sap/cds": "^5.0.4",
|
"@sap/cds": "^5.0.4",
|
||||||
"cors": "^2.8.5",
|
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"passport": "0.4.1"
|
"passport": "0.4.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"genres": "cds serve test/genres.cds",
|
"genres": "cds serve test/genres.cds",
|
||||||
"start": "cds run",
|
"start": "cds run",
|
||||||
"watch": "cds watch",
|
"watch": "cds watch"
|
||||||
"to-openapi": "cds compile srv --to openapi -s all -o srv --openapi:diagram"
|
|
||||||
},
|
},
|
||||||
"cds": {
|
"cds": {
|
||||||
"requires": {
|
"requires": {
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
// Serves a Swagger UI with API definitions either created on the fly
|
|
||||||
// or loaded from file system.
|
|
||||||
//
|
|
||||||
// Needs @sap/cds-dk >= 3.3.0 installed
|
|
||||||
|
|
||||||
const {resolve} = require ('path')
|
|
||||||
const {promisify} = require('util')
|
|
||||||
const readFile = promisify(require('fs').readFile)
|
|
||||||
const swaggerUi = require ('swagger-ui-express')
|
|
||||||
const cds = require ('@sap/cds')
|
|
||||||
const cors = require('cors')
|
|
||||||
|
|
||||||
const debug = cds.debug('openapi')
|
|
||||||
let app, docCache={}
|
|
||||||
|
|
||||||
cds
|
|
||||||
.on ('bootstrap', _app => {
|
|
||||||
app = _app
|
|
||||||
app.use(cors()) // allow to be called from e.g. editor.swagger.io
|
|
||||||
})
|
|
||||||
.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, docCache)
|
|
||||||
next()
|
|
||||||
}, swaggerUi.serve, swaggerUi.setup())
|
|
||||||
addLinkToIndexHtml(service, apiPath)
|
|
||||||
})
|
|
||||||
|
|
||||||
async function toOpenApiDoc(service, cache) {
|
|
||||||
if (!cache[service.name]) {
|
|
||||||
const spec = await openApiFromFile(service)
|
|
||||||
if (spec) { // pre-compiled spec file available?
|
|
||||||
cache[service.name] = spec
|
|
||||||
}
|
|
||||||
// On-the-fly exporter available? Needs @sap/cds-dk >= 3.3.0
|
|
||||||
else if (cds.compile.to.openapi) {
|
|
||||||
debug && debug ('Compiling Open API spec for', service.name)
|
|
||||||
cache[service.name] = cds.compile.to.openapi (service.model, {
|
|
||||||
service: service.name,
|
|
||||||
'openapi:url': service.path,
|
|
||||||
'openapi:diagram': true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addLinkToIndexHtml(service, apiPath) {
|
|
||||||
const provider = (entity) => {
|
|
||||||
if (entity) return // avoid link on entity level, looks too messy
|
|
||||||
return { href:apiPath, name:'Swagger UI', title:'Show in Swagger UI' }
|
|
||||||
}
|
|
||||||
// Needs @sap/cds >= 4.4.0
|
|
||||||
service.$linkProviders ? service.$linkProviders.push(provider) : service.$linkProviders = [provider]
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cds.server
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
const cds = require ('@sap/cds')
|
const cds = require ('@sap/cds')
|
||||||
|
module.exports = cds.server
|
||||||
|
|
||||||
cds.once('bootstrap',(app)=>{
|
cds.once('bootstrap',(app)=>{
|
||||||
app.use ('/orders/webapp', _from('@capire/orders/app/orders/webapp/manifest.json'))
|
app.use ('/orders/webapp', _from('@capire/orders/app/orders/webapp/manifest.json'))
|
||||||
@@ -8,7 +9,11 @@ cds.once('bootstrap',(app)=>{
|
|||||||
|
|
||||||
cds.once('served', require('./srv/mashup'))
|
cds.once('served', require('./srv/mashup'))
|
||||||
|
|
||||||
module.exports = cds.server
|
// Swagger UI - see https://cap.cloud.sap/docs/advanced/openapi
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
const cds_swagger = require ('cds-swagger-ui-express')
|
||||||
|
cds.once ('bootstrap', app => app.use (cds_swagger()) )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
"@capire/reviews": "./reviews"
|
"@capire/reviews": "./reviews"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cds-swagger-ui-express": "^0.1.0",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"chai-subset": "^1.6.0",
|
"chai-subset": "^1.6.0",
|
||||||
"sqlite3": "^5.0.0",
|
"sqlite3": "^5.0.0"
|
||||||
"swagger-ui-express": "^4.1.4"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",
|
"cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ Each sub directory essentially is an individual npm package arranged in an [all-
|
|||||||
- Support for [Value Helps](https://cap.cloud.sap/docs/guides/fiori#value-help)
|
- Support for [Value Helps](https://cap.cloud.sap/docs/guides/fiori#value-help)
|
||||||
- Serving SAP Fiori apps locally
|
- Serving SAP Fiori apps locally
|
||||||
- [The Vue.js app](bookshop/app/vue) imported from bookshop is served as well
|
- [The Vue.js app](bookshop/app/vue) imported from bookshop is served as well
|
||||||
|
- [OpenAPI export + Swagger UI](https://cap.cloud.sap/docs/advanced/openapi)
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user