Customizing cds build
Build Configurations
cds build
executes build tasks on your project folders to prepare them for deployment. Build tasks compile source files (typically CDS sources) and create the required artifacts, for example, EDMX files, SAP HANA design-time artifacts, and so on. By default, cds build
dynamically determines the build tasks from the CDS configuration and from the project context. See build task properties for a concrete list of the different build task types.
The CDS model folders and files used by cds build
are determined as follows:
- Known root folders, by default the folders db/, srv/, app/, can also be configured by folders.db, folders.srv, folders.app.
- The src folder configured for the individual build task.
- If Feature toggles are enabled: subfolders of the folder fts.
- CDS Model folders and files defined by the required services of your project. This also includes models used by required built-in CDS services, like persistent outbox or MTX related services.
Feature toggle folders and required built-in service models will also be added if user defined models have already been configured as model option in your build tasks.
Learn more about the calculation of the concrete list of CDS models.
If custom build tasks are configured, those properties have precedence
For example, you want to configure the src folder and add the default models. To achieve this, do not define the model option in your build task. That way, the model paths will still be dynamically determined, but the src folder is taken from the build task configuration. So you benefit from the automatic determination of models, for example, when adding a new external services, or when CAP is changing any built-in service configuration values.
To control which tasks cds build
executes, you can add them as part of your project configuration in package.json or .cdsrc.json.
Properties
Build Task
The following build tasks represent the default configuration dynamically determined by cds build
for a minimal Node.js project when executing cds build --production
or cds build --profile production
:
{
"build": {
"target": "gen",
"tasks": [
{ "for": "hana", "src": "db", "options": {"model": ["db","srv"] } },
{ "for": "nodejs", "src": "srv", "options": {"model": ["db","srv"] } }
]
}
}
TIP
The executed build tasks are logged to the command line. You can use them as a blue print – copy & paste them into your CDS configuration and adapt them to your needs. See also the command line help for further details using cds build --help
.
The for
property defines the executed build task type. Currently supported types are:
hana
: Creates a deployment layout for the SAP HANA Development Infrastructure (HDI) if an SAP HANA database has been configured.nodejs
(deprecated:node-cf
): Creates a deployment layout using a self-contained folder ./gen for Node.js apps.java
(deprecated:java-cf
): Creates a deployment layout for Java apps.mtx
: Creates a deployment layout for Node.js applications using multitenancy, feature toggles, extensibility or a combination of these without sidecar architecture.
In this scenario the required services are implemented by the Node.js application itself which is the default for Node.js.mtx-sidecar
: Creates a deployment layout for Java or Node.js projects using multitenancy, feature toggles, extensibility or a combination of these with sidecar architecture.
Java projects have to use a sidecar architecture. For Node.js this is optional, but allows for better scalability in multitenant scenarios. Learn more about Multitenant Saas Application Deploymentmtx-extension
: Creates a deployment layout (extension.tgz file) for an MTX extension project, which is required for extension activation usingcds push
. Extension point restrictions defined by the SaaS app provider are validated by default. If any restriction is violated the build aborts and the errors are logged.
The build task is created by default for projects that have"cds": { "extends": "\<SaaS app name\>" }
configured in their package.json.
Learn more about Extending and Customizing SaaS Solutions- Additional types may be supported by build plugin contributions.
Learn more about Running Build Plugins
Build tasks can be customized using the following properties:
src
: Source folder of the module that is about to be build.dest
: Optional destination of the modules builds, relative to the enclosing project. The src folder is used by default.options
: Sets the options according to the target technology.model
: It has type string or array of string. The given list of folders or individual .cds file names is resolved based on the current working dir or the project folder passed to cds build. CDS built-in models (prefix @sap/cds*) are added by default to the user-defined list of models. Learn more about Core Data Services (CDS)
Note: Alternatively you can execute build tasks and pass the described arguments from command line. See also cds build --help
for further details.
Build Target Folder
If you want to change the default target folder, use the target
property in .cdsrc.json or package.json. It is resolved based on the root folder of your project.
{
"build": { "target" : "myfolder" }
}
Node.js
Node.js projects use the folder ./gen below the project root as build target folder by default.
Relevant source files from db or srv folders are copied into this folder, which makes it a self-contained folder that is ready for deployment. The default folder names can be changed with the folders.db, folders.srv, folders.app configuration. Or you can go for individual build task configuration for full flexibility.
Project files like .cdsrc.json or .npmrc located in the root folder or in the srv folder of your project are copied into the application's deployment folder (default gen/srv). Files located in the srv folder have precedence over the corresponding files located in the project root directory. As a consequence these files are used when deployed to production. Make sure that the folders do not contain one of these files by mistake. Consider using profiles development
or production
in order to distinguish environments. CDS configuration that should be kept locally can be defined in a file .cdsrc-private.json.
The contents of the node_modules folder is not copied into the deployment folder. For security reasons the files default-env.json and .env are also not copied into the deployment folder.
You can verify the CDS configuration settings that become effective in production
deployments. Executing cds env --profile production
in the deployment folder gen/srv will log the CDS configuration used in production environment.
Note:cds build
provides options you can use to switch on or off the copy behavior on build task level:
{
"build": {
"tasks": [
{ "for": "nodejs", "options": { "contentCdsrcJson": false, "contentNpmrc": false } },
{ "for": "hana", "options": { "contentNpmrc": false } }
]
}
}
npm Workspace Support beta
Use CLI option --ws-pack
to enable tarball based deployment of npm workspace dependencies. Workspaces are typically used to manage multiple local packages within a singular top-level root package. Such a setup is often referred to as a monorepo.
As an effect, your workspace dependencies can be deployed to SAP BTP without them being published to an npm registry before.
Behind the scenes, cds build --ws-pack
creates a tarball in folder gen/srv for each workspace dependency of your project that has a *
version identifier. Dependencies in gen/package.json will be adapted to point to the correct tarball file URL.
Packaging of the tarball content is based on the rules of the npm pack
command:
- Files and folders defined in .gitignore will not be added
- If an optional
files
field is defined in the workspace's package.json, only those files will be added.
Java
Java projects use the project's root folder ./ as build target folder by default.
This causes cds build
to create the build output below the individual source folders. For example, db/src/gen contains the build output for the db/ folder. No source files are copied to db/src/gen because they're assumed to be deployed from their original location, the db/ folder itself.
Implement a Build Plugin
CDS already offers build plugins to create deployment layouts for the most use cases. However, you find cases where these plugins are not enough and you have to develop your own. This section shows how such a build plugin can be implemented and how it can be used in projects.
Build plugins are run by cds build
to generate the required deployment artifacts. Build tasks hold the actual project specific configuration. The task's for
property value has to match the build plugin ID.
Note: Minimum version 7.5.0 of @sap/cds-dk
and @sap/cds
needs to be installed.
The following description uses the postgres build plugin as reference implementation. It combines runtime and design-time integration in a single plugin @cap-js/postgres
.
Add Build Logic
A build plugin is a Node.js module complying to the CDS plugin architecture. It must be registered to the CDS build system inside a top-level cds-plugin.js file:
const cds = require('@sap/cds')
const { fs, path } = cds.utils;
cds.build?.register?.('postgres', class PostgresBuildPlugin extends cds.build.Plugin {
static taskDefaults = { src: cds.env.folders.db }
static hasTask() {
return cds.requires.db?.kind === 'postgres';
}
init() {
this.task.dest = path.join(this.task.dest, 'pg');
}
async build() {
const model = await this.model();
if (!model) return;
await this.write(cds.compile.to.json(model)).to(path.join('db', 'csn.json'))
if (fs.existsSync(path.join(this.task.src, 'data'))) {
await this.copy(data).to(path.join('db', 'data'))
}
. . .
}
})
Notes:
- The build plugin id has to be unique. In the previous snippet, the ID is
postgres
. cds.build
will beundefined
in non-build CLI scenarios or if the@sap/cds-dk
package isn't installed (globally or locally as adevDependency
of the project).
CDS offers a base build plugin implementation, which you can extend to implement your own behavior. The following methods are called by the build system in this sequence:
static taskDefaults
- defines default settings for build tasks of this type. For database related plugins the defaultsrc
folder valuecds.folders.db
should be used, while for cds services related pluginscds.folders.srv
.static hasTask()
- determines whether the plugin should be called for the runningcds build
command, returns true by default. This will create a build task with default settings defined bytaskDefaults
and settings calculated by the framework.init()
- can be used to initialize properties of the plugin, for example, changing the default build output directory defined by the propertydest
.async clean
- deletes existing build output, folderthis.task.dest
is deleted by default.async build
- performs the build.
The CDS build system auto-detects all required build tasks by invoking the static method hasTask
on each registered build plugin.
The compiled CSN model can be accessed using the asynchronous methods model()
or basemodel()
.
- The method
model()
returns a CSN model for the scope defined by theoptions.model
setting. If feature toggles are enabled, this model also includes any toggled feature enhancements. - To get a CSN model without features, use the method
baseModel()
instead. The model can be used as input for further model processing, liketo.edmx
,to.hdbtable
,for.odata
, etc. - Use
cds.reflect
to access advanced query and filter functionality on the CDS model.
Add build task type to cds schema
Note: Minimum version 7.6.0
of @sap/cds-dk
and @sap/cds
needs to be installed.
In addition you can also add a new build task type provided by your plugin. This build task type will then be part of code completion suggestions for package.json
and .cdsrc.json
files.
Learn more about schema contributions here.
Write Build Output
The cds.build.Plugin
class provides methods for copying or writing contents to the file system:
await this.copy(path.join(this.task.src, 'package.json')).to('package.json');
await this.write({
dependencies: { '@sap/cds': '^7', '@cap-js/postgres': '^1' },
scripts: { start: 'cds-deploy' }
}).to('package.json');
These copy
and write
methods ensure that build output is consistently reported in the console log. Paths are relative to the build task's dest
folder.
Handle Errors
Messages can be issued using the pushMessage
method:
const { Plugin } = cds.build
const { INFO, WARNING } = Plugin
this.pushMessage('Info message', INFO);
this.pushMessage('Warning message', WARNING);
These messages are sorted and filtered according to the CLI parameter log-level
. They will be logged after the CDS build has been finished. A BuildError
can be thrown in case of severe errors. In case of any CDS compilation errors, the entire build process is aborted and a corresponding message is logged. The messages
object can be accessed using this.messages
. When accessing the compiler API it should be passed as an option - otherwise compiler messages won't get reported.
Run the Plugin
In the application's package.json, add a dependency to your plugin package to the list of devDependencies
.
Only use
dependencies
if the plugin also provides runtime integration, which is the case for the@cap-js/postgres
plugin.
"dependencies": {
"@cap-js/postgres": "^1"
}
The CDS build system by default auto-detects all required build tasks. Alternatively, users can run or configure required build tasks in the very same way as for the built-in tasks.
cds build
cds build --for postgres
"tasks": [
{ "for": "nodejs" },
{ "for": "postgres" }
]
See also the command line help for further details using
cds build --help
.