Easily add an explicit cds.requires.db to your CAP project's package.json
In an experimental CAP project serving data in an in-memory SQLite persistence mechanism, seeded from CSV files (as per the classic starting point in CAP's Grow As You Go approach), I wanted to have the persistence layer requirements stated explicitly in the project's package.json
file, rather than just be implicit.
Remember, a newly initialised CAP project's package.json
file looks something like this:
{
"name": "proj",
"version": "1.0.0",
"description": "A simple CAP project.",
"repository": "<Add your repository here>",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@sap/cds": "^7",
"express": "^4"
},
"devDependencies": {
"@cap-js/sqlite": "^1"
},
"scripts": {
"start": "cds-serve"
}
}
So to add the section explicitly, I'd normally have to remember the correct cds.requires
JSON stanza structure and manually add it to the file, something like this:
{
"name": "proj",
"version": "1.0.0",
"description": "A simple CAP project.",
"repository": "<Add your repository here>",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@sap/cds": "^7",
"express": "^4"
},
"devDependencies": {
"@cap-js/sqlite": "^1"
},
"scripts": {
"start": "cds-serve"
},
"cds": {
"requires": {
"db": {
"kind": "sqlite",
"credentials": { "url": ":memory:" }
}
}
}
}
Finding out what the value should be
With cds env
we can find out what this is already:
; cds env requires.db
{
impl: '@cap-js/sqlite',
credentials: { url: ':memory:' },
kind: 'sqlite'
}
The June 2023 release brought an improved cds env which is why I'm not using the
get
subcommand (i.e.cds env get requires.db
) any more here.
Adding it to package.json
And as the contents of package.json
is just JSON, we have the power of jq at our disposal, of course. We can process the file, and bring in the JSON value of requires.db
above with jq's --argjson
option.
Before we do that, however, we need to have that JSON value in a more compact format, not spanning multiple lines. And we can do that with the --raw
option (short: -r
) to cds env
like this:
; cds env --raw requires.db
{"impl":"@cap-js/sqlite","credentials":{"url":":memory:"},"kind":"sqlite"}
Now all we need is something like this:
; jq \
--argjson db $(cds env -r requires.db) \
'. + {cds:{requires:{db:$db}}}' \
package.json
which will produce what we want:
{
"name": "proj",
"version": "1.0.0",
"description": "A simple CAP project.",
"repository": "<Add your repository here>",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@sap/cds": "^7",
"express": "^4"
},
"devDependencies": {
"@cap-js/sqlite": "^1"
},
"scripts": {
"start": "cds-serve"
},
"cds": {
"requires": {
"db": {
"impl": "@cap-js/sqlite",
"credentials": {
"url": ":memory:"
},
"kind": "sqlite"
}
}
}
}
We get the extra
"impl": "@cap-js/sqlite"
but that's fine!
In order to replace the contents of package.json
in one go you'll need to do something like this:
; cat package.json \
| jq \
--argjson db $(cds env -r requires.db) \
'. + {cds:{requires:{db:$db}}}' \
> package.json
Use with cds deploy
I may find myself using this approach more often, especially as the cds deploy --to sqlite
no longer modifies package.json
, which was also a change made in the same CAP release.
Good to know!
You may want to read Using @cap-js/sqlite in CF for your CAP services which is closely related to this, too, as well as Running non-production CAP services in CF.