@sap/cds-dk 8.1.0 → 8.1.2

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 (34) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/bin/version.js +2 -3
  3. package/lib/build/buildTaskFactory.js +29 -12
  4. package/lib/build/constants.js +1 -1
  5. package/lib/build/provider/hana/2migration.js +4 -4
  6. package/lib/build/provider/internalBuildTaskProvider.js +2 -35
  7. package/lib/build/provider/mtx/resourcesTarBuilder.js +2 -2
  8. package/lib/cds.js +1 -0
  9. package/lib/compile/to_openapi.js +2 -1
  10. package/lib/deploy/to-hana/hdiDeployUtil.js +1 -0
  11. package/lib/import/common.js +1 -1
  12. package/lib/import/message.js +2 -2
  13. package/lib/import/odata/v2parser.js +2 -2
  14. package/lib/init/bas.js +73 -32
  15. package/lib/init/constants.js +2 -5
  16. package/lib/init/merge.js +5 -3
  17. package/lib/init/projectReader.js +0 -1
  18. package/lib/init/template/data/as-json.js +22 -12
  19. package/lib/init/template/data/index.js +1 -1
  20. package/lib/init/template/helm-unified-runtime/index.js +3 -1
  21. package/lib/init/template/multitenancy/index.js +9 -31
  22. package/lib/init/template/sample/files/nodejs/cat-service.js +2 -2
  23. package/lib/init/template/sample/files/srv/cat-service.cds +5 -1
  24. package/lib/init/template/xsuaa/index.js +10 -3
  25. package/lib/mtx/push.js +3 -1
  26. package/lib/mtx/settings_manager.js +4 -1
  27. package/npm-shrinkwrap.json +27 -19
  28. package/package.json +1 -1
  29. package/lib/init/template/cov2ap/files/dependencies.package.json +0 -5
  30. package/lib/init/template/cov2ap/index.js +0 -31
  31. package/lib/init/template/event-queue/files/dependencies.package.json +0 -5
  32. package/lib/init/template/event-queue/index.js +0 -35
  33. package/lib/init/template/websocket/files/dependencies.package.json +0 -5
  34. package/lib/init/template/websocket/index.js +0 -35
package/CHANGELOG.md CHANGED
@@ -7,6 +7,37 @@ 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.1.2 - 2024-08-17
11
+
12
+ ### Fixed
13
+
14
+ - Dependency update for `axios` to fix CVE-2024-39338
15
+ - `cds login` now fetches the passcode URL for the subscriber tenant if the subdomain is given.
16
+ - `cds build` now correctly generates migration tables for `CodeList` entities.
17
+
18
+ ## Version 8.1.1 - 2024-08-07
19
+
20
+ ### Added
21
+
22
+ - Add more features to CAP project creation wizard in SAP Business Application Studio.
23
+ - `cds.add.merge` now you specify a `key` in its `deletions` semantics.
24
+
25
+ ### Changed
26
+
27
+ - `cds init` uses latest Maven Java archetype version 3.1.0 for creating Java projects.
28
+
29
+ ### Fixed
30
+
31
+ - `cds import` now gives proper error message for OData import in case of invalid OData version or invalid encoding.
32
+ - `cds import` now able to ignore invalid escape sequence in the description of properties for OData V2.
33
+ - `cds add mta` does not error when the `app/router` folder was deleted.
34
+ - `cds version -i` does not show a globally installed version when none is installed or linked.
35
+ - `cds compile --to openapi` no longer fails with `Error: Unknown protocol: graphql`.
36
+ - `cds add data` can now correctly handle circular dependencies in entities that point to themselves via associations and compositions.
37
+ - `cds add` returns correct suggestions for shell completion.
38
+ - `cds version` reports correct `@sap/cds-compiler` version.
39
+ - `cds deploy` falls back correctly to `@sap/hana-client` when `HDI_DEPLOY_OPTIONS='{"use_hdb":false}'` is set.
40
+
10
41
  ## Version 8.1.0 - 2024-07-26
11
42
 
12
43
  ### Added
@@ -63,6 +94,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
63
94
  - `cds add helm` removed `saasRegistryParameters` key and moved parameters to `saas-registry`.
64
95
  - `cds init` no longer creates a `.cdsrc.json` for Node.js projects.
65
96
  - `cds build` configuration cleanup for `data.model` and `service.model` to only support configuration of a single model folder.
97
+ - `cds build` now fully supports default model definitions for custom build plugins.
66
98
 
67
99
  ## Version 8.0.1 - 2024-07-09
68
100
 
package/bin/version.js CHANGED
@@ -71,13 +71,12 @@ function info({ root:cwd=process.cwd() }) {
71
71
 
72
72
  const npmRoot = execSync('npm root -g').toString().trim()
73
73
  let versions = {
74
- ..._versions_from(_pkg_path('@sap/cds-dk', __dirname), '@sap/cds-dk (global)'), // ... linked in cap/dev setup
75
- ..._versions_from(_pkg_path('@sap/cds-dk', npmRoot), '@sap/cds-dk (global)'), // ... or installed globally
74
+ ..._versions_from(_pkg_path('@sap/cds-dk', npmRoot), '@sap/cds-dk (global)'), // linked in cap/dev or installed globally
76
75
  ..._versions_from(_pkg_path('@sap/cds-dk', cwd)), // local dk, important for Java projects
77
76
  ..._versions_from(_pkg_path('@sap/cds', __dirname)), // @sap/cds from here
78
77
  ..._versions_from(_pkg_path('@sap/cds', cds.home)), // ... or local @sap/cds
79
78
  ..._versions_from(cwd), // ... more from local app dependencies
80
- ..._versions_from(_pkg_path('@sap/cds-compiler', cwd, __dirname)), // compiler is no direct dependency, so list it explicitly
79
+ '@sap/cds-compiler': cds.compiler.version(),
81
80
  'Node.js': process.version,
82
81
  'home': cds.home, // effective cds home
83
82
  }
@@ -3,7 +3,7 @@ const path = require('path')
3
3
  const cds = require('../cds')
4
4
  const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
5
5
  const { hasJavaNature, getProperty, getDefaultModelOptions, hasOptionValue, BuildError } = require('./util')
6
- const { FILE_EXT_CDS, OPTION_WS } = require("./constants")
6
+ const { FILE_EXT_CDS, OPTION_WS, IGNORE_DEFAULT_MODELS, NODEJS_MODEL_EXCLUDE_LIST, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF } = require("./constants")
7
7
  const term = require('../util/term')
8
8
  const DEBUG = cds.debug('cli|build')
9
9
 
@@ -95,11 +95,7 @@ class BuildTaskFactory {
95
95
  task.options.model = [task.options.model]
96
96
  }
97
97
  })
