Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
Showing results for 
Search instead for 
Did you mean: 
Developer Advocate
Developer Advocate
This is a searchable description of the content of a live stream recording, specifically "Episode 1 - Setting up for the Node.js flavoured version of SAP’s Cloud Application Programming Model" in the "Hands-on SAP dev with qmacro" series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the "Catch the replays" section of the series blog post.

This episode, titled "Setting up for the Node.js flavoured version of SAP’s Cloud Application Programming Model", was streamed live on Fri 25 Jan 2019 and is approximately one hour in length. The stream recording is available on YouTube.

Below is a brief synopsis, and links to specific highlights - use these links to jump directly to particular places of interest in the recording, based on 'hh:mm:ss' style timestamps.

Brief synopsis

While we warmed our grey matter up in the previous episode, in this episode we set up what we need to build with the Node.js (JavaScript) flavoured version of SAP's Cloud Application Programming Model (CAPM). This version allows us to build locally, with tools on our own machines, so that's what we'll be doing.

Therefore, we use the SAP NPM registry to find & install the command line tool 'cds' that we can use to generate and manage Node.js based CAPM projects and also install the CDS language support for the VS Code editor, which comes in the form of an VS Code extension. Then we set up our Cloud Foundry environment on SAP Cloud Platform and install the 'cf' command line tool which we can use to interact with that environment.

00:01:12: Live stream starts.

00:02:35: Starting to look at the setup section of the Create a Business Service with Node.js using Visual Studio Code tutorial.

00:07:30: Talking about wanting to be able to try things out on my own machine, in a way that I can then blast away those attempts to get back to a clean state.

00:08:45: Achieving this via Docker. Starting a minimal Linux environment Docker container with docker run -t -i debian /bin/bash.

00:10:30: Looking at using nvm - the Node Version Manager, to install and manage Node.js versions.

00:11:20: Installing curl via apt-get, so we can then use curl to download and install nvm. We also set 'vi mode' in my shell, and bind Ctrl-L so that it will work for clearing the screen for us:
set -o vi
bind -x '"\C-l": clear'

Note that we also have to do an apt-get update in this minimal Linux container before we can get it to find and install curl.

00:13:30: Finally getting to be able to install nvm with curl.

00:13:56: Now we can use nvm to install Node.js, and we choose version 8 (see for other versions).

00:15:14: Starting out with the setup by trying to search for the @sap/cds package with npm search @sap/cds. This doesn't give us what we're really looking for, so we search simply for 'cds' with npm search cds, but this yields results that don't look quite right.

00:16:45: The @sap prefix in @sap/cds is a scope, which relates packages to a specific registry. The searches we've done thus far are using the default registry, which we can see in the npm configuration with npm config ls -l | grep registry, which gives us:
registry =

We can also get that info via npm config get registry.

00:18:10: Looking at the blog post announcing the SAP NPM registry:

00:18:39: Modifying the previous search command with the --registry option, thus: npm search @sap/cds --registry, where we get much better results that look something like this:
NAME                      | DESCRIPTION          | AUTHOR          | DATE       | VERSION  | KEYWORDS
@sap/cds | Entry Point and API… | | 2019-02-19 | 3.5.2 |
@sap/generator-cds | Project generator… | | 2019-02-19 | 2.3.9 | cds cdx
@sap/cds-compiler | CDS (Core Data… | | 2019-02-14 | 1.8.1 | CDS
@sap/cds-hana | Driver package for… | | 2019-02-14 | 1.5.1 |
@sap/cds-ql | This package deals… | | 2019-02-14 | 1.5.1 |
@sap/cds-services | This package… | | 2019-02-14 | 1.5.2 |
@sap/cds-sql | This package offers… | | 2019-02-14 | 1.5.1 |
@sap/cds-sqlite | Driver package for… | | 2019-02-14 | 1.5.1 |
@sap/cds-reflect | Reflection for CDS… | | 2019-02-08 | 2.3.0 |

00:19:50: Using npm view (as an alternative to npm search) to look at details of a package. At the time of writing these annotations, this is what npm view gives us:
@sap/cds@3.5.2 | SEE LICENSE IN developer-license-3.1.txt | deps: 6 | versions: 16
Entry Point and API Facade for CDS

bin: cds

.shasum: 975fe7d2c64550c71d30f6f869e63c3250a21ca0
.integrity: sha512-8NKmfpLFSW4GwKnnnoMB1l+srhDhJ8wlkGrC7cf7NxW+XUDO2bnlPIt/dSKlCSQRnHgssAlyjGffrbMMQknVRw==

@sap/cds-compiler: 1.8.1 @sap/cds-reflect: 2.3.0 @sap/generator-cds: 2.3.9
@sap/cds-ql: 1.5.1 @sap/cds-services: 1.5.2 fs-extra: 7.0.1

- <>

latest: 3.5.2

published a week ago by <>

00:22:00: Now it's time to install the package with npm install. But before we do, we check the list of packages already installed, with npm list, using the -g option to check globally (rather than only local to the directory / project I'm currently in).

00:22:55: Restricting the output of npm list with the --depth option, to see the top level packages installed (with npm list -g --depth=0).

00:23:08: A (cultural) reference to lyrics from the track Natural Science by Canadian rock band Rush.

00:23:38: An attempt at install with npm install -g @sap/cds --registry, and a brief look at the error that occurs (via the --verbose flag).

