Modules, modularity & reuse in CDS models - part 4 - from passive to active with @capire/common
Starting with a simple use of the published @qmacro/common reuse module, I then turn to @capire/common for a first look at what I call an "active" reuse module.
(Get to all the parts in this series via the series post.)
In the previous
part
we published @qmacro/common. Let's start out here by creating a new simple
CAP Node.js project and bringing in that @qmacro/common package; not only
will this show that we really do have a publicly available & shareable reuse
package, but observing what happens will also underline its simple and
passive
nature.
Creating a simple host project
Instead of turning back to the "host" CAP Node.js project that we created in
part
1
with the packages/@qmacro/common workspace, let's create a fresh host project
to have a clean context into which to bring each reuse module. First, let's set
up1 use-qmacro for
qmacro/common:
cds init \
--add tiny-sample \
use-qmacro \
&& cd $_ \
&& npm install
The CDS model artifacts in the "tiny-sample" facet are still simple enough,
which is what we want. Starting the server now (with cds watch) will allow us
to see what happens (and, perhaps a little more telling, what does not happen)
in subsequent steps:
[cds] - loaded model from 3 file(s):
srv/cat-service.cds
node_modules/@sap/cds/srv/outbox.cds
db/schema.cds
[cds] - connect to db > sqlite { url: ':memory:' }
> init from db/data/my.bookshop-Books.csv
/> successfully deployed to in-memory database.
Noteworthy here are the files which are being loaded for the CDS model, and the initial data load from a CSV file that was found.
@qmacro/common
It's now time to start exploring what it's like to actually use a reuse
package. We'll start here with @qmacro/common and then later take a first
look at @capire/common, so that we can compare what happens.
Adding @qmacro/common
In a second terminal session (so we can monitor the cds watch output in the
first) let's install2 the @qmacro/common reuse
module:
npm add @qmacro/common
This emits something like this3:
added 1 package, and audited 115 packages in 858ms
found 0 vulnerabilities
More importantly, it causes the CAP server to restart. But so far, there are no new log lines of interest - the same 3 files as before are loaded for the CDS model, and the same single CSV file.
Using @qmacro/common
Let's now make use of this simple passive reuse package by importing4, as a first step:
using qmacro from '@qmacro/common'; // <--
namespace my.bookshop;
entity Books {
key ID : Integer;
title : String;
stock : Integer;
}
As soon as the file is saved with this new using directive, the CAP server
restarts, and a new CDS file appears in the list of sources used to create the
CDS model:
[cds] - loaded model from 4 file(s):
srv/cat-service.cds
node_modules/@sap/cds/srv/outbox.cds
db/schema.cds
node_modules/@qmacro/common/index.cds
It's the index.cds file that we created in part 2, nice!
We haven't made use of the qmacro.common.T type yet, but the compiler still
loads the reuse package contents (whatever index.cds contains and / or refers
to).
But the important thing to observe with this "passive" reuse package is that it's only once we explicitly refer to it in our model definitions that anything happens.
To complete the test of this simple reuse package, we can of course add a
further element to the Books entity definition like this, defined with this
imported type:
using qmacro from '@qmacro/common';
namespace my.bookshop;
entity Books {
key ID : Integer;
title : String;
stock : Integer;
newel : qmacro.common.T; // <--
}
but this has no further effect on how the package is used or behaves.
So far, so good! Let's now compare that with a first look at using
@capire/common.
Creating a second host project
To keep things clean and separate, let's now create a second host project just
like the first, this time called use-capire,
and start up the CAP server straight after:
cds init \
--add tiny-sample \
use-capire \
&& cd $_ \
&& npm install \
&& cds watch
If you're playing along at home, make sure you create this parallel to
use-qmacro, not within it, of course.
From the cds watch output, we see the same output as previously, at the same
stage, with use-qmacro, most notably that the CDS model is composed of 3 files:
[cds] - loaded model from 3 file(s):
srv/cat-service.cds
node_modules/@sap/cds/srv/outbox.cds
db/schema.cds
@capire/common
In the same way as with @qmacro/common, let's this time add @capire/common
to the project.
Associating the scope with the registry
Just like how we associated @qmacro with the GitHub Packages NPM registry in
the previous
part,
we'll need to do the same for @capire, by adding another line to our
~/.npmrc file5:
@capire:registry=https://npm.pkg.github.com
Adding @capire/common
Now we can add it:
npm add @capire/common
We get similar output to this as before, but significantly, when the CAP server restarts, we see this:
[cds] - loaded model from 7 file(s):
srv/cat-service.cds
node_modules/@sap/cds/srv/outbox.cds
node_modules/@capire/common/index.cds
node_modules/@capire/common/regions.cds
node_modules/@capire/common/currencies.cds
db/schema.cds
node_modules/@sap/cds/common.cds
Waitwhat?
Active vs passive
What's going on? Where did they come from? Why are they appearing, even when we
haven't imported anything into the use-capire model yet?
This is our first glimpse of a side effect coming from the fact that -- unlike
@qmacro/common, which is passive -- @capire/common is
active6. In other words, the reuse package will do
things, explicitly and sometimes immediately, as soon as we've added it.
How does that work? We'll find out in the next part!
Footnotes
-
While things would be fine without an
npm installat this setup stage (using the globally installed@sap/cdspackage rather than a project-local one), we'll usenpm installhere mostly for cosmetics - references in the log output will be to project-local resources rather than global ones which have far longer paths; also, we'll be running a package install shortly anyway, so the main part of the install work might as well be done now. -
Remember that you'll have to have the appropriate settings in an npmrc file; see the Preparing to publish the package section of the previous part for a reminder about this. Basically, you'll need something like this, say, in
~/.npmrc:@qmacro:registry=https://npm.pkg.github.com //npm.pkg.github.com/:_authToken=A-CLASSIC-TOKEN-WITH-AT-LEAST-READ-PACKAGES-SCOPE -
The use of the top level name only (i.e. just
qmacro) in theusingdirective is deliberate here, just to show a different way of referencing the scope and subsequent use in definition positions. See the Namespaces section of Capire's CDL topic for further details. -
I have
fund=falsein my~/.npmrcfile so the "... packages are looking for funding ..." messages are suppressed. -
There's an entire blog post on Using @capire modules from GitHub Packages, in case you're interested.
-
The terms "active" and "passive" aren't official CAP terms, they're just what I have come up wih to distinguish reuse package types.