98
- // there must be at least one task without model options
99
- if (!tasks.some(task => !task.options?.model?.length > 0)) {
100
- return
101
- }
102
- const modelPaths = await getDefaultModelOptions()
98
+ const modelPaths = await getDefaultModelOptions(false)
103
99
  let wsModelPaths
104
100
  // calculate only once
105
101
  if (cds.cli.options?.[OPTION_WS] || tasks.some(task => hasOptionValue(task.options?.[OPTION_WS], true))) {
@@ -107,10 +103,12 @@ class BuildTaskFactory {
107
103
  }
108
104
  // set default model options
109
105
  tasks.forEach(task => {
110
- this._setTaskModelOptions(task, cds.cli.options?.[OPTION_WS] || hasOptionValue(task.options?.[OPTION_WS], true) ? wsModelPaths : modelPaths)
111
106
  if (!task.src) {
112
107
  throw new BuildError(`Mandatory property 'src' not defined for build task '${task.for}'.`)
113
108
  }
109
+ const optionWs = cds.cli.options?.[OPTION_WS] || hasOptionValue(task.options?.[OPTION_WS], true)
110
+ // shallow copy model paths
111
+ this._setTaskModelOptions(task, optionWs ? [...wsModelPaths] : [...modelPaths])
114
112
  })
115
113
  }
116
114
 
@@ -180,14 +178,33 @@ class BuildTaskFactory {
180
178
  }
181
179
 
182
180
  static _setTaskModelOptions(task, defaultModelPaths) {
181
+ // bootstrap service model is only required for Nodejs build task - issues/12770#issuecomment-1805719
182
+ if (task.for !== BUILD_TASK_NODEJS && task.for !== BUILD_TASK_NODE_CF) {
183
+ defaultModelPaths = defaultModelPaths.filter(p => !NODEJS_MODEL_EXCLUDE_LIST.includes(p))
184
+ }
185
+
186
+ let taskModelPaths = task.options?.model
187
+ if (taskModelPaths && !Array.isArray(taskModelPaths)) {
188
+ taskModelPaths = [taskModelPaths]
189
+ }
190
+ const allowList = new RegExp(`^@sap/cds${cds.env.requires.toggles ? '|^' + cds.env.features.folders.replace('*', '') : ''}`)
183
191
  task.options = task.options || {}
184
- if (!task.options.model?.length > 0) {
185
- defaultModelPaths = new Set(defaultModelPaths)
186
- if (task.src) {
187
- defaultModelPaths.add(task.src)
192
+ let modelPaths = []
193
+ if (taskModelPaths?.length) {
194
+ if (!hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
195
+ modelPaths = defaultModelPaths.filter(p => p.match(allowList))
196
+ }
197
+ } else {
198
+ modelPaths = [...defaultModelPaths]
199
+ if (!modelPaths.includes(task.src)) {
200
+ modelPaths.push(task.src)
201
+ }
202
+ if (hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
203
+ // all default models except the built-in models
204
+ modelPaths = modelPaths.filter(p => !p.match(allowList))
188
205
  }
189
- task.options.model = [...defaultModelPaths]
190
206
  }
207
+ task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(modelPaths) : modelPaths)]
191
208
  }
192
209
 
193
210
  static _stringifyTask(task) {
@@ -48,7 +48,7 @@ exports.FILE_EXT_CDS = ".cds"
48
48
  exports.MTX_SIDECAR_FOLDER = "mtx/sidecar" // default name of the mtx sidecar folder
49
49
  exports.DEFAULT_CSN_FILE_NAME = "csn.json"
50
50
  // REVISIT: the models are not required if a custom server.js file is used for MTX bootstrap
51
- exports.NODEJS_MODEL_EXCLUDE_LIST = ['@sap/cds/srv/mtx', '@sap/cds-mtxs/srv/bootstrap']
51
+ exports.NODEJS_MODEL_EXCLUDE_LIST = ['@sap/cds-mtxs/srv/bootstrap']
52
52
 
53
53
  exports.CDS_CONFIG_PATH_SEP = "/"
54
54
  exports.SEVERITY_ERROR = "Error"
@@ -195,11 +195,11 @@ function _filterJournalArtifacts(afterImage) {
195
195
  function _isPersistedAsJournalTable(artifact) {
196
196
  return (
197
197
  artifact.kind === 'entity' &&
198
- artifact['@cds.persistence.journal'] &&
198
+ artifact['@cds.persistence.journal'] === true &&
199
199
  !artifact.abstract &&
200
- !artifact['@cds.persistence.skip'] &&
201
- !artifact['@cds.persistence.exists'] &&
202
- ((!artifact.query && !artifact.projection) || artifact['@cds.persistence.table'])
200
+ artifact['@cds.persistence.skip'] !== true && // might have value 'if-unused'
201
+ artifact['@cds.persistence.exists'] !== true &&
202
+ (!artifact.query && !artifact.projection || artifact['@cds.persistence.table'] === true)
203
203
  )
204
204
  }
205
205
 
@@ -1,11 +1,10 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
  const cds = require('../../cds')
4
- const { hasJavaNature, getDefaultModelOptions, BuildError, hasOptionValue, normalizePath } = require('../util')
4
+ const { hasJavaNature, BuildError, normalizePath } = require('../util')
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
- BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION, NODEJS_MODEL_EXCLUDE_LIST,
8
- IGNORE_DEFAULT_MODELS, OPTION_WS } = require("../constants")
7
+ BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION } = require("../constants")
9
8
  const ResourcesTarBuilder = require('./mtx/resourcesTarBuilder')
10
9
  const DEBUG = cds.debug('cli|build')
11
10
 
@@ -19,10 +18,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
19
18
  }
20
19
 
21
20
  async applyTaskDefaults(task) {
22
- // src folder needs to be initialized first
23
21
  InternalBuildTaskProvider._setDefaultSrcFolder(task)
24
-
25
- await InternalBuildTaskProvider._setDefaultModel(task)
26
22
  }
27
23
 
28
24
  getPlugin(task) {
@@ -284,35 +280,6 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
284
280
  }
285
281
  }
286
282
 