00:26:15: Setting the registry for @sap with npm config set @sap:registry= (and checking the results with npm config list to see that this configuration was indeed successfully recorded.

00:26:55: Now retrying the install, with npm install -g @sap/cds, and seeing that this is now successful, and that @sap/cds version 3.0.0 was installed globally (checking with npm list -g --depth=1, and also noticing the dependencies).

00:28:08: Removing the experimental Docker container.

00:28:26: "Back" on my own local machine, we check what is installed globally (again with npm list -g --depth=0), and go through the process of installing @sap/cds globally here now.

00:28:56: What that gives us is a whole lot of stuff, including the command line program cds:
=> cds


cds <command> [<args>]


c | compile ...individual models (= the default)
d | deploy models to a database
s | serve ...service models to REST clients
b | build ...whole modules or projects
i | init ...jump-starts a new project
e | env get/set current cds configuration
r | repl cds's read-eval-event-loop
h | help shows usage for cds and individual commands
v | version prints detailed version information

cds help <command> gives more help about each (also with --help)
cds <file> without <command> defaults to cds compile.
cds without any arguments shows this help.


cds model.cds
cds compile model.cds
cds compile model.json --to cdl
cds serve cat-service
cds build --clean
cds compile --help

00:29:50: Starting to look at the VS Code extension that's available on the SAP Development Tools website, downloading the file vscode-cds-1.0.36.vsix, and noting that it's actually a gzipped tarball in disguise. So changing the .vsix extension to .tgz makes it more palatable and we can look inside it with tar tvzf vscode-cds-1.0.36.tgz!

00:31:15: Being curious of course, we therefore then proceed to unpack it with tar xzf vscode-cds-1.0.36.tgz and have a look what we have, particularly at the SAP Node.js packages in the node_modules/ directory. It's at this point we get a first glimpse of @sap/cds-lsp which is a Language Protocol Server implementation for the CDS language.

00:32:50: Removing the existing extension in VS Code so we can install it together ("Install from VSIX..."), noting that the latest version is 1.0.36 and the details for this show up in the Change Log. The extension will automatically look for updates, as we see in the configuration.

00:35:02: Talking about EditorConfig which I was reminded about in the PluralSight course I'm following. EditorConfig is a way of keeping configuration in sync across editors. I added an EditorConfig plugin to my Vim config, and you can see my editorconfig file (which I took from the UI5 team) here: The PluralSight course is "Building a JavaScript Development Environment".

00:36:35: Taking a quick look through the rest of the extensions I've installed in VS Code (including EditorConfig, DraculaOfficial, Python, Quokka.js, SQLite, Vim, vimL and VS Live Share).

00:37:38: Talking about eventual deployment to the Cloud Foundry environment on SAP Cloud Platform, and taking a look at my trial account to orientate ourselves.

00:39:25: Looking at what the the Cloud Foundry command line interface (CLI) is and ways to install it (I already had it installed and available to me in /usr/local/bin/cf via Homebrew for macOS).

00:40:50: Examining the cf configuration that's maintained in my home directory in the .cf/ directory, and logging in to a Cloud Foundry endpoint with cf login, specifically the endpoint that I have in my trial at

00:42:50: Noticing that cf asks me to select an organisation.

00:42:58: A subtle reference by one of the live stream participants HunterGatherer to the classic quote on QDB: - nicely done 🙂

00:43:00: Thinking about why I was asked to select an organisation, and examining the other organisations available to me in other SAP Cloud Platform accounts, so the selection makes more sense.

00:44:10: Selecting the I347491trial_trial organisation automatically causes the dev space to be selected within that, because that's the only space that exists inside I347491trial_trial.

00:44:35: Looking at what's available from a services perspective with cf marketplace.

00:45:00: Looking at the current target with cf target and switching targets. First looking at what the possible target orgs are with cf orgs, which gives me this:
Getting orgs as


and then selecting one of them with cf target -o serverlessorg (noting again that the single dev space is automatically selected within that).

00:46:20: Targeting an organisation with multiple spaces (cf target -o tdash) gives us "No space targeted, use cf target -S SPACE" because there are multiple spaces within the tdash organisation, which we can see with cf spaces, which gives this:

00:46:45: Referring to Luke Smith from whom I've learned a lot recently, and talking about dmenu, and a similar utility called fzf which is wonderful (the author of fzf also wrote the Vim plugins Goyo and Limelight which are also wonderful).

00:48:15: A brief look at what the Goyo plugin does, in conjunction with Limelight. Fab.

00:49:00: Taking a look at how fzf works, by looking at the sort of things it can do. We end up taking the names of the Northwind products and offering them as a selection like this:
curl '$format=json?$select=ProductName' | jq -r '.value[].ProductName' | fzf

Note that we use the equally wonderful jq to process the JSON. If you're interested in learning more about jq you might want to watch this short video "Using jq to parse out SCP destination info".

00:54:17: Using fzf to improve the experience of selecting choosing and setting target organisations and spaces. Check out the script to see how we did this. Basically, introducing fzf into the cf CLI mix looks like this, from a CF organisation perspective, for example:
function cfto() {
local org
org=$(cf orgs | sed -e '1,3d' | fzf -1 -q "$1")
if [ -n "$org" ]; then
echo Setting target org to "$org"
cf target -o "$org"