Skip to Content
Technical Articles
Author's profile photo Tia Xu

Useful CAP CDS and Fiori Commands to Accelerate Development and Deployment

Overview

Common

  • Import API Definition with cds import

Database

  • Compile CDS Models to Different Outputs with cds compile
  • Persist Data by Deploying to SQLite with cds deploy --to sqlite
  • Add HANA Configuration with cds add hana
  • Persist Data by Deploying to HANA with cds deploy –-to hana

Security

  • Generate XSUAA Deploy Configuration with cds add xsuaa Based on CDS Annotations
  • Update XSUAA Deploy Configuration with cds compile

MTA

  • Generate Deploy Configuration with cds add mta Based on package.json

Fiori Tools

  • Add Deployment Configuration with fiori add deploy-config

Common

Import API Definition with cds import

The first thing you need to do is to get the XML files (EDM XML – Entity Data Model XML – in short EDMX) which define the entities that compose the OData services to be consumed in the application. You can get such files from SAP API Business Hub.

Import the API to your project using cds import.

cds import srv/<api-definition-file-name>.edmx

This adds the API in CSN (Core Schema Notation) format to the srv/external folder and also copies the EDMX file into that folder. You can see the content is nothing else than a JSON representation of the service metadata with the description of the entities contained in it. This JSON is used by the CDS framework to let you make type-safe OData calls to the service in the form of simple queries via the easy-to-use low-code CDS Query Language (CQL).

Additionally, for Node.js it adds the API as an external OData service to your package.json.

"cds": {
 "requires": {
     "API_BUSINESS_PARTNER": {
         "kind": "odata-v2",
         "model": "srv/external/API_BUSINESS_PARTNER"
     }
 }
}

You use this declaration later to connect to the remote service using a destination. A destination should be created in the Cockpit called e.g. S4HANA.

"cds": {
 "requires": {
     "API_BUSINESS_PARTNER": {
         "kind": "odata",
         "model": "srv/external/API_BUSINESS_PARTNER",
         "[production]": {
             "credentials": {
                 "destination": "S4HANA",
                 "path": "/sap/opu/odata/sap/API_BUSINESS_PARTNER"
             }
         }
     }
 }
}

Alternatively, you can set the options and flags for cds import in the .cdsrc.json file in your project root:

For example:

{
 "import": {
     "as": "cds",
     "force": true,
     "include_namespaces": "sap,c4c"
 }
}

Now run cds import <file-name>

Database

Compile CDS Models to Different Outputs with cds compile

cds compile db/ --to sql
cds compile db/ --to json
cds compile db/ --to yml
...

Or,

cds db/ -2 sql
cds db/ -2 json
cds db/ -2 yml
...

Currently supported:

- json, yml
- edm, edmx, edmx-v2, edmx-v4, edmx-w4, edmx-x4
- sql, hdbcds, hdbtable
- cdl [beta]
- xsuaa
- openapi

For example: cds compile db/ --to sql

CREATE TABLE sap_ui_riskmanagement_Risks (
createdAt TIMESTAMP_TEXT,
createdBy NVARCHAR(255),
modifiedAt TIMESTAMP_TEXT,
modifiedBy NVARCHAR(255),
ID NVARCHAR(36) NOT NULL,
title NVARCHAR(100),
prio NVARCHAR(5),
descr NVARCHAR(5000),
miti_ID NVARCHAR(36),
impact INTEGER,
criticality INTEGER,
PRIMARY KEY(ID)
);

CREATE TABLE sap_ui_riskmanagement_Mitigations (
createdAt TIMESTAMP_TEXT,
createdBy NVARCHAR(255),
modifiedAt TIMESTAMP_TEXT,
modifiedBy NVARCHAR(255),
ID NVARCHAR(36) NOT NULL,
description NVARCHAR(5000),
owner NVARCHAR(5000),
timeline NVARCHAR(5000),
PRIMARY KEY(ID)
);

Persist Data by Deploying to SQLite with cds deploy --to sqlite

Instead of using in-memory, we can also use persistent databases, e.g. SQLite. The difference from the automatically provided in-memory database is that we now get a persistent database stored in the local file ./sqlite.db. This is also recorded in the package.json.

cds deploy --to sqlite

Then we can use the sqlite3 CLI to query with the newly created database:

sqlite3 sqlite.db .dump
sqlite3 sqlite.db .tables

Add HANA Configuration with cds add hana

Some configurations should be added in order to use HANA as the database.

cds add hana

In the package.json file, dependency and cds requires will be added:

