@Sap/cds
module family, which is a rich source of learning for us in our journey towards ES6 mastery.grab.js
script that we've been building, which allows us to retrieve data from the Northwind service, paging through it where skip tokens are used.@Sap/cds
module family.cds deploy
gave me a clue that parts of @Sap/cds
were indeed (of course) handling CSV data, and I was curious to take a look:grep -R 'initializing from csv' *
node_modules/@sap/cds/bin/etc/init-from-csv.js
file.cds
command line tool, and taking a brief look at how the other @Sap/cds
modules are related via the "dependencies" information shown in the output of:npm info @sap/cds
@Sap/cds/
directory in the node_modules/
directory in the project, we see the common.cds
file that we've looked at before, and also lib/
and bin/
directories.bin/
directory we have cds.js
that responds when we invoke the cds command line client, and we can then also see more or less a one-to-one relationship between what you commands are available:=> 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
[...]
bin/
directory:=> ls -1 node_modules/@sap/cds/bin | grep .js
cds.js*
compile.js
deploy.js
dev.js
env.js
eval.js
help.js
init.js
repl.js
run.js
serve.js
version.js
deploy.js
- where we see a promise chain that makes use of the init-from-csv
module! Inside this module we place a breakpoint to see what happens when we invoke the cds deploy
command.cds d
within the integrated terminal in VS Code - but of course we don't hit the breakpoint like this as we're not in debug mode.cds run
not cds deploy
here..vscode/launch.json
:{
"version": "0.2.0",
"configurations": [
{
"name": "cds run",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/.vscode/cds", "args": [ "run" ],
"skipFiles": [
"<node_internals>/**/*.js",
"**/cds-reflect/lib/index.js",
"**/cds/lib/index.js",
"**/.vscode/cds.js",
],
"autoAttachChildProcesses": true,
"console": "integratedTerminal"
}
]
}
cds
here is "run".cds deploy
. Then we can re-start debugging mode, choose the specific "cds deploy" launch configuration, and we end up at the breakpoint we set. Lovely!model
, which is an Array with two values, "db" and "srv". Now we know that, reading the code in init-from-csv
becomes easier - it looks for CSV files and loads the contents into the persistence layer via the CDS API.lib/utils/fs.js
, and in turn, how this custom fs
module bases itself on the builtin fs
module, via the __proto__
feature._init
function in the init-from-csv
module parses the CSV data and then inserts into the tables. We take a quick look at what exactly the expression .slice(0,-4)
is doing here, which looks initially a bit odd, until we realise that slice works on strings on a character-by-character basis: 'filename.ext'.slice(0,-4)
produces "filename".csv.parse
comes from, which is another module in the @Sap/cds
bundle - in lib/utils/csv.js
. There is a parsing function and a serialising function in this module - I can definitely make use of the former!csvf
, and having a look what it does:=> node ./cli.js
Usage: csvf [options]
Options:
-i, --input Input CSV file (mandatory)
-o, --output Output CSV file (defaults to _out.csv)
-f, --fields List of fields to output (space separated)
-h, --help Shows this help
-v, --verbose Talkative mode
Example:
csvf -i data.csv -f supplierID companyName city -o smaller.csv
=> node ./cli.js -i tmp/Suppliers.csv --fields supplierID companyName -v
>> Processing tmp/Suppliers.csv
>> Filtering to supplierID,companyName
>> Written to _out.csv
_out.csv
we see that we have a reduced CSV set:supplierID,companyName
1,Exotic Liquids
2,New Orleans Cajun Delights
3,Grandma Kelly's Homestead
cli.js
to see how we can use the @Sap/cds
's csv
module in our own program - by installing @Sap/cds
in the project, I have access to all the modules in the bundle, which means I can do this:const csv = require('@sap/cds/lib/utils/csv')
const log = (isVerbose => x => isVerbose && console.log(">>", x))(options.verbose)
serialise
function which also uses an ES6 feature, specifically default function parameters.csv.parse
function is used in this script:let [cols, ...rows] = csv.parse(src)
indices
function in the script, where we use the interesting function application thus:const selectedIndices = indices(cols)(options.fields)
indices(cols)
which produces a function, which we then call, passing options.fields
.indices
function, we can better understand how this works:const indices = ref => fields => fields.map(x => ref.indexOf(x))
indices
function, we take a quick look in the last moments at the pick
function which is possibly a little bit more exciting:const pick = indices => source =>
indices.reduce((a, x) => (_ => a)(a.push(source[x])), [])
pick
function is partially applied:writefile(
options.output.
serialise(outCols, rows.map(pick(selectedIndices))),
'utf8',
e => err(e) || log(`Written to ${options.output}`)
)
map
call. And then go and watch that video! 😉
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
35 | |
17 | |
17 | |
15 | |
11 | |
9 | |
8 | |
8 | |
8 | |
7 |