Search

Bootstrapping Process

A Node.js CAP server process is started with the cds serve CLI command, with cds run and cds watch as convenience variants.

Besides, handling command line arguments and adding log output, cds serve essentially loads a built-in server.js module, which can be accessed through cds.server.

You can plug-in custom logic to the default bootstrapping choreography using a custom server.js in your project.

cds.server (options) => {…}

This is essentially a shortcut getter to require('@sap/cds/server'), that is, it loads and returns the built-in server.js implementation. You’d mainly use this in custom server.js to delegate to the default implementation, for example:.

const cds = require('@sap/cds')
// ... some custom bootstrapping ...
module.exports = cds.server //> delegate to default server.js

Built-in server.js

The built-in server.js constructs an express.js app, and bootstraps all CAP services using cds.connect and cds.serve. Its implementation essentially is as follows:

const cds = require('./lib'), {folders} = cds.env
const express = require('express')
module.exports = async(o)=>{                //> o = options from CLI

    const app = cds.app = o.app || express() 
    cds.emit ('bootstrap',app)              //> before bootstrapping

    app.use (express.static (folders.app))  //> default is ./app
    app.use ('/favicon.ico', o.favicon)     //> if none in ./app
    app.get ('/', o.index_html)             //> if none in ./app
    app.use (o.logger)                      //> basic logging

    cds.model = await cds.load (o.from)     //> default is '*'
    if (cds.requires.messaging)   await cds.connect.to('messaging')
    if (cds.requires.db) cds.db = await cds.connect.to('db')
    if (o.in_memory) await cds.deploy(cds.model).to(cds.db,o)
    cds.services = await cds.serve(o).from(cds.model).in(app)

    cds.emit ('served', cds.services)       //> after bootstrapping
    return app.listen (o.port || process.env.PORT || 4004)
}

Custom server.js

The CLI command cds serve optionally bootstraps from project-local ./server.js or ./srv/server.js. In there, register own handlers to bootstrap events emitted to the cds facade object as below:

const cds = require('@sap/cds')
// react on bootstrapping events...
cds.on('bootstrap', ...)
cds.on('served', ...)
module.exports = cds.server //> delegate to default server.js

Provide an own bootstrapping function if you want to access and process the command line options. This also allows you to override certain options before delegating to the built-in server.js. In the example below, we construct the express.js app ourselves and fix the models to be loaded.

const cds = require('@sap/cds')
// react on bootstrapping events...
cds.on('bootstrap', ...)
cds.on('served', ...)
// handle and override options
module.exports = (o)=>{
  o.from = 'srv/precompiled-csn.json'
  o.app = require('express')()
  return cds.server(o) //> delegate to default server.js
}

cds.once (‘bootstrap’, (express.js app)=>{})

A one-time event, emitted immediately after the express.js app has been created and before any middleware or CDS services are added to it.

const cds = require('@sap/cds')
cds.on('bootstrap', (app)=>{
  // add your own middleware before any by cds are added
})

cds.on (‘loaded’, (csn)=>{})

Emitted whenever a CDS model got loaded using cds.load()

cds.on (‘serving’, (service)=>{})

Emitted for each service constructed by cds.serve.

cds.on (‘connect’, (service)=>{})

Emitted for each service constructed through cds.connect.

cds.on (‘subscribe’, (service,event)=>{})

Emitted whenever a handler is registered for a declared event with [srv.on].

cds.once (‘served’, (services)=>{})

A one-time event, emitted when all services have been bootstrapped and added to the express.js app.

const cds = require('@sap/cds')
cds.on('served', ()=>{
  // add more middleware after all CDS services
})

cds.once (‘listening’, ({server,url})=>{})

A one-time event, emitted when the server has been started and is listening to incoming requests.

Show/Hide Beta Features