{
 ...
 "dependencies": {
    ...
    "hdb": "^0.19.0"
 },
 ...
 "cds": {
    "requires": {
      ...
      "db": {
        "kind": "hana-cloud"        
      }
    }
 }
}

Or, you can add HANA configuration for production:

cds add hana --for production

In the package.json file, dependency and cds requires will be added:

{
...
"dependencies": {
 ...
 "hdb": "^0.19.0"
},
...
"cds": {
 "requires": {
   ...
   "[production]": {
     "db": {
       "kind": "hana-cloud"
     }
   },
   "db": {
     "kind": "sql"        
   }
 }
}
}

Or, you can add HANA configuration for hybrid mode:

cds add hana --for hybrid

Persist Data by Deploying to HANA with cds deploy –-to hana

cds deploy lets you deploy just the database parts of the project to an SAP HANA instance. The server application (the Node.js or Java part) still runs locally and connects to the remote database instance, allowing for fast development roundtrips.

cds deploy –-to hana
cds watch

cds deploy does the following behind:

  1. Build the database artifacts from the CAP project in the gen folder that’s created under the project root folder, for further deployment to SAP HANA Cloud.

  2. Create a service instance of type SAP HANA Schemas & HDI Containers with the hdi-shared plan, that handles the HDI container

  3. Create the SAP HANA database artifacts from the application inside the HDI container

  4. Bind the service instance to the local project by modifying the default-env.json file, adding the database credentials (actually the service key from the service binding).

Or, in the hybrid mode:

cds deploy –-to hana --profile hybrid
cds watch --profile hybrid

Security

Generate XSUAA Deploy Configuration with cds add xsuaa Based on CDS Annotations

cds add xsuaa
cds add xsuaa --for production

cds add xsuaa does the following behind:

  • Adds the XSUAA service to the package.json file of your project

  • Creates the XSUAA security configuration xs-security.json for your project with roles/scopes derived from authorization-related annotations in your CDS models.

Ensure to rerun cds compile --to xsuaa, as documented in the Authorization guide whenever there are changes to these annotations.

Update XSUAA Deploy Configuration with cds compile

Ensure to rerun cds compile --to xsuaa, as documented in the Authorization guide whenever there are changes to these annotations.

cds compile srv/ --to xsuaa > xs-security.json
{
"scopes": [
 {
   "name": "$XSAPPNAME.Admin",
   "description": "Admin"
 }
],
"role-templates": [
 {
   "name": "Admin",
   "description": "generated",
   "scope-references": [
     "$XSAPPNAME.Admin"
   ],
   "attribute-references": []
 }
]
}

Then, use cf create-service xsuaa application <servicename> -c xs-security.json to create the XSUAA service with the XSUAA configuration, or cf update-service <servicename> -c xs-security.json to update the configuration.

MTA

Generate Deploy Configuration with cds add mta Based on package.json

To deploy your application to Cloud Foundry on SAP BTP, you are going to use the MTA (Multi-Target Application) approach, which facilitates the deployment as it pushes everything at once to the platform with file mta.yaml: UI application, backend service, database, service instances creation and binding, etc.

Let the CAP server generate an initial mta.yaml file. The file is generated based on your previously created settings in the package.json file.

cds add mta

For example:

package.json:

{
"name": "cpapp",
"version": "1.0.0",
"description": "A simple CAP project.",
"repository": "<Add your repository here>",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@sap/cds": "^6",
"@sap/xssec": "^3.2.8",
"express": "^4",
"passport": "^0.5.0",
"hdb": "^0.19.0"
},
"devDependencies": {
"@sap/ux-specification": "^1.90.12",
"sqlite3": "^5.0.2"
},
"engines": {
"node": "^16"
},
"scripts": {
"start": "cds run",
"watch-risks": "cds watch --open risks/webapp/index.html#fe-lrop-v4",
"watch-mitigations": "cds watch --open mitigations/webapp/index.html#fe-lrop-v4"
},
"eslintConfig": {
"extends": "eslint:recommended",
"env": {
    "es2020": true,
    "node": true,
    "jest": true,
    "mocha": true
},
"globals": {
    "SELECT": true,
    "INSERT": true,
    "UPDATE": true,
    "DELETE": true,
    "CREATE": true,
    "DROP": true,
    "CDL": true,
    "CQL": true,
    "CXL": true,
    "cds": true
},
"rules": {
    "no-console": "off",
    "require-atomic-updates": "off"
}
},
"sapux": [
"app/risks",
"app/mitigations"
],
"cds": {
"requires": {
    "[production]": {
        "db": {
            "kind": "hana-cloud"
        },
        "auth": {
            "kind": "xsuaa"
        }
    },
    "db": {
        "kind": "sql"
    },
    "uaa": {
        "kind": "xsuaa",
        "credentials": {}
    }
}
}
}