287
- static async _setDefaultModel(task) {
288
- const ws = hasOptionValue(task.options?.[OPTION_WS], true) || cds.cli.options?.[OPTION_WS]
289
- // REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
290
- const filter = hasJavaNature() ? (m) => !NODEJS_MODEL_EXCLUDE_LIST.includes(m) : null
291
- let taskModelPaths = task.options?.model
292
- if (taskModelPaths && !Array.isArray(taskModelPaths)) {
293
- taskModelPaths = [taskModelPaths]
294
- }
295
- const allowList = new RegExp(`^@sap/cds${cds.env.requires.toggles ? '|^' + cds.env.features.folders.replace('*', '') : ''}`)
296
- task.options = task.options || {}
297
- let defaultModelPaths = []
298
- if (taskModelPaths?.length) {
299
- if (!hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
300
- defaultModelPaths = await getDefaultModelOptions(ws, filter)
301
- defaultModelPaths = defaultModelPaths.filter(p => p.match(allowList))
302
- }
303
- } else {
304
- defaultModelPaths = await getDefaultModelOptions(ws, filter)
305
- defaultModelPaths.push(task.src)
306
- if (hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
307
- // all default models except the built-in models
308
- defaultModelPaths = defaultModelPaths.filter(p => !p.match(allowList))
309
- }
310
- }
311
- if (defaultModelPaths.length) {
312
- task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(defaultModelPaths) : defaultModelPaths)]
313
- }
314
- }
315
-
316
283
  /**
317
284
  * Determines the module folder from the given list that may represent files or folders w or w/o .cds file extension.
318
285
  * @param {Array} filesOrFolders
@@ -92,10 +92,10 @@ class ResourcesTarBuilder {
92
92
 
93
93
  return hanaTasks.find(hanaTask => {
94
94
  // if called from internalBuildTaskProvider, the src folder for the tenant db task might still not set
95
- // while an existing second shared db always requires src to be configured using a relative path
95
+ // while an existing second shared db always requires src to be set
96
96
  if (!hanaTask.src) return true
97
97
  const srcFolder = path.isAbsolute(hanaTask.src) ? path.relative(cds.root, hanaTask.src) : hanaTask.src
98
- return mtxTask.options?.model?.includes(srcFolder)
98
+ return mtxTask.options?.model?.includes(srcFolder) || srcFolder === cds.env.folders.db.replace('/', '')
99
99
  })
100
100
  }
101
101
  }
package/lib/cds.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /** @type { import('@sap/cds/lib') } */
2
2
  const cds = _local ('@sap/cds')
3
3
 
