@sap/cds-dk 8.1.2 → 8.2.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/bin/bind.js +44 -11
  3. package/bin/cds-tsx.js +2 -0
  4. package/bin/cds.js +10 -4
  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 +18 -17
  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 +25 -24
  64. package/package.json +3 -2
  65. package/readme.md +2 -2
package/CHANGELOG.md CHANGED
@@ -7,6 +7,50 @@ 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.1 - 2024-09-05
11
+
12
+ ### Fixed
13
+
14
+ - Update `@sap/hdi-deploy` to fix CVE-2024-4067 with `micromatch` 4.0.7
15
+ - `cds add` plugins now correctly parse flags (options with `type: 'boolean'`) if not used as the last argument.
16
+
17
+ ## Version 8.2.0 - 2024-09-02
18
+
19
+ ### Added
20
+
21
+ - `cds add dynatrace` adds configuration for Dynatrace.
22
+ - `cds add cloud-logging` adds configuration for SAP Cloud Logging. Option `--with-telemetry` allows for configuration with telemetry.
23
+ - `cds version` shows version information for `@cap-js/db-service`.
24
+ - `cds add portal` now adds portal configuration for Kyma.
25
+ - `cds add handler` allows to create handler stubs (for Java only, beta)
26
+ - `cds init --add java --no-db` lets you create a Java project without persistent database.
27
+ - `cds import` supports plugins.
28
+ - `cds add containerize` now supports unified-runtime.
29
+ - `cds add helm` now supports templating in the mountPath in the additionalVolumes.
30
+ - Experimental support for `tsx` through `cds-tsx`.
31
+ - `cds bind --to-app-services` now uses `vcap.name` to resolve multiple services with same type. A warning is issued in case of ambiguities.
32
+ - `cds compile --to ord -o <name>` supports `.json` file extension.
33
+ - `cds import --destination` applies destination credentials to existing service configurations.
34
+
35
+ ### Changed
36
+
37
+ - `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).
38
+ - `cds login` prints shorter messages about refresh tokens.
39
+ - `cds init` uses latest Maven Java archetype version 3.2.0 for creating Java projects.
40
+
41
+ ### Fixed
42
+
43
+ - `cds import` fix for single entity schema in OData V2.
44
+ - `cds add portal` correctly sets the `appId` in its `CommonDataModel.json` from the `manifest.json` app ID.
45
+ - `cds add html5-repo` adds the SAP BTP Destination service as a hard dependency again for Kyma projects.
46
+ - `cds build --ws-pack` correctly creates tarball archives for workspaces with nested `node_modules` folders.
47
+ - `cds import` now shows proper error message in case of bound action collision.
48
+ - `cds deploy --to hana` now runs an existing `hana` build task configuration instead of a default one.
49
+
50
+ ### Removed
51
+
52
+ - Removed `build` and `build:ts` npm scripts that were generated into `package.json` when adding the `typescript` facet.
53
+
10
54
  ## Version 8.1.2 - 2024-08-17
11
55
 
12
56
  ### Fixed
@@ -201,6 +245,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
201
245
 
202
246
  - `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
247
 
248
+
249
+ ## Version 7.9.7 - 2024-08-22
250
+
251
+ ### Fixed
252
+
253
+ - Dependency update for `axios` to fix CVE-2024-39338
254
+ - `cds build --for mtx-sidecar` now correctly supports different `srv` folder name.
255
+ - `cds build --ws-pack` correctly creates tarball archives for workspaces with nested `node_modules` folders.
256
+ - `cds version` now reports the correct version of `@sap/cds` if this one is installed locally along with a local `@sap/cds-dk` installation.
257
+ - `cds version -i` does not show a globally installed version when none is installed or linked.
258
+ - `cds version` reports correct `@sap/cds-compiler` version.
259
+ - `cds version` can skip over check for Java version
260
+
204
261
  ## Version 7.9.6 - 2024-07-19
205
262
 
206
263
  ### 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