Generated mta.yaml:

---
_schema-version: '3.1'
ID: cpapp
version: 1.0.0
description: "A simple CAP project."
parameters:
enable-parallel-deployments: true
build-parameters:
before-all:
    - builder: custom
      commands:
        - npx -p @sap/cds-dk cds build --production

modules:
  - name: cpapp-srv
    type: nodejs
    path: gen/srv
    parameters:
      buildpack: nodejs_buildpack
    build-parameters:
      builder: npm-ci
    provides:
      - name: srv-api # required by consumers of CAP services (e.g. approuter)
        properties:
          srv-url: ${default-url}
    requires:
      - name: cpapp-db
      - name: cpapp-auth

  - name: cpapp-db-deployer
    type: hdb
    path: gen/db
    parameters:
      buildpack: nodejs_buildpack
    requires:
      - name: cpapp-db

resources:
  - name: cpapp-db
    type: com.sap.xs.hdi-container
    parameters:
      service: hana
      service-plan: hdi-shared
  - name: cpapp-auth
    type: org.cloudfoundry.managed-service
    parameters:
      service: xsuaa
      service-plan: application
      path: ./xs-security.json
      config:
        xsappname: cpapp-${org}-${space}
        tenant-mode: dedicated

The mta.yaml file consists of different modules (Cloud Foundry apps) and resources (Cloud Foundry services):

modules
  • cpapp-srv – OData service

  • cpapp-db-deployer – Deploy CAP schema and data (CSV files) to database

resources

The resources are generated from the requires section of cds in the package.json.

  • cpapp-db – SAP HANA DB HDI container

  • cpapp-uaa – XSUAA service

The resources are Cloud Foundry service instances that are automatically created and updated during the MTA deployment.

Fiori Tools

Add Deployment Configuration with fiori add deploy-config

npm install --global @sap/ux-ui5-tooling
npm install --global @sap/generator-fiori
cd app/<appname>
fiori add deploy-config cf

For example:

mta.yaml:

_schema-version: "3.1"
ID: sfsf-projman
description: A simple CAP project.
version: 1.0.0
modules:
- name: sfsf-projman-srv
  type: nodejs
  path: gen/srv
  requires:
  - name: sfsf-projman-db
  - name: sfsf-projman_html_repo_host
  - name: sfsf-projman-destination-service
  provides:
  - name: srv-api
    properties:
      srv-url: ${default-url}
  parameters:
    buildpack: nodejs_buildpack
  build-parameters:
    builder: npm-ci
- name: sfsf-projman-db-deployer
  type: hdb
  path: gen/db
  requires:
  - name: sfsf-projman-db
  parameters:
    buildpack: nodejs_buildpack
- name: sfsf-projman-destination-content
  type: com.sap.application.content
  requires:
  - name: sfsf-projman-destination-service
    parameters:
      content-target: true
  - name: sfsf-projman_html_repo_host
    parameters:
      service-key:
        name: sfsf-projman_html_repo_host-key
  - name: uaa_sfsf-projman
    parameters:
      service-key:
        name: uaa_sfsf-projman-key
  parameters:
    content:
      instance:
        destinations:
        - Name: sfsf_projman_tia_sfsf_projman_html_repo_host
          ServiceInstanceName: sfsf-projman-html5-app-host-service
          ServiceKeyName: sfsf-projman_html_repo_host-key
          sap.cloud.service: sfsf-projman-tia
        - Authentication: OAuth2UserTokenExchange
          Name: sfsf_projman_tia_uaa_sfsf_projman
          ServiceInstanceName: sfsf-projman-xsuaa-service
          ServiceKeyName: uaa_sfsf-projman-key
          sap.cloud.service: sfsf-projman-tia
        existing_destinations_policy: ignore
  build-parameters:
    no-source: true
resources:
- name: sfsf-projman-db
  type: com.sap.xs.hdi-container
  parameters:
    service: hana
    service-plan: hdi-shared
- name: sfsf-projman-destination-service
  type: org.cloudfoundry.managed-service
  parameters:
    config:
      HTML5Runtime_enabled: true
      version: 1.0.0
    service: destination
    service-name: sfsf-projman-destination-service
    service-plan: lite
