@sap/cds-dk 8.0.2 → 8.0.3

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 (30) hide show
  1. package/CHANGELOG.md +23 -3
  2. package/bin/cds.js +11 -6
  3. package/bin/watch.js +12 -4
  4. package/lib/build/constants.js +1 -0
  5. package/lib/build/provider/hana/index.js +51 -33
  6. package/lib/build/provider/internalBuildTaskProvider.js +2 -2
  7. package/lib/build/provider/nodejs/index.js +4 -3
  8. package/lib/init/constants.js +5 -1
  9. package/lib/init/projectReader.js +0 -1
  10. package/lib/init/template/data/as-json.js +25 -11
  11. package/lib/init/template/destination/files/mta.yaml.hbs +6 -0
  12. package/lib/init/template/destination/files/package.sidecar.json +7 -0
  13. package/lib/init/template/destination/index.js +12 -2
  14. package/lib/init/template/html5-repo/files/mta.yaml.hbs +6 -58
  15. package/lib/init/template/html5-repo/files/package.sidecar.json +7 -0
  16. package/lib/init/template/html5-repo/files/xs-app.json.hbs +1 -15
  17. package/lib/init/template/html5-repo/index.js +13 -10
  18. package/lib/init/template/malware-scanner/index.js +1 -1
  19. package/lib/init/template/mta/files/package.json +1 -1
  20. package/lib/init/template/redis/files/mta.yaml.hbs +25 -0
  21. package/lib/init/template/redis/files/package.json.hbs +5 -0
  22. package/lib/init/template/redis/index.js +44 -0
  23. package/lib/init/template/redis-messaging/files/package.json.hbs +0 -3
  24. package/lib/init/template/redis-messaging/index.js +4 -18
  25. package/lib/init/template/workzone/index.js +4 -0
  26. package/lib/init/template/workzone-standard/files/mta.yaml.hbs +59 -0
  27. package/lib/init/template/workzone-standard/index.js +24 -8
  28. package/npm-shrinkwrap.json +14 -14
  29. package/package.json +1 -1
  30. package/lib/init/template/redis-messaging/files/mta.yaml.hbs +0 -14
package/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ 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.0.3 - 2024-07-20
11
+
12
+ ### Fixed
13
+
14
+ - `cds build --ws` no longer creates migration tables in shared db if already existing in a workspace.
15
+ - `cds add destination` adds the destination service as an MTX SaaS dependency.
16
+ - `cds add html5-repo` adds the HTML5 repo runtime as an MTX SaaS dependency.
17
+ - `cds add html5-repo` does not add a destination service any more if not required by other services.
18
+ - `cds add workzone` runs `cds add destination` as a dependent facet.
19
+ - `cds add` plugins don't fail if custom options are provided via the `options` API.
20
+ - `cds add data` can now correctly handle circular associations. The maximum depth of associations is increased to 5.
21
+ - `cds add redis` is separated from `cds add redis-messaging` to allow for separate consumption.
22
+ - `cds add redis` uses the `standard` service plan by default.
23
+ - `cds watch` no longer leads to a warning `'@sap/cds' was loaded from different installations` when local project dependencies are installed.
24
+ - `cds init` uses latest Maven Java archetype version 3.0.0 for creating Java projects.
25
+
26
+
10
27
  ## Version 8.0.2 - 2024-07-12
11
28
 
12
29
  ### Added
@@ -20,9 +37,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
20
37
  - `cds init` no longer creates a `.cdsrc.json` for Node.js projects.
21
38
  - `cds build` configuration cleanup for `data.model` and `service.model` to only support configuration of a single model folder.
22
39
 
23
- ### Fixed
24
-
25
-
26
40
  ## Version 8.0.1 - 2024-07-09
27
41
 
28
42
  ### Added
