@sap/cds-dk 8.1.2 → 8.2.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/bin/bind.js +44 -11
  3. package/bin/cds-tsx.js +2 -0
  4. package/bin/cds.js +5 -3
  5. package/bin/compile/index.js +2 -1
  6. package/bin/deploy/index.js +19 -1
  7. package/bin/import.js +13 -4
  8. package/bin/init.js +1 -1
  9. package/bin/version.js +1 -0
  10. package/bin/watch.js +2 -2
  11. package/lib/bind/bindingManager.js +1 -1
  12. package/lib/bind/cfKeyProvider.js +1 -1
  13. package/lib/build/buildTaskProviderFactory.js +9 -3
  14. package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +1 -1
  15. package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +1 -1
  16. package/lib/build/plugins/helm/files/subcharts/service-instance/Chart.yaml +1 -1
  17. package/lib/build/plugins/helm/files/subcharts/service-instance/values.yaml +1 -1
  18. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
  19. package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +2 -2
  20. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +1 -1
  21. package/lib/build/provider/hana/2migration.js +2 -2
  22. package/lib/build/provider/nodejs/index.js +5 -4
  23. package/lib/build/util.js +2 -1
  24. package/lib/compile/to-mermaid.js +4 -6
  25. package/lib/import/common.js +16 -18
  26. package/lib/import/message.js +6 -5
  27. package/lib/import/odata/index.js +1 -1
  28. package/lib/import/odata/v2parser.js +18 -17
  29. package/lib/import/odata/v4parser.js +62 -62
  30. package/lib/init/constants.js +3 -2
  31. package/lib/init/mvn.js +43 -6
  32. package/lib/init/plugin.js +1 -1
  33. package/lib/init/projectReader.js +1 -1
  34. package/lib/init/template/approuter/files/containerize.yaml.hbs +5 -0
  35. package/lib/init/template/cloud-logging/files/mta.yaml.hbs +25 -0
  36. package/lib/init/template/cloud-logging/files/package.json +14 -0
  37. package/lib/init/template/cloud-logging/index.js +80 -0
  38. package/lib/init/template/containerize/files/containerize.yaml.hbs +5 -0
  39. package/lib/init/template/dynatrace/files/mta.yaml.hbs +24 -0
  40. package/lib/init/template/dynatrace/files/package.json.hbs +14 -0
  41. package/lib/init/template/dynatrace/files/sidecar.package.json +0 -0
  42. package/lib/init/template/dynatrace/index.js +55 -0
  43. package/lib/init/template/hana/files/containerize.yaml.hbs +5 -0
  44. package/lib/init/template/hana/files/package.json.hbs +5 -3
  45. package/lib/init/template/handler/index.js +22 -0
  46. package/lib/init/template/helm/index.js +5 -1
  47. package/lib/init/template/html5-repo/index.js +5 -0
  48. package/lib/init/template/http/index.js +1 -1
  49. package/lib/init/template/java/index.js +2 -2
  50. package/lib/init/template/multitenancy/files/containerize.yaml.hbs +5 -0
  51. package/lib/init/template/portal/files/portal-site/CommonDataModel.json.hbs +2 -2
  52. package/lib/init/template/portal/files/values.yaml.hbs +43 -0
  53. package/lib/init/template/portal/index.js +4 -2
  54. package/lib/init/template/telemetry/index.js +19 -0
  55. package/lib/init/template/typescript/files/package.json +1 -3
  56. package/lib/mtx/auth_manager.js +12 -15
  57. package/lib/mtx/settings_manager.js +1 -1
  58. package/lib/mtx/util/logging.js +4 -4
  59. package/lib/util/cf.js +15 -5
  60. package/lib/util/command.js +3 -3
  61. package/lib/watch/livereload-server.js +3 -3
  62. package/lib/watch/node-watch.js +3 -3
  63. package/npm-shrinkwrap.json +17 -16
  64. package/package.json +3 -2
  65. package/readme.md +2 -2