- name: sfsf-projman_html_repo_host
  type: org.cloudfoundry.managed-service
  parameters:
    service: html5-apps-repo
    service-name: sfsf-projman-html5-app-host-service
    service-plan: app-host
- name: uaa_sfsf-projman
  type: org.cloudfoundry.managed-service
  parameters:
    path: ./xs-security.json
    service: xsuaa
    service-name: sfsf-projman-xsuaa-service
    service-plan: application
parameters:
  enable-parallel-deployments: true
build-parameters:
  before-all:
  - builder: custom
    commands:
    - npx -p @sap/cds-dk cds build --production

In the mta.yaml, two modules related to the SAP Fiori app are added:

- name: sfsf-projman-app-content
  type: com.sap.application.content
  path: .
  requires:
  - name: sfsf-projman_html_repo_host
    parameters:
      content-target: true
  build-parameters:
    build-result: resources
    requires:
    - artifacts:
      - sfsfprojmansfsfprojman.zip
      name: sfsfprojmansfsfprojman
      target-path: resources/
- name: sfsfprojmansfsfprojman
  type: html5
  path: app/sfsf-projman
  build-parameters:
    build-result: dist
    builder: custom
    commands:
    - npm install
    - npm run build:cf
    supported-platforms: []

In the mta.yaml, parameters and requires are added:

- name: sfsf-projman-destination-service
  type: org.cloudfoundry.managed-service
  parameters:
    config:
      HTML5Runtime_enabled: true
      init_data:
        instance:
          destinations:
          - Authentication: NoAuthentication
            Name: ui5
            ProxyType: Internet
            Type: HTTP
            URL: https://ui5.sap.com
          - Authentication: NoAuthentication
            HTML5.DynamicDestination: true
            HTML5.ForwardAuthToken: true
            Name: sfsf-projman-srv-api
            ProxyType: Internet
            Type: HTTP
            URL: ~{srv-api/srv-url}
          existing_destinations_policy: update
      version: 1.0.0
    service: destination
    service-name: sfsf-projman-destination-service
    service-plan: lite
  requires:
  - name: srv-api

xs-app.json file will be created, which holds the configuration of the routes to be mapped by the approuter to point to the destination of the backend service.

{
  "welcomeFile": "/index.html",
  "authenticationMethod": "route",
  "routes": [
    {
      "source": "^/projman/(.*)$",
      "target": "/projman/$1",
      "destination": "sfsf-projman-srv-api",
      "authenticationType": "xsuaa",
      "csrfProtection": false
    },
    {
      "source": "^/resources/(.*)$",
      "target": "/resources/$1",
      "authenticationType": "none",
      "destination": "ui5"
    },
    {
      "source": "^/test-resources/(.*)$",
      "target": "/test-resources/$1",
      "authenticationType": "none",
      "destination": "ui5"
    },
    {
      "source": "^(.*)$",
      "target": "$1",
      "service": "html5-apps-repo-rt",
      "authenticationType": "xsuaa"
    }
  ]
}

ui5-deploy.yaml file will be created:

# yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json
specVersion: '2.4'
metadata:
  name: sfsf.projman.sfsfprojman
type: application
resources:
  configuration:
    propertiesFileSourceEncoding: UTF-8
builder:
  resources:
    excludes:
      - "/test/**"
      - "/localService/**"
  customTasks:
  - name: webide-extension-task-updateManifestJson
    beforeTask: generateManifestBundle
    configuration:
      appFolder: webapp
      destDir: dist
  - name: ui5-task-zipper
    afterTask: generateCachebusterInfo
    configuration:
      archiveName: sfsfprojmansfsfprojman
      additionalFiles:
      - xs-app.json

And, some other configuration will be added in the package.json and manifest.json files.

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Minjie Lao
      Minjie Lao

      Great article,

       

      Just a quick Q, what is 'ui5-deploy.yaml' doing for?

      Author's profile photo Sebastian Mantsch
      Sebastian Mantsch

      The ui5-deploy.yaml file acts as a deployment descriptor for the added Fiori/UI5 application and will be used during the build stage (triggered by MTA build)

      Author's profile photo Yogananda Muthaiah
      Yogananda Muthaiah

      Tia Xu

      still there are plenty of new commands for cds for further usage which can add it in your blog.

      Author's profile photo Tia Xu
      Tia Xu
      Blog Post Author

      Hi Muthaiah,

      Welcome to give your input! Which new commands do you mean?

      Looking forward to your expertise.

      BR,

      Tia