@sap/cds-dk 9.6.0 → 9.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/bin/add.js +5 -2
- package/bin/cds.js +11 -26
- package/bin/compile/index.js +3 -2
- package/bin/data-products/import.js +3 -0
- package/bin/debug.js +76 -16
- package/bin/env.js +2 -1
- package/bin/export.js +18 -13
- package/bin/help/export.md +2 -1
- package/bin/import.js +21 -18
- package/bin/init.js +8 -1
- package/bin/minify.js +11 -12
- package/bin/mock.js +17 -9
- package/bin/repl.js +2 -2
- package/bin/up.js +34 -4
- package/bin/version.js +202 -131
- package/lib/build/buildTaskEngine.js +4 -0
- package/lib/build/buildTaskFactory.js +5 -35
- package/lib/build/index.js +10 -10
- package/lib/build/plugin.js +6 -3
- package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +3 -1
- package/lib/build/plugins/helm/files/subcharts/content-deployment/templates/_helpers.tpl +1 -1
- package/lib/build/plugins/helm/files/subcharts/content-deployment/templates/job.yaml +8 -0
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.schema.json +18 -0
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +11 -1
- package/lib/build/plugins.js +8 -16
- package/lib/build/provider/hana/index.js +16 -19
- package/lib/build/provider/internalBuildPlugin.js +28 -4
- package/lib/build/provider/internalBuildTaskProvider.js +26 -88
- package/lib/build/provider/mtx/index.js +0 -8
- package/lib/build/provider/mtx-sidecar/index.js +88 -80
- package/lib/build/provider/nodejs/index.js +3 -8
- package/lib/build/util.js +52 -87
- package/lib/deploy/to-hana/hana.js +117 -109
- package/lib/env/schemas/cds-rc.js +0 -4
- package/lib/import/odata/v4parser.js +80 -56
- package/lib/init/constants.js +5 -2
- package/lib/init/index.js +44 -41
- package/lib/init/merge.js +7 -2
- package/lib/init/projectReader.js +4 -10
- package/lib/init/template/ams/index.js +1 -4
- package/lib/init/template/attachments/files/package.json.hbs +1 -1
- package/lib/init/template/data/index.js +1 -1
- package/lib/init/template/extension/index.js +4 -4
- package/lib/init/template/hana/files/package.json.hbs +3 -3
- package/lib/init/template/handler/index.js +1 -1
- package/lib/init/template/helm/index.js +3 -3
- package/lib/init/template/helm-unified-runtime/index.js +5 -1
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +1 -1
- package/lib/init/template/ias/files/mta.yaml.hbs +3 -3
- package/lib/init/template/initial/files/.vscode/tasks.json +10 -0
- package/lib/init/template/{nodejs/files/README.md → initial/files/readme.md} +2 -3
- package/lib/init/template/initial/index.js +15 -0
- package/lib/init/template/java/index.js +4 -11
- package/lib/init/template/kyma/index.js +21 -20
- package/lib/init/template/lint/index.js +3 -1
- package/lib/init/template/mta/index.js +0 -5
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +1 -2
- package/lib/init/template/multitenancy/files/values.yaml.hbs +30 -0
- package/lib/init/template/nodejs/files/.vscode/tasks.json +1 -14
- package/lib/init/template/nodejs/files/package.json.hbs +2 -4
- package/lib/init/template/nodejs/index.js +8 -12
- package/lib/init/template/sample/files/app/common.cds +1 -1
- package/lib/init/template/sample/index.js +5 -6
- package/lib/init/template/sqlite/files/package.json.hbs +7 -1
- package/lib/init/template/test/index.js +1 -1
- package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +6 -0
- package/lib/init/template/tiny-sample/files/nodejs/srv/cat-service.cds +5 -0
- package/lib/init/template/tiny-sample/index.js +2 -2
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +6 -0
- package/lib/init/template/workzone-standard/index.js +13 -3
- package/lib/init/validate.js +11 -6
- package/lib/util/checksum.js +2 -2
- package/lib/util/fs.js +109 -53
- package/lib/util/glob.js +2 -1
- package/lib/util/term.js +4 -8
- package/lib/util/write.js +2 -4
- package/lib/watch/livereload-server.js +4 -3
- package/lib/watch/node-watch.js +5 -8
- package/lib/watch/watched.js +1 -1
- package/lib/watch/watcher.js +136 -0
- package/npm-shrinkwrap.json +245 -284
- package/package.json +2 -3
- package/lib/init/template/nodejs/files/.vscode/settings.json +0 -11
- package/lib/init/template/tiny-sample/files/nodejs/db/data/my.bookshop-Books.csv +0 -3
- package/lib/init/template/tiny-sample/files/nodejs/db/schema.cds +0 -7
- package/lib/init/template/tiny-sample/files/nodejs/srv/cat-service.cds.hbs +0 -5
package/bin/minify.js
CHANGED
|
@@ -34,13 +34,11 @@ class Minify extends Command {
|
|
|
34
34
|
async exec ( args, options ) {
|
|
35
35
|
let [sources,o] = this.parseArgs ({ args, options })
|
|
36
36
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
this.csn = await this.load (sources,o)
|
|
38
|
+
this.min = await this.minify (this.csn,o)
|
|
39
39
|
if (o.dry) return
|
|
40
|
-
if (o.inspect) return this.inspect (min,o)
|
|
41
|
-
|
|
42
|
-
else await this.export (min,o)
|
|
43
|
-
console.log()
|
|
40
|
+
if (o.inspect) return this.inspect (this.min,o)
|
|
41
|
+
else return this.output (this.min,o)
|
|
44
42
|
} catch (e) {
|
|
45
43
|
if (typeof e === 'string') return console.error (e)
|
|
46
44
|
if (e.code) return console.error (e.message)
|
|
@@ -66,7 +64,7 @@ class Minify extends Command {
|
|
|
66
64
|
* Subclasses override this method to provide custom minification behavior.
|
|
67
65
|
*/
|
|
68
66
|
async minify (csn,o) {
|
|
69
|
-
let m = this.minifier ??= o.dry ? new Dryifier(csn) : new Minifier
|
|
67
|
+
let m = this.minifier ??= o.dry ? (new Dryifier).for(csn) : new Minifier
|
|
70
68
|
csn = await this.cleanse (csn,o)
|
|
71
69
|
return m.minify (csn,o)
|
|
72
70
|
}
|
|
@@ -79,7 +77,7 @@ class Minify extends Command {
|
|
|
79
77
|
/**
|
|
80
78
|
* Subclasses override this method to provide custom print behavior.
|
|
81
79
|
*/
|
|
82
|
-
|
|
80
|
+
output (csn,o) { // eslint-disable-line no-unused-vars
|
|
83
81
|
console.log (cds.compile.to.json (csn))
|
|
84
82
|
}
|
|
85
83
|
|
|
@@ -95,12 +93,13 @@ class Minify extends Command {
|
|
|
95
93
|
*/
|
|
96
94
|
class Dryifier extends Minifier {
|
|
97
95
|
|
|
98
|
-
|
|
96
|
+
for (csn) { this.all = Object.keys (csn.definitions); return this }
|
|
99
97
|
capture = {}
|
|
100
98
|
level = 0
|
|
101
99
|
|
|
102
100
|
keep (each,d) {
|
|
103
|
-
if (each in this.kept) return
|
|
101
|
+
if (each in this.kept) return
|
|
102
|
+
if (each in this.defs) this.capture[each] = ++this.level
|
|
104
103
|
super.keep (each, d)
|
|
105
104
|
this.level--
|
|
106
105
|
}
|
|
@@ -109,10 +108,10 @@ class Dryifier extends Minifier {
|
|
|
109
108
|
const { GREEN, GRAY, DIMMED, RESET } = cds.utils.colors
|
|
110
109
|
const min = super.minify (csn, o)
|
|
111
110
|
const kept = Object.keys(this.capture)
|
|
112
|
-
console.log (RESET+'\n', '
|
|
111
|
+
console.log (RESET+'\n', 'Kept:', kept.length, '\n')
|
|
113
112
|
for (let [ each, level ] of Object.entries(this.capture))
|
|
114
113
|
console.log (' '+GRAY,'•'.repeat(level)+GREEN, each, RESET)
|
|
115
|
-
console.log (RESET+'\n', '
|
|
114
|
+
console.log (RESET+'\n', 'Skipped:', this.all.length - kept.length, '\n')
|
|
116
115
|
for (let each of this.all)
|
|
117
116
|
each in this.capture || console.log (DIMMED, ' -', each, RESET)
|
|
118
117
|
console.log (RESET+'\n', 'Total:', this.all.length, '\n')
|
package/bin/mock.js
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
|
-
const cds = require ('../lib/cds')
|
|
2
|
-
const serve =
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const cds = require ('../lib/cds'); require = cds._local // eslint-disable-line no-global-assign
|
|
2
|
+
const serve = require ('@sap/cds/bin/serve') // eslint-disable-line cds-dk/use-api-require, cds-dk/use-relative-require
|
|
3
|
+
|
|
4
|
+
module.exports = exports = Object.assign (cds_mock, serve)
|
|
5
|
+
|
|
6
|
+
exports.help = `
|
|
5
7
|
# SYNOPSIS
|
|
6
8
|
|
|
7
9
|
*cds mock* <service> [<options>]
|
|
8
10
|
|
|
9
11
|
This command is essentially just a convenience shortcut to
|
|
10
|
-
_cds serve --mocked <service> --in-memory? --port 0_
|
|
12
|
+
_cds serve --mocked <service> --in-memory? --port 0_.
|
|
13
|
+
|
|
14
|
+
If <service> resolves to an existing CAP project root, that changes to
|
|
15
|
+
_cds serve --mocked --project <service> --in-memory? --port 0_.
|
|
11
16
|
|
|
12
17
|
# OPTIONS
|
|
13
18
|
|
|
14
19
|
- see _cds help serve_
|
|
15
20
|
|
|
16
21
|
# OPTIONS
|
|
17
|
-
`
|
|
22
|
+
`
|
|
18
23
|
|
|
19
|
-
function cds_mock (
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
function cds_mock (argv, options) {
|
|
25
|
+
const [service] = argv
|
|
26
|
+
const o = { mocked: true, port: '0', 'in-memory?': true, ...options }
|
|
27
|
+
if (!o.project && cds.utils.isfile (service, 'package.json'))
|
|
28
|
+
o.project = true
|
|
29
|
+
return serve (argv, o)
|
|
22
30
|
}
|
package/bin/repl.js
CHANGED
|
@@ -46,7 +46,6 @@ async function repl ([project], options={}) {
|
|
|
46
46
|
inspect.defaultOptions.depth = 11
|
|
47
47
|
|
|
48
48
|
Object.defineProperty (cds,'repl',{value:true})
|
|
49
|
-
await cds.service.bindings // REVISIT: this pre-populates many of the cds facade's lazy properties
|
|
50
49
|
let context={}, repl = { context, displayPrompt(){} }
|
|
51
50
|
if ((options.run ??= project)) await _run (options.run)
|
|
52
51
|
if (options.use) _export (...options.use.split(','))
|
|
@@ -95,8 +94,9 @@ async function repl ([project], options={}) {
|
|
|
95
94
|
|
|
96
95
|
async function _run (project) {
|
|
97
96
|
await require('../bin/serve') ([project], { project, port: 0,
|
|
97
|
+
'with-bindings': true,
|
|
98
|
+
'with-mocks': true,
|
|
98
99
|
'in-memory?': true,
|
|
99
|
-
'with-mocks': true
|
|
100
100
|
})
|
|
101
101
|
_export ('entities', 'services')
|
|
102
102
|
}
|
package/bin/up.js
CHANGED
|
@@ -33,15 +33,16 @@ const { execSync } = require('node:child_process')
|
|
|
33
33
|
const { tmpdir } = require('node:os')
|
|
34
34
|
const crypto = require('node:crypto')
|
|
35
35
|
const cds = require('../lib/cds')
|
|
36
|
-
const { highlight, warn, dim, info } = require('../lib/util/term')
|
|
36
|
+
const { highlight, warn, dim, info, bold, link } = require('../lib/util/term')
|
|
37
37
|
const { exists, fs, path, path: { join }, read, write } = cds.utils
|
|
38
38
|
const { ask4 } = require('../lib/util/question')
|
|
39
39
|
const { readProject } = require('../lib/init/projectReader')
|
|
40
40
|
const { mkdirp, copy } = cds.utils
|
|
41
41
|
const { containerize } = require('../bin/util/containerize')
|
|
42
42
|
const { calcDirChecksum } = require('../lib/util/checksum')
|
|
43
|
+
const { URLS } = require('../lib/init/constants')
|
|
43
44
|
|
|
44
|
-
const DEBUG = /\b(y|all|cli)\b/.test(process.env.DEBUG) ? console.debug : undefined
|
|
45
|
+
const DEBUG = /\b(y|all|cli|up)\b/.test(process.env.DEBUG) ? console.debug : undefined
|
|
45
46
|
|
|
46
47
|
const run = (cmd, { continueOnFail = false, silent = false } = {}) => {
|
|
47
48
|
const redactedCmd = cmd.replace(/(--docker-password=)(['"]?)[^'"\s]+(['"]?)/, '$1[REDACTED]$3')
|
|
@@ -101,9 +102,26 @@ function writeStoredChecksum(appName, checksum) {
|
|
|
101
102
|
async function up() {
|
|
102
103
|
const project = readProject()
|
|
103
104
|
const { apps, appName, hasApprouter, hasXsuaa, isMonorepoMicroservice, hasKyma, hasMta, k8s } = project
|
|
104
|
-
const toKyma = cds.cli.options.to === 'k8s' || hasKyma && !hasMta
|
|
105
|
+
const toKyma = cds.cli.options.to === 'k8s' || hasKyma && !hasMta, toCf = !toKyma
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
if (toCf) {
|
|
108
|
+
if (!hasCommand('mbt')) {
|
|
109
|
+
throw `Missing 'mbt' command. Run ${bold('npm install -g mbt')} to install the Cloud MTA Build Tool.`
|
|
110
|
+
}
|
|
111
|
+
if (!hasCommand('cf')) {
|
|
112
|
+
throw `Missing 'cf' command. Refer to ${link(URLS.CF_INSTALL)} to install the Cloud Foundry CLI.`
|
|
113
|
+
}
|
|
114
|
+
} else if (toKyma) {
|
|
115
|
+
if (!hasCommand('docker')) {
|
|
116
|
+
throw `Missing 'docker' command. Refer to ${link(URLS.DOCKER_INSTALL)} to install Docker.`
|
|
117
|
+
}
|
|
118
|
+
if (!hasCommand('helm')) {
|
|
119
|
+
throw `Missing 'helm' command. Refer to ${link(URLS.HELM_INSTALL)} to install Helm.`
|
|
120
|
+
}
|
|
121
|
+
if (!hasCommand('kubectl')) {
|
|
122
|
+
throw `Missing 'kubectl' command. Refer to ${link(URLS.KUBECTL_INSTALL)} to install kubectl.`
|
|
123
|
+
}
|
|
124
|
+
}
|
|
107
125
|
|
|
108
126
|
for (const { app } of apps) {
|
|
109
127
|
const appPath = path.join(cds.root, cds.env.folders.app, app)
|
|
@@ -137,6 +155,8 @@ async function up() {
|
|
|
137
155
|
if (!exists('chart') || !exists('containerize.yaml')) run('cds add kyma')
|
|
138
156
|
|
|
139
157
|
if (project.hasHtml5Repo) {
|
|
158
|
+
const html5DeployerPath = join(cds.root, cds.env.folders.app, 'html5-deployer', 'resources')
|
|
159
|
+
|
|
140
160
|
if (apps.length > 0) {
|
|
141
161
|
await mkdirp(html5DeployerPath)
|
|
142
162
|
}
|
|
@@ -270,3 +290,13 @@ async function up() {
|
|
|
270
290
|
run(`cf deploy gen/mta.tar -f ${retries}`)
|
|
271
291
|
}
|
|
272
292
|
}
|
|
293
|
+
|
|
294
|
+
const hasCommand = cmd => {
|
|
295
|
+
try {
|
|
296
|
+
execSync(process.platform === 'win32' ? `where ${cmd}` : `command -v ${cmd}`, { stdio: 'ignore' })
|
|
297
|
+
return true
|
|
298
|
+
} catch (e) {
|
|
299
|
+
DEBUG?.(e)
|
|
300
|
+
return false
|
|
301
|
+
}
|
|
302
|
+
}
|
package/bin/version.js
CHANGED
|
@@ -1,166 +1,237 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
|
|
2
|
+
module.exports = exports = async function cds_version (pattern, options) {
|
|
3
|
+
console.log()
|
|
4
|
+
const o = canonic_options4 (pattern, options)
|
|
5
|
+
const all = await Promise.all([
|
|
6
|
+
node_versions(o),
|
|
7
|
+
java_versions(o),
|
|
8
|
+
])
|
|
9
|
+
print_versions (all.flat(),o)
|
|
10
|
+
if (o.info) console.log ('\n','> Project:', project_info (o))
|
|
11
|
+
if (o._elsp) console.log ('\n', `${RED}ELSPROBLEMS${RESET} reported by ${BOLD}npm ls${RESET}. Run ${BOLD}npm install${RESET} to fix dependency problems, then rerun ${BOLD}cds version${RESET}.`)
|
|
12
|
+
console.log()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.options = [ '--depth', '--omit' ]
|
|
16
|
+
exports.flags = [ '--info', '--markdown', '--abs', '--all' ]
|
|
17
|
+
exports.shortcuts = [ '-d', '-o', '-i', '-m', '-a' ]
|
|
18
|
+
exports.help = `
|
|
8
19
|
# SYNOPSIS
|
|
9
20
|
|
|
10
21
|
*cds version* <options>
|
|
11
22
|
*cds -v* <option>
|
|
12
23
|
|
|
13
|
-
|
|
24
|
+
Uses _npm ls_ to fetch the versions of installed CAP packages, and
|
|
25
|
+
prints them in a tabular layout.
|
|
14
26
|
|
|
15
27
|
# OPTIONS
|
|
16
28
|
|
|
17
|
-
*-
|
|
29
|
+
*-d | --depth* <n>
|
|
18
30
|
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
Specifies the depth of the dependency tree to traverse.
|
|
32
|
+
Passed to _npm ls --depth_.
|
|
21
33
|
|
|
22
|
-
*-
|
|
34
|
+
*-o | --omit* <dev/optional/peer>
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
Omits certain types of dependencies when traversing the
|
|
37
|
+
dependency tree. Passed to _npm ls --omit_.
|
|
25
38
|
|
|
26
|
-
*-
|
|
27
|
-
*-ll | --npm-tree* <pattern>
|
|
39
|
+
*-m | --markdown*
|
|
28
40
|
|
|
29
|
-
Prints
|
|
30
|
-
|
|
41
|
+
Prints version information in a tabular markdown format,
|
|
42
|
+
which you can embed into your bug reports.
|
|
31
43
|
|
|
32
|
-
|
|
44
|
+
*-i | --info*
|
|
33
45
|
|
|
34
|
-
|
|
46
|
+
Same as *--markdown*, plus prints project name and
|
|
47
|
+
repository URL at the end as a markdown link.
|
|
48
|
+
`
|
|
35
49
|
|
|
36
|
-
function list_versions (args, options) {
|
|
37
|
-
const {colors} = require('../lib/util/term')
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
line.replace(/(@sap[^@]*)@([\S]+)( -> [\S]+)?(deduped)?/,replacement)
|
|
48
|
-
)
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
const versions = info (options)
|
|
52
|
-
|
|
53
|
-
process.stdout.isTTY && console.log()
|
|
54
|
-
if (options.markdown || options.info) {
|
|
55
|
-
_markdown (versions, options)
|
|
56
|
-
} else {
|
|
57
|
-
const mark = !colors ? s => s : require('../lib/util/term').info
|
|
58
|
-
for (let each of Object.keys(versions)) console.log(`${mark(each)}: ${versions[each]}`)
|
|
59
|
-
}
|
|
60
|
-
process.stdout.isTTY && console.log()
|
|
51
|
+
const DEBUG = process.env.DEBUG ? (...args) => console.debug('[cds.version] -',...args) : undefined
|
|
52
|
+
const child_process = require ('node:child_process')
|
|
53
|
+
const $ = (cmd,..._) => {
|
|
54
|
+
if (cmd.raw) cmd = String.raw (cmd,..._) // the cmd may be a tagged template
|
|
55
|
+
DEBUG?.(cmd)
|
|
56
|
+
return new Promise ((resolve, reject) => child_process.exec (cmd,
|
|
57
|
+
(e,stdout) => e ? reject(e) : resolve (stdout.trim().split('\n'))
|
|
58
|
+
))
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
61
|
+
// Like $, but tolerates npm ls ELSPROBLEMS
|
|
62
|
+
const $npm_ls = (cmd,..._) => {
|
|
63
|
+
if (cmd.raw) cmd = String.raw (cmd,..._) // the cmd may be a tagged template
|
|
64
|
+
DEBUG?.(cmd)
|
|
65
|
+
return new Promise ((resolve, reject) => child_process.exec (cmd, (e, stdout, stderr) => {
|
|
66
|
+
const out = (stdout || '').trim()
|
|
67
|
+
const err = (stderr || '').trim()
|
|
68
|
+
if (err) DEBUG?.('npm ls stderr:\n' + err)
|
|
69
|
+
const isELSPROBLEMS = !!(e && /\bELSPROBLEMS\b/.test(err))
|
|
70
|
+
if (e && !isELSPROBLEMS) {
|
|
71
|
+
const code = e.code ?? e.signal ?? 'UNKNOWN'
|
|
72
|
+
const msg =
|
|
73
|
+
`Failed to run ${BOLD}npm ls${RESET} to collect Node.js package versions.\n` +
|
|
74
|
+
`\n` +
|
|
75
|
+
` Command: ${cmd}\n` +
|
|
76
|
+
` Exit: ${code}\n` +
|
|
77
|
+
`\n` +
|
|
78
|
+
`Re-run with DEBUG=1 to see npm output.\n` +
|
|
79
|
+
`Run ${BOLD}npm install${RESET}, then rerun ${BOLD}cds version${RESET}.`
|
|
80
|
+
const nice = new Error(msg, {cause: e})
|
|
81
|
+
return reject(nice)
|
|
82
|
+
}
|
|
83
|
+
resolve({
|
|
84
|
+
lines: out ? out.split('\n') : [],
|
|
85
|
+
elsp: isELSPROBLEMS
|
|
86
|
+
})
|
|
87
|
+
}))
|
|
88
|
+
}
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
for (let k of keys) if (!(k in sorted)) sorted[k] = versions[k]
|
|
88
|
-
|
|
89
|
-
// For Java projects we also need to collect the Java SDK version
|
|
90
|
-
const javaInfo = !env.cli?.version?.skipjava && env['project-nature'] === 'java'
|
|
91
|
-
if (javaInfo) {
|
|
92
|
-
if (process.stderr.isTTY) console.error('\x1b[2m'+'This takes a while. Collecting Java versions...', '\x1b[0m')
|
|
93
|
-
Object.assign(sorted, capJavaVersion(cwd))
|
|
94
|
-
}
|
|
90
|
+
const cds = require('../lib')
|
|
91
|
+
const home = require('os').homedir()
|
|
92
|
+
const cap_packages = /@sap\/cds|@cap-js\//
|
|
93
|
+
const { GREEN, YELLOW, RED, DIMMED, BOLD, RESET } = cds.utils.colors
|
|
94
|
+
const { join, dirname } = require ('node:path')
|
|
95
95
|
|
|
96
|
-
return sorted
|
|
97
|
-
}
|
|
98
96
|
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
105
|
-
for (let dep in deps) {
|
|
106
|
-
if (!dep.match(/@sap\/.*cds.*/) && !dep.startsWith('@cap-js/')) continue
|
|
107
|
-
try {
|
|
108
|
-
const dep_path = require.resolve(join(dep, 'package.json'), {paths:[pkg_path]})
|
|
109
|
-
const dep_pkg = require(dep_path)
|
|
110
|
-
versions[dep_pkg.name] = dep_pkg.version
|
|
111
|
-
} catch (e) {
|
|
112
|
-
if (e.code !== 'MODULE_NOT_FOUND') console.error(e)
|
|
113
|
-
}
|
|
97
|
+
function canonic_options4 ([pattern], options) {
|
|
98
|
+
const o = {
|
|
99
|
+
root: cds.root,
|
|
100
|
+
depth: options.all ? 11 : 1,
|
|
101
|
+
...options,
|
|
114
102
|
}
|
|
115
|
-
|
|
103
|
+
if (pattern) o.pattern = pattern
|
|
104
|
+
if (o.info) o.markdown ??= true
|
|
105
|
+
DEBUG?.('options:',o)
|
|
106
|
+
return o
|
|
116
107
|
}
|
|
117
108
|
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
109
|
+
async function node_versions(o) {
|
|
110
|
+
|
|
111
|
+
// Call npm root and npm ls in parallel...
|
|
112
|
+
const [ [npm_root_g],[npm_root_l], { lines, elsp } ] = await Promise.all ([
|
|
113
|
+
$`npm root --global`,
|
|
114
|
+
$`npm root --local`,
|
|
115
|
+
$npm_ls`npm ls -lp ${
|
|
116
|
+
(o.omit ? o.omit.split(',').map(o => `--omit=${o} `).join('') : '') +
|
|
117
|
+
(o.depth ? `--depth=${o.depth}` : '--depth=1')
|
|
118
|
+
}`
|
|
119
|
+
])
|
|
120
|
+
|
|
121
|
+
// Parse information returned by npm ls -lp
|
|
122
|
+
// Example macOS: /Users/me/projects/bookshop/node_modules/@sap/cds-dk:@sap/cds-dk@1.0.0:/Users/me/projects/bookshop/cds-dk
|
|
123
|
+
// Example Windows: C:\Users\me\projects\bookshop\node_modules\@sap\cds-dk:@sap/cds-dk@1.0.0:C:\Users\me\projects\bookshop\cds-dk
|
|
124
|
+
const _path = /(?:\\\\\?\\)?[A-Za-z]:[^:]+|[^:]+/.source
|
|
125
|
+
const _line = new RegExp(`^(${_path}):(@?.+)@([^:]+):?(.*)?$`)
|
|
126
|
+
const _pkg = o.pattern ? RegExp(o.pattern) : cap_packages
|
|
127
|
+
const deps = lines.map (line => {
|
|
128
|
+
let [, path, name, version, location = path ] = _line.exec(line) || []
|
|
129
|
+
if (!location || location.includes('EXTRANEOUS')) return
|
|
130
|
+
if (name.match(_pkg)) return [ name, version, location ]
|
|
131
|
+
}) .filter (x => x)
|
|
132
|
+
|
|
133
|
+
// Sort SAP packages and CAP packages on top
|
|
134
|
+
const entries = deps.sort (function sap_then_cap_on_top ([a],[b]) {
|
|
135
|
+
let a_is_cdk = a === '@sap/cds-dk'
|
|
136
|
+
let b_is_cdk = b === '@sap/cds-dk'
|
|
137
|
+
if (a_is_cdk && !b_is_cdk) return -1
|
|
138
|
+
if (b_is_cdk && !a_is_cdk) return 1
|
|
139
|
+
let a_is_sap = a.startsWith('@sap/cds')
|
|
140
|
+
let b_is_sap = b.startsWith('@sap/cds')
|
|
141
|
+
if (a_is_sap && !b_is_sap) return -1
|
|
142
|
+
if (b_is_sap && !a_is_sap) return 1
|
|
143
|
+
let a_is_cap = a.startsWith('@cap-js')
|
|
144
|
+
let b_is_cap = b.startsWith('@cap-js')
|
|
145
|
+
if (a_is_cap && !b_is_cap) return -1
|
|
146
|
+
if (b_is_cap && !a_is_cap) return 1
|
|
147
|
+
return a < b ? -1 : a > b ? 1 : 0
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// Put global cds-dk at the top
|
|
151
|
+
try {
|
|
152
|
+
const loc = require.resolve ('@sap/cds-dk/package.json', { paths: [npm_root_g] })
|
|
153
|
+
const gdk = require (loc)
|
|
154
|
+
entries.unshift (
|
|
155
|
+
[ '@sap/cds-dk (global)', gdk.version, dirname(loc) ]
|
|
156
|
+
)
|
|
157
|
+
} catch (e) { if (e.code !== 'MODULE_NOT_FOUND') throw e }
|
|
158
|
+
|
|
159
|
+
// Add some environment info at the end
|
|
160
|
+
entries.push (
|
|
161
|
+
[ 'cds.home', null, cds.home ],
|
|
162
|
+
[ 'cds.root', null, o.root ],
|
|
163
|
+
[ 'npm root -l', null, npm_root_l ],
|
|
164
|
+
[ 'npm root -g', null, npm_root_g ],
|
|
165
|
+
[ 'Node.js', process.version.slice(1), process.execPath ],
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
if (elsp) o._elsp = true
|
|
169
|
+
|
|
170
|
+
return entries
|
|
171
|
+
}
|
|
127
172
|
|
|
128
|
-
Object.keys(versions)
|
|
129
|
-
.filter(mod => mod != pkg.name)
|
|
130
|
-
.forEach(id => console.log ('|', $(id, versions[id]), '|'))
|
|
131
173
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
174
|
+
function java_versions (o) {
|
|
175
|
+
const javaInfo = !cds.env.cli?.version?.skipjava && cds.env['project-nature'] === 'java'
|
|
176
|
+
if (!javaInfo) return []
|
|
177
|
+
else if (process.stderr.isTTY) console.warn (DIMMED, 'This takes a while. Collecting Java versions...', RESET)
|
|
178
|
+
const { MAVEN_ARCHETYPE_VERSION:mav } = require ('../lib/init/constants')
|
|
179
|
+
const cmd = `mvn com.sap.cds:cds-maven-plugin:${mav}:version -B -ntp -Dcds.version.excludeCds -Dcds.version.json`
|
|
180
|
+
try {
|
|
181
|
+
const out = child_process.spawnSync (cmd, { cwd: o.root, shell: true }).stdout.toString().trim()
|
|
182
|
+
const [,match] = out.match (/===\n(.*)\n===/ms) || []
|
|
183
|
+
if (match) return Object.entries(JSON.parse(match)).map(([name,v]) => {
|
|
184
|
+
let versions = Object.entries(v).map(([k,v]) => (k === 'version' || k === 'name') ? v : `${k}:${v}`).join(', ')
|
|
185
|
+
return [ name, versions ]
|
|
186
|
+
})
|
|
187
|
+
} catch { /* ignored */ }
|
|
188
|
+
return [[ 'CAP Java SDK', '-- missing --' ]]
|
|
136
189
|
}
|
|
137
190
|
|
|
138
|
-
|
|
191
|
+
|
|
192
|
+
function project_info (o) {
|
|
139
193
|
try {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
194
|
+
const { name, repository } = require (join (o.root,'package.json'))
|
|
195
|
+
const repo = repository?.url || repository || ''
|
|
196
|
+
return `[${GREEN}${name}${RESET}](${DIMMED}${repo}${RESET})`
|
|
197
|
+
} catch { /* ignored */ }
|
|
145
198
|
}
|
|
146
199
|
|
|
147
|
-
function capJavaVersion(cwd) {
|
|
148
|
-
const { MAVEN_ARCHETYPE_VERSION } = require('../lib/init/constants')
|
|
149
|
-
const cmd = `mvn com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:version -B -ntp -Dcds.version.excludeCds -Dcds.version.json`
|
|
150
200
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Object.entries(JSON.parse(match[1])).forEach(([k,v]) => {
|
|
160
|
-
const entries = Object.entries(v)
|
|
161
|
-
res[k] = entries.map(([k,v]) => (k === 'version' || k === 'name') ? v : `${k}: ${v}`).join(', ')
|
|
162
|
-
})
|
|
163
|
-
return res
|
|
201
|
+
function print_versions (rows, o, cwd = o.root+'/') {
|
|
202
|
+
|
|
203
|
+
if (!rows || rows.length === 0) return console.error (YELLOW, ' No CAP packages found.', RESET)
|
|
204
|
+
const local = o.abs ? p => p : p => !p ? '' : p.startsWith(cwd) ? p.replace(cwd,'./') : p.replace(home,'~')
|
|
205
|
+
|
|
206
|
+
if (cds.env['project-nature'] === 'java') { // cds10: remove
|
|
207
|
+
console.log(rows.map(([name,version,location]) => `${GREEN}${name}:${RESET} ${version??location}`).join('\n'))
|
|
208
|
+
return
|
|
164
209
|
}
|
|
165
|
-
|
|
210
|
+
|
|
211
|
+
// compute column widths for tabular printing
|
|
212
|
+
const header = o.markdown && [ 'Package', 'Version', 'Location' ]
|
|
213
|
+
const all = Object.values(rows); if (header) all.push (header)
|
|
214
|
+
const w1 = Math.max (...all.map(s => s[0]?.length || 0))
|
|
215
|
+
const w2 = Math.max (...all.map(s => s[1]?.length || 0))
|
|
216
|
+
const w3 = Math.max (...all.map(s => (s[2] = local(s[2]))?.length || 0))
|
|
217
|
+
|
|
218
|
+
// prepare line printer function for column-aligned output
|
|
219
|
+
const I = header ? '|' : ''
|
|
220
|
+
const print = ([ name, version, location ], [c1,c2,c3]) => console.log(
|
|
221
|
+
RESET,I+c1, (name||'').padEnd(w1),
|
|
222
|
+
RESET+I+c2, (version||'').padEnd(w2),
|
|
223
|
+
RESET+I+c3, (location||'').padEnd(w3),
|
|
224
|
+
RESET+I
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
// print table header
|
|
228
|
+
if (header) {
|
|
229
|
+
const uncolored = ['','','']
|
|
230
|
+
print (header, uncolored)
|
|
231
|
+
print ([w1,w2,w3].map(n => '-'.repeat(n)), uncolored)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// print table rows
|
|
235
|
+
const colored = [ GREEN, YELLOW, DIMMED ]
|
|
236
|
+
for (let each of rows) print (each, colored)
|
|
166
237
|
}
|
|
@@ -15,6 +15,10 @@ const DEBUG = cds.debug('cli|build')
|
|
|
15
15
|
const LOG_LIMIT = 30
|
|
16
16
|
|
|
17
17
|
class BuildTaskEngine {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {import('../build').BuildOptions} options - command options
|
|
21
|
+
*/
|
|
18
22
|
constructor(options) {
|
|
19
23
|
this._taskFactory = new BuildTaskFactory(options)
|
|
20
24
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const path = require('path')
|
|
4
2
|
const cds = require('../cds')
|
|
5
3
|
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
6
|
-
const { hasJavaNature, getProperty,
|
|
7
|
-
const {
|
|
4
|
+
const { hasJavaNature, getProperty, getDefaultModelPaths, hasOptionValue, BuildError } = require('./util')
|
|
5
|
+
const { OPTION_WS, IGNORE_DEFAULT_MODELS, NODEJS_MODEL_EXCLUDE_LIST, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF } = require("./constants")
|
|
8
6
|
const DEBUG = cds.debug('cli|build')
|
|
9
7
|
|
|
10
|
-
class BuildTaskFactory {
|
|
8
|
+
module.exports = class BuildTaskFactory {
|
|
11
9
|
constructor(options) {
|
|
12
10
|
this._providerFactory = new BuildTaskProviderFactory(options)
|
|
13
11
|
}
|
|
@@ -86,11 +84,11 @@ class BuildTaskFactory {
|
|
|
86
84
|
task.options.model = [task.options.model]
|
|
87
85
|
}
|
|
88
86
|
})
|
|
89
|
-
const modelPaths = await
|
|
87
|
+
const modelPaths = await getDefaultModelPaths(false)
|
|
90
88
|
let wsModelPaths
|
|
91
89
|
// calculate only once
|
|
92
90
|
if (cds.cli.options?.[OPTION_WS] || tasks.some(task => hasOptionValue(task.options?.[OPTION_WS], true))) {
|
|
93
|
-
wsModelPaths = await
|
|
91
|
+
wsModelPaths = await getDefaultModelPaths(true)
|
|
94
92
|
}
|
|
95
93
|
// set default model options
|
|
96
94
|
tasks.forEach(task => {
|
|
@@ -197,32 +195,4 @@ class BuildTaskFactory {
|
|
|
197
195
|
}
|
|
198
196
|
task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(modelPaths) : modelPaths)]
|
|
199
197
|
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Determines the module folder from the past list that may represent files or folders w or w/o .cds file extension.
|
|
203
|
-
* @param {Array} filesOrFolders
|
|
204
|
-
*/
|
|
205
|
-
static _getModuleFolder(filesOrFolders) {
|
|
206
|
-
const resources = [...filesOrFolders]
|
|
207
|
-
filesOrFolders.forEach(fileOrFolder => {
|
|
208
|
-
if (path.extname(fileOrFolder) !== FILE_EXT_CDS) {
|
|
209
|
-
resources.push(fileOrFolder + FILE_EXT_CDS)
|
|
210
|
-
}
|
|
211
|
-
})
|
|
212
|
-
return resources.reduce((acc, resource) => {
|
|
213
|
-
if (!acc) {
|
|
214
|
-
let resourcePath = path.resolve(cds.root, resource)
|
|
215
|
-
if (fs.existsSync(resourcePath)) {
|
|
216
|
-
if (cds.utils.isdir(resourcePath)) {
|
|
217
|
-
acc = resource
|
|
218
|
-
} else {
|
|
219
|
-
// represents file
|
|
220
|
-
acc = path.dirname(resource)
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return acc
|
|
225
|
-
}, null)
|
|
226
|
-
}
|
|
227
198
|
}
|
|
228
|
-
module.exports = BuildTaskFactory
|