@@ -60,7 +60,11 @@ const cli = {
60
60
  cds.cli = { command: 'add' }
61
61
  await cds.plugins
62
62
  for (const [, Plugin] of cds.add.registered) {
63
- task.options.push(...Object.keys((new Plugin).options()).map(key => '--'+key))
63
+ const all = Object.entries((new Plugin).options())
64
+ const flags = all.filter(([,f]) => f.type === 'boolean')
65
+ const options = all.filter(([,o]) => o.type !== 'boolean')
66
+ task.options.push(...options.map(([key]) => '--'+key))
67
+ task.flags.push(...flags.map(([key]) => '--'+key))
64
68
  }
65
69
  }
66
70
  const args = this.args(task, argv)
@@ -215,9 +219,11 @@ function _require (id,o) {
215
219
  return require (resolved)
216
220
  }
217
221
 
218
- if (process[Symbol.for('ts-node.register.instance')]) {
219
- process.env.CDS_TYPESCRIPT = process.env.CDS_TYPESCRIPT || 'true'
220
- }
222
+ const { sep } = require ('path')
223
+ if (process[Symbol.for('ts-node.register.instance')])
224
+ process.env.CDS_TYPESCRIPT = 'ts-node'
225
+ else if (process._preload_modules?.some(m => m?.includes(`${sep}tsx${sep}`)))
226
+ process.env.CDS_TYPESCRIPT = 'tsx'
221
227
 
222
228
  module.exports = Object.assign ((..._) => cli.exec(..._), cli)
223
229
 
@@ -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
  }
@@ -322,20 +322,21 @@ async function _updatePackageJson(dest, services, kind, cwd, config) {
322
322
  const package_json = path.resolve(cwd, 'package.json');
323
323
  const conf = await exists(package_json) ? require(package_json) : {};
324
324
  const requires = ['cds', 'requires'].reduce((p, n) => p[n] || (p[n] = {}), conf);
325
- if (kind !== 'rest') {
325
+ if (kind !== 'rest' && kind !== 'rfc') {
326
326
  kind = (kind === "V2") ? 'odata-v2' : 'odata';
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, ' '));
330
+ // existing service configuration data can be updated, e.g. in case of delta imports
331
+ const model = path.relative(cwd, dest).replace(/\\/g, '/'); // cds env must not be platform specific
332
+ const serviceConfig = { kind, model, ...config }
333
+ if (!requires[service] || JSON.stringify(serviceConfig) !== JSON.stringify(requires[service])) {
334
+ cds.env.requires[service] = requires[service] = serviceConfig;
335
335
  package_json_updated = true;
336
336
  }
337
337
  }
338
338
  if (package_json_updated) {
339
+ await write(package_json, JSON.stringify(conf, null, ' '));
339
340
  console.log(`[cds] - updated ./package.json`);
340
341
  }
341
342
  }
@@ -353,6 +354,13 @@ function _parseValidJsonConfig(config) {
353
354
  async function postProcess(filePath, options, csn, cwd) {
354
355
  const services = _getServiceNames(csn);
355
356
  let config = _parseValidJsonConfig(options.config);
357
+
358
+ // add destination configuration
359
+ if (options.destination) {
360
+ config ??= {};
361
+ config.credentials = { destination: options.destination };
362
+ }
363
+
356
364
  const external = path.resolve(cwd, 'srv/external');
357
365
  const destFilePath = path.join(external, path.basename(filePath));
358
366
  if (options.out) options.out = _validateAndComputeOutputFilePath(options.out, options.as, destFilePath);
@@ -385,13 +393,6 @@ async function identifyFile(filepath) {
385
393
  return extension;
386
394
  }
387
395
 
388
- function isLinux() {
389
- let platform = process.platform;
390
- if (platform === 'linux' || platform === 'win32') {
391
- return true;
392
- }
393
- }
394
-
395
396
  function readEnvVariables(options, cliCheck) {
396
397
  if (cds.env.import) {
397
398
  if (cliCheck) {