@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
194 lines (161 loc) • 7.82 kB
JavaScript
module.exports = Object.assign(build, {
handleCompletion,
options: ['--project', '--src', '--dest', '--for', '--opts', '--log-level', '--options-model'],
shortcuts: ['-in', '-s', '-o', '-4'],
flags: ['--clean', '--no-clean', '--ws', '--ws-pack'], // REVISIT: --clean is deprecated, backward compatibility
help: `
*cds build* [<project>] [<options>]
Builds all modules in the current project by compiling contained CDS
sources.
The modules are folders in the project root directory. All well known
modules (db, srv, app) or those configured by build tasks defined in
*package.json* or *.cdsrc.json* are built.
# OPTIONS
*-4 | --for* hana | java | nodejs | mtx | mtx-sidecar | mtx-extension
Name of the build task that is applied to the source folder, either
explicitly configured in the build task list or generated out of the
project setup
For example, the 'hana' build task will create SAP HANA artefacts.
The module folder can be defined using option '--src', a default is used
otherwise.
*-s | --src* <folder>
The module folder to build using the build task defined by option
'--for'.
This option is only supported when building an individual module of the
project.
The folder is resolved based on '<project>/<cds.env.build.target>'.
A default is used based on the type of the build task, for example, the
folder 'db' is used for a
*hana* build task, 'srv' for *nodejs* or *java* build task.
*-o | --dest* <folder>
Output folder of the build task. The type of build task is defined by
option '--for'.
The folder is resolved based on '<project>/<cds.env.build.target>'.
Default - folder defined by option '--src'.
Note: <cds.env.build.target> can be configured in *.cdsrc.json* or
*package.json*.
For Node.js projects the folder 'gen' is used by default. The output is
written to '<project>/gen/*<dest>*/*'.
For Java projects '.' is used by default. The output is written to
'<project>/*<dest>*/*'.
*--opts* <build task specific options>
Add a comma-separated list of build task specific options in the format
<opt1>=[value1,value2],<opt2>=value.
For example, --opts model=[db,srv,schema.cds] loads and compiles the CDS
model based on the given sources.
*--profile* <profile,...>
Loads the configuration data for the specified profile(s) and executes
'cds build' based on this profile settings.
E.g. you may want to create the HANA deployment artefacts only if the
*production* profile is set.
The *development* profile is used by default.
*--production*
Shortcut for '--profile production'
*--log-level* <debug | info | warn | error>
Choose which level of cds build messages to log, default is *warn*.
*-in | --project* [<project>]
Runs 'cds build' for the specified project, default is current working
directory.
*--no-clean*
Skips cleaning the build output folder before running the actual build
operation. Clients need to clean the output folder upfront to ensure
consistent build results.
*--ws-pack* (beta)
Enable tarball based packaging of npm workspace dependencies - typically defined for
Node.js mono or multi-repo setups.
For each workspace dependency of your project using '*' as version identifier,
a tarball will be created in folder 'gen/srv'. Dependencies in package.json
will be adapted to point to the correct tarball file URL.
Contents is packaged based on the rules of the 'npm pack' command.
*--ws* (beta)
Npm workspaces are typically used in mono or multi-repo setups whereas each workspace
folder represents a microservice CAP project with subfolders _db_, _srv_, _app_.
With the *ws* option the model scope used in executed build tasks is calculated based on
all workspaces. This also applies to the feature toggles. Feature toggles defined cross workspace
are merged. The output is created in the _mtx/sidecar_ for multitenant applications
or in the 'srv' folder for node.js apps if no sidecar exists.
HANA native content distributed across the workspaces is copied into the top-level 'db'
folder of the project. This 'db' folder represents the single database shared by all workspaces.
*Note:* Make sure to use consistent package versions in your workspace dependencies in order
to avoid compilation errors caused by duplicate model definitions.
# EXAMPLES
*cds* build
*cds* build --production --log-level info
*cds* build --for hana
*cds* build --for java --src service1
*cds* build --for java --dest ../srv/target --opts model=[db/model,srv,schema]
`})
async function handleCompletion(currentWord, previousWord, argv, util) {
const allOptionsFlags = [
...build.options ?? [],
...build.flags ?? []
].filter(e => !argv.includes(e));
if (currentWord?.startsWith('-')) {
return allOptionsFlags;
}
switch (previousWord) {
case '--log-level':
return ['debug', 'info', 'warn', 'error'];
case '-4':
case '--for':
return ['hana', 'java', 'mtx', 'mtx-extension', 'mtx-sidecar', 'nodejs'];
case '--dest':
case '-o':
case '-s':
case '--src': {
return util.completionFs.readdir(currentWord, { files: false });
}
}
if (!currentWord && build.options?.includes(previousWord)) {
return [];
}
return allOptionsFlags;
}
async function build([project], options = {}) {
const path = require('path')
// ensure that cds build plugins defined as devDependencies are loaded
if (process.env.NODE_ENV === 'production') delete process.env.NODE_ENV
const cds = require('../lib/cds')
// plugins are loaded based on cds.root path
cds.root = path.resolve(process.cwd(), project || options.project || '.')
// IMPORTANT: call plugins before subsequent access to cds.env
await cds.plugins
cds.env = cds.env.for('cds', cds.root)
delete options.project // avoid that relative project paths are resolved twice
if (typeof options["options-model"] === "string") {
options.opts = "model=[" + options["options-model"].split(",").map((entry) => entry.trim()) + "]"
delete options["options-model"]
}
if (options["no-clean"]) {
// mapping to the existing 'clean' option
if (options["no-clean"] === "true" || options["no-clean"] === true) {
options.clean = false
}
delete options["no-clean"]
}
// convert opts string to task options object
if (options.opts) {
options.taskOptions = scanTaskOptionParams(options.opts)
delete options.opts
}
const { build } = require('../lib/build')
await build(options)
}
function scanTaskOptionParams(optsParams) {
// need to create new regex every call since a constant would keep the match state
const quoteRegex = /([\w-]+)=([\w/.-]+|\[([\w/,.-]+)\])/g
// captures a=1 => a:1
// a=[x,y,z] => a:[x,y,z]
// a=1,b=[x,y,z] => a:1 b=[x,y,z]
let match = quoteRegex.exec(optsParams)
const taskOptions = {}
while (match != null) {
const key = match[1]
const value = match[3] || match[2]
const valueArray = value.split(",")
taskOptions[key] = valueArray.length > 1 ? valueArray.map((entry) => entry.trim()) : value
match = quoteRegex.exec(optsParams)
}
return taskOptions
}