@@ -129,6 +143,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
129
143
  - `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.
130
144
 
131
145
 
146
+ ## Version 7.9.6 - 2024-07-19
147
+
148
+ ### Fixed
149
+
150
+ - `cds add data` can now correctly handle circular associations. The maximum depth of associations is increased to 5.
151
+
132
152
  ## Version 7.9.5 - 2024-07-12
133
153
 
134
154
  ### Added
package/bin/cds.js CHANGED
@@ -55,7 +55,8 @@ const cli = {
55
55
  argv = argv.slice(0, endOfOptions)
56
56
  }
57
57
 
58
- const args = this.args(task, argv)
58
+ const unknown = new Set
59
+ const args = this.args(task, argv, unknown)
59
60
  args[0].push(...appendArgs)
60
61
  cds.cli = {
61
62
  command: cmd,
@@ -63,13 +64,17 @@ const cli = {
63
64
  options: args[1],
64
65
  }
65
66
 
66
- // REVISIT: Have to do it here to allow custom flags for plugins!
67
- if (cmd === 'add') {
67
+ if (cmd === 'add') { // cds add plugins allow additional custom options
68
68
  await cds.plugins
69
69
  for (const [, Plugin] of cds.add.registered) {
70
- task.options.push(...Object.keys((new Plugin).options()).map(key => '--'+key))
70
+ const options = Object.keys((new Plugin).options()).map(key => '--'+key)
71
+ task.options.push(options)
72
+ options.forEach(o => unknown.delete(o))
71
73
  }
72
74
  }
75
+ if (unknown.size === 1) throw 'Invalid option: ' + Array.from(unknown)[0]
76
+ if (unknown.size > 1) throw 'Invalid options: ' + Array.from(unknown).join(', ')
77
+
73
78
  if (args[1]?.['resolve-bindings']) await _resolveBindings({ silent: cmd === 'env' })
74
79
 
75
80
  // cds.root may for some subcommands not point to the correct directory (e.g. cds w where users can pass a project directory)
@@ -101,7 +106,7 @@ const cli = {
101
106
  },
102
107
 
103
108
  // TODO replace w/ common arg parser from node
104
- args (task, argv) {
109
+ args (task, argv, unknown) {
105
110
 
106
111
  const { options:o=[], flags:f=[], shortcuts:s=[] } = task
107
112
  const _global = /^--(profile|production|sql|odata|add-.*|build-.*|cdsc-.*|odata-.*|folders-.*)$/
@@ -115,7 +120,7 @@ const cli = {
115
120
  else if ((k = o.indexOf(a)) >= 0) add(o[k],argv[++i])
116
121
  else if ((k = f.indexOf(a)) >= 0) add(f[k])
117
122
  else if (_global.test(a)) add_global(a, _flags[a] || argv[++i])
118
- else throw 'Invalid option: '+ a
123
+ else unknown.add(a)
119
124
  }
120
125
  // consistent production setting for NODE_ENV and CDS_ENV
121
126
  // if (process.env.NODE_ENV !== 'production') process.env.NODE_ENV = process.env.CDS_ENV?.split(',').find(p => p === 'production') || process.env.NODE_ENV
package/bin/watch.js CHANGED
@@ -76,6 +76,7 @@ async function watch ([cwd], {
76
76
  } catch (err) {
77
77
  throw `Error: No such folder or package: '${cwd}'`
78
78
  }
79
+ const _cwd = cwd || process.cwd()
79
80
 
80
81
  if (!Object.keys(options).includes('with-mocks')) args.push ('--with-mocks')
81
82
  if (!Object.keys(options).find(a => /^in-memory\??$/.test(a))) args.push ('--in-memory?')
@@ -91,18 +92,20 @@ async function watch ([cwd], {
91
92
  })
92
93
  if (process.env.CDS_TYPESCRIPT) {
93
94
  // Needed by ts-node/tsc to find the tsconfig.json. Same as `--project`.
94
- env.TS_NODE_PROJECT = env.TS_NODE_PROJECT ?? cwd ?? process.cwd()
95
+ env.TS_NODE_PROJECT = env.TS_NODE_PROJECT ?? _cwd
95
96
  }
96
97
 
97
- // allow running w/o or partial local node_modules, also add cds-dk for its sqlite
98
- env.NODE_PATH = [...paths(cwd||process.cwd()), ...paths(__dirname)].join(delimiter)
98
+ // if sap/cds is not installed locally, run with cds-dk's deps. (sap/cds, sqlite etc)
99
+ if (!installed('@sap/cds', _cwd)) {
100
+ env.NODE_PATH = [...paths(_cwd), ...paths(__dirname)].join(delimiter)
101
+ }
99
102
 
100
103
  if (typeof ext !== 'string') ext = extDefaults
101
104
  const delay = parseInt(process.env.CDS_WATCH_DELAY) || 200
102
105
 
103
106
  let liveReload //= ...
104
107
  let firstTime = true
105
- if (!/false|no/.test(options['livereload']) && cds.env.for('cds', cwd||process.cwd()).livereload !== false) {
108
+ if (!/false|no/.test(options['livereload']) && cds.env.for('cds', _cwd).livereload !== false) {
106
109
  liveReload = new (require ('../lib/watch/livereload-server'))
107
110
  env.CDS_LIVERELOAD_PATH = require.resolve ('../lib/watch/livereload-connect')
108
111
  env.CDS_LIVERELOAD_URL = await liveReload.start (options['livereload'], cwd, delay)
@@ -199,3 +202,8 @@ function paths (dir) {
199
202
  const parts = resolve(dir).split(sep), n = parts.length, nm = sep+'node_modules'
200
203
  return parts.map ((_,i,a)=> a.slice(0,n-i).join(sep)+nm).filter(p => fs.existsSync(p))
201
204
  }
205
+
206
+ function installed(id, ...paths) {
207
+ try { return require.resolve (id, { paths }) }
208
+ catch(e) { if (e.code !== 'MODULE_NOT_FOUND') throw e }
209
+ }
@@ -35,6 +35,7 @@ exports.CONTENT_ENV = "contentEnv" // copy .env fil
35
35
  exports.CONTENT_DEFAULT_ENV_JSON = "contentDefaultEnvJson" // copy default-env.json file into deployment folder - DISABLED by default
36
36
 
37
37
  exports.OPTION_WS = "ws" // run a workspace build, e.g. including model folders of configured npm workspaces
38
+ exports.OPTION_WS_PACK = "ws-pack" // enable tarball based packaging of workspace dependencies
38
39
  exports.CSV_FILE_TARGET = "csvFileTarget" // target folder when copying CSV files to the deployment target folder ./db/src/gen/*, default is 'data'
39
40
  exports.CSV_FILE_DETECTION = "csvFileDetection" // detect CSV files based on CDS model location - ENABLED by default
40
41
  exports.EXTENSION_POINT_VALIDATION = "extensionPointValidation" // validate extension point restrictions defined by the extended SaaS app - ENABLED by default
@@ -6,7 +6,7 @@ const InternalBuildPlugin = require('../internalBuildPlugin')
6
6
  const { BuildError, relativePaths, BuildMessage, getWorkspaces, hasOptionValue, getFiles } = require('../../util')
7
7
  const { OUTPUT_MODE_NONE, OUTPUT_MODE, CONTENT_PACKAGE_JSON, CONTENT_HDBTABLEDATA, CSV_FILE_DETECTION,
8
8
  CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, OUTPUT_MODE_RESULT, CONTINUE_UNRESOLVED_SCHEMA_CHANGES,
9
- CSV_FILE_TARGET, OPTION_WS} = require('../../constants')
9
+ CSV_FILE_TARGET, OPTION_WS } = require('../../constants')
10
10
  const { WARNING } = InternalBuildPlugin
11
11
  const DEFAULT_COMPILE_DEST_FOLDER = path.normalize("src/gen")
12
12
  const FILE_EXT_CSV = ".csv"
@@ -38,9 +38,14 @@ class HanaBuildPlugin extends InternalBuildPlugin {
38
38
  if (!model) {
39
39
  return
40
40
  }
41
+ let workspaceFiles
42
+ if (cds.cli.options?.[OPTION_WS] || hasOptionValue(this.task.options[OPTION_WS], true)) {
43
+ workspaceFiles = await this._getWorkspaceFiles()
44
+ }
45
+
41
46
  // the order of 1 and 2 is important
42
47
  // 1. compile
43
- const hdiPlugins = await this._compileToHana(model)
48
+ const hdiPlugins = await this._compileToHana(model, workspaceFiles)
44
49
 
45
50
  if (!this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_NONE)) {
46
51
  // 2. copy resources
@@ -49,9 +54,15 @@ class HanaBuildPlugin extends InternalBuildPlugin {
49
54
  } else {
50
55
  await this._copyResourcesExt(src, dest, model)
51
56
  }
52
- // copy native hana artifacts from workspace dependencies
53
- if (cds.cli.options?.[OPTION_WS] || hasOptionValue(this.task.options?.[OPTION_WS], true)) {
54
- await this._addWorkspaceContent()
57
+ // copy native hana artifacts from workspaces
58
+ if (workspaceFiles) {
59
+ const dest = path.join(this.task.dest, 'src/gen')
60
+ await Promise.all(
61
+ workspaceFiles.map((src) => {
62
+ const { dir, filePath } = src
63
+ return this.copy(path.join(dir, filePath)).to(path.join(dest, filePath))
64
+ })
65
+ )
55
66
  }
56
67
 
57
68
  // create additional stuff in dest
@@ -254,7 +265,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
254
265
  *
255
266
  * @param {object} model The compiled csn model
256
267
  */
257
- async _compileToHana(model) {
268
+ async _compileToHana(model, workspaceFiles) {
258
269
  // compile to old format (.hdbcds) or new format (.hdbtable / .hdbview)
259
270
  const format = this.getBuildOption(DEPLOY_FORMAT) || cds.env.requires.db?.[DEPLOY_FORMAT] || cds.env.hana?.[DEPLOY_FORMAT]
260
271
  if (!cds.compile.to[format]) {
@@ -267,7 +278,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
267
278
  // compatibility with existing cds.compile.to.hdbtable plugins cds < 8.0.0
268
279
  return await this._compileToHdb(model, format)
269
280
  } else {
270
- return await this._compileToHdbmigration(model, format)
281
+ return await this._compileToHdbmigration(model, format, workspaceFiles)
271
282
  }
272
283
  }
273
284
 
@@ -303,7 +314,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
303
314
  return hdiPlugins
304
315
  }
305
316
 
306
- async _compileToHdbmigration(model, format) {
317
+ async _compileToHdbmigration(model, format, workspaceFiles) {
307
318
  const hdiPlugins = new Set()
308
319
  const relDestDir = path.relative(this.task.dest, this.task.options.compileDest)
309
320
  const relDbDestDir = path.relative(cds.root, this.task.options.compileDest)
@@ -326,33 +337,37 @@ class HanaBuildPlugin extends InternalBuildPlugin {
326
337
 
327
338
  for (const { name, suffix, content, changed } of definitions) {
328
339
  hdiPlugins.add(suffix)
329
- const file = name + suffix
340
+ const fileName = name + suffix
330
341
  if (suffix === FILE_EXT_HDBMIGRATIONTABLE) {
331
- migrationTableFiles.push(path.join(relDbSrcDir, file))
332
- if (changed) {
333
- if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
334
- this._result.hana.push(path.join("src", file))
342
+ // Skip the .hdbmigrationtable file if its origin is a different workspace.
343
+ // The workspace build copies artifacts located in 'db/src/**' workspace folders.
344
+ if (!workspaceFiles?.find(wsFile => wsFile.fileName === fileName)) {
345
+ migrationTableFiles.push(path.join(relDbSrcDir, fileName))
346
+ if (changed) {
347
+ if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
348
+ this._result.hana.push(path.join("src", fileName))
349
+ }
350
+ promises.push(this.write(content).to(path.join(dbSrcDir, fileName)))
351
+ } else {
352
+ DEBUG?.(`no change, keep existing ${fileName}`)
335
353
  }
336
- promises.push(this.write(content).to(path.join(dbSrcDir, file)))
337
- } else {
338
- DEBUG?.(`no change, keep existing ${file}`)
339
354
  }
340
355
  } else {
341
356
  if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
342
- this._result.hana.push(path.join(relDestDir, file))
357
+ this._result.hana.push(path.join(relDestDir, fileName))
343
358
  }
344
- promises.push(this.write(content).to(path.join(this.task.options.compileDest, file)))
359
+ promises.push(this.write(content).to(path.join(this.task.options.compileDest, fileName)))
345
360
  if (suffix === FILE_EXT_HDBTABLE) {
346
361
  // issue an error in case a .hdbmigrationtable file already exists
347
362
  if (fs.existsSync(path.join(dbSrcDir, name + FILE_EXT_HDBMIGRATIONTABLE))) {
348
- validationError = new BuildError(`Multiple files exist defining the same HANA artifact - [${path.join(relDbSrcDir, name + FILE_EXT_HDBMIGRATIONTABLE)}, ${path.join(relDbDestDir, file)}].\nEither annotate the model entity using @cds.persistence.journal or undeploy the file [${path.join('src', name + FILE_EXT_HDBMIGRATIONTABLE)}] using an undeploy.json file.`)
363
+ validationError = new BuildError(`Multiple files exist defining the same HANA artifact - [${path.join(relDbSrcDir, name + FILE_EXT_HDBMIGRATIONTABLE)}, ${path.join(relDbDestDir, fileName)}].\nEither annotate the model entity using @cds.persistence.journal or undeploy the file [${path.join('src', name + FILE_EXT_HDBMIGRATIONTABLE)}] using an undeploy.json file.`)
349
364
  }
350
365
  }
351
366
  }
352
367
  }
353
- // the last-dev CSN shall only be updated, if all .hdbmigrationtable files could be successfully updated
354
- // of course, .hdbmigrationtable files already written would need to be manually reverted before the
355
- // cds build command is again executed
368
+ // The last-dev CSN shall only be updated, if all .hdbmigrationtable files could be successfully updated.
369
+ // Of course, .hdbmigrationtable files already written would need to be manually reverted before the
370
+ // cds build command is again executed.
356
371
  await Promise.all(promises)
357
372
 
358
373
  try {
@@ -531,35 +546,38 @@ class HanaBuildPlugin extends InternalBuildPlugin {
531
546
  }
532
547
  }
533
548
 
534
-
535
549
  /**
536
- * Copy native hana content from workspaces.
550
+ * Returns all hana native artifacts located in db/src/** workspace folders.
551
+ * @returns {Array} Array of workspace files, each entry contains the db src directory,
552
+ * the relative file path and the file name.
537
553
  */
538
- async _addWorkspaceContent() {
539
- const srcPaths = new Set()
554
+ async _getWorkspaceFiles() {
555
+ const dbPaths = new Set()
540
556
  const workspaces = await getWorkspaces()
541
557
 
542
558
  workspaces.forEach(workspace => {
543
559
  const dbSrc = path.join(cds.root, workspace, 'db/src')
544
560
  const dbCfg = path.join(cds.root, workspace, 'db/cfg')
545
561
  if (fs.existsSync(dbSrc)) {
546
- srcPaths.add(dbSrc)
562
+ dbPaths.add(dbSrc)
547
563
  }
548
564
  if (fs.existsSync(dbCfg)) {
549
- srcPaths.add(dbCfg)
565
+ dbPaths.add(dbCfg)
550
566
  }
551
567
  })
552
- DEBUG?.(`Copying hana native artifacts from folders '${[...srcPaths].map(f => path.relative(cds.root, f)).join(', ')}'`)
553
- const dest = path.join(this.task.dest, 'src/gen')
554
- for (const src of srcPaths) {
555
- await this.copyNativeContent(src, dest, (entry) => {
568
+ const workspaceFiles = [...dbPaths].reduce((acc, src) => {
569
+ const files = getFiles(src, (entry) => {
556
570
  if (entry.match(/(\/|\\)gen(\/|\\)?$/)) {
557
571
  // skip gen folder content
558
572
  return false
559
573
  }
560
574
  return true
561
575
  })
562
- }
576
+ files.forEach(file => acc.add({ dir: src, filePath: path.relative(src, file), fileName: path.basename(file) }))
577
+ return acc
578
+ }, new Set())
579
+
580
+ return [...workspaceFiles]
563
581
  }
564
582
 
565
583
  static async _readTemplateAsJson(template) {
@@ -5,7 +5,7 @@ const { hasJavaNature, getDefaultModelOptions, BuildError, hasOptionValue, norma
5
5
  const BuildTaskProvider = require('../buildTaskProvider')
6
6
  const { FILE_EXT_CDS, BUILD_TASK_HANA, BUILD_TASK_FIORI, BUILD_TASK_JAVA, BUILD_TASK_JAVA_CF, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF, BUILD_TASK_MTX,
7
7
  BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION, NODEJS_MODEL_EXCLUDE_LIST,
8
- IGNORE_DEFAULT_MODELS, CONTENT_WS } = require("../constants")
8
+ IGNORE_DEFAULT_MODELS, OPTION_WS } = require("../constants")
9
9
  const ResourcesTarBuilder = require('./mtx/resourcesTarBuilder')
10
10
  const DEBUG = cds.debug('cli|build')
11
11
 
@@ -285,7 +285,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
285
285
  }
286
286
 
287
287
  static async _setDefaultModel(task) {
288
- const ws = hasOptionValue(task.options?.[CONTENT_WS], true) || cds.cli.options?.ws
288
+ const ws = hasOptionValue(task.options?.[OPTION_WS], true) || cds.cli.options?.[OPTION_WS]
289
289
  // REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
290
290
  const filter = hasJavaNature() ? (m) => !NODEJS_MODEL_EXCLUDE_LIST.includes(m) : null
291
291
  let taskModelPaths = task.options?.model
@@ -5,7 +5,8 @@ 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 } = require('../../constants')
8
+ CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX,
9
+ OPTION_WS_PACK} = require('../../constants')
9
10
  const { WARNING } = EdmxBuildPlugin
10
11
  const DEBUG = cds.debug('cli|build')
11
12
 
@@ -36,7 +37,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
36
37
  }
37
38
  // by default model contains all features
38
39
  const model = await this.model()
39
- if (!model && !this.context.options['ws-pack']) {
40
+ if (!model && !this.context.options[OPTION_WS_PACK]) {
40
41
  return
41
42
  }
42
43
  if (model) {
@@ -55,7 +56,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
55
56
  if (this.isStagingBuild() && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
56
57
  const srcSrv = this.task.src === cds.root ? path.resolve(this.task.src, cds.env.folders.srv) : this.task.src
57
58
  await this._copyNativeContent(cds.root, srcSrv, destRoot, destSrv)
58
- if (this.context.options['ws-pack']) {
59
+ if (this.context.options[OPTION_WS_PACK]) {
59
60
  await this._packWorkspaceDependencies(destRoot)
60
61
  }
61
62
  }
@@ -5,9 +5,10 @@ module.exports = {
5
5
  COMMAND_ADD: 'add',
6
6
 
7
7
  JAVA_LTS_VERSIONS: [17, 21],
8
- MAVEN_ARCHETYPE_VERSION: '2.10.1',
8
+ MAVEN_ARCHETYPE_VERSION: '3.0.0',
9
9
 
10
10
  OPTIONS: Object.freeze({
11
+ COMPLETION: 'completion',
11
12
  JAVA: 'java',
12
13
  JAVA_MVN: 'java:mvn',
13
14
  JAVA_PACKAGE: 'java:package',
@@ -30,6 +31,9 @@ module.exports = {
30
31
  SQLITE: 'sqlite',
31
32
  H2: 'h2',
32
33
  LIQUIBASE: 'liquibase',
34
+ REDIS: 'redis',
35
+ ATTACHMENTS: 'attachments',
36
+ MALWARE_SCANNER: 'malware-scanner',
33
37
  LOCAL_MESSAGING: 'local-messaging',
34
38
  FILE_BASED_MESSAGING: 'file-based-messaging',
35
39
  ENTERPRISE_MESSAGING: 'enterprise-messaging',
@@ -41,7 +41,6 @@ module.exports = new class ProjectReader {
41
41
  }
42
42
  }
43
43
 
44
- // REVISIT: There should an API provided by cds.env
45
44
  /**
46
45
  * Returns cds.env using 'production' profile by default as mta deployment is executed with having production profile set.
47
46
  */
@@ -3,7 +3,7 @@ const { dirname } = require('node:path')
3
3
  const cds = require('../../../cds')
4
4
 
5
5
  let counter = Math.round(Math.random() * 10000) // Default random seed // Non-deterministic behaviour
6
- const MAX_ASSOC_DEPTH = 1
6
+ const MAX_ASSOC_DEPTH = 5
7
7
 
8
8
  /**
9
9
  * Creates JSON test data for the given entities
@@ -40,25 +40,35 @@ const asJson = module.exports = async (data, csn, numRecords=1, options={}) => {
40
40
 
41
41
  for (const name of entityNames) {
42
42
  if (!data[name] // removed on purpose because records are created inline through compositions
43
- || data[name].length >= numRecords) { // already created by following associations
43
+ || data[name].length >= numRecords) { // numRecords already created by following associations
44
44
  continue
45
45
  }
46
46
 
47
- const records = data[name] = Array(numRecords).fill({}).map(() => ({}))
47
+ let numRecordsToGenerate // numRecords might be reduced if some records were created by following associations
48
+ let records = []
49
+ if (data[name].length > 0) {
50
+ numRecordsToGenerate = numRecords - data[name].length
51
+ records = Array(numRecordsToGenerate).fill({}).map(() => ({}))
52
+ } else {
53
+ numRecordsToGenerate = numRecords
54
+ records = data[name] = Array(numRecordsToGenerate).fill({}).map(() => ({}))
55
+ }
48
56
  const entity = defs[name]
49
57
 
50
58
  const idNum = randomNumber()
51
- for (let i = 0; i < numRecords; i++) {
59
+ for (let i = 0; i < numRecordsToGenerate; i++) {
52
60
  fillRecord(records[i], idNum+i, entity, csn, data, null, 0, referenceData)
53
61
  }
54
- // Remove records w/ duplicate keys. This can happen if the key is an enum (and we have less enum values than requested records).
55
- data[name] = uniqRecords(records, entity)
62
+ data[name] = data[name].concat(records) // append the new records to the possibly existingand referenced records
63
+ // remove records w/ duplicate keys. This can happen if the key is an enum (and we have less enum values than requested records).
64
+ data[name] = uniqRecords(data[name], entity)
56
65
  }
57
66
  return data
58
67
  }
59
68
 
60
69
  function fillRecord(record, recordID, entity, csn, data, parentEntity, depth, referenceData) {
61
70
  Object.defineProperty(record, '$id', {value: recordID, enumerable: false})
71
+ if (data[entity.name]) data[entity.name].push(record) // add id to data, to be referenced by associations to prevent circular dependencies
62
72
 
63
73
  const { elements } = entity
64
74
  Object.values(elements).sort(asJson.elementsSorter(csn)).forEach(el => {
@@ -242,7 +252,7 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
242
252
  if (element.is2many)
243
253
  return
244
254
  const target = csn.definitions[element.target]
245
- if (!target || target === parentEntity || depth > MAX_ASSOC_DEPTH)
255
+ if (!target || depth > MAX_ASSOC_DEPTH)
246
256
  return
247
257
 
248
258
  let targetRecord = randomFromReferenceData(target, csn, referenceData)
@@ -256,10 +266,14 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
256
266
  targetRecords = data[target.name] = []
257
267
  else if (!targetRecords) // target entity is not in the list of entities to be created
258
268
  return
259
-
260
- targetRecord = fillRecord({}, randomNumber(), target, csn, data, entity, depth, referenceData)
261
- targetRecords.push(targetRecord)
262
- uniqRecords(targetRecords, target)
269
+
270
+ if (targetRecords.length > 0) { // use record generated by following asociation
271
+ targetRecord = targetRecords[0]
272
+ } else {
273
+ targetRecord = fillRecord({}, randomNumber(), target, csn, data, entity, depth+1, referenceData)
274
+ targetRecords.push(targetRecord)
275
+ uniqRecords(targetRecords, target)
276
+ }
263
277
  }
264
278
 
265
279
  // TODO: handle foreign keys correctly
@@ -11,6 +11,12 @@ modules:
11
11
  requires:
12
12
  - name: {{appName}}-destination
13
13
 
14
+ - name: {{appName}}-mtx
15
+ type: nodejs
16
+ path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
17
+ requires:
18
+ - name: {{appName}}-destination
19
+
14
20
  resources:
15
21
  - name: {{appName}}-destination
16
22
  type: org.cloudfoundry.managed-service
@@ -0,0 +1,7 @@
1
+ {
2
+ "cds": {
3
+ "requires": {
4
+ "destinations": true
5
+ }
6
+ }
7
+ }
@@ -1,6 +1,6 @@
1
1
  const { readProject } = require('../../projectReader')
2
2
  const { merge } = require('../../merge')
3
- const { srv4, approuter, destination } = require('../../registries/mta')
3
+ const { srv4, approuter, destination, mtxSidecar4 } = require('../../registries/mta')
4
4
 
5
5
  module.exports = class DestinationTemplate extends require('../../plugin') {
6
6
 
@@ -24,7 +24,11 @@ module.exports = class DestinationTemplate extends require('../../plugin') {
24
24
 
25
25
  async combine() {
26
26
  const project = readProject()
27
- const { hasHelm, hasApprouter, hasHelmUnifiedRuntime, hasMta, srvPath } = project
27
+ const { hasHelm, hasApprouter, hasMultitenancy, hasHelmUnifiedRuntime, hasMta, srvPath, isJava } = project
28
+
29
+ if (hasMultitenancy) {
30
+ await merge(__dirname, 'files/package.sidecar.json').into('mtx/sidecar/package.json')
31
+ }
28
32
 
29
33
  if (hasMta) {
30
34
  const srv = srv4(srvPath)
@@ -39,6 +43,12 @@ module.exports = class DestinationTemplate extends require('../../plugin') {
39
43
  into: [approuter, 'requires', 'name']
40
44
  })
41
45
  }
46
+ if (hasMultitenancy) {
47
+ relationships.push({
48
+ insert: [destination, 'name'],
49
+ into: [mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar'), 'requires', 'name']
50
+ })
51
+ }
42
52
  await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project, additions, relationships })
43
53
  }
44
54
 
@@ -12,6 +12,12 @@ modules:
12
12
  requires:
13
13
  - name: {{appName}}-html5-runtime
14
14
 
15
+ - name: {{appName}}-mtx
16
+ type: nodejs
17
+ path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
18
+ requires:
19
+ - name: {{appName}}-html5-runtime
20
+
15
21
  - name: {{appName}}-app-deployer
16
22
  type: com.sap.application.content
17
23
  path: {{#isNodejs}}gen{{/isNodejs}}{{#isJava}}.{{/isJava}}
@@ -42,38 +48,6 @@ modules:
42
48
  supported-platforms: []
43
49
  {{/apps}}
44
50
 
45
- - name: {{appName}}-destinations
46
- type: com.sap.application.content
47
- requires:
48
- - name: {{appName}}-auth
49
- parameters:
50
- service-key:
51
- name: {{appName}}-auth-key
52
- - name: {{appName}}-html5-repo-host
53
- parameters:
54
- service-key:
55
- name: {{appName}}-html5-repo-host-key
56
- - name: srv-api
57
- - name: {{appName}}-destination
58
- parameters:
59
- content-target: true
60
- build-parameters:
61
- no-source: true
62
- parameters:
63
- content:
64
- instance:
65
- existing_destinations_policy: update
66
- destinations:
67
- - Name: {{appName}}-html5-repository
68
- ServiceInstanceName: {{appName}}-html5-repo-host
69
- ServiceKeyName: {{appName}}-html5-repo-host-key
70
- sap.cloud.service: {{appName}}.service
71
- - Name: {{appName}}-auth
72
- Authentication: OAuth2UserTokenExchange
73
- ServiceInstanceName: {{appName}}-auth
74
- ServiceKeyName: {{appName}}-auth-key
75
- sap.cloud.service: {{appName}}.service
76
-
77
51
  resources:
78
52
  {{#hasApprouter}}
79
53
  - name: {{appName}}-html5-runtime
@@ -88,29 +62,3 @@ resources:
88
62
  parameters:
89
63
  service: html5-apps-repo
90
64
  service-plan: app-host
91
-
92
- - name: {{appName}}-destination
93
- type: org.cloudfoundry.managed-service
94
- parameters:
95
- service: destination
96
- service-plan: lite
97
- config:
98
- HTML5Runtime_enabled: true
99
- init_data:
100
- instance:
101
- existing_destinations_policy: update
102
- destinations:
103
- - Name: {{appName}}-srv-api
104
- URL: ~{srv-api/srv-url}
105
- Authentication: NoAuthentication
106
- Type: HTTP
107
- ProxyType: Internet
108
- HTML5.ForwardAuthToken: true
109
- HTML5.DynamicDestination: true
110
- requires:
111
- - name: srv-api
112
- group: destinations
113
- properties:
114
- name: srv-api # must be used in xs-app.json as well
115
- url: ~{srv-url}
116
- forwardAuthToken: true
@@ -0,0 +1,7 @@
1
+ {
2
+ "cds": {
3
+ "requires": {
4
+ "html5-repo": true
5
+ }
6
+ }
7
+ }
@@ -4,24 +4,10 @@
4
4
  {
5
5
  "source": "^/?odata/(.*)$",
6
6
  "target": "/odata/$1",
7
- "destination": "{{appName}}-srv-api",
7
+ "destination": "srv-api",
8
8
  {{#hasXsuaa}}"authenticationType": "xsuaa",{{/hasXsuaa}}
9
9
  "csrfProtection": true
10
10
  },
11
- {{#hasUI5}}
12
- {
13
- "source": "^/resources/(.*)$",
14
- "target": "/resources/$1",
15
- "authenticationType": "none",
16
- "destination": "ui5"
17
- },
18
- {
19
- "source": "^/test-resources/(.*)$",
20
- "target": "/test-resources/$1",
21
- "authenticationType": "none",
22
- "destination": "ui5"
23
- },
24
- {{/hasUI5}}
25
11
  {
26
12
  "source": "^(.*)$",
27
13
  "target": "$1",
@@ -1,7 +1,7 @@
1
1
  const { join } = require('path')
2
2
  const { readProject } = require('../../projectReader')
3
3
  const { merge } = require('../../merge')
4
- const { srv4, destination, destinations, html5RepoHost, html5Runtime, appDeployer, approuter } = require('../../registries/mta')
4
+ const { srv4, html5RepoHost, html5Runtime, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
5
5
 
6
6
  module.exports = class Html5RepoTemplate extends require('../../plugin') {
7
7
 
@@ -9,10 +9,6 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
9
9
  return 'SAP BTP HTML5 Application Repository'
10
10
  }
11
11
 
12
- requires() {
13
- return ['destination']
14
- }
15
-
16
12
  static hasInProduction(env) {
17
13
  return !!env.requires['html5-repo']
18
14
  }
@@ -47,13 +43,17 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
47
43
 
48
44
  async combine() {
49
45
  const project = readProject()
50
- const { srvPath, appPath, hasMta, hasHelm, hasHelmUnifiedRuntime, hasApprouter, apps } = project
46
+ const { isJava, srvPath, appPath, hasMta, hasMultitenancy, hasHelm, hasHelmUnifiedRuntime, hasApprouter, apps } = project
51
47
 
52
48
  await Promise.all(apps.map(async ({app}) => {
53
49
  project.app = app
54
50
  await merge(__dirname, 'files/xs-app.json.hbs').into(join(appPath, app, 'xs-app.json'), { project })
55
51
  }))
56
52
 
53
+ if (hasMultitenancy) {
54
+ await merge(__dirname, 'files/package.sidecar.json').into('mtx/sidecar/package.json')
55
+ }
56
+
57
57
  if (hasMta) {
58
58
  const srv = srv4(srvPath)
59
59
  project.apps = apps
@@ -61,11 +61,8 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
61
61
  in: 'modules',
62
62
  where: { type: 'html5', path: `${appPath}${app.app}` }
63
63
  }))
64
- const additions = [srv, appDeployer, destinations, destination, html5RepoHost, ...appModules]
64
+ const additions = [srv, appDeployer, html5RepoHost, ...appModules]
65
65
  const relationships = [{
66
- insert: [destination, 'name'],
67
- into: [appDeployer, 'requires', 'name'],
68
- }, {
69
66
  insert: [html5RepoHost, 'name'],
70
67
  into: [appDeployer, 'requires', 'name'],
71
68
  }]
@@ -76,6 +73,12 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
76
73
  into: [approuter, 'requires', 'name'],
77
74
  })
78
75
  }
76
+ if (hasMultitenancy) {
77
+ relationships.push({
78
+ insert: [html5Runtime, 'name'],
79
+ into: [mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar'), 'requires', 'name']
80
+ })
81
+ }
79
82
  await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project,
80
83
  additions,
81
84
  relationships
@@ -5,7 +5,7 @@ const { srv4, malwareScanner } = require('../../registries/mta')
5
5
  module.exports = class MalwareScannerTemplate extends require('../../plugin') {
6
6
 
7
7
  static help() {
8
- return 'SAP Malware Scanning service'
8
+ return 'SAP Malware Scanning Service'
9
9
  }
10
10
 
11
11
  static hasInProduction(env) {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "devDependencies": {
3
- "@sap/cds-dk": ">=7"
3
+ "@sap/cds-dk": "^8"
4
4
  }
5
5
  }
@@ -0,0 +1,25 @@
1
+ ---
2
+ modules:
3
+ - name: {{appName}}-srv
4
+ type: {{language}}
5
+ path: {{& srvPath}}
6
+ requires:
7
+ - name: {{appName}}-redis
8
+
9
+ resources:
10
+ - name: {{appName}}-redis
11
+ type: org.cloudfoundry.managed-service
12
+ parameters:
13
+ service: redis-cache
14
+ service-plan: standard
15
+ # config:
16
+ # memory: 2 # GB, can be 2 or 4
17
+ # multi_az: true
18
+ # cluster_mode: true
19
+ # shard_count: 1
20
+ # node_count: 3 # per shard minimum is 3 (for standard plan)
21
+ # engine_version: "6.0" # can be "4.0" or "6.0"
22
+ # maintenance_window:
23
+ # day_of_week: Friday
24
+ # start_hour_utc: 0
25
+ # duration: 5 # hours
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "redis": "^4"
4
+ }
5
+ }
@@ -0,0 +1,44 @@
1
+ const { readProject } = require('../../projectReader')
2
+ const { merge } = require('../../merge')
3
+ const { srv4, redis } = require('../../registries/mta')
4
+
5
+ module.exports = class extends require('../../plugin') {
6
+
7
+ static help() {
8
+ return 'SAP BTP Redis, Hyperscaler Option'
9
+ }
10
+
11
+ async canRun() {
12
+ const { hasMta, hasHelm, hasHelmUnifiedRuntime, isJava } = readProject()
13
+ const onlyHelm = !hasMta && (hasHelmUnifiedRuntime || hasHelm)
14
+ if (isJava) throw `'cds add redis' is not available for Java yet`
15
+ if (onlyHelm) throw `'cds add redis' is not available for Kyma yet`
16
+ return true
17
+ }
18
+
19
+ static hasInProduction() {
20
+ const { dependencies } = readProject()
21
+ return !!dependencies?.['redis']
22
+ }
23
+
24
+ async run() {
25
+ await merge(__dirname, 'files/package.json.hbs').into('package.json')
26
+ }
27
+
28
+ async combine() {
29
+ const project = readProject()
30
+ const { hasMta, srvPath } = project
31
+
32
+ if (hasMta) {
33
+ const srv = srv4(srvPath)
34
+ await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
35
+ project,
36
+ additions: [srv, redis],
37
+ relationships: [{
38
+ insert: [redis, 'name'],
39
+ into: [srv, 'requires', 'name']
40
+ }]
41
+ })
42
+ }
43
+ }
44
+ }
@@ -1,8 +1,5 @@
1
1
  {
2
2
  {{#isNodejs}}
3
- "dependencies": {
4
- "redis": "^4"
5
- },
6
3
  "cds": {
7
4
  {{/isNodejs}}
8
5
  "requires": {
@@ -2,7 +2,6 @@ const cds = require('../../../cds')
2
2
  const { read } = cds.utils
3
3
  const { readProject } = require('../../projectReader')
4
4
  const { merge } = require('../../merge')
5
- const { srv4, redis } = require('../../registries/mta')
6
5
 
7
6
  module.exports = class RedisMessagingTemplate extends require('../../plugin') {
8
7
 
@@ -10,6 +9,10 @@ module.exports = class RedisMessagingTemplate extends require('../../plugin') {
10
9
  return 'messaging via Redis'
11
10
  }
12
11
 
12
+ requires() {
13
+ return ['redis']
14
+ }
15
+
13
16
  async canRun() {
14
17
  const { hasMta, hasHelm, hasHelmUnifiedRuntime, isJava } = readProject()
15
18
  const onlyHelm = !hasMta && (hasHelmUnifiedRuntime || hasHelm)
@@ -28,21 +31,4 @@ module.exports = class RedisMessagingTemplate extends require('../../plugin') {
28
31
  project.shortcut = !(await read(configFile)).cds?.requires?.messaging?.kind
29
32
  await merge(__dirname, 'files/package.json.hbs').into(configFile, { project })
30
33
  }
31
-
32
- async combine() {
33
- const project = readProject()
34
- const { hasMta, srvPath } = project
35
-
36
- if (hasMta) {
37
- const srv = srv4(srvPath)
38
- await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
39
- project,
40
- additions: [srv, redis],
41
- relationships: [{
42
- insert: [redis, 'name'],
43
- into: [srv, 'requires', 'name']
44
- }]
45
- })
46
- }
47
- }
48
34
  }
@@ -1,4 +1,8 @@
1
1
  module.exports = class extends require('../../plugin') {
2
+ help() {
3
+ return 'SAP BTP Work Zone'
4
+ }
5
+
2
6
  requires() {
3
7
  return ['workzone-standard']
4
8
  }
@@ -0,0 +1,59 @@
1
+ ---
2
+ modules:
3
+ - name: {{appName}}-destinations
4
+ type: com.sap.application.content
5
+ requires:
6
+ - name: {{appName}}-auth
7
+ parameters:
8
+ service-key:
9
+ name: {{appName}}-auth-key
10
+ - name: {{appName}}-html5-repo-host
11
+ parameters:
12
+ service-key:
13
+ name: {{appName}}-html5-repo-host-key
14
+ - name: srv-api
15
+ - name: {{appName}}-destination
16
+ parameters:
17
+ content-target: true
18
+ build-parameters:
19
+ no-source: true
20
+ parameters:
21
+ content:
22
+ instance:
23
+ existing_destinations_policy: update
24
+ destinations:
25
+ - Name: {{appName}}-html5-repository
26
+ ServiceInstanceName: {{appName}}-html5-repo-host
27
+ ServiceKeyName: {{appName}}-html5-repo-host-key
28
+ sap.cloud.service: {{appName}}.service
29
+ - Name: {{appName}}-auth
30
+ Authentication: OAuth2UserTokenExchange
31
+ ServiceInstanceName: {{appName}}-auth
32
+ ServiceKeyName: {{appName}}-auth-key
33
+ sap.cloud.service: {{appName}}.service
34
+
35
+ - name: {{appName}}-destination
36
+ type: org.cloudfoundry.managed-service
37
+ parameters:
38
+ service: destination
39
+ service-plan: lite
40
+ config:
41
+ HTML5Runtime_enabled: true
42
+ init_data:
43
+ instance:
44
+ existing_destinations_policy: update
45
+ destinations:
46
+ - Name: {{appName}}-srv-api
47
+ URL: ~{srv-api/srv-url}
48
+ Authentication: NoAuthentication
49
+ Type: HTTP
50
+ ProxyType: Internet
51
+ HTML5.ForwardAuthToken: true
52
+ HTML5.DynamicDestination: true
53
+ requires:
54
+ - name: srv-api
55
+ group: destinations
56
+ properties:
57
+ name: srv-api # must be used in xs-app.json as well
58
+ url: ~{srv-url}
59
+ forwardAuthToken: true
@@ -2,22 +2,27 @@ const cds = require('../../../cds')
2
2
  const { readProject } = require('../../projectReader')
3
3
  const { merge } = require('../../merge')
4
4
  const { join } = require('path')
5
+ const { destination, destinations } = require('../../registries/mta')
5
6
 
6
7
  module.exports = class extends require('../../plugin') {
7
8
 
8
- canRun() {
9
- if (cds.requires.multitenancy) {
10
- throw `SAP BTP Work Zone, Standard Edition does not support multitenancy yet.`
11
- }
12
- return true
9
+ static help() {
10
+ return 'SAP BTP Work Zone, Standard Edition'
13
11
  }
14
12
 
15
13
  requires() {
16
- return ['html5-repo']
14
+ return ['html5-repo', 'destination']
17
15
  }
18
16
 
19
- static help() {
20
- return 'SAP BTP Work Zone, Standard Edition'
17
+ static hasInProduction(env) {
18
+ return !!env.requires?.workzone
19
+ }
20
+
21
+ canRun() {
22
+ if (cds.requires.multitenancy) {
23
+ throw `SAP BTP Work Zone, Standard Edition does not support multitenancy yet.`
24
+ }
25
+ return true
21
26
  }
22
27
 
23
28
  async run() {
@@ -26,5 +31,16 @@ module.exports = class extends require('../../plugin') {
26
31
  await Promise.all(appUIPaths.map(p =>
27
32
  merge(__dirname, 'files/manifest.json.hbs').into(join(appPath, p, 'webapp/manifest.json'), { project })
28
33
  ))
34
+ await merge({ cds: { requires: { workzone: true } } }).into('package.json')
29
35
  }
36
+
37
+ async combine() {
38
+ const project = readProject()
39
+ const { hasMta } = project
40
+
41
+ if (hasMta) {
42
+ const additions = [destinations, destination]
43
+ await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project, additions })
44
+ }
45
+ }
30
46
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "8.0.2",
3
+ "version": "8.0.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sap/cds-dk",
9
- "version": "8.0.2",
9
+ "version": "8.0.3",
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "dependencies": {
12
12
  "@cap-js/asyncapi": "^1.0.0",
@@ -35,10 +35,10 @@
35
35
  }
36
36
  },
37
37
  "node_modules/@cap-js/asyncapi": {
38
- "version": "1.0.1",
38
+ "version": "1.0.2",
39
39
  "license": "SEE LICENSE IN LICENSE",
40
40
  "peerDependencies": {
41
- "@sap/cds": ">=7.3"
41
+ "@sap/cds": ">=7.6"
42
42
  }
43
43
  },
44
44
  "node_modules/@cap-js/db-service": {
@@ -135,7 +135,7 @@
135
135
  }
136
136
  },
137
137
  "node_modules/@eslint/js": {
138
- "version": "9.6.0",
138
+ "version": "9.7.0",
139
139
  "license": "MIT",
140
140
  "engines": {
141
141
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -200,7 +200,7 @@
200
200
  }
201
201
  },
202
202
  "node_modules/@sap/cds": {
203
- "version": "8.0.3",
203
+ "version": "8.0.4",
204
204
  "license": "SEE LICENSE IN LICENSE",
205
205
  "dependencies": {
206
206
  "@sap/cds-compiler": ">=5",
@@ -262,7 +262,7 @@
262
262
  }
263
263
  },
264
264
  "node_modules/@sap/cds-mtxs": {
265
- "version": "2.0.2",
265
+ "version": "2.0.3",
266
266
  "license": "SEE LICENSE IN LICENSE",
267
267
  "dependencies": {
268
268
  "@sap/hdi-deploy": ">=4",
@@ -866,14 +866,14 @@
866
866
  }
867
867
  },
868
868
  "node_modules/eslint": {
869
- "version": "9.6.0",
869
+ "version": "9.7.0",
870
870
  "license": "MIT",
871
871
  "dependencies": {
872
872
  "@eslint-community/eslint-utils": "^4.2.0",
873
- "@eslint-community/regexpp": "^4.6.1",
873
+ "@eslint-community/regexpp": "^4.11.0",
874
874
  "@eslint/config-array": "^0.17.0",
875
875
  "@eslint/eslintrc": "^3.1.0",
876
- "@eslint/js": "9.6.0",
876
+ "@eslint/js": "9.7.0",
877
877
  "@humanwhocodes/module-importer": "^1.0.1",
878
878
  "@humanwhocodes/retry": "^0.3.0",
879
879
  "@nodelib/fs.walk": "^1.2.8",
@@ -882,7 +882,7 @@
882
882
  "cross-spawn": "^7.0.2",
883
883
  "debug": "^4.3.2",
884
884
  "escape-string-regexp": "^4.0.0",
885
- "eslint-scope": "^8.0.1",
885
+ "eslint-scope": "^8.0.2",
886
886
  "eslint-visitor-keys": "^4.0.0",
887
887
  "espree": "^10.1.0",
888
888
  "esquery": "^1.5.0",
@@ -915,7 +915,7 @@
915
915
  }
916
916
  },
917
917
  "node_modules/eslint-scope": {
918
- "version": "8.0.1",
918
+ "version": "8.0.2",
919
919
  "license": "BSD-2-Clause",
920
920
  "dependencies": {
921
921
  "esrecurse": "^4.3.0",
@@ -2015,7 +2015,7 @@
2015
2015
  "license": "ISC"
2016
2016
  },
2017
2017
  "node_modules/semver": {
2018
- "version": "7.6.2",
2018
+ "version": "7.6.3",
2019
2019
  "license": "ISC",
2020
2020
  "bin": {
2021
2021
  "semver": "bin/semver.js"
@@ -2301,7 +2301,7 @@
2301
2301
  }
2302
2302
  },
2303
2303
  "node_modules/uglify-js": {
2304
- "version": "3.18.0",
2304
+ "version": "3.19.0",
2305
2305
  "license": "BSD-2-Clause",
2306
2306
  "optional": true,
2307
2307
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "8.0.2",
3
+ "version": "8.0.3",
4
4
  "description": "Command line client and development toolkit for the SAP Cloud Application Programming Model",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "keywords": [
@@ -1,14 +0,0 @@
1
- ---
2
- modules:
3
- - name: {{appName}}-srv
4
- type: {{language}}
5
- path: {{& srvPath}}
6
- requires:
7
- - name: {{appName}}-redis
8
-
9
- resources:
10
- - name: {{appName}}-redis
11
- type: org.cloudfoundry.managed-service
12
- parameters:
13
- service: redis-cache
14
- service-plan: default