4
+ /** @type { import('@sap/cds/lib') & {_local: (id: string) => any} } */
4
5
  module.exports = Object.defineProperties (cds, {
5
6
  // for internal use in cds-dk only
6
7
  _log: { value: _local ('../bin/util/log'), configurable: true },
@@ -1,4 +1,5 @@
1
- const { compile } = require('@cap-js/openapi')
1
+ const cds = require('../cds')
2
+ const { compile } = cds._local('@cap-js/openapi') // load a local cap-js/openapi (fallback to our own)
2
3
 
3
4
  function cds_compile_to_openapi (csn, options) {
4
5
  return compile(csn, options)
@@ -37,6 +37,7 @@ module.exports = new class HdiDeployUtil {
37
37
  else throw e
38
38
  }
39
39
  if (options.use_hdb !== false) options.use_hdb = true
40
+ if (options.use_hdb === false) options.use_hdb = undefined
40
41
  deployerEnv.HDI_DEPLOY_OPTIONS = JSON.stringify(options)
41
42
 
42
43
  const asyncDeploy = util.promisify(deploy);
@@ -67,7 +67,7 @@ async function getVersion(fileInputStream){
67
67
  oDataVersion = 'V4';
68
68
  }
69
69
  else {
70
- throw new Error(messages.INVALID_EDMX_METADATA_VERSION);
70
+ throw new Error(messages.INVALID_ODATA_VERSION_OR_UNSUPPORTED_ENCODING);
71
71
  }
72
72
 
73
73
  return oDataVersion;
@@ -2,7 +2,7 @@
2
2
 
3
3
  const messages = {
4
4
  INVALID_EDMX_METADATA: 'The OData model is not valid. Specify the correct OData model.',
5
- INVALID_EDMX_METADATA_VERSION: 'The OData version is not valid. Specify the correct OData version.',
5
+ INVALID_ODATA_VERSION_OR_UNSUPPORTED_ENCODING: 'Either the OData version is not valid, or the encoding of the file is not utf-8. Please specify the supported OData version and file encoding. OData version is expected one of [1.0, 2.0, 4.0, 4.01] and the input file encoding is expected UTF-8.',
6
6
  INVALID_OUTPUT_FILE: 'Please provide an output file with one of these [cds, csn, json] file extension.',
7
7
  SPECIFY_INPUT_FILE: 'Specify an input file that exists.',
8
8
  SPECIFY_OUTPUT_FILE: 'Specify an output file or correct the output file path provided.',
@@ -45,4 +45,4 @@ function getMessages() {
45
45
 
46
46
  module.exports = {
47
47
  getMessages
48
- };
48
+ };
@@ -355,7 +355,7 @@ function _extractAllFunctionImports(functionImports, parserContext) {
355
355
  }
356
356
 
357
357
  function _replaceSpecialCharacters(text) {
358
- return text.replace(/(?:\\[rn]|[\r\n]+)+/gm, "\\n").replace(/\s+/g, ' ').replace(/"/g, """).trim();
358
+ return text.replace(/\\/g, "\\\\").replace(/(?:\\[rn]|[\r\n]+)+/gm, "\\n").replace(/\s+/g, ' ').replace(/"/g, """).trim();
359
359
  }
360
360
 
361
361
  // to parse the documentation tag
@@ -972,7 +972,7 @@ function _parseEntityProperty(properties, parserContext) {
972
972
  // Has more than one entities
973
973
  for (let i = 0; i < properties.length; i++) {
974
974
  propAttributes = properties[i]._attributes;
975
- // if the property contains documentatin tag
975
+ // if the property contains documentation tag
976
976
  if (properties[i] && properties[i].Documentation)
977
977
  propAttributes.doc = _parseDocumentationTag(properties[i].Documentation);
978
978
  retProperties[propAttributes.Name] = _getPropertyAttributes(propAttributes, parserContext);
package/lib/init/bas.js CHANGED
@@ -5,8 +5,10 @@ const { bold } = require('../util/term')
5
5
  const { OPTIONS } = require('./constants')
6
6
  const {
7
7
  NODEJS, JAVA,
8
- HANA, APPROUTER, XSUAA, APPLICATION_LOGGING, ENTERPRISE_MESSAGING,
9
- MTA, MULTITENANCY, PIPELINE,
8
+ XSUAA, APPROUTER, CONNECTIVITY, DESTINATION, HTML5_REPO, PORTAL, APPLICATION_LOGGING, AUDIT_LOGGING, NOTIFICATIONS,
9
+ ENTERPRISE_MESSAGING, KAFKA, REDIS_MESSAGING,
10
+ HANA, POSTGRES,
11
+ MTA, HELM, CONTAINERIZE, MULTITENANCY, PIPELINE,
10
12
  TINY_SAMPLE, SAMPLE
11
13
  } = OPTIONS
12
14
  const cwd = process.cwd()
@@ -17,75 +19,114 @@ module.exports = [{
17
19
  default: '',
18
20
  target: 'projectName',
19
21
  validate: async projectName => {
20
- try {
21
- cds.root = path.resolve(cwd, projectName || '.')
22
- validate.projectName(projectName)
23
- validate.projectFolder(path.join(cwd, projectName), cwd)
24
- } catch (e) {
25
- return e // BAS Yeoman generator requires error to be returned
26
- }
27
- return true
22
+ try {
23
+ cds.root = path.resolve(cwd, projectName || '.')
24
+ validate.projectName(projectName)
25
+ validate.projectFolder(path.join(cwd, projectName), cwd)
26
+ } catch (e) {
27
+ return e // BAS Yeoman generator requires error to be returned
28
+ }
29
+ return true
28
30
  },
29
31
  guiOptions: {
30
- hint: 'This name is restricted to certain characters. A valid project name is compatible across platforms.',
31
- mandatory: true
32
+ breadcrumb: 'Project Name',
33
+ hint: 'This name is restricted to certain characters. A valid project name is compatible across platforms.',
34
+ mandatory: true
32
35
  }
33
36
  }, {
34
37
  title: 'Type',
35
38
  description: `Select your runtime.`,
36
39
  default: NODEJS,
37
40
  choices: [
38
- { name: 'Node.js', value: NODEJS },
39
- { name: 'Java', value: JAVA }
41
+ { name: 'Node.js', value: NODEJS },
42
+ { name: 'Java', value: JAVA }
40
43
  ],
41
44
  multiple: false,
42
45
  target: 'add',
43
46
  guiOptions: {
44
- hint: `The preferred runtime can't be changed afterwards. To use a different runtime, create a new project.`,
45
- mandatory: true
47
+ breadcrumb: 'Runtime',
48
+ hint: `The preferred runtime can't be changed afterwards. To use a different runtime, create a new project.`,
49
+ mandatory: true
46
50
  }
47
51
  }, {
48
- title: 'Features',
49
- description: 'Choose productive runtime capabilities for your application.',
52
+ title: 'Databases',
53
+ description: 'Choose a database for your application.',
50
54
  default: '',
51
55
  choices: [
52
- { name: 'SAP HANA Cloud', value: HANA },
53
- { name: 'SAP Application Router', value: APPROUTER },
54
- { name: 'User Authentication via XSUAA', value: XSUAA },
55
- { name: 'Application Logging', value: APPLICATION_LOGGING },
56
- { name: 'SAP BTP Event Mesh', value: ENTERPRISE_MESSAGING }
56
+ { name: 'SAP HANA Cloud', value: HANA },
57
+ { name: 'PostgreSQL', value: POSTGRES }
57
58
  ],
58
59
  multiple: true,
59
60
  target: 'add',
60
61
  guiOptions: {
61
- hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
62
+ breadcrumb: 'Databases',
63
+ hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
62
64
  }
63
65
  }, {
64
66
  title: 'Deployment',
65
67
  description: 'Choose which way to deploy your project.',
66
68
  default: '',
67
69
  choices: [
68
- { name: 'Cloud Foundry: MTA Deployment', value: MTA },
69
- // { name: 'Kyma: Helm Deployment', value: HELM },
70
- { name: 'Multitenancy', value: MULTITENANCY },
71
- { name: 'CI/CD Pipeline Integration', value: PIPELINE },
70
+ { name: 'Cloud Foundry: MTA Deployment', value: MTA },
71
+ { name: 'Kyma: Helm Deployment', value: HELM },
72
+ { name: 'Kyma: Containerization using ctz CLI', value: CONTAINERIZE },
73
+ { name: 'Multitenancy', value: MULTITENANCY },
74
+ { name: 'CI/CD Pipeline Integration', value: PIPELINE }
75
+ ],
76
+ multiple: true,
77
+ target: 'add',
78
+ guiOptions: {
79
+ breadcrumb: 'Deployment',
80
+ hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
81
+ }
82
+ }, {
83
+ title: 'Runtime Features',
84
+ description: 'Choose productive runtime capabilities for your application.',
85
+ default: '',
86
+ choices: [
87
+ { name: 'SAP BTP Authorization and Trust Management Service (XSUAA)', value: XSUAA },
88
+ { name: 'SAP BTP Application Router', value: APPROUTER },
89
+ { name: 'SAP BTP Connectivity Service', value: CONNECTIVITY },
90
+ { name: 'SAP BTP Destination Service', value: DESTINATION },
91
+ { name: 'SAP BTP HTML5 Application Repository', value: HTML5_REPO },
92
+ { name: 'SAP BTP Portal Service', value: PORTAL },
93
+ { name: 'SAP BTP Application Logging Service', value: APPLICATION_LOGGING },
94
+ { name: 'SAP BTP Audit Logging Service', value: AUDIT_LOGGING },
95
+ { name: 'SAP BTP Notification Service', value: NOTIFICATIONS }
96
+ ],
97
+ multiple: true,
98
+ target: 'add',
99
+ guiOptions: {
100
+ breadcrumb: 'Runtime Features',
101
+ hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
102
+ }
103
+ }, {
104
+ title: 'Messaging',
105
+ description: 'Choose messaging capabilities for your application.',
106
+ default: '',
107
+ choices: [
108
+ { name: 'SAP BTP Event Mesh', value: ENTERPRISE_MESSAGING },
109
+ { name: 'Apache Kafka', value: KAFKA },
110
+ { name: 'Redis', value: REDIS_MESSAGING }
72
111
  ],
73
112
  multiple: true,
74
113
  target: 'add',
75
114
  guiOptions: {
76
- hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
115
+ breadcrumb: 'Messaging',
116
+ hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
77
117
  }
78
118
  }, {
79
119
  title: 'Samples',
80
120
  description: `Add sample content to your project.`,
81
121
  default: '',
82
122
  choices: [
83
- { name: 'Minimal Sample', value: TINY_SAMPLE },
84
- { name: 'Extended Sample with UI', value: SAMPLE }
123
+ { name: 'Minimal Sample', value: TINY_SAMPLE },
124
+ { name: 'Extended Sample with UI', value: SAMPLE }
85
125
  ],
86
126
  multiple: true,
87
127
  target: 'add',
88
128
  guiOptions: {
89
- hint: 'Speed up your ramp-up phase with sample files in your project.'
129
+ breadcrumb: 'Samples',
130
+ hint: 'Speed up your ramp-up phase with sample files in your project.'
90
131
  }
91
132
  }]
@@ -5,7 +5,7 @@ module.exports = {
5
5
  COMMAND_ADD: 'add',
6
6
 
7
7
  JAVA_LTS_VERSIONS: [17, 21],
8
- MAVEN_ARCHETYPE_VERSION: '3.0.1',
8
+ MAVEN_ARCHETYPE_VERSION: '3.1.1',
9
9
 
10
10
  OPTIONS: Object.freeze({
11
11
  COMPLETION: 'completion',
@@ -57,10 +57,7 @@ module.exports = {
57
57
  LINT_DEV: 'lint:dev',
58
58
  PIPELINE: 'pipeline',
59
59
  TYPER: 'typer',
60
- TYPESCRIPT: 'typescript',
61
- EVENT_QUEUE: 'event-queue',
62
- COV2AP: 'cov2ap',
63
- WEBSOCKET: 'websocket'
60
+ TYPESCRIPT: 'typescript'
64
61
  }),
65
62
 
66
63
  REGEX_JAVA_PACKAGE: /^[a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*)*$/g,
package/lib/init/merge.js CHANGED
@@ -70,7 +70,8 @@ module.exports.mergeGitignore = async function(into, from) {
70
70
  /**
71
71
  * @typedef {Object} Deletion
72
72
  * @property {MatchedNode} item - matched node to delete
73
- * @property {Object[]} relationships - list of relationships to delete
73
+ * @property {MatchedNode} [key] - key path to property to delete in node (optional)
74
+ * @property {Object[]} [relationships] - list of relationships to delete
74
75
  * @property {string} relationships[].removeProperty - key path to to-be-removed property
75
76
  * @property {string[]} relationships[].allWithin - key path to relationship
76
77
  */
@@ -285,10 +286,11 @@ async function _mergeYAML(into, from, project, semantics = {}) {
285
286
  })
286
287
 
287
288
  // 4. Delete entries from the project (e.g. separate deployer module when adding mtx)
288
- deletions?.forEach(({ item, relationships }) => {
289
+ deletions?.forEach(({ item, relationships, key }) => {
289
290
  const entry = entryMap.get(item)
290
291
  if (!entry) return
291
- entry.collection.delete(entry.index)
292
+ if (key) entry.collection.deleteIn([entry.index, ...key.split('.')])
293
+ else entry.collection.delete(entry.index)
292
294
 
293
295
  relationships?.forEach(relationship => {
294
296
  const [allWithinKeyPath, inKeyPath, into] = relationship.allWithin
@@ -3,7 +3,6 @@ const { join, resolve, basename } = require('path')
3
3
  const { fs, exists, isdir, path } = cds.utils
4
4
  const { parseXml } = require('./xml')
5
5
  const { REGEX_JAVA_VERSION, JAVA_LTS_VERSIONS } = require('./constants')
6
- const DEBUG = cds.debug('cli')
7
6
  const TRACE = cds.debug('trace')
8
7
 
9
8
  module.exports = new class ProjectReader {
@@ -15,7 +15,7 @@ const MAX_ASSOC_DEPTH = 5
15
15
  * @returns {Record<string, object[]>} the filled data
16
16
  */
17
17
  const asJson = module.exports = async (data, csn, numRecords=1, options={}) => {
18
- let { referenceData } = options
18
+ let { referenceData, contentType } = options
19
19
 
20
20
  // if no entity restrictions are given, use all entities
21
21
  if (!data) data = csn.all('entity').reduce((all, e) => { all[e.name] = []; return all }, {})
@@ -63,6 +63,14 @@ const asJson = module.exports = async (data, csn, numRecords=1, options={}) => {
63
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
64
  data[name] = uniqRecords(data[name], entity)
65
65
  }
66
+ for (let [key, d] of Object.entries(data)) {
67
+ if (contentType === 'json' && d.deleteReference && !d.keepReferece) {
68
+ delete data[key]
69
+ }
70
+ delete d.keepReferece
71
+ delete d.deleteReference
72
+ uniqRecords(d, csn.definitions[key])
73
+ }
66
74
  return data
67
75
  }
68
76
 
@@ -222,17 +230,16 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
222
230
  }
223
231
  case 'cds.Composition': {
224
232
  const target = csn.definitions[element.target]
225
- if (!target)
226
- return
227
- delete data[target.name] // as data for the target is created inline below, no need to have it separately
228
- if (target === parentEntity || depth > MAX_ASSOC_DEPTH)
229
- return
230
-
231
- const targetRecords = []
233
+ if (!target || entity.name === target.name || depth > MAX_ASSOC_DEPTH) return
234
+
235
+ let targetRecords = [] // in findKeysInOnCondition target records are linked to the entity, we don't want to overwrite any existing data
236
+ if (data[target.name]) data[target.name].deleteReference = true // for json composites references are nested and will be deleted when writing to file
237
+
232
238
  const targetRecordCount = element.is2many ? 2 : 1 // TODO: make this configurable
233
239
  const targetRecordID = randomNumber()
234
240
  for (let i = 0; i < targetRecordCount; i++) {
235
- targetRecords.push(fillRecord({}, targetRecordID+i, target, csn, data, entity, depth+1, referenceData))
241
+ const newRecord = fillRecord({}, targetRecordID+i, target, csn, data, entity, depth+1, referenceData)
242
+ if (newRecord) targetRecords.push(newRecord)
236
243
  }
237
244
 
238
245
  const [ownKey, ownKeyStructured, targetKey] = findKeysInOnCondition(element, target)
@@ -268,11 +275,14 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
268
275
  return
269
276
 
270
277
  if (targetRecords.length > 0) { // use record generated by following asociation
271
- targetRecord = targetRecords[0]
278
+ targetRecord = targetRecords.at(-1) // make sure the localized record references the newly generated texts
272
279
  } else {
273
280
  targetRecord = fillRecord({}, randomNumber(), target, csn, data, entity, depth+1, referenceData)
274
- targetRecords.push(targetRecord)
275
- uniqRecords(targetRecords, target)
281
+ if (targetRecord) {
282
+ targetRecords.push(targetRecord)
283
+ uniqRecords(targetRecords, target)
284
+ }
285
+ if (parentEntity && (parentEntity.name != entity.name)) data[target.name].keepReferece = true
276
286
  }
277
287
  }
278
288
 
@@ -77,7 +77,7 @@ module.exports = class DataTemplate extends require('../../plugin') {
77
77
  .filter (e => queries || !e.query) // remove all projection-like entities unless specified differently
78
78
  .reduce((all, e) => { all[e.name] = []; return all }, {})
79
79
 
80
- await asJson(data, csn, records)
80
+ await asJson(data, csn, records, {contentType})
81
81
 
82
82
  if (contentType === 'csv') {
83
83
  const headerOnly = !cds.cli.options['records'] // compat to old behavior which only creates headers
@@ -1,7 +1,9 @@
1
1
  const cds = require('../../..')
2
2
  const { rimraf, exists, readFileSync, yaml } = cds.utils
3
3
  const { join } = require('path')
4
- const { merge, readProject } = cds.add ?? {}
4
+
5
+ const { readProject } = require('../../projectReader')
6
+ const { merge } = require('../../merge')
5
7
 
6
8
  module.exports = class HelmUnifiedRuntimeTemplate extends require('../helm') {
7
9
 
@@ -8,7 +8,7 @@ const { copyRenderedJSON } = require('../../../util/fs')
8
8
  const {
9
9
  srv4, // Server
10
10
  mtxSidecar4, // Additional Modules
11
- saasRegistry, serviceManager, xsuaa, // BTP Services
11
+ saasRegistry, // BTP Services
12
12
  srvApi4, providedMtxApiSidecar4, requiredMtxSidecarApi4 // APIs
13
13
  } = require('../../registries/mta')
14
14
 
@@ -47,13 +47,9 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
47
47
  const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
48
48
  const modules = [srv, mtxSidecar]
49
49
  const services = [saasRegistry]
50
- if (hasXsuaa) services.push(xsuaa)
51
50
  const apis = [srvApi4(srv), providedMtxApiSidecar4(mtxSidecar)]
52
51
  if (isJava) apis.push(requiredMtxSidecarApi4(srv))
53
52
  const additions = [...modules, ...services, ...apis]
54
-
55
- const overwrites = hasXsuaa ? [{ item: [xsuaa, 'parameters.config.tenant-mode'], withValue: 'shared' }] : []
56
-
57
53
  const relationships = [{
58
54
  insert: [saasRegistry, 'name'],
59
55
  into: [isJava ? srv : mtxSidecar, 'requires', 'name']
@@ -64,34 +60,16 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
64
60
  into: [mtxSidecar, 'build-parameters.requires', 'name']
65
61
  })
66
62
  }
67
- if (hasXsuaa) {
68
- relationships.push({
69
- insert: [xsuaa, 'name'],
70
- into: [mtxSidecar, 'requires', 'name']
71
- })
72
- }
73
- if (hasHana) {
74
- relationships.push({
75
- insert: [serviceManager, 'name'],
76
- into: [mtxSidecar, 'requires', 'name'],
77
- })
78
- }
79
63
 
80
- const templateMtaPath = join(__dirname, 'files', 'mta.yaml.hbs')
81
- await merge(templateMtaPath).into('mta.yaml', { with: project, additions, overwrites, relationships })
64
+ const templateMtaPath = join(__dirname, 'files/mta.yaml.hbs')
65
+ await merge(templateMtaPath).into('mta.yaml', { with: project, additions, relationships })
82
66
  }
83
67
 
84
68
  if (hasHelm || hasHelmUnifiedRuntime) {
85
- const overwrites = hasXsuaa ? [{
86
- item: [{
87
- in: 'xsuaa',
88
- where: { serviceOfferingName: 'xsuaa' }
89
- }, 'parameters.tenant-mode'], withValue: 'shared'
90
- }] : []
91
69
 
92
- await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project, overwrites })
70
+ await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
93
71
 
94
- const domain = hasApprouter ? 'svc.cluster.local:8080' : '{{ .Values.global.domain }}'
72
+ const domain = hasApprouter ? 'svc.cluster.local:8080' : '{{ .Values.global.domain }}'
95
73
  const applicationWorkload = hasApprouter ? 'approuter' : 'srv'
96
74
  const serviceCommunicatingWithSaasReg = hasApprouter ? 'approuter' : isNodejs ? 'sidecar' : 'srv';
97
75
  await merge({
@@ -102,7 +80,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
102
80
  appUrls: {
103
81
  getDependencies: `https://{{ .Release.Name }}-${serviceCommunicatingWithSaasReg}-{{ .Release.Namespace }}.{{ .Values.global.domain }}${isNodejs ? '/-/cds/saas-provisioning' : '/mt/v1.0/subscriptions'}/dependencies`,
104
82
  onSubscription: `https://{{ .Release.Name }}-${serviceCommunicatingWithSaasReg}-{{ .Release.Namespace }}.{{ .Values.global.domain }}${isNodejs ? '/-/cds/saas-provisioning/tenant/{tenantId}' : '/mt/v1.0/subscriptions/tenants/{tenantId}'}`,
105
- }
83
+ }
106
84
  }
107
85
  },
108
86
  ...(isNodejs) && { sidecar: {
@@ -110,12 +88,12 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
110
88
  SUBSCRIPTION_URL: `https://\${tenant_subdomain}-{{ .Release.Name }}-${applicationWorkload}-{{ .Release.Namespace }}.{{ .Values.global.domain }}`
111
89
  }
112
90
  }},
113
- ...(isJava) && { srv: {
91
+ ...(isJava) && { srv: {
114
92
  env: {
115
93
  CDS_MULTITENANCY_APPUI_URL: `https://{{ .Release.Name }}-${applicationWorkload}-{{ .Release.Namespace }}.{{ .Values.global.domain }}`,
116
94
  CDS_MULTITENANCY_SIDECAR_URL: `http${hasApprouter ? '' : 's'}://{{ .Release.Name }}-sidecar${hasApprouter ? '.' : '-'}{{ .Release.Namespace }}.${domain}`
117
- }
118
- }}
95
+ }
96
+ }}
119
97
  }).into('chart/values.yaml',{ forceOverwrite: true })
120
98
  }
121
99
 
@@ -13,12 +13,12 @@ class CatalogService extends cds.ApplicationService { init() {
13
13
  // Reduce stock of ordered books if available stock suffices
14
14
  this.on('submitOrder', async req => {
15
15
  let { book:id, quantity } = req.data
16
- let book = await SELECT.from (Books, id, b => b.stock)
16
+ let book = await SELECT.one.from (Books, id, b => b.stock)
17
17
 
18
18
  // Validate input data
19
19
  if (!book) return req.error (404, `Book #${id} doesn't exist`)
20
20
  if (quantity < 1) return req.error (400, `quantity has to be 1 or more`)
21
- if (quantity > book.stock) return req.error (409, `${quantity} exceeds stock for book #${id}`)
21
+ if (!book.stock || quantity > book.stock) return req.error (409, `${quantity} exceeds stock for book #${id}`)
22
22
 
23
23
  // Reduce stock in database and return updated stock value
24
24
  await UPDATE (Books, id) .with ({ stock: book.stock -= quantity })
@@ -11,6 +11,10 @@ service CatalogService {
11
11
  } excluding { createdBy, modifiedBy };
12
12
 
13
13
  @requires: 'authenticated-user'
14
- action submitOrder ( book: Books:ID, quantity: Integer ) returns { stock: Integer };
14
+ action submitOrder (
15
+ book : Books:ID @mandatory,
16
+ quantity: Integer @mandatory
17
+ ) returns { stock: Integer };
18
+
15
19
  event OrderedBook : { book: Books:ID; quantity: Integer; buyer: String };
16
20
  }
@@ -39,7 +39,7 @@ module.exports = class XsuaaTemplate extends require('../../plugin') {
39
39
  const additions = [srv, xsuaa]
40
40
  const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
41
41
  if (hasMultitenancy && isJava) additions.push(mtxSidecar)
42
-
42
+ const overwrites = hasMultitenancy ? [{ item: [xsuaa, 'parameters.config.tenant-mode'], withValue: 'shared' }] : []
43
43
  const relationships = [{
44
44
  insert: [xsuaa, 'name'],
45
45
  into: [srv, 'requires', 'name']
@@ -48,11 +48,18 @@ module.exports = class XsuaaTemplate extends require('../../plugin') {
48
48
  insert: [xsuaa, 'name'],
49
49
  into: [mtxSidecar, 'requires', 'name']
50
50
  })
51
- await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { project, additions, relationships })
51
+
52
+ await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { project, additions, overwrites, relationships })
52
53
  }
53
54
 
54
55
  if (hasHelm || hasHelmUnifiedRuntime) {
55
- await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
56
+ const overwrites = hasMultitenancy ? [{
57
+ item: [{
58
+ in: 'xsuaa',
59
+ where: { serviceOfferingName: 'xsuaa' }
60
+ }, 'parameters.tenant-mode'], withValue: 'shared'
61
+ }] : []
62
+ await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project, overwrites })
56
63
 
57
64
  await merge({
58
65
  xsuaa: {
package/lib/mtx/push.js CHANGED
@@ -95,7 +95,9 @@ module.exports = class Push {
95
95
  }, 5 * 60 * 1000);
96
96
 
97
97
  const interval = setInterval(async () => {
98
- const { status, error = 'cds push failed' } = (await axios.get(jobUrl, options)).data;
98
+ const jobResult = await axios.get(jobUrl, options);
99
+ const { status, tasks } = jobResult.data;
100
+ const error = tasks[0]?.error ?? 'cds push failed'
99
101
  if (status === JOB_STATUS.FINISHED || status === JOB_STATUS.FAILED) {
100
102
  clearInterval(interval);
101
103
  clearTimeout(timeout);
@@ -115,7 +115,10 @@ async function fetchPasscodeUrl(params) {
115
115
  DEBUG?.(`Trying to get passcode URL from GET`, url);
116
116
  let responseData;
117
117
  try {
118
- const response = await axios.get(url /* no auth required */);
118
+ const config = params.has('subdomain')
119
+ ? { params: { subdomain: params.get('subdomain') } }
120
+ : undefined;
121
+ const response = await axios.get(url, config /* no auth required */);
119
122
  responseData = response.data;
120
123
  } catch (error) {
121
124
  if (error.status === 404) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "8.1.0",
3
+ "version": "8.1.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sap/cds-dk",
9
- "version": "8.1.0",
9
+ "version": "8.1.2",
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "dependencies": {
12
12
  "@cap-js/asyncapi": "^1.0.0",
@@ -53,13 +53,13 @@
53
53
  }
54
54
  },
55
55
  "node_modules/@cap-js/openapi": {
56
- "version": "1.0.4",
56
+ "version": "1.0.5",
57
57
  "license": "SEE LICENSE IN LICENSE",
58
58
  "dependencies": {
59
59
  "pluralize": "^8.0.0"
60
60
  },
61
61
  "peerDependencies": {
62
- "@sap/cds": ">=7.3"
62
+ "@sap/cds": ">=7.6"
63
63
  }
64
64
  },
65
65
  "node_modules/@cap-js/sqlite": {
@@ -138,7 +138,7 @@
138
138
  }
139
139
  },
140
140
  "node_modules/@eslint/js": {
141
- "version": "9.8.0",
141
+ "version": "9.9.0",
142
142
  "license": "MIT",
143
143
  "engines": {
144
144
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -203,7 +203,7 @@
203
203
  }
204
204
  },
205
205
  "node_modules/@sap/cds": {
206
- "version": "8.1.0",
206
+ "version": "8.1.1",
207
207
  "license": "SEE LICENSE IN LICENSE",
208
208
  "dependencies": {
209
209
  "@sap/cds-compiler": ">=5",
@@ -229,7 +229,7 @@
229
229
  }
230
230
  },
231
231
  "node_modules/@sap/cds-compiler": {
232
- "version": "5.1.0",
232
+ "version": "5.1.2",
233
233
  "license": "SEE LICENSE IN LICENSE",
234
234
  "dependencies": {
235
235
  "antlr4": "4.9.3"
@@ -265,7 +265,7 @@
265
265
  }
266
266
  },
267
267
  "node_modules/@sap/cds-mtxs": {
268
- "version": "2.0.3",
268
+ "version": "2.0.5",
269
269
  "license": "SEE LICENSE IN LICENSE",
270
270
  "dependencies": {
271
271
  "@sap/hdi-deploy": ">=4",
@@ -313,12 +313,12 @@
313
313
  }
314
314
  },
315
315
  "node_modules/@sap/hdi-deploy": {
316
- "version": "5.2.0",
316
+ "version": "5.2.1",
317
317
  "hasInstallScript": true,
318
318
  "license": "See LICENSE file",
319
319
  "dependencies": {
320
320
  "@sap/hdi": "4.5.2",
321
- "@sap/xsenv": "5.1.0",
321
+ "@sap/xsenv": "5.2.0",
322
322
  "async": "3.2.5",
323
323
  "dotenv": "16.4.5",
324
324
  "handlebars": "4.7.8",
@@ -345,10 +345,10 @@
345
345
  "license": "MIT"
346
346
  },
347
347
  "node_modules/@sap/xsenv": {
348
- "version": "5.1.0",
348
+ "version": "5.2.0",
349
349
  "license": "SEE LICENSE IN LICENSE file",
350
350
  "dependencies": {
351
- "debug": "4.3.4",
351
+ "debug": "4.3.5",
352
352
  "node-cache": "^5.1.0",
353
353
  "verror": "1.10.1"
354
354
  },
@@ -449,7 +449,7 @@
449
449
  "license": "MIT"
450
450
  },
451
451
  "node_modules/axios": {
452
- "version": "1.7.2",
452
+ "version": "1.7.4",
453
453
  "license": "MIT",
454
454
  "dependencies": {
455
455
  "follow-redirects": "^1.15.6",
@@ -723,7 +723,7 @@
723
723
  }
724
724
  },
725
725
  "node_modules/debug": {
726
- "version": "4.3.4",
726
+ "version": "4.3.5",
727
727
  "license": "MIT",
728
728
  "dependencies": {
729
729
  "ms": "2.1.2"
@@ -869,14 +869,14 @@
869
869
  }
870
870
  },
871
871
  "node_modules/eslint": {
872
- "version": "9.8.0",
872
+ "version": "9.9.0",
873
873
  "license": "MIT",
874
874
  "dependencies": {
875
875
  "@eslint-community/eslint-utils": "^4.2.0",
876
876
  "@eslint-community/regexpp": "^4.11.0",
877
877
  "@eslint/config-array": "^0.17.1",
878
878
  "@eslint/eslintrc": "^3.1.0",
879
- "@eslint/js": "9.8.0",
879
+ "@eslint/js": "9.9.0",
880
880
  "@humanwhocodes/module-importer": "^1.0.1",
881
881
  "@humanwhocodes/retry": "^0.3.0",
882
882
  "@nodelib/fs.walk": "^1.2.8",
@@ -915,6 +915,14 @@
915
915
  },
916
916
  "funding": {
917
917
  "url": "https://eslint.org/donate"
918
+ },
919
+ "peerDependencies": {
920
+ "jiti": "*"
921
+ },
922
+ "peerDependenciesMeta": {
923
+ "jiti": {
924
+ "optional": true
925
+ }
918
926
  }
919
927
  },
920
928
  "node_modules/eslint-scope": {
@@ -1345,7 +1353,7 @@
1345
1353
  }
1346
1354
  },
1347
1355
  "node_modules/hdb": {
1348
- "version": "0.19.8",
1356
+ "version": "0.19.9",
1349
1357
  "license": "Apache-2.0",
1350
1358
  "dependencies": {
1351
1359
  "iconv-lite": "^0.4.18"
@@ -1398,7 +1406,7 @@
1398
1406
  "optional": true
1399
1407
  },
1400
1408
  "node_modules/ignore": {
1401
- "version": "5.3.1",
1409
+ "version": "5.3.2",
1402
1410
  "license": "MIT",
1403
1411
  "engines": {
1404
1412
  "node": ">= 4"
@@ -2304,7 +2312,7 @@
2304
2312
  }
2305
2313
  },
2306
2314
  "node_modules/uglify-js": {
2307
- "version": "3.19.0",
2315
+ "version": "3.19.2",
2308
2316
  "license": "BSD-2-Clause",
2309
2317
  "optional": true,
2310
2318
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "8.1.0",
3
+ "version": "8.1.2",
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,5 +0,0 @@
1
- {
2
- "dependencies": {
3
- "@cap-js-community/odata-v2-adapter": "^1"
4
- }
5
- }
@@ -1,31 +0,0 @@
1
- const { readProject } = require('../../projectReader')
2
- const { merge, sort } = require('../../merge')
3
- const { link } = require('../../../util/term')
4
- const { CAP_JS_COMMUNITY_ODATA_V2 } = require('../../constants').URLS
5
-
6
- module.exports = class Cov2apTemplate extends require('../../plugin') {
7
-
8
- static help() {
9
- return 'cap-js-community: expose CDS services via the OData V2 protocol'
10
- }
11
-
12
- static hasInProduction() {
13
- const { dependencies } = readProject()
14
- return !!dependencies?.['@cap-js-community/odata-v2-adapter']
15
- }
16
-
17
- async canRun() {
18
- const { isJava } = readProject()
19
- if (isJava) throw `'cds add cov2ap' is not available for Java`
20
- return true
21
- }
22
-
23
- async run() {
24
- await merge(__dirname, 'files/dependencies.package.json').into('package.json')
25
- await sort('package.json', 'dependencies')
26
- }
27
-
28
- async finalize() {
29
- console.log(`Find plugin documentation on ${link(CAP_JS_COMMUNITY_ODATA_V2)}`)
30
- }
31
- }
@@ -1,5 +0,0 @@
1
- {
2
- "dependencies": {
3
- "@cap-js-community/event-queue": "^1"
4
- }
5
- }
@@ -1,35 +0,0 @@
1
- const { readProject } = require('../../projectReader')
2
- const { merge, sort } = require('../../merge')
3
- const { link } = require('../../../util/term')
4
- const { CAP_JS_COMMUNITY_EVENT_QUEUE } = require('../../constants').URLS
5
-
6
- module.exports = class EventQueueTemplate extends require('../../plugin') {
7
-
8
- static help() {
9
- return 'cap-js-community: transactional event processing with automatic load distribution'
10
- }
11
-
12
- async canRun() {
13
- const { isJava } = readProject()
14
- if (isJava) throw `'cds add event-queue' is not available for Java`
15
- return true
16
- }
17
-
18
- static hasInProduction() {
19
- const { dependencies } = readProject()
20
- return !!dependencies?.['@cap-js-community/event-queue']
21
- }
22
-
23
- requires() {
24
- return ['redis']
25
- }
26
-
27
- async run() {
28
- await merge(__dirname, 'files/dependencies.package.json').into('package.json')
29
- await sort('package.json', 'dependencies')
30
- }
31
-
32
- async finalize() {
33
- console.log(`Find plugin documentation on ${link(CAP_JS_COMMUNITY_EVENT_QUEUE)}`)
34
- }
35
- }
@@ -1,5 +0,0 @@
1
- {
2
- "dependencies": {
3
- "@cap-js-community/websocket": "^1"
4
- }
5
- }
@@ -1,35 +0,0 @@
1
- const { readProject } = require('../../projectReader')
2
- const { merge, sort } = require('../../merge')
3
- const { link } = require('../../../util/term')
4
- const { CAP_JS_COMMUNITY_WEBSOCKET } = require('../../constants').URLS
5
-
6
- module.exports = class WebsocketTemplate extends require('../../plugin') {
7
-
8
- static help() {
9
- return 'cap-js-community: expose CDS services via the Websocket protocol'
10
- }
11
-
12
- async canRun() {
13
- const { isJava } = readProject()
14
- if (isJava) throw `'cds add websocket' is not available for Java`
15
- return true
16
- }
17
-
18
- requires() {
19
- return ['redis']
20
- }
21
-
22
- static hasInProduction() {
23
- const { dependencies } = readProject()
24
- return !!dependencies?.['@cap-js-community/websocket']
25
- }
26
-
27
- async run() {
28
- await merge(__dirname, 'files/dependencies.package.json').into('package.json')
29
- await sort('package.json', 'dependencies')
30
- }
31
-
32
- async finalize() {
33
- console.log(`Find plugin documentation on ${link(CAP_JS_COMMUNITY_WEBSOCKET)}`)
34
- }
35
- }