UNPKG

@sap/cds-dk

Version:

Command line client and development toolkit for the SAP Cloud Application Programming Model

202 lines (154 loc) 7.78 kB
module.exports = Object.assign(build, { handleCompletion, options: ['--project', '--src', '--dest', '--for', '--opts', '--log-level', '--options-model'], shortcuts: ['-in', '-s', '-o', '-4'], flags: ['--no-clean', '--ws', '--ws-pack'], help: ` # SYNOPSIS *cds build* [<project>] [<options>] Builds modules in current project by compiling resolved CDS sources. 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 applied to the source folder. Explicitly configured in the build tasks or derived from the project setup and plugins. For example, the 'hana' build task will create SAP HANA artifacts. *-s | --src* <folder> The module folder to build using the build task defined by option '--for'. This option is only supported for building an individual module of the project. The folder is resolved based on '<project>/<cds.env.build.target>'. A default may be pre-configured, for example, the folder 'db' for the *hana* build task, or 'srv' for *nodejs* and *java*. *-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 'gen' is used by default - output is written to '<project>/gen/*<dest>*/*'. For Java '.' is used by default - 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). 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 the current working directory. *--no-clean* Skips cleaning the output folder before running the build. *--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, BuildError } = require('../lib/build') try { return await build(options) } catch (e) { if (e instanceof BuildError || e.constructor.name === 'CompilationError') { cds._log(e.messages.length ? e.messages : e.message, { 'log-level': options['log-level'] || cds.env['log-level'] }) console.log() // CompilationError.message also includes the detail messages - do not log twice throw e.constructor.name === 'CompilationError' ? 'CDS compilation failed' : e.messages.length ? e.message : 'CDS build failed' } throw e } } const quoteRegex = /([\w-]+)=([\w/.-]+|\[([\w/,.-]+)\])/g function scanTaskOptionParams(optsParams) { // 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] quoteRegex.lastIndex = 0 // so we don't need to create a new regex every call since a constant would keep the match state 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 }