package/CHANGELOG.md CHANGED
@@ -7,6 +7,43 @@ This project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
  The format is based on [Keep a Changelog](http://keepachangelog.com/).
9
9
 
10
+ ## Version 8.2.0 - 2024-09-02
11
+
12
+ ### Added
13
+
14
+ - `cds add dynatrace` adds configuration for Dynatrace.
15
+ - `cds add cloud-logging` adds configuration for SAP Cloud Logging. Option `--with-telemetry` allows for configuration with telemetry.
16
+ - `cds version` shows version information for `@cap-js/db-service`.
17
+ - `cds add portal` now adds portal configuration for Kyma.
18
+ - `cds add handler` allows to create handler stubs (for Java only, beta)
19
+ - `cds init --add java --no-db` lets you create a Java project without persistent database.
20
+ - `cds import` supports plugins.
21
+ - `cds add containerize` now supports unified-runtime.
22
+ - `cds add helm` now supports templating in the mountPath in the additionalVolumes.
23
+ - Experimental support for `tsx` through `cds-tsx`.
24
+ - `cds bind --to-app-services` now uses `vcap.name` to resolve multiple services with same type. A warning is issued in case of ambiguities.
25
+ - `cds compile --to ord -o <name>` supports `.json` file extension.
26
+ - `cds import --destination` applies destination credentials to existing service configurations.
27
+
28
+ ### Changed
29
+
30
+ - `cds add hana` writes configuration for `cds build/compile` to no longer produce native SAP HANA associations. This improves deployment performance, but has a one-time performance penalty (in the next deployment).
31
+ - `cds login` prints shorter messages about refresh tokens.
32
+ - `cds init` uses latest Maven Java archetype version 3.2.0 for creating Java projects.
33
+
34
+ ### Fixed
35
+
36
+ - `cds import` fix for single entity schema in OData V2.
37
+ - `cds add portal` correctly sets the `appId` in its `CommonDataModel.json` from the `manifest.json` app ID.
38
+ - `cds add html5-repo` adds the SAP BTP Destination service as a hard dependency again for Kyma projects.
39
+ - `cds build --ws-pack` correctly creates tarball archives for workspaces with nested `node_modules` folders.
40
+ - `cds import` now shows proper error message in case of bound action collision.
41
+ - `cds deploy --to hana` now runs an existing `hana` build task configuration instead of a default one.
42
+
43
+ ### Removed
44
+
45
+ - Removed `build` and `build:ts` npm scripts that were generated into `package.json` when adding the `typescript` facet.
46
+
10
47
  ## Version 8.1.2 - 2024-08-17
11
48
 
12
49
  ### Fixed
@@ -201,6 +238,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
201
238
 
202
239
  - `cds add notebook` is removed. CAP Jupyter Notebooks have been replaced by custom CAP Notebooks for VS Code which are now part of the CDS Editor. See https://cap.cloud.sap/docs/tools/#add-cds-editor for more.
203
240
 
241
+
242
+ ## Version 7.9.7 - 2024-08-22
243
+
244
+ ### Fixed
245
+
246
+ - Dependency update for `axios` to fix CVE-2024-39338
247
+ - `cds build --for mtx-sidecar` now correctly supports different `srv` folder name.
248
+ - `cds build --ws-pack` correctly creates tarball archives for workspaces with nested `node_modules` folders.
249
+ - `cds version` now reports the correct version of `@sap/cds` if this one is installed locally along with a local `@sap/cds-dk` installation.
250
+ - `cds version -i` does not show a globally installed version when none is installed or linked.
251
+ - `cds version` reports correct `@sap/cds-compiler` version.
252
+ - `cds version` can skip over check for Java version
253
+
204
254
  ## Version 7.9.6 - 2024-07-19
205
255
 
206
256
  ### Fixed
package/bin/bind.js CHANGED
@@ -110,6 +110,16 @@ async function cds_bind(args, options) {
110
110
  throw `Option ${term.bold('--credentials')} requires a JSON object or a file path.`;
111
111
  }
112
112
 
113
+ if (!to && !app) {
114
+ // we currently don't support binding to a service without specifying the target instance
115
+ // const cds = require('../lib/cds');
116
+ // if (args[0] && cds.env.requires[args[0]]?.vcap?.name) {
117
+ // options.to = cds.env.requires[args[0]].vcap.name
118
+ // } else {
119
+ throw `Use option ${term.bold('--to')} or ${term.bold('-2')} to specify the target instance, e.g. ${term.bold('cds bind --to myInstance:myService')}`;
120
+ // }
121
+ }
122
+
113
123
  // read credentials from file if it is a file, from JSON if it is JSON
114
124
  if (credentials) {
115
125
  let credentialsJson = options.credentials;
@@ -137,10 +147,6 @@ async function cds_bind(args, options) {
137
147
  }
138
148
  }
139
149
 
140
- if (!to && !app) {
141
- throw `Use option ${term.bold('--to')} or ${term.bold('-2')} to specify the target instance, e.g. ${term.bold('cds bind --to myInstance:myService')}`;
142
- }
143
-
144
150
  if (app === true) {
145
151
  throw `Option ${term.bold('--to-app-services')} requires an app name, for example ${term.bold('cds bind --to-app-services bookshop-srv')}.`
146
152
  }
@@ -148,13 +154,40 @@ async function cds_bind(args, options) {
148
154
  options.for ??= 'hybrid';
149
155
 
150
156
  if (app) {
151
- const services = await require('../lib/util/cf').getServices(app)
152
- const allServices = await Promise.all(
153
- services
154
- .filter(s => Object.keys(s.credentials).length > 0)
155
- .map(s => bind({ ...options, to: s.name, out }))
156
- )
157
- await storeBindings(allServices.flat(), options);
157
+ const cds = require('../lib/cds');
158
+ const resolvedServices = [], unresolvedServices = {}
159
+ const services = (await require('../lib/util/cf').getServices(app)).filter(s => Object.keys(s.credentials).length > 0)
160
+
161
+ services.forEach(service => {
162
+ const type = service.label || service.type;
163
+ const requiredServiceEntry = Object.entries(cds.env.requires).find(([, requiredService]) => requiredService.kind === type && requiredService?.vcap?.name === service.name)
164
+ if (requiredServiceEntry) {
165
+ resolvedServices.push({ options: { ...options, ...{ to: service.name, serviceArg: requiredServiceEntry[0] } } })
166
+ } else {
167
+ // check whether we can resolve this service
168
+ // multiple services of the same type cannot be resolved
169
+ if (services.some(s => (s.label || s.type) === type && s.name != service.name)) {
170
+ unresolvedServices[type] ??= [];
171
+ unresolvedServices[type].push(service);
172
+ } else {
173
+ resolvedServices.push({ options: { ...options, ...{ to: service.name } } })
174
+ }
175
+ }
176
+ })
177
+
178
+ const resolvedServiceBindings = (await Promise.all(resolvedServices.map(service => bind(service.options, service.options.to, out)))).flat();
179
+
180
+ if (resolvedServiceBindings.length > 0) {
181
+ await storeBindings(resolvedServiceBindings, options);
182
+ }
183
+
184
+ Object.values(unresolvedServices)
185
+ .filter(services => services.length > 1)
186
+ .forEach(services => {
187
+ console.warn(`Found multiple service instances of the same type ${services[0].label || services[0].type}. This is not supported.`);
188
+ console.warn('Instead, bind each service individually, e.g.:');
189
+ services.forEach((service, idx) => console.warn(` cds bind <your local service name ${idx + 1}> --to ${service.name}`));
190
+ });
158
191
  } else {
159
192
  if (args.length > 1) {
160
193
  throw 'Too many arguments: Please specify only one or no service.';
package/bin/cds-tsx.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env tsx
2
+ require('./cds').apply(process.argv)
package/bin/cds.js CHANGED
@@ -215,9 +215,11 @@ function _require (id,o) {
215
215
  return require (resolved)
216
216
  }
217
217
 
218
- if (process[Symbol.for('ts-node.register.instance')]) {
219
- process.env.CDS_TYPESCRIPT = process.env.CDS_TYPESCRIPT || 'true'
220
- }
218
+ const { sep } = require ('path')
219
+ if (process[Symbol.for('ts-node.register.instance')])
220
+ process.env.CDS_TYPESCRIPT = 'ts-node'
221
+ else if (process._preload_modules?.some(m => m?.includes(`${sep}tsx${sep}`)))
222
+ process.env.CDS_TYPESCRIPT = 'tsx'
221
223
 
222
224
  module.exports = Object.assign ((..._) => cli.exec(..._), cli)
223
225
 
@@ -345,7 +345,8 @@ async function compile (models, options={}) {
345
345
  sql: '.sql',
346
346
  edm: '.json',
347
347
  asyncapi: '.json',
348
- xsuaa: '.json'
348
+ xsuaa: '.json',
349
+ ord: '.json'
349
350
  }[x] || '.'+x) }
350
351
 
351
352
  }
@@ -1,6 +1,6 @@
1
1
  module.exports = Object.assign(deploy, {
2
2
  options: ['--to', '--for', '--tunnel-address', '--vcap-file', '--delta-from' ],
3
- flags: ['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--model-only', '--with-auto-schema-evolution' ],
3
+ flags: ['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--model-only', '--script', '--with-auto-schema-evolution' ],
4
4
  shortcuts: ['-2', '-4'],
5
5
  help: `
6
6
  # SYNOPSIS
@@ -81,6 +81,12 @@ module.exports = Object.assign(deploy, {
81
81
  *cds deploy --model-only --dry*. When used with *--dry* it writes the
82
82
  generated SQL to stdout.
83
83
 
84
+ *--script
85
+
86
+ This is a schema evolution option to be used with --delta-from to generate
87
+ a script of SQL statements to then check and execute manually or for usage with tools such as LiquiBase.
88
+ This script might contain potentially lossy statements!
89
+
84
90
 
85
91
  # EXAMPLES
86
92
  cds deploy --to sqlite:db
@@ -127,7 +133,11 @@ async function deploy(_model, options) { // NOSONAR
127
133
  }
128
134
  }
129
135
  try {
136
+ options.messages = []
137
+ if(options.script) options.dry = true // to ensure that we don't accidentally execute any SQLs
130
138
  await deployer.deploy(_model, _db, options)
139
+ const log = this.log || _log
140
+ if (options.messages.length) log (options.messages, options)
131
141
  } catch (e) {
132
142
  if (e.code === 'MODEL_NOT_FOUND') {
133
143
  if (!_model) throw new Error('No .cds models found, please specify one as an argument')
@@ -135,3 +145,11 @@ async function deploy(_model, options) { // NOSONAR
135
145
  } else throw e
136
146
  }
137
147
  }
148
+
149
+ function _log (messages, options) {
150
+ const cds = require('../../lib/cds')
151
+ const { sortMessagesSeverityAware, deduplicateMessages } = cds.compiler
152
+ deduplicateMessages(messages)
153
+ messages = sortMessagesSeverityAware (messages)
154
+ cds._log (messages, options)
155
+ }
package/bin/import.js CHANGED
@@ -1,8 +1,8 @@
1
1
  module.exports = Object.assign(_import, {
2
2
  _name: 'import',
3
- options: ['--out', '--as', '--include-namespaces', '--from', '--config'],
3
+ options: ['--out', '--as', '--include-namespaces', '--from', '--config', '--destination'],
4
4
  flags: ['--dry', '--force', '--no-copy', '--no-save', '--keep-namespace', '--beta'],
5
- shortcuts: ['-o', '-as', '-ns', undefined, '-c', '-', '-f'],
5
+ shortcuts: ['-o', '-as', '-ns', undefined, '-c', undefined, '-', '-f'],
6
6
  help: `
7
7
  # SYNOPSIS
8
8
 
@@ -62,6 +62,9 @@ module.exports = Object.assign(_import, {
62
62
  For OData V2 attributes with the namespace "sap" & "m" are captured by
63
63
  default.
64
64
 
65
+ *--destination*
66
+ Destination name under which the remote service can be reached.
67
+ Not supported by import types "edmx", "openapi" or "asyncapi".
65
68
 
66
69
 
67
70
  # EXAMPLES
@@ -75,7 +78,7 @@ module.exports = Object.assign(_import, {
75
78
  cds import ~/Downloads/Petstore_OpenAPI.json --from openapi
76
79
  cds import ~/Downloads/BookStore_AsyncAPI.json
77
80
  cds import ~/Downloads/BookStore_AsyncAPI.json --from asyncapi
78
- cds import ~/Downloads/API_BUSINESS_PARTNER.edmx -c {\\"[production]\\":{\\"credentials\\":{\\"destination\\":\\"UI3_noauth\\",\\"path\\":\\"/sap/cap/odata\\"}}}
81
+ cds import ~/Downloads/API_BUSINESS_PARTNER.edmx -c "{\\"[production]\\":{\\"credentials\\":{\\"destination\\":\\"UI3_noauth\\",\\"path\\":\\"/sap/cap/odata\\"}}}"
79
82
 
80
83
  `})
81
84
  const messages = require('../lib/import/message').getMessages();
@@ -93,10 +96,16 @@ async function _import(file, options = {}) {
93
96
  await common.processOptions(options, apiOptions);
94
97
  const srcFilePath = await common.preProcess(file, options, cwd);
95
98
 
99
+ const cds = require('../lib/cds')
100
+ await cds.plugins
101
+
96
102
  // process - csn generation
97
103
  // if --from option is given, call api directly accordingly
98
104
  if (options.from) {
99
- if (!cdsImport.import.from[options.from]) throw new Error(messages.INVALID_FROM_OPTION);
105
+ if (!cdsImport.import.from[options.from]) {
106
+ // the required plugin might not be installed, e.g. rfc importer
107
+ throw messages.UNSUPPORTED_FROM_OPTION;
108
+ }
100
109
  csn = await cdsImport.import.from[options.from](srcFilePath, apiOptions);
101
110
  } else {
102
111
  csn = await cdsImport.import(srcFilePath, apiOptions);
package/bin/init.js CHANGED
@@ -7,7 +7,7 @@ cds.root = join(process.cwd(), process.argv[3]?.startsWith('--') ? '.' : process
7
7
 
8
8
  module.exports = Object.assign(init, {
9
9
  handleCompletion,
10
- options: ['--add', '--java:mvn', '--java:package', '--lint:custom', '--lint:custom:example'],
10
+ options: ['--add', '--java:mvn', '--java:package', '--lint:custom', '--lint:custom:example', '--no-db'],
11
11
  shortcuts: ['-a'],
12
12
  flags: ['--force', '--verbose'],
13
13
  help: `
package/bin/version.js CHANGED
@@ -75,6 +75,7 @@ function info({ root:cwd=process.cwd() }) {
75
75
  ..._versions_from(_pkg_path('@sap/cds-dk', cwd)), // local dk, important for Java projects
76
76
  ..._versions_from(_pkg_path('@sap/cds', __dirname)), // @sap/cds from here
77
77
  ..._versions_from(_pkg_path('@sap/cds', cds.home)), // ... or local @sap/cds
78
+ ..._versions_from(_pkg_path('@cap-js/db-service', cwd)), // only required transitively
78
79
  ..._versions_from(cwd), // ... more from local app dependencies
79
80
  '@sap/cds-compiler': cds.compiler.version(),
80
81
  'Node.js': process.version,
package/bin/watch.js CHANGED
@@ -49,7 +49,7 @@ module.exports = Object.assign ( watch, {
49
49
  `})
50
50
 
51
51
  const cds = require('../lib/cds')
52
- const DEBUG = cds.debug('cli|watch')
52
+ const DEBUG = cds.log('cli|watch')._debug
53
53
  const {delimiter,dirname,relative,resolve,sep} = require ('path')
54
54
  const {codes} = require('../lib/util/term'), t = codes
55
55
  const fs = require ('fs')
@@ -90,7 +90,7 @@ async function watch ([cwd], {
90
90
  _args: JSON.stringify(args),
91
91
  _options: JSON.stringify(options)
92
92
  })
93
- if (process.env.CDS_TYPESCRIPT) {
93
+ if (process.env.CDS_TYPESCRIPT === 'ts-node' || process.env.CDS_TYPESCRIPT === 'true') {
94
94
  // Needed by ts-node/tsc to find the tsconfig.json. Same as `--project`.
95
95
  env.TS_NODE_PROJECT = env.TS_NODE_PROJECT ?? _cwd
96
96
  }
@@ -1,7 +1,7 @@
1
1
  const bindingResolver = require('./bindingResolver')
2
2
  const { logger } = require('./bindingUtil')
3
3
  const cds = require('../cds')
4
- const DEBUG = cds.debug('cli') // REVISIT: This loads cds.env too early!
4
+ const DEBUG = cds.log('cli')._debug // REVISIT: This loads cds.env too early!
5
5
 
6
6
  class BindingManager {
7
7
  constructor(options = {}) {
@@ -1,5 +1,5 @@
1
1
  const cds = require('../cds');
2
- const DEBUG = cds.debug('cli')
2
+ const DEBUG = cds.log('cli')._debug
3
3
 
4
4
  const cfUtil = require('../util/cf');
5
5
  const { bold } = require('../util/term');
@@ -4,7 +4,7 @@ const cds = require('../cds')
4
4
  const { OUTPUT_MODE_FILESYSTEM, DEFAULT_SRC_FOLDER } = require('./constants')
5
5
  const InternalBuildTaskProvider = require('./provider/internalBuildTaskProvider')
6
6
  const BuildTaskProvider = require('./buildTaskProvider')
7
- const { BuildError } = require('./util')
7
+ const { BuildError, normalizePath } = require('./util')
8
8
  const DEBUG = cds.debug('cli|build')
9
9
 
10
10
  class BuildTaskProviderFactory {
@@ -14,8 +14,14 @@ class BuildTaskProviderFactory {
14
14
  options.clean = true
15
15
  }
16
16
  ['for', 'src', 'dest'].forEach(key => {
17
- if (options[key] && typeof options[key] !== 'string') {
18
- throw new BuildError(`Invalid build options - property '${key}' must be a string`)
17
+ if (options[key]) {
18
+ if (typeof options[key] !== 'string') {
19
+ throw new BuildError(`Invalid build options - property '${key}' must be a string`)
20
+ }
21
+ if (key === 'src' || key === 'dest') {
22
+ // normalize path separator and remove trailing slash
23
+ options[key] = normalizePath(options[key])
24
+ }
19
25
  }
20
26
  })
21
27
  this._context = { options, tasks: [] } // resolved tasks
@@ -2,4 +2,4 @@ apiVersion: v2
2
2
  description: A Helm Chart for creating a Content Deployment job
3
3
  name: content-deployment
4
4
  type: application
5
- version: 1.6.1
5
+ version: 1.6.2
@@ -15,7 +15,7 @@ global:
15
15
  _internal:
16
16
  content-deployment:
17
17
  versions:
18
- 1.6.1: true
18
+ 1.6.2: true
19
19
  # Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
20
20
  # nameOverride: name
21
21
 
@@ -2,4 +2,4 @@ apiVersion: v2
2
2
  description: A Helm chart for creating service instances on btp-service-operator
3
3
  name: service-instance
4
4
  type: application
5
- version: 1.5.1
5
+ version: 1.5.2
@@ -65,4 +65,4 @@ global:
65
65
  _internal:
66
66
  service-instance:
67
67
  versions:
68
- 1.5.1: true
68
+ 1.5.2: true
@@ -3,4 +3,4 @@ description: A Helm chart for web app
3
3
  kubeVersion: '>= 1.21'
4
4
  name: web-application
5
5
  type: application
6
- version: 1.16.0
6
+ version: 1.17.0
@@ -83,7 +83,7 @@ spec:
83
83
  mountPath: /bindings
84
84
  {{- range $volume := .Values.additionalVolumes }}
85
85
  - name: {{ $volume.name | quote }}
86
- {{- toYaml $volume.volumeMount | nindent 10 }}
86
+ {{- tpl ($volume.volumeMount | toYaml) $ | nindent 10 }}
87
87
  {{- end }}
88
88
  {{- include "web-application.internal.serviceMounts" . | nindent 8 }}
89
89
  resources:
@@ -136,7 +136,7 @@ spec:
136
136
  mountPath: /bindings
137
137
  {{- range $volume := $.Values.additionalVolumes }}
138
138
  - name: {{ $volume.name | quote }}
139
- {{- toYaml $volume.volumeMount | nindent 10 }}
139
+ {{- tpl ($volume.volumeMount | toYaml) $ | nindent 10 }}
140
140
  {{- end }}
141
141
  {{- include "web-application.internal.serviceMounts" $ | nindent 8 }}
142
142
  {{- if $sidecar.resources }}
@@ -15,7 +15,7 @@ global:
15
15
  _internal:
16
16
  web-application:
17
17
  versions:
18
- 1.16.0: true
18
+ 1.17.0: true
19
19
  ## Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
20
20
  # nameOverride: name
21
21
 
@@ -5,7 +5,7 @@ const { SEVERITY_WARNING } = require('../../constants')
5
5
  const cds = require('../../../cds'), { compiler: cdsc } = cds
6
6
  const cdscVersion = `-- generated by cds-compiler version ${cdsc.version()}`
7
7
  const { getArtifactCdsPersistenceName } = cdsc
8
- const DEBUG = cds.debug('cli|build')
8
+ const LOG = cds.log('cli|build'), DEBUG = cds.debug('cli|build')
9
9
 
10
10
  module.exports = async (model, beforeImage, srcPath, options = {}) => {
11
11
  const { definitions, migrations, afterImage, journalFileNames } = _compileToHana(model, options, beforeImage)
@@ -204,7 +204,7 @@ function _isPersistedAsJournalTable(artifact) {
204
204
  }
205
205
 
206
206
  function _debug(definitions, migrations, journalFileNames) {
207
- if (DEBUG) {
207
+ if (LOG._debug) {
208
208
  DEBUG('compile.to.hana returned')
209
209
  for (const { name, suffix, sql } of definitions) {
210
210
  if (suffix === '.hdbtable' && journalFileNames.has(name)) {
@@ -5,10 +5,10 @@ const cmd = require('../../../util/command');
5
5
  const EdmxBuildPlugin = require('../edmxBuildPlugin')
6
6
  const { BuildError, getWorkspaces } = require('../../util')
7
7
  const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTENT_EDMX, CONTENT_PACKAGELOCK_JSON,
8
- CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX,
8
+ CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX,
9
9
  OPTION_WS_PACK} = require('../../constants')
10
10
  const { WARNING } = EdmxBuildPlugin
11
- const DEBUG = cds.debug('cli|build')
11
+ const LOG = cds.log('cli|build'), DEBUG = cds.debug('cli|build')
12
12
 
13
13
  class NodejsBuildPlugin extends EdmxBuildPlugin {
14
14
  init() {
@@ -166,6 +166,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
166
166
  if (this.task.options.workspaces) {
167
167
  workspaces = Array.isArray(this.task.options.workspaces) ? this.task.options.workspaces : [this.task.options.workspaces]
168
168
  } else {
169
+ // devDependencies are not considered
169
170
  workspaces = await getWorkspaces(true, false, wsRoot);
170
171
  }
171
172
  if (workspaces.length) {
@@ -204,7 +205,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
204
205
  } catch (err) {
205
206
  // ignore
206
207
  }
207
- if (fs.existsSync(path.join(dir, '.gitmodules')) || fs.existsSync(path.join(dir, 'node_modules'))) {
208
+ if (fs.existsSync(path.join(dir, '.gitmodules'))) {
208
209
  return // project root reached
209
210
  }
210
211
  if (path.dirname(dir) !== dir) {
@@ -217,7 +218,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
217
218
  workspaces.forEach(w => args.push(`-w=${w}`))
218
219
 
219
220
  DEBUG?.(`execute command: npm ${args.join(', ')}`)
220
- const result = await cmd.spawnCommand('npm', args, { cwd: wsRoot }, true, !!DEBUG)
221
+ const result = await cmd.spawnCommand('npm', args, { cwd: wsRoot }, true, !!LOG._debug)
221
222
  DEBUG?.(result)
222
223
  return JSON.parse(result)
223
224
  }
package/lib/build/util.js CHANGED
@@ -190,7 +190,8 @@ async function getWorkspaces(resolve = false, devDependencies = true, wsRoot = c
190
190
  // read npm workspaces
191
191
  const pkgs = await _execNpmWs(wsRoot)
192
192
  pkgs.forEach(pkg => {
193
- if (!resolve || devDependencies && pgkJson.devDependencies?.[pkg] || pgkJson.dependencies?.[pkg]) {
193
+ // only create tarball archives for dependencies with version '*'
194
+ if (!resolve || devDependencies && pgkJson.devDependencies?.[pkg] === '*' || pgkJson.dependencies?.[pkg] === '*') {
194
195
  const workspace = _getWorkspace(wsRoot, pkg)
195
196
  if (workspace) {
196
197
  workspaces.push(workspace)
@@ -35,12 +35,10 @@ module.exports = function to_mermaid (model, options={}) {
35
35
  .filter (srv => !srvFilter || srv.name === srvFilter)
36
36
  .forEach(srv => {
37
37
  namespaces[srv.name] = []
38
- model.entities(srv)
39
- .filter (entityFilter)
40
- .forEach (e => {
38
+ for (let e of model.entities(srv)) if (entityFilter(e)) {
41
39
  namespaces[srv.name].push(e)
42
40
  seenEntities.add(e.name)
43
- })
41
+ }
44
42
  })
45
43
 
46
44
  // group other namespaces/services
@@ -69,7 +67,7 @@ module.exports = function to_mermaid (model, options={}) {
69
67
  diag += `["${simpleName}"]` // simple name as label
70
68
  if (elemOpts) {
71
69
  diag += ` {\n`
72
- e.elements?.forEach (el => {
70
+ if (e.elements) [...e.elements].forEach (el => {
73
71
  if ((elemOpts === 'all' || elemOpts === true) || (el.key && elemOpts == 'keys')) {
74
72
  diag += ` +${el._type?.replace('cds.','')} ${el.name}`
75
73
  diag += `\n`
@@ -90,7 +88,7 @@ module.exports = function to_mermaid (model, options={}) {
90
88
  : model.all('entity').filter (entityFilter) // if no grouping and no service filter is on
91
89
  entities.forEach(e => {
92
90
  if (!diag.length) diag = `classDiagram\n${direction}`
93
- e.elements?.forEach (el => {
91
+ if (e.elements) [...e.elements].forEach (el => {
94
92
  if (el instanceof cds.Association) {
95
93
  if (el.target.endsWith('.texts')) return
96
94
  const type = el.type === 'cds.Composition' ? '*-->' : '-->'
@@ -239,7 +239,7 @@ async function _generateChecksumValidate(dest, output, force) {
239
239
  }
240
240
  }
241
241
 
242
- // if force flag enbabled
242
+ // if force flag enabled
243
243
  if (force) {
244
244
  // current and existing file content are same, and the existing
245
245
  // checksum is not modified, then return the existing file content
@@ -296,12 +296,12 @@ async function _getResult(output, as, dest, force, kind) {
296
296
  }
297
297
 
298
298
  async function _write(result, service, cwd) {
299
- let dest, output, using, message, extenstion;
299
+ let dest, output, using, message, extension;
300
300
  output = result[0];
301
301
  dest = result[1];
302
302
  await write(dest, output, "utf-8");
303
- extenstion = dest.substring(dest.lastIndexOf('.'));
304
- dest = dest.replace(extenstion, '');
303
+ extension = dest.substring(dest.lastIndexOf('.'));
304
+ dest = dest.replace(extension, '');
305
305
  if (service.length > 1){
306
306
  using = `using { ${service.join(', ')}} from './${path.relative('srv', dest).replace(/\\/g, '/')}'`;
307
307
  }
@@ -327,13 +327,11 @@ async function _updatePackageJson(dest, services, kind, cwd, config) {
327
327
  }
328
328
  let package_json_updated = false;
329
329
  for (let service of services) {
330
- if (!requires[service]) {
331
- const initial_model = path.relative(cwd, dest);
332
- const model = isLinux() ? initial_model.replace(/\\/g, '/') : initial_model;
333
- cds.env.requires[service] = requires[service] = { kind: kind, model, ...config };
334
- await write(package_json, JSON.stringify(conf, null, ' '));
335
- package_json_updated = true;
336
- }
330
+ // always update from given config data - e.g. delta imports may want to add service configuration data
331
+ const model = path.relative(cwd, dest).replace(/\\/g, '/'); // cds env must not be platform specific
332
+ cds.env.requires[service] = requires[service] = { kind: kind, model, ...config };
333
+ await write(package_json, JSON.stringify(conf, null, ' '));
334
+ package_json_updated = true;
337
335
  }
338
336
  if (package_json_updated) {
339
337
  console.log(`[cds] - updated ./package.json`);
@@ -353,6 +351,13 @@ function _parseValidJsonConfig(config) {
353
351
  async function postProcess(filePath, options, csn, cwd) {
354
352
  const services = _getServiceNames(csn);
355
353
  let config = _parseValidJsonConfig(options.config);
354
+
355
+ // add destination configuration
356
+ if (options.destination) {
357
+ config ??= {};
358
+ config.credentials = { destination: options.destination };
359
+ }
360
+
356
361
  const external = path.resolve(cwd, 'srv/external');
357
362
  const destFilePath = path.join(external, path.basename(filePath));
358
363
  if (options.out) options.out = _validateAndComputeOutputFilePath(options.out, options.as, destFilePath);
@@ -385,13 +390,6 @@ async function identifyFile(filepath) {
385
390
  return extension;
386
391
  }
387
392
 
388
- function isLinux() {
389
- let platform = process.platform;
390
- if (platform === 'linux' || platform === 'win32') {
391
- return true;
392
- }
393
- }
394
-
395
393
  function readEnvVariables(options, cliCheck) {
396
394
  if (cds.env.import) {
397
395
  if (cliCheck) {
@@ -12,6 +12,7 @@ const messages = {
12
12
  FILE_MODIFIED: 'The file with the same name exists and is been modified. Use --force flag to forcefully overwrite the file.',
13
13
  OUTPUT_FILE_MISMATCH: 'Specify the file extension that --as option supports.',
14
14
  INVALID_AS_OPTION: 'For --as option, please specify one of these output file format [cds, csn, json].',
15
+ UNSUPPORTED_FROM_OPTION: 'For --from option, please specify one of these types [edmx, openapi, asyncapi, rfc]. Make sure the required importer plugin is installed.',
15
16
  INCORRECT_EXTENSION: 'If --as option is not provided, then please provide either .json or .csn output file extension.',
16
17
  INCORRECT_INPUT_NAMESPACES: 'Invalid value for --include-namespaces option. Specify namespaces as comma-separated list or "*"',
17
18
  MISSING_ASSOCIATION: 'Association is missing in the input file provided. Please check the edmx file.',
@@ -22,14 +23,14 @@ const messages = {
22
23
  UNRESOLVED_TYPE: 'Could not resolve the type: ',
23
24
  NO_RETURN_TYPE: 'No ReturnType found in Function: ',
24
25
  INVALID_ENUM_TYPE: 'The Underlying type provided is not supported for the EnumType: ',
25
- UNBOUNDED_ACTION_COLLISION: 'Unbounded Action does not support collision. Check the Action ',
26
- INVALID_BOUNDED_PARAM_TYPE: 'Parameter Type of Bounded Action/Function should not refer to an Entity in another Schema.',
27
- BOUNDED_ACTION_COLLISION: 'For Bounded Action, combination of action name and binding parameter type should be unique.',
26
+ INVALID_BOUND_PARAM_TYPE: 'Parameter Type of Bound Action/Function should not refer to an Entity in another Schema.',
27
+ UNBOUND_ACTION_COLLISION: 'Unbound Action does not support collision. Check the Action ',
28
+ BOUND_ACTION_COLLISION: 'The combination of Action name and binding parameter type must be unique for Bound Action ',
28
29
  STREAM_NO_COLLECTION: `'Edm.Stream' cannot be of Collection type.`,
29
30
  UNSUPPORTED_PROPERTY_TYPE: 'Property cannot be of EntityType. Check the type: ',
30
- UNRESOLVED_SCHEMA_NAMESPACE: `Could not resolve the schema `,
31
+ UNRESOLVED_SCHEMA_NAMESPACE: `Could not resolve the schema `,
31
32
  INVALID_DATATYPE: `Invalid Data Type `,
32
- ELEMENT_NAME_COLLISION: 'Collision between EntityContainer Element Name and Schema Element Name is currenlty not supported. Please check the element name: ',
33
+ ELEMENT_NAME_COLLISION: 'Collision between EntityContainer Element Name and Schema Element Name is currently not supported. Please check the element name: ',
33
34
  NO_DEFAULT_FOR_COLLECTIONS: 'WARNING: Collection type cannot have a Default value.',
34
35
  BINARY_MAXLENGTH: 'WARNING: MaxLength for type Edm.Binary should not exceed 5000.',
35
36
  SCALE_GT_PRECISION: 'WARNING: Scale value should not be greater than Precision value.',
@@ -61,7 +61,7 @@ async function edmx2csn(edmx, filename, context) {
61
61
  namespace = (index > 0) ? result[1].substring(0, index) : result[1];
62
62
  }
63
63
  else {
64
- // to support edmx without entities - unbounded actions and functions only
64
+ // to support edmx without entities - unbound actions and functions only
65
65
  console.warn('There are no entities in the OData model');
66
66
  let schema = edmx.match(/(<Schema [^>]*>)/);
67
67
  if (!schema) throw new Error(messages.INVALID_EDMX_METADATA);