@sap/cds-dk 9.0.6 → 9.1.1
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 +41 -0
- package/bin/add.js +9 -6
- package/bin/debug.js +14 -7
- package/bin/repl.js +9 -2
- package/bin/up.js +16 -6
- package/index.d.ts +3 -0
- package/lib/build/provider/fiori/index.js +2 -4
- package/lib/deploy/to-hana/hana.js +9 -4
- package/lib/init/constants.js +12 -11
- package/lib/init/index.js +36 -5
- package/lib/init/merge.js +4 -1
- package/lib/init/plugin.js +0 -33
- package/lib/init/projectReader.js +1 -1
- package/lib/init/template/ams/files/Chart.yaml.hbs +3 -1
- package/lib/init/template/approuter/files/mta.yaml.hbs +2 -1
- package/lib/init/template/cloud-logging/files/java-cdsrc.json.hbs +6 -0
- package/lib/init/template/cloud-logging/files/package.json.hbs +7 -0
- package/lib/init/template/cloud-logging/index.js +9 -10
- package/lib/init/template/containerize/index.js +1 -1
- package/lib/init/template/data/as-json.js +3 -3
- package/lib/init/template/hana/index.js +3 -2
- package/lib/init/template/handler/files/extension/package.json +1 -1
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +3 -1
- package/lib/init/template/html5-repo/index.js +1 -1
- package/lib/init/template/http/index.js +56 -54
- package/lib/init/template/ias/files/Chart.yaml.hbs +3 -1
- package/lib/init/template/ias/files/mta.yaml.hbs +2 -2
- package/lib/init/template/ias/index.js +3 -4
- package/lib/init/template/mta/index.js +5 -5
- package/lib/init/template/multitenancy/index.js +3 -4
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/template/portal/index.js +1 -1
- package/lib/init/template/test/files/package.json +8 -0
- package/lib/init/template/test/files/test/test.xs.hbs +36 -0
- package/lib/init/template/test/index.js +152 -0
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/xsuaa/index.js +2 -2
- package/lib/lint/Linter.js +1 -4
- package/lib/lint/eslintHelp.json +84 -0
- package/lib/mtx/auth_manager.js +0 -2
- package/lib/util/axios.js +77 -31
- package/npm-shrinkwrap.json +24 -21
- package/package.json +3 -2
- package/lib/init/template/cloud-logging/files/java-cdsrc.json +0 -5
- package/lib/lint/generators.js +0 -103
package/CHANGELOG.md
CHANGED
|
@@ -6,11 +6,52 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
8
8
|
|
|
9
|
+
## Version 9.1.1 - 2025-07-10
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- shipping an `index.d.ts` file containing a subset of the dk types now.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- `cds add http` now generates auth headers with `:` separators again, as this is the only separator supporting empty passwords with the RestClient extension in VS Code. (For use with IntelliJ, separate username and password with a blank.)
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `cds deploy --to hana --no-build` now works correctly
|
|
22
|
+
- fixed bug in call from SAP Business Application Studio wizard
|
|
23
|
+
|
|
24
|
+
## Version 9.1.0 - 2025-07-02
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- `cds add test` to generate test files for CDS services [experimental]
|
|
29
|
+
- `cds debug --no-devtools` allows to skip opening the developer tools.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `cds add helm` doesn't route the subscription callbacks through the app router any longer.
|
|
34
|
+
- `cds lint` now uses local copy of `eslint` help content.
|
|
35
|
+
- `cds add cloud-logging` will correctly add the Helm dependency to `Chart.yaml`.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- `cds add hana` for Java correctly adds the HANA dependencies to `chart/Chart.yaml`.
|
|
40
|
+
- `cds add xsuaa` for Java doesn't throw an error when the `.cdsrc.json` is not existing.
|
|
41
|
+
- `cds build --for fiori` stores EDMX files again relative if `dataSources.mainService.settings.localUri` in UI5's `manifest.json` is a relative path.
|
|
42
|
+
- `cds add ams/ias` add the `repository` in combination with `cds add helm-unified-runtime`.
|
|
43
|
+
- `cds add xsuaa` adds a wildcard prefix to the domain name to allow for multitenancy use cases.
|
|
44
|
+
- `cds add portal` for Java binds the HTML5 repo runtime and portal service to the Java server instead of the MTX sidecar, to allow for CAP Java built-in dependencies resolution.
|
|
45
|
+
- `cds repl --run` can now run again w/o `@cap-js/cds-test` installed.
|
|
46
|
+
- `cds push` and other commands now handle request errors more robustly
|
|
47
|
+
- `cds debug` now also honors the `--host` parameter when it starts `cds watch`.
|
|
48
|
+
|
|
9
49
|
## Version 9.0.6 - 2025-06-18
|
|
10
50
|
|
|
11
51
|
### Changed
|
|
12
52
|
|
|
13
53
|
- `cds build` now adds an `engines.node = ">=20"` entry to the effective _package.json_ iff it is missing from the project's _package.json_ to avoid engine confusion when deploying to Cloud Foundry
|
|
54
|
+
- `cds add` without any flag now shows the help (`cds add --help`) instead of throwing an error
|
|
14
55
|
|
|
15
56
|
## Version 9.0.5 - 2025-06-06
|
|
16
57
|
|
package/bin/add.js
CHANGED
|
@@ -65,17 +65,20 @@ ${Object.entries(conf).sort(([a], [b]) => a.localeCompare(b)).flatMap(([pluginNa
|
|
|
65
65
|
|
|
66
66
|
# EXAMPLES
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
*cds add* sample
|
|
69
|
+
*cds add* multitenancy,hana,xsuaa
|
|
70
|
+
*cds add* data --filter my.namespace.MyEntity
|
|
71
|
+
*cds add* mta
|
|
72
|
+
*cds add* helm
|
|
74
73
|
|
|
75
74
|
# SEE ALSO
|
|
76
75
|
|
|
77
76
|
*cds init*
|
|
78
77
|
|
|
78
|
+
# SUMMARY
|
|
79
|
+
|
|
80
|
+
*cds add* <feature | comma-separated list of features>
|
|
81
|
+
|
|
79
82
|
`});
|
|
80
83
|
|
|
81
84
|
async function handleCompletion(currentWord, previousWord, argv, util) {
|
package/bin/debug.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module.exports = Object.assign(debug, {
|
|
2
|
-
options: ['--port', '--host', '--force'],
|
|
2
|
+
options: ['--port', '--host', '--force', '--no-devtools'],
|
|
3
3
|
shortcuts: ['-p', '-h', '-f'],
|
|
4
4
|
flags: [/*'--vscode', '--k8s'*/],
|
|
5
5
|
help: `
|
|
@@ -14,6 +14,7 @@ module.exports = Object.assign(debug, {
|
|
|
14
14
|
If <app> is given, it's assumed to be running on the currently logged-in
|
|
15
15
|
Cloud Foundry space (check with 'cf target').
|
|
16
16
|
SSH access to the app is required (check with 'cf ssh-enabled').
|
|
17
|
+
Chrome DevTools are opened automatically for Node.js applications.
|
|
17
18
|
|
|
18
19
|
If no <app> is given, the app in the current working directory is started
|
|
19
20
|
(with 'cds watch --debug' for Node.js and 'mvn spring-boot:run' for Java).
|
|
@@ -28,6 +29,10 @@ module.exports = Object.assign(debug, {
|
|
|
28
29
|
|
|
29
30
|
the debug port (default: '9229' for Node.js, '8000' for Java)
|
|
30
31
|
|
|
32
|
+
*--no-devtools*
|
|
33
|
+
|
|
34
|
+
don't open developer tools automatically
|
|
35
|
+
|
|
31
36
|
*-f* | *--force*
|
|
32
37
|
|
|
33
38
|
if necessary, automatically enable ssh for the app and restart it
|
|
@@ -36,6 +41,7 @@ module.exports = Object.assign(debug, {
|
|
|
36
41
|
|
|
37
42
|
*cds debug*
|
|
38
43
|
*cds debug* bookshop-srv --port 8001
|
|
44
|
+
*cds debug* bookshop-srv --host 0.0.0.0
|
|
39
45
|
`})
|
|
40
46
|
|
|
41
47
|
async function debug() {
|
|
@@ -45,7 +51,7 @@ async function debug() {
|
|
|
45
51
|
const DEBUG = /\b(y|all|debug)\b/.test(process.env.DEBUG) ? console.debug : undefined
|
|
46
52
|
|
|
47
53
|
const [appName] = cds.cli.argv
|
|
48
|
-
const { port, host = '127.0.0.1', vscode, force } = cds.cli.options
|
|
54
|
+
const { port = 9229, host = '127.0.0.1', vscode, force } = cds.cli.options
|
|
49
55
|
|
|
50
56
|
const maxAttempts = 15
|
|
51
57
|
let attempts = 0
|
|
@@ -60,8 +66,9 @@ async function debug() {
|
|
|
60
66
|
}
|
|
61
67
|
else {
|
|
62
68
|
const script = process.argv[1] // `.../cds` or `.../cds-tsx`
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
const hostport = `${host}:${port}`
|
|
70
|
+
console.log(`Starting '${cds.utils.path.basename(script)} watch --debug ${(host != '127.0.0.1' || port != 9229) ? hostport : ''}'`)
|
|
71
|
+
fork(script, ['watch', '--debug', hostport]).on('error', e => { throw 'Failed to start debug process:' + e.message })
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
else if (cds.cli.options.k8s) { // Kyma/Kubernetes
|
|
@@ -74,7 +81,7 @@ async function debug() {
|
|
|
74
81
|
if (kind === 'node') {
|
|
75
82
|
enableNodeDebugging(pid, appName)
|
|
76
83
|
const portLocal = openTunnel(9229)
|
|
77
|
-
openDevTools(portLocal)
|
|
84
|
+
if (!cds.cli.options['no-devtools']) openDevTools(portLocal)
|
|
78
85
|
}
|
|
79
86
|
else if (kind === 'java') {
|
|
80
87
|
const portRemote = findJavaDebugPort(pid, appName)
|
|
@@ -114,8 +121,8 @@ async function debug() {
|
|
|
114
121
|
|
|
115
122
|
function openTunnel(portRemote) {
|
|
116
123
|
const portLocal = port || portRemote
|
|
117
|
-
console.log(`\nOpening SSH tunnel on ${portRemote}:${host}:${portLocal}`)
|
|
118
|
-
spawn('cf', ['ssh', '-N', '-L', `${portRemote}:${host}:${portLocal}`, appName], { stdio: 'inherit' })
|
|
124
|
+
console.log(`\nOpening SSH tunnel on ${host}:${portRemote}:${host}:${portLocal}`)
|
|
125
|
+
spawn('cf', ['ssh', '-N', '-L', `${host}:${portRemote}:${host}:${portLocal}`, appName], { stdio: 'inherit' })
|
|
119
126
|
return portLocal
|
|
120
127
|
}
|
|
121
128
|
|
package/bin/repl.js
CHANGED
|
@@ -28,7 +28,7 @@ module.exports = Object.assign (repl, {
|
|
|
28
28
|
|
|
29
29
|
*cds repl* --run bookshop
|
|
30
30
|
*cds repl* --run .
|
|
31
|
-
*cds repl* --use
|
|
31
|
+
*cds repl* --use ql
|
|
32
32
|
|
|
33
33
|
# SEE ALSO
|
|
34
34
|
|
|
@@ -92,7 +92,14 @@ async function repl (_, options={}) {
|
|
|
92
92
|
process.on = (event, listener) => event !== 'uncaughtException' && event !== 'unhandledRejection' && process.addListener(event, listener)
|
|
93
93
|
|
|
94
94
|
async function _run (project) {
|
|
95
|
-
|
|
95
|
+
try {
|
|
96
|
+
if (require.resolve('@cap-js/cds-test', {paths: [cds.root, cds.home]})) {
|
|
97
|
+
await cds.test (project)
|
|
98
|
+
}
|
|
99
|
+
} catch (e) {
|
|
100
|
+
if (e.code !== 'MODULE_NOT_FOUND') throw e
|
|
101
|
+
await cds.exec ('--project', project, '--port', '0', '--in-memory?')
|
|
102
|
+
}
|
|
96
103
|
_export ('entities', 'services')
|
|
97
104
|
}
|
|
98
105
|
|
package/bin/up.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = Object.assign(up, {
|
|
2
|
-
options: ['--to'],
|
|
3
|
-
shortcuts: ['-2'],
|
|
2
|
+
options: ['--to', '--namespace'],
|
|
3
|
+
shortcuts: ['-2', '-n'],
|
|
4
4
|
flags: [],
|
|
5
5
|
help: `
|
|
6
6
|
# SYNOPSIS
|
|
@@ -15,10 +15,16 @@ module.exports = Object.assign(up, {
|
|
|
15
15
|
|
|
16
16
|
The platform to deploy to. Default is 'cf'.
|
|
17
17
|
|
|
18
|
+
*-n* | *--namespace* <name>
|
|
19
|
+
|
|
20
|
+
(Kubernetes only) Target namespace. If it does not yet exist it will be
|
|
21
|
+
created automatically via *helm --create-namespace*.
|
|
22
|
+
|
|
18
23
|
# EXAMPLES
|
|
19
24
|
|
|
20
25
|
*cds up*
|
|
21
26
|
*cds up --to k8s*
|
|
27
|
+
*cds up --to k8s --namespace e2e-tests*
|
|
22
28
|
`})
|
|
23
29
|
|
|
24
30
|
const { execSync, spawn } = require('node:child_process')
|
|
@@ -95,14 +101,18 @@ async function up() {
|
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
if (cds.cli.options.to === 'k8s') {
|
|
104
|
+
const ns = cds.cli.options.namespace
|
|
105
|
+
const nsHelm = ns ? `--namespace ${ns} --create-namespace` : ''
|
|
106
|
+
const nsKubectl = ns ? `-n ${ns}` : ''
|
|
107
|
+
|
|
98
108
|
run('npm i --package-lock')
|
|
99
109
|
await runDetectingError('ctz containerize.yaml --log --push', /^\[?ERROR\]?.*/m)
|
|
100
|
-
let helmUpgrade = `helm upgrade --install ${appName} ./gen/chart --wait --wait-for-jobs`
|
|
110
|
+
let helmUpgrade = `helm upgrade --install ${appName} ./gen/chart ${nsHelm} --wait --wait-for-jobs`
|
|
101
111
|
if (hasXsuaa) helmUpgrade += ' --set-file xsuaa.jsonParameters=xs-security.json'
|
|
102
112
|
run(helmUpgrade)
|
|
103
|
-
run(`kubectl rollout status deployment ${appName}-srv --timeout=8m`)
|
|
104
|
-
if (hasApprouter) run(`kubectl rollout status deployment ${appName}-approuter --timeout=8m`)
|
|
105
|
-
if (exists('mtx/sidecar')) run(`kubectl rollout status deployment ${appName}-sidecar --timeout=8m`)
|
|
113
|
+
run(`kubectl rollout status deployment ${appName}-srv ${nsKubectl} --timeout=8m`)
|
|
114
|
+
if (hasApprouter) run(`kubectl rollout status deployment ${appName}-approuter ${nsKubectl} --timeout=8m`)
|
|
115
|
+
if (exists('mtx/sidecar')) run(`kubectl rollout status deployment ${appName}-sidecar ${nsKubectl} --timeout=8m`)
|
|
106
116
|
} else {
|
|
107
117
|
run('mbt build -t gen --mtar mta.tar')
|
|
108
118
|
run('cf deploy gen/mta.tar -f')
|
package/index.d.ts
ADDED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
2
|
const cds = require('../../../cds')
|
|
3
3
|
const EdmxBuildPlugin = require('../edmxBuildPlugin')
|
|
4
|
-
const { URL } = require('node:url')
|
|
5
4
|
const { getProperty, relativePaths } = require('../../util')
|
|
6
5
|
const { OUTPUT_MODE, OUTPUT_MODE_RESULT, BUILD_TASK_FIORI, CDS_CONFIG_PATH_SEP, OUTPUT_MODE_FILESYSTEM } = require('../../constants')
|
|
7
6
|
const DEBUG = cds.debug('cli|build')
|
|
@@ -9,7 +8,7 @@ const DEBUG = cds.debug('cli|build')
|
|
|
9
8
|
/**
|
|
10
9
|
* With cds 4 service metadata for the UI service binding is no longer created by default.
|
|
11
10
|
* For SAP Web IDE Full-Stack compatibility a corresponding metadata.xml is still generated.
|
|
12
|
-
* Though, 'fiori' build tasks can still be configured for UI5 mock server usage - see
|
|
11
|
+
* Though, 'fiori' build tasks can still be configured for UI5 mock server usage - see cap/issues#8673
|
|
13
12
|
*/
|
|
14
13
|
class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
15
14
|
init() {
|
|
@@ -159,8 +158,7 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
159
158
|
}
|
|
160
159
|
|
|
161
160
|
_strippedUrlPath(urlString) {
|
|
162
|
-
|
|
163
|
-
return url.pathname.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash
|
|
161
|
+
return urlString.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash
|
|
164
162
|
}
|
|
165
163
|
}
|
|
166
164
|
|
|
@@ -29,7 +29,8 @@ const allowList = [
|
|
|
29
29
|
'--to',
|
|
30
30
|
'--tunnel-address',
|
|
31
31
|
'--vcap-file',
|
|
32
|
-
'--with-mocks'
|
|
32
|
+
'--with-mocks',
|
|
33
|
+
'--no-build'
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
module.exports = new class HanaDeployer {
|
|
@@ -110,7 +111,8 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
|
|
|
110
111
|
}
|
|
111
112
|
} else {
|
|
112
113
|
// the primary database is always built and deployed
|
|
113
|
-
const dest = buildResult.dest
|
|
114
|
+
// const dest = buildResult.dest
|
|
115
|
+
const dest = path.join(cds.root, cds.env.build.target, cds.env.folders.db);
|
|
114
116
|
|
|
115
117
|
if (undeployWhitelist) {
|
|
116
118
|
console.log('Writing undeploy.json');
|
|
@@ -130,7 +132,9 @@ metadata:
|
|
|
130
132
|
name: ${appName}-db
|
|
131
133
|
spec:
|
|
132
134
|
serviceOfferingName: hana
|
|
133
|
-
servicePlanName: hdi-shared
|
|
135
|
+
servicePlanName: hdi-shared
|
|
136
|
+
`
|
|
137
|
+
|
|
134
138
|
const binding =
|
|
135
139
|
`apiVersion: services.cloud.sap.com/v1
|
|
136
140
|
kind: ServiceBinding
|
|
@@ -139,7 +143,8 @@ metadata:
|
|
|
139
143
|
spec:
|
|
140
144
|
serviceInstanceName: ${appName}-db
|
|
141
145
|
secretName: ${appName}-db-secret
|
|
142
|
-
|
|
146
|
+
|
|
147
|
+
`
|
|
143
148
|
|
|
144
149
|
try {
|
|
145
150
|
cp.execSync('kubectl apply -f -', { input: instance })
|
package/lib/init/constants.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = {
|
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
7
|
JAVA_LTS_VERSIONS: [17, 21],
|
|
8
|
-
MAVEN_ARCHETYPE_VERSION: '4.
|
|
8
|
+
MAVEN_ARCHETYPE_VERSION: '4.1.1',
|
|
9
9
|
|
|
10
10
|
OPTIONS: Object.freeze({
|
|
11
11
|
COMPLETION: 'completion',
|
|
@@ -17,29 +17,30 @@ module.exports = {
|
|
|
17
17
|
TYPER: 'typer',
|
|
18
18
|
TYPESCRIPT: 'typescript', // must run before SAMPLE, as that influences whether .js or .ts files are created
|
|
19
19
|
EXTENSION: 'extension',
|
|
20
|
-
SAMPLES: 'samples', // deprecated
|
|
21
|
-
TINY_SAMPLE: 'tiny-sample',
|
|
22
|
-
SAMPLE: 'sample',
|
|
23
|
-
HANDLER: 'handler', // influenced by esm, typer and typescript
|
|
24
20
|
MTA: 'mta',
|
|
25
21
|
CF_MANIFEST: 'cf-manifest',
|
|
26
22
|
HELM: 'helm',
|
|
27
23
|
HELM_UNIFIED_RUNTIME: 'helm-unified-runtime',
|
|
28
24
|
CONTAINERIZE: 'containerize',
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
SAMPLES: 'samples', // deprecated
|
|
26
|
+
TINY_SAMPLE: 'tiny-sample',
|
|
27
|
+
SAMPLE: 'sample',
|
|
28
|
+
HANDLER: 'handler', // influenced by esm, typer and typescript
|
|
29
|
+
TEST: 'test', // needs sample code
|
|
34
30
|
XSUAA: 'xsuaa',
|
|
35
31
|
IAS: 'ias',
|
|
36
32
|
AMS: 'ams',
|
|
37
33
|
HANA: 'hana',
|
|
38
34
|
POSTGRES: 'postgres',
|
|
39
35
|
SQLITE: 'sqlite',
|
|
40
|
-
H2: 'h2',
|
|
41
36
|
LIQUIBASE: 'liquibase',
|
|
42
37
|
REDIS: 'redis',
|
|
38
|
+
H2: 'h2',
|
|
39
|
+
MULTITENANCY: 'multitenancy',
|
|
40
|
+
TOGGLES: 'toggles',
|
|
41
|
+
EXTENSIBILITY: 'extensibility',
|
|
42
|
+
SIDE_BY_SIDE_EXTENSIBILITY: 'side-by-side-extensibility',
|
|
43
|
+
MTX: 'mtx',
|
|
43
44
|
ATTACHMENTS: 'attachments',
|
|
44
45
|
MALWARE_SCANNER: 'malware-scanner',
|
|
45
46
|
LOCAL_MESSAGING: 'local-messaging',
|
package/lib/init/index.js
CHANGED
|
@@ -60,7 +60,13 @@ module.exports = class CDSGenerator {
|
|
|
60
60
|
* @param {any} options, additional options
|
|
61
61
|
*/
|
|
62
62
|
async add(facets) {
|
|
63
|
-
if (!facets?.length)
|
|
63
|
+
if (!facets?.length) {
|
|
64
|
+
const cli = require('../../bin/cds');
|
|
65
|
+
const help = await cli?.load('add', () => ({ help: '' }))?.help ?? '';
|
|
66
|
+
console.log (require('../../bin/help').formatHelp(help))
|
|
67
|
+
process.exitCode=0
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
64
70
|
|
|
65
71
|
this._initialize(null);
|
|
66
72
|
this._greetings();
|
|
@@ -88,13 +94,16 @@ module.exports = class CDSGenerator {
|
|
|
88
94
|
async stepInit(projectName, options) { // Also used by CAP Generator
|
|
89
95
|
if (options) {
|
|
90
96
|
// called from CAP generator with options
|
|
97
|
+
// cds.cli is not set correctly when called from CAP generator
|
|
98
|
+
// so set defaults here
|
|
91
99
|
cds.cli = {
|
|
92
100
|
command: COMMAND_INIT,
|
|
93
101
|
// keep caller independent from internal names
|
|
94
102
|
options: {
|
|
95
103
|
cwd: options.cwd,
|
|
96
104
|
add: new Set(options.add)
|
|
97
|
-
}
|
|
105
|
+
},
|
|
106
|
+
argv:[]
|
|
98
107
|
}
|
|
99
108
|
|
|
100
109
|
// must be called after above code to ensure cds.cli.options.add is set
|
|
@@ -151,11 +160,33 @@ module.exports = class CDSGenerator {
|
|
|
151
160
|
for (const [i, facet] of Object.entries(sorted)) {
|
|
152
161
|
if (!cds.cli.options.dry) console.log(`adding ${term.bold(facet)}`)
|
|
153
162
|
const template = this.templateList[i]
|
|
154
|
-
await template.run()
|
|
155
|
-
await template.combine()
|
|
156
|
-
|
|
163
|
+
await template.run()
|
|
164
|
+
await template.combine()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
DEBUG && console.log()
|
|
168
|
+
DEBUG && console.log('plugins active for production:')
|
|
169
|
+
const fromDk = readdirSync(join(__dirname, './template'))
|
|
170
|
+
const { registered } = require('./add')
|
|
171
|
+
const { env4 } = require('./projectReader')
|
|
172
|
+
const processPlugins = async (plugins) => {
|
|
173
|
+
const cmds = Object.values(OPTIONS)
|
|
174
|
+
const byPriority = (a, b) => cmds.indexOf(a) - cmds.indexOf(b)
|
|
175
|
+
const sorted = Array.from(plugins).sort(byPriority)
|
|
176
|
+
for (const plugin of sorted) {
|
|
177
|
+
const Plugin = registered.get(plugin) ?? require('./template/' + plugin)
|
|
178
|
+
const template = new Plugin()
|
|
179
|
+
const inProduction = Plugin.hasInProduction(env4('production')) || cds.cli.argv.includes(plugin) || cds.cli.options.add?.has(plugin)
|
|
180
|
+
DEBUG && console.log(inProduction ? '✅' : '❌', plugin)
|
|
181
|
+
if (inProduction) await template.combine()
|
|
182
|
+
}
|
|
157
183
|
}
|
|
158
184
|
|
|
185
|
+
if (DEBUG) console.log(`\n ${fromDk.length} from @sap/cds-dk:`)
|
|
186
|
+
await processPlugins(fromDk)
|
|
187
|
+
if (DEBUG) console.log(`\n ${registered.size} from plugins:`)
|
|
188
|
+
await processPlugins(registered.keys())
|
|
189
|
+
|
|
159
190
|
if (cds.env['project-nature'] === 'java') {
|
|
160
191
|
console.log('updating frozen dependencies in package-lock.json…')
|
|
161
192
|
await cmd.spawnCommand('npm' , ['i', '--package-lock-only'], { cwd:cds.root })
|
package/lib/init/merge.js
CHANGED
|
@@ -255,9 +255,12 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
255
255
|
let node
|
|
256
256
|
if (inEntry && entryMap.get(inEntry)) {
|
|
257
257
|
node = entryMap.get(inEntry).node // starting from item found in nested array cache
|
|
258
|
-
} else {
|
|
258
|
+
} else if (typeof inEntry === 'string') {
|
|
259
259
|
node = collectionStack[collectionStack.length - 1] // starting from root
|
|
260
|
+
} else {
|
|
261
|
+
return
|
|
260
262
|
}
|
|
263
|
+
|
|
261
264
|
const keys = keyPath.split('.')
|
|
262
265
|
for (const key of keys.slice(0, -1)) {
|
|
263
266
|
if (!node?.get(key) && typeof inEntry === 'string') return // node doesn't exist, will be added by template
|
package/lib/init/plugin.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
const cds = require('../cds')
|
|
3
|
-
const { readdir } = cds.utils
|
|
4
|
-
|
|
5
1
|
module.exports = class Plugin {
|
|
6
2
|
|
|
7
3
|
/**
|
|
@@ -61,33 +57,4 @@ module.exports = class Plugin {
|
|
|
61
57
|
* Runs the finalize operations.
|
|
62
58
|
*/
|
|
63
59
|
async finalize() { }
|
|
64
|
-
|
|
65
|
-
/* ––––––––––––
|
|
66
|
-
Private APIs
|
|
67
|
-
–––––––––––– */
|
|
68
|
-
|
|
69
|
-
async combineSupported() {
|
|
70
|
-
const DEBUG = cds.log('cli|add')._debug
|
|
71
|
-
DEBUG && console.log()
|
|
72
|
-
DEBUG && console.log('plugins active for production:')
|
|
73
|
-
const fromDk = await readdir(join(__dirname, './template'))
|
|
74
|
-
const { registered } = require('./add')
|
|
75
|
-
const { env4 } = require('./projectReader')
|
|
76
|
-
const processPlugins = async (plugins) => {
|
|
77
|
-
for (const plugin of plugins) {
|
|
78
|
-
const Plugin = registered.get(plugin) ?? require('./template/' + plugin)
|
|
79
|
-
const template = new Plugin()
|
|
80
|
-
const inProduction = Plugin.hasInProduction(env4('production'))
|
|
81
|
-
DEBUG && console.log(inProduction ? '✅' : '❌', plugin)
|
|
82
|
-
if (inProduction) await template.combine()
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (DEBUG) console.log(`\n ${fromDk.length} from @sap/cds-dk:`)
|
|
87
|
-
await processPlugins(fromDk)
|
|
88
|
-
if (DEBUG) console.log(`\n ${registered.size} from plugins:`)
|
|
89
|
-
await processPlugins(registered.keys())
|
|
90
|
-
|
|
91
|
-
DEBUG && console.log()
|
|
92
|
-
}
|
|
93
60
|
}
|
|
@@ -121,7 +121,7 @@ module.exports = new class ProjectReader {
|
|
|
121
121
|
const _isESM = () => pkgJson().type === 'module'
|
|
122
122
|
const _isTypescript = () => !!pkgJson().dependencies?.typescript || !!pkgJson().devDependencies?.typescript
|
|
123
123
|
const _hasTyper = () => !!pkgJson().dependencies?.['@cap-js/cds-typer'] || !!pkgJson().devDependencies?.['@cap-js/cds-typer']
|
|
124
|
-
const _inProd = plugin => require(`./template/${plugin}`).hasInProduction(env)
|
|
124
|
+
const _inProd = plugin => require(`./template/${plugin}`).hasInProduction(env) || cds.cli.argv.includes(plugin) || cds.cli.options.add?.has(plugin)
|
|
125
125
|
const _ui5 = () => pkgJson().sapux
|
|
126
126
|
const _uiEmbedded = () => exists(join(env.folders.app, 'xs-app.json'))
|
|
127
127
|
const _uiModule = () => !_uiEmbedded() && isdir(env.folders.app) && fs.readdirSync(resolve(cds.root, env.folders.app)).length > 0
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
{{#withTelemetry}}
|
|
2
3
|
"dependencies": {
|
|
3
4
|
"@cap-js/telemetry": ">=0",
|
|
4
5
|
"@grpc/grpc-js": "^1",
|
|
@@ -6,13 +7,19 @@
|
|
|
6
7
|
"@opentelemetry/exporter-metrics-otlp-grpc": "<0.200",
|
|
7
8
|
"@opentelemetry/host-metrics": "<0.200"
|
|
8
9
|
},
|
|
10
|
+
{{/withTelemetry}}
|
|
9
11
|
"cds": {
|
|
10
12
|
"requires": {
|
|
13
|
+
{{^withTelemetry}}
|
|
14
|
+
"cloud-logging": true
|
|
15
|
+
{{/withTelemetry}}
|
|
16
|
+
{{#withTelemetry}}
|
|
11
17
|
"[{{profile}}]": {
|
|
12
18
|
"telemetry": {
|
|
13
19
|
"kind": "to-cloud-logging"
|
|
14
20
|
}
|
|
15
21
|
}
|
|
22
|
+
{{/withTelemetry}}
|
|
16
23
|
}
|
|
17
24
|
}
|
|
18
25
|
}
|
|
@@ -7,7 +7,7 @@ const { srv4, mtxSidecar4, approuter } = require('../../registries/mta')
|
|
|
7
7
|
module.exports = class extends require('../../plugin') {
|
|
8
8
|
|
|
9
9
|
static hasInProduction(env) {
|
|
10
|
-
return env.requires?.telemetry?.kind === 'to-cloud-logging'
|
|
10
|
+
return env.requires?.telemetry?.kind === 'to-cloud-logging' || env.requires['cloud-logging']
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
options() {
|
|
@@ -24,15 +24,14 @@ module.exports = class extends require('../../plugin') {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
async run() {
|
|
27
|
-
const project = readProject(), {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
27
|
+
const project = readProject(), { isNodejs, isJava } = project
|
|
28
|
+
project.withTelemetry = cds.cli.options['with-telemetry'] || project.hasTelemetry
|
|
29
|
+
if (isNodejs) {
|
|
30
|
+
project.profile ??= 'production'
|
|
31
|
+
await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: project })
|
|
32
|
+
await sort('package.json', 'dependencies')
|
|
33
|
+
} else if (isJava) {
|
|
34
|
+
await merge(__dirname, 'files/java-cdsrc.json.hbs').into('.cdsrc.json', { with: project })
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
@@ -184,7 +184,7 @@ function dataForField(element, artifact, csn, record, data, parent, depth, refer
|
|
|
184
184
|
if (element.key) {
|
|
185
185
|
str = `${artifact.name.split('.').pop()}-${record['$id']}`
|
|
186
186
|
if (element.name === 'locale' && artifact.name.endsWith('texts')) {
|
|
187
|
-
const record = randomFromReferenceData(artifact, csn, referenceData)
|
|
187
|
+
const record = asJson.randomFromReferenceData(artifact, csn, referenceData)
|
|
188
188
|
if (record) return record.locale
|
|
189
189
|
return randomLanguage()
|
|
190
190
|
}
|
|
@@ -273,7 +273,7 @@ function dataForField(element, artifact, csn, record, data, parent, depth, refer
|
|
|
273
273
|
if (!target || depth > MAX_ASSOC_DEPTH)
|
|
274
274
|
return
|
|
275
275
|
|
|
276
|
-
let targetRecord = randomFromReferenceData(target, csn, referenceData)
|
|
276
|
+
let targetRecord = asJson.randomFromReferenceData(target, csn, referenceData)
|
|
277
277
|
if (targetRecord) {
|
|
278
278
|
delete data[target.name] // indicate that existing data is used and no new data shall be created
|
|
279
279
|
delete data[target.name + '.texts'] // also delete associated texts entity
|
|
@@ -318,7 +318,7 @@ function dataForField(element, artifact, csn, record, data, parent, depth, refer
|
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
asJson.randomFromReferenceData = function(entity, csn, referenceData) {
|
|
322
322
|
const files = Object.entries(referenceData)
|
|
323
323
|
.filter(([, name]) => matchesEntityOrProjection(name, entity, csn))
|
|
324
324
|
.map(([file]) => file)
|
|
@@ -13,8 +13,9 @@ module.exports = class HanaTemplate extends require('../../plugin') {
|
|
|
13
13
|
return 'database support for SAP HANA'
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
static hasInProduction() {
|
|
17
|
-
|
|
16
|
+
static hasInProduction(env) {
|
|
17
|
+
const { dependencies, isJava } = readProject()
|
|
18
|
+
return dependencies?.['@cap-js/hana'] || isJava && env.requires?.db?.kind === 'hana'
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
async run() {
|
|
@@ -94,7 +94,7 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
94
94
|
if (hasMultitenancy) {
|
|
95
95
|
relationships.push({
|
|
96
96
|
insert: [html5Runtime, 'name'],
|
|
97
|
-
into: [
|
|
97
|
+
into: [isJava ? srv : mtxSidecar4('gen/mtx/sidecar'), 'requires', 'name']
|
|
98
98
|
})
|
|
99
99
|
}
|
|
100
100
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|