Event Information
Annotated links: Episode 1 of Hands-on SAP dev with qmacro
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.
Links to specific highlights
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 https://nodejs.org/en/download/ 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 = https://registry.npmjs.org/
We can also get that info via npm config get registry
.
00:18:10: Looking at the blog post announcing the SAP NPM registry: https://blogs.sap.com/2017/05/16/sap-npm-registry-launched-making-the-lives-of-node.js-developers-easier/.
00:18:39: Modifying the previous search command with the --registry
option, thus: npm search @sap/cds --registry https://npm.sap.com
, 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
dist
.tarball: https://npm.sap.com/@sap/cds/-/cds-3.5.2.tgz
.shasum: 975fe7d2c64550c71d30f6f869e63c3250a21ca0
.integrity: sha512-8NKmfpLFSW4GwKnnnoMB1l+srhDhJ8wlkGrC7cf7NxW+XUDO2bnlPIt/dSKlCSQRnHgssAlyjGffrbMMQknVRw==
dependencies:
@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
maintainers:
- https-support.sap.com <do.not.reply@sap.com>
dist-tags:
latest: 3.5.2
published a week ago by https-support.sap.com <do.not.reply@sap.com>
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 https://npm.sap.com
, 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=https://npm.sap.com
(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
USAGE
cds <command> [<args>]
COMMANDS
c | compile ...individual models (= the default)
d | deploy ...data 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.
EXAMPLES
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: https://github.com/qmacro/scripts/blob/master/editorconfig. 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 https://api.cf.eu10.hana.ondemand.com.
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: http://bash.org/?244321 – 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 dj.adams@sap.com...
name
I347491trial_trial
serverlessorg
tdash
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:
name
prod
qa
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 'https://services.odata.org/V3/Northwind/Northwind.svc/Products?$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 fzfutils.sh 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"
fi
}
I believe the code snippet around 00:49:00 is slightly incorrect. For me the following works
Thanks so much Andrew for picking this up! I just looked back into it, and I think basically both you and I are using the same URL … however, what was tripping me up on the live stream was the difference between single and double quotes in Bash, my shell.
I was using the following invocation:
but despite the $format=json I was getting XML.
This was, as it turns out, because I forgot that in double quotes, there are certain things that are interpolated, including variables (as described in Shell Expansions in the Bash reference guide).
So this invocation was being translated to:
i.e. with fundamental parts of the query options missing as the “variables” $format and $select had been expanded to nothing.
Using single quotes would have seen success, like this:
because there’s no interpolation within single quotes.
Again, thanks for taking the time to (a) watch the video recording and (b) pick up on this!