@sap/cds-dk 7.4.0 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/bin/activate.js +1 -1
  2. package/bin/add.js +6 -4
  3. package/bin/build.js +10 -12
  4. package/bin/cds.js +4 -1
  5. package/bin/deploy/index.js +5 -2
  6. package/bin/eval.js +1 -1
  7. package/bin/extend.js +3 -3
  8. package/bin/login.js +2 -2
  9. package/bin/logout.js +1 -1
  10. package/bin/pull.js +1 -1
  11. package/bin/push.js +5 -5
  12. package/bin/subscribe.js +2 -2
  13. package/bin/unsubscribe.js +2 -2
  14. package/bin/upgrade.js +2 -2
  15. package/bin/version.js +2 -2
  16. package/bin/watch.js +1 -1
  17. package/lib/bind/bindingUtil.js +6 -3
  18. package/lib/bind/cfKeyProvider.js +1 -1
  19. package/lib/bind/userCdsrcJsonStorageProvider.js +1 -1
  20. package/lib/build/buildPlugin.js +6 -12
  21. package/lib/build/buildTaskEngine.js +24 -19
  22. package/lib/build/buildTaskFactory.js +27 -33
  23. package/lib/build/buildTaskProvider.js +1 -1
  24. package/lib/build/buildTaskProviderFactory.js +26 -41
  25. package/lib/build/constants.js +0 -1
  26. package/lib/build/index.js +3 -3
  27. package/lib/build/plugins.js +15 -15
  28. package/lib/build/provider/edmxBuildPlugin.js +6 -7
  29. package/lib/build/provider/fiori/index.js +8 -8
  30. package/lib/build/provider/hana/2migration.js +12 -16
  31. package/lib/build/provider/hana/index.js +5 -7
  32. package/lib/build/provider/hana/template/package.json +1 -1
  33. package/lib/build/provider/internalBuildPlugin.js +0 -8
  34. package/lib/build/provider/internalBuildTaskProvider.js +17 -21
  35. package/lib/build/provider/java/index.js +2 -1
  36. package/lib/build/provider/mtx-extension/index.js +8 -5
  37. package/lib/build/provider/mtx-sidecar/index.js +2 -1
  38. package/lib/build/provider/nodejs/index.js +64 -58
  39. package/lib/compile/openapi/csdl2openapi.js +29 -15
  40. package/lib/compile/openapi/index.js +6 -6
  41. package/lib/deploy/to-hana/hana.js +5 -3
  42. package/lib/env/schema.js +2 -3
  43. package/lib/index.js +68 -28
  44. package/lib/init/add.js +17 -0
  45. package/lib/init/constants.js +5 -3
  46. package/lib/init/index.js +39 -25
  47. package/lib/init/{util/merge.js → merge.js} +32 -20
  48. package/lib/init/{util/mvn.js → mvn.js} +5 -5
  49. package/lib/init/plugin.js +85 -0
  50. package/lib/init/projectReader.js +145 -0
  51. package/lib/init/registries/mta.js +151 -0
  52. package/lib/init/template/{kibana → application-logging}/files/mta.yaml.hbs +3 -3
  53. package/lib/init/template/application-logging/index.js +49 -0
  54. package/lib/init/template/approuter/files/mta.yaml.hbs +11 -11
  55. package/lib/init/template/approuter/files/xs-app.json.hbs +2 -2
  56. package/lib/init/template/approuter/index.js +36 -81
  57. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +3 -3
  58. package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +4 -4
  59. package/lib/init/template/cf-manifest/index.js +4 -4
  60. package/lib/init/template/connectivity/index.js +22 -35
  61. package/lib/init/template/data/index.js +3 -2
  62. package/lib/init/template/destination/files/values.yaml +9 -0
  63. package/lib/init/template/destination/index.js +15 -47
  64. package/lib/init/template/enterprise-messaging/index.js +26 -58
  65. package/lib/init/template/enterprise-messaging-shared/index.js +23 -39
  66. package/lib/init/template/extensibility/index.js +16 -30
  67. package/lib/init/template/file-based-messaging/index.js +7 -8
  68. package/lib/init/template/h2/index.js +4 -4
  69. package/lib/init/template/hana/files/mta.yaml.hbs +8 -8
  70. package/lib/init/template/hana/index.js +29 -115
  71. package/lib/init/template/helm/files/chart/templates/NOTES.txt +12 -0
  72. package/lib/init/template/helm/files/chart/templates/_deployment_helpers.tpl +82 -0
  73. package/lib/init/template/helm/files/chart/templates/_helpers.tpl +28 -0
  74. package/lib/init/template/helm/files/chart/values.root.schema.json +61 -0
  75. package/lib/init/template/helm/files/chart/values.schema.json +366 -0
  76. package/lib/init/template/helm/{subcharts → files}/web-application/Chart.yaml +1 -1
  77. package/lib/init/template/helm/{subcharts → files}/web-application/templates/_api.tpl +1 -1
  78. package/lib/init/template/helm/{subcharts → files}/web-application/values.yaml +1 -1
  79. package/lib/init/template/helm/index.js +84 -85
  80. package/lib/init/template/helm-unified-runtime/files/Chart.yaml.hbs +10 -0
  81. package/lib/init/template/helm-unified-runtime/files/values.yaml.hbs +26 -0
  82. package/lib/init/template/helm-unified-runtime/index.js +91 -0
  83. package/lib/init/template/helm-unified-runtime/lib/build.js +0 -0
  84. package/lib/init/template/helm-unified-runtime/package.json +4 -0
  85. package/lib/init/template/html5-repo/files/values.yaml.hbs +28 -0
  86. package/lib/init/template/html5-repo/index.js +23 -97
  87. package/lib/init/template/java/index.js +3 -3
  88. package/lib/init/template/lint/index.js +2 -2
  89. package/lib/init/template/liquibase/index.js +16 -0
  90. package/lib/init/template/local-messaging/index.js +7 -8
  91. package/lib/init/template/mta/index.js +7 -19
  92. package/lib/init/template/mtx/index.js +2 -2
  93. package/lib/init/template/multitenancy/index.js +38 -89
  94. package/lib/init/template/nodejs/index.js +5 -4
  95. package/lib/init/template/notebook/index.js +1 -1
  96. package/lib/init/template/notifications/index.js +16 -19
  97. package/lib/init/template/pipeline/index.js +1 -1
  98. package/lib/init/template/postgres/index.js +25 -31
  99. package/lib/init/template/redis-messaging/index.js +23 -27
  100. package/lib/init/template/sample/index.js +4 -4
  101. package/lib/init/template/samples/index.js +2 -2
  102. package/lib/init/template/sqlite/files/{package.json.hbs → package.json} +0 -2
  103. package/lib/init/template/sqlite/index.js +6 -10
  104. package/lib/init/template/tiny-sample/index.js +6 -6
  105. package/lib/init/template/toggles/index.js +7 -8
  106. package/lib/init/template/typer/index.js +6 -6
  107. package/lib/init/template/xsuaa/files/mta.yaml.hbs +3 -3
  108. package/lib/init/template/xsuaa/files/values.yaml.hbs +3 -3
  109. package/lib/init/template/xsuaa/index.js +27 -52
  110. package/lib/init/{util/template.js → template.js} +1 -1
  111. package/lib/{client → mtx}/activate.js +15 -11
  112. package/lib/{client → mtx}/auth_manager.js +5 -4
  113. package/lib/{client → mtx}/download_legacy.js +6 -4
  114. package/lib/{client → mtx}/extend.js +14 -9
  115. package/lib/{client → mtx}/index.js +1 -1
  116. package/lib/{client → mtx}/params.js +4 -1
  117. package/lib/{client → mtx}/pull.js +6 -4
  118. package/lib/{client → mtx}/push.js +11 -10
  119. package/lib/{client → mtx}/settings_manager.js +8 -6
  120. package/lib/{client → mtx}/tenant_action.js +9 -8
  121. package/lib/{client/helper/cf_helper.js → mtx/util/cf.js} +4 -3
  122. package/lib/{client/helper/dependency_helper.js → mtx/util/dependencies.js} +1 -0
  123. package/lib/mtx/util/errors.js +27 -0
  124. package/lib/mtx/util/legacy_ext.js +16 -0
  125. package/lib/{client/helper/url_helper.js → mtx/util/urls.js} +12 -1
  126. package/lib/util/fs.js +5 -1
  127. package/lib/util/pruneAxiosErrors.js +35 -18
  128. package/lib/util/write.js +1 -1
  129. package/npm-shrinkwrap.json +27 -27
  130. package/package.json +10 -1
  131. package/lib/client/base_command.js +0 -54
  132. package/lib/init/template/_merging/registry-mta.js +0 -304
  133. package/lib/init/template/helm/Model.d.ts +0 -53
  134. package/lib/init/template/kibana/files/package.json.hbs +0 -17
  135. package/lib/init/template/kibana/index.js +0 -54
  136. package/lib/init/template/templateBase.js +0 -100
  137. package/lib/init/util/md5.js +0 -86
  138. package/lib/init/util/projectReader.js +0 -94
  139. /package/lib/init/{util/indent.js → indent.js} +0 -0
  140. /package/lib/init/template/helm/{subcharts → files}/content-deployment/Chart.yaml +0 -0
  141. /package/lib/init/template/helm/{subcharts → files}/content-deployment/templates/_helpers.tpl +0 -0
  142. /package/lib/init/template/helm/{subcharts → files}/content-deployment/templates/job.yaml +0 -0
  143. /package/lib/init/template/helm/{subcharts → files}/content-deployment/templates/secret.yaml +0 -0
  144. /package/lib/init/template/helm/{subcharts → files}/content-deployment/templates/service-account.yaml +0 -0
  145. /package/lib/init/template/helm/{subcharts → files}/content-deployment/templates/service-binding.yaml +0 -0
  146. /package/lib/init/template/helm/{subcharts → files}/content-deployment/values.schema.json +0 -0
  147. /package/lib/init/template/helm/{subcharts → files}/content-deployment/values.yaml +0 -0
  148. /package/lib/init/template/helm/{subcharts → files}/service-instance/Chart.yaml +0 -0
  149. /package/lib/init/template/helm/{subcharts → files}/service-instance/templates/_helpers.tpl +0 -0
  150. /package/lib/init/template/helm/{subcharts → files}/service-instance/templates/serviceinstance.yaml +0 -0
  151. /package/lib/init/template/helm/{subcharts → files}/service-instance/values.schema.json +0 -0
  152. /package/lib/init/template/helm/{subcharts → files}/service-instance/values.yaml +0 -0
  153. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/NOTES.txt +0 -0
  154. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/_helpers.tpl +0 -0
  155. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/api-rule.yaml +0 -0
  156. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/deployment.yaml +0 -0
  157. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/network-policy.yaml +0 -0
  158. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/pod-disruption-budget.yaml +0 -0
  159. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/rbac.yaml +0 -0
  160. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/secret.yaml +0 -0
  161. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/service-account.yaml +0 -0
  162. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/service-binding.yaml +0 -0
  163. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/service.yaml +0 -0
  164. /package/lib/init/template/helm/{subcharts → files}/web-application/templates/virtual-service.yaml +0 -0
  165. /package/lib/init/template/helm/{subcharts → files}/web-application/values.schema.json +0 -0
  166. /package/lib/init/template/{helm/chart → helm-unified-runtime/files}/templates/NOTES.txt +0 -0
  167. /package/lib/init/template/{helm/chart → helm-unified-runtime/files}/templates/_deployment_helpers.tpl +0 -0
  168. /package/lib/init/template/{helm/chart → helm-unified-runtime/files}/templates/_helpers.tpl +0 -0
  169. /package/lib/init/template/{helm/chart → helm-unified-runtime/files}/values.root.schema.json +0 -0
  170. /package/lib/init/template/{helm/chart → helm-unified-runtime/files}/values.schema.json +0 -0
  171. /package/lib/init/template/postgres/files/{mta.yaml.hbs → mta.yml.hbs} +0 -0
  172. /package/lib/init/{util/xml.js → xml.js} +0 -0
  173. /package/lib/{client/helper/env_helper.js → mtx/util/env.js} +0 -0
  174. /package/lib/{client/helper/fs_helper.js → mtx/util/fs.js} +0 -0
  175. /package/lib/{client/helper → mtx/util}/logging.js +0 -0
  176. /package/lib/{client/helper → mtx/util}/question.js +0 -0
  177. /package/lib/{client/helper/string_helper.js → mtx/util/strings.js} +0 -0
  178. /package/lib/util/{cfUtil.js → cf.js} +0 -0
  179. /package/lib/util/{gitUtil.js → git.js} +0 -0
@@ -6,6 +6,7 @@ const { OUTPUT_MODE, OUTPUT_MODE_RESULT, FILE_EXT_CDS, CONTENT_LANGUAGE_BUNDLES,
6
6
  OUTPUT_MODE_FILESYSTEM, FLAVOR_LOCALIZED_EDMX, CONTENT_EDMX, CONTENT_LOCALIZED_EDMX } = require('../../constants')
7
7
  const { getI18nDefaultFolder } = require('../../util')
8
8
  const DEFAULT_COMPILE_DEST_FOLDER = path.normalize('src/main/resources/edmx')
9
+ const DEBUG = cds.debug('cli|build')
9
10
 
10
11
  class JavaBuildPlugin extends EdmxBuildPlugin {
11
12
  init() {
@@ -49,7 +50,7 @@ class JavaBuildPlugin extends EdmxBuildPlugin {
49
50
  if (this.isStagingBuild()) {
50
51
  return super.clean()
51
52
  }
52
- this.logger._debug && this.logger.debug(`Deleting build target folder ${this.task.options.compileDest}`)
53
+ DEBUG?.(`Deleting build target folder ${this.task.options.compileDest}`)
53
54
  await fs.promises.rm(this.task.options.compileDest, { force: true, recursive: true })
54
55
  }
55
56
 
@@ -1,11 +1,11 @@
1
1
  const path = require('path')
2
2
  const fs = require('fs')
3
3
  const cds = require('../../../cds')
4
-
5
4
  const InternalBuildPlugin = require('../internalBuildPlugin')
6
5
  const { FOLDER_GEN, EXTENSION_POINT_VALIDATION } = require('../../constants')
7
6
  const ResourcesTarBuilder = require('../mtx/resourcesTarBuilder')
8
7
  const { BuildError, BuildMessage } = require('../../util')
8
+ const DEBUG = cds.debug('cli|build')
9
9
 
10
10
  class MtxExtensionBuildPlugin extends InternalBuildPlugin {
11
11
  init() {
@@ -37,12 +37,14 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
37
37
  extModel.requires.length = 0
38
38
  }
39
39
 
40
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
41
- // perform all model operations before the linter is called as the linter
40
+ // IMPORTANT NOTE: perform all model operations before the linter is called as the linter
42
41
  // will modify the model causing the creation of 'unresolved' associations
43
42
  await this.compileToJson(extModel, path.join(destExt, 'extension.csn'))
44
43
  await this.collectLanguageBundles(extModel, path.join(destExt, 'i18n'))
45
44
 
45
+ // perform SQL backend validation to prevent extension deployment problems later on
46
+ cds.compile.to.sql(model)
47
+
46
48
  const files = Object.keys(await cds.deploy.resources(model))
47
49
  if (files.length > 0) {
48
50
  const dataDest = path.join(destExt, 'data')
@@ -54,11 +56,12 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
54
56
  })
55
57
  )
56
58
  }
59
+
57
60
  if (!this.hasBuildOption(EXTENSION_POINT_VALIDATION, false)) {
58
61
  try {
59
62
  // throws error in case of linting errors
60
63
  this._lintExtModel(extModel, model)
61
- } catch(error) {
64
+ } catch (error) {
62
65
  // cleanup existing files in case of an error
63
66
  await fs.promises.rm(this.task.dest, { recursive: true })
64
67
  throw error
@@ -105,7 +108,7 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
105
108
  return
106
109
  }
107
110
  const env = cds.env.for('cds', path.join(this.task.src, this._getAppPackageFolder()))
108
- this.logger._debug && this.logger.debug(`Saas extension point restrictions:\n${env.requires?.['cds.xt.ExtensibilityService']}`)
111
+ DEBUG?.(`Saas extension point restrictions:\n${env.requires?.['cds.xt.ExtensibilityService']}`)
109
112
 
110
113
  const messages = linter.lint(extModel, model, env)
111
114
  if (messages.length) {
@@ -6,6 +6,7 @@ const NodejsBuildPlugin = require('../nodejs')
6
6
  const ResourcesTarProvider = require('../mtx/resourcesTarBuilder')
7
7
  const { ERROR } = NodejsBuildPlugin
8
8
  const { relativePaths, BuildError, resolveRequiredSapModels, getI18nDefaultFolder } = require('../../util')
9
+ const DEBUG = cds.debug('cli|build')
9
10
 
10
11
  const DEFAULT_MAIN_FOLDER = "_main"
11
12
 
@@ -114,7 +115,7 @@ class MtxSidecarBuildPlugin extends NodejsBuildPlugin {
114
115
  if (!modelFilePaths || modelFilePaths.length === 0) {
115
116
  throw new BuildError("No CDS models found in MTX sidecar. Make sure up-to-date versions of the required npm modules are installed.")
116
117
  }
117
- this._logger._debug && this._logger.debug(`sidecar model: ${relativePaths(cds.root, modelFilePaths).join(", ")}`)
118
+ DEBUG?.(`sidecar model: ${relativePaths(cds.root, modelFilePaths).join(", ")}`)
118
119
 
119
120
  // check whether all models belonging to the @sap namespace can be resolved
120
121
  const unresolved = resolveRequiredSapModels(modelPaths)
@@ -3,10 +3,11 @@ const path = require('path')
3
3
  const cds = require('../../../cds')
4
4
  const cmd = require('../../../util/command');
5
5
  const EdmxBuildPlugin = require('../edmxBuildPlugin')
6
- const { BuildError, pathExists } = require('../../util')
6
+ const { BuildError } = require('../../util')
7
7
  const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTENT_EDMX, CONTENT_PACKAGELOCK_JSON,
8
8
  CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX } = require('../../constants')
9
9
  const { WARNING } = EdmxBuildPlugin
10
+ const DEBUG = cds.debug('cli|build')
10
11
 
11
12
  class NodejsBuildPlugin extends EdmxBuildPlugin {
12
13
  init() {
@@ -67,7 +68,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
67
68
  if (cds.env.build.target === '.') {
68
69
  // delete the entire 'task.dest' folder otherwise, for details see #constructor
69
70
  // - the value of the folder 'src' has been appended to the origin 'task.dest' dir
70
- this.logger._debug && this.logger.debug(`Deleting build target folder ${this.destSrv}`)
71
+ DEBUG?.(`Deleting build target folder ${this.destSrv}`)
71
72
  await fs.promises.rm(this.isStagingBuild() ? this.task.dest : this.destSrv, { force: true, recursive: true })
72
73
  }
73
74
  }
@@ -159,74 +160,79 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
159
160
  }
160
161
 
161
162
  async _addWorkspaceDependencies(dest) {
162
- let packageDescriptors
163
- try {
164
- packageDescriptors = await this._execNpmPack(dest)
165
- } catch (e) {
166
- this.logger.debug(e)
167
- throw new BuildError(`Failed to package npm workspace dependencies\n${e.message}`)
163
+ const wsRoot = this._findWorkspaceRoot(cds.root)
164
+ const appPkg = require(path.join(dest, 'package.json'))
165
+ let workspaces
166
+ if (this.task.options?.workspaces) {
167
+ workspaces = Array.isArray(this.task.options.workspaces) ? this.task.options.workspaces : [this.task.options.workspaces]
168
168
  }
169
- if (packageDescriptors?.length) {
170
- const packageJson = require(path.join(dest, 'package.json'))
171
- const dependencies = packageJson.dependencies
172
- const devDependencies = packageJson.devDependencies
173
- let changed
174
- const promises = []
175
- for (const packageDescriptor of packageDescriptors) {
176
- const {name, filename: fileName} = packageDescriptor
177
- const filePath = path.join(dest, fileName)
178
- if (dependencies?.[name] === '*' || devDependencies?.[name] === '*') {
179
- if (dependencies?.[name] === '*') {
180
- dependencies[name] = `file:${fileName}`
181
- } else {
182
- devDependencies[name] = `file:${fileName}`
183
- }
184
- this.pushFile(filePath)
185
- changed |= true
186
- } else {
187
- if (await pathExists(filePath)) {
188
- promises.push(fs.promises.rm(filePath))
169
+ if (!workspaces) {
170
+ workspaces = []
171
+ for (const name in appPkg.dependencies) {
172
+ if (appPkg.dependencies[name] === '*') {
173
+ try {
174
+ const pkg = require.resolve(path.join(name, 'package.json'), { paths: [wsRoot] })
175
+ workspaces.push(path.dirname(path.relative(wsRoot, pkg)))
176
+ } catch(e) {
177
+ if (e.code === 'MODULE_NOT_FOUND') {
178
+ throw new BuildError(`Workspace packaging failed - module '${name}' not found. Make sure that configured npm workspaces are installed.`)
179
+ }
180
+ throw e
189
181
  }
190
182
  }
191
183
  }
192
- if (changed) {
193
- promises.push(this.write(JSON.stringify(packageJson, 0, 2)).to(path.join(dest, 'package.json')))
194
- } else {
195
- throw new BuildError('No matching workspaces found!')
196
- }
197
- await Promise.all(promises)
198
184
  }
199
- }
200
-
201
- async _execNpmPack(dest) {
202
- function findWorkspaceRoot(dir) {
203
- if(fs.existsSync(path.join(dir, 'package.json'))) {
204
- if(require(path.join(dir, 'package.json')).workspaces) {
205
- return dir
206
- }
185
+ if (workspaces.length) {
186
+ let pkgDescriptors
187
+ try {
188
+ pkgDescriptors = await this._execNpmPack(dest, wsRoot, workspaces)
189
+ } catch (e) {
190
+ DEBUG?.(e)
191
+ throw new BuildError(`Failed to package npm workspace dependencies\n${e.message}`)
207
192
  }
208
- if(fs.existsSync(path.join(dir, '.gitmodules')) || fs.existsSync(path.join(dir, 'node_modules'))) {
209
- return // project root reached
193
+ if (pkgDescriptors?.length) {
194
+ let changed
195
+ for (const pkgDescriptor of pkgDescriptors) {
196
+ const {name, filename: fileName} = pkgDescriptor
197
+ const filePath = path.join(dest, fileName)
198
+ if (appPkg.dependencies?.[name] === '*') {
199
+ appPkg.dependencies[name] = `file:${fileName}`
200
+ this.pushFile(filePath)
201
+ changed |= true
202
+ }
203
+ }
204
+ if (changed) {
205
+ await this.write(JSON.stringify(appPkg, 0, 2)).to(path.join(dest, 'package.json'))
206
+ } else {
207
+ throw new BuildError('No matching workspaces found!')
208
+ }
210
209
  }
211
- if (path.dirname(dir) !== dir) {
212
- return findWorkspaceRoot(path.dirname(dir))
210
+ }
211
+ }
212
+
213
+ _findWorkspaceRoot(dir) {
214
+ try {
215
+ if(require(path.join(dir, 'package.json')).workspaces) {
216
+ return dir
213
217
  }
218
+ } catch(err) {
219
+ // ignore
214
220
  }
215
- const wsRoot = findWorkspaceRoot(cds.root)
216
- if (!wsRoot) {
217
- throw new BuildError('No workspace configuration found!')
221
+ if(fs.existsSync(path.join(dir, '.gitmodules')) || fs.existsSync(path.join(dir, 'node_modules'))) {
222
+ return // project root reached
218
223
  }
219
- const args = ['pack', '-ws', '--json', `--pack-destination=${dest}`]
220
- if (this.task.options?.workspaces) {
221
- let {workspaces} = this.task.options
222
- workspaces = Array.isArray(workspaces) ? workspaces : [workspaces]
223
- workspaces.forEach(w => args.push(`-w=${w}`))
224
+ if (path.dirname(dir) !== dir) {
225
+ return this._findWorkspaceRoot(path.dirname(dir))
224
226
  }
225
- this.logger._debug && this.logger.debug(`execute command: npm ${args}`)
226
-
227
- const result = await cmd.spawnCommand( 'npm', args, { cwd: wsRoot || cds.root }, true, !!this.logger._debug)
227
+ }
228
+
229
+ async _execNpmPack(dest, wsRoot, workspaces) {
230
+ const args = ['pack', '-ws', '--json', `--pack-destination=${dest}`]
231
+ workspaces.forEach(w => args.push(`-w=${w}`))
228
232
 
229
- this.logger._debug && this.logger.debug(result)
233
+ DEBUG?.(`execute command: npm ${args}`)
234
+ const result = await cmd.spawnCommand( 'npm', args, { cwd: wsRoot }, true, !!DEBUG)
235
+ DEBUG?.(result)
230
236
  return JSON.parse(result)
231
237
  }
232
238
  }
@@ -77,8 +77,18 @@ module.exports.csdl2openapi = function (
77
77
  preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc);
78
78
 
79
79
  const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {};
80
+ if (csdl.$EntityContainer) {
81
+ let serviceName = nameParts(csdl.$EntityContainer).qualifier;
82
+ Object.keys(entityContainer).forEach(element => {
83
+ if (entityContainer[element].$Type) {
84
+ let type = nameParts(entityContainer[element].$Type).name;
85
+ if (csdl[serviceName]?.[type]?.['@cds.autoexpose'] || csdl[serviceName]?.[type]?.['@cds.autoexposed'])
86
+ entityContainer[element]['$cds.autoexpose'] = true;
87
+ }
88
+ });
89
+ }
90
+
80
91
  const keyAsSegment = entityContainer ? entityContainer[voc.Capabilities.KeyAsSegmentSupported] : {};
81
- const deepUpdate = entityContainer ? entityContainer[voc.Capabilities.DeepUpdateSupport] && entityContainer[voc.Capabilities.DeepUpdateSupport].Supported : {};
82
92
 
83
93
  const openapi = {
84
94
  openapi: '3.0.2',
@@ -534,7 +544,7 @@ module.exports.csdl2openapi = function (
534
544
  if (prefixParameters.length > 0) pathItem.parameters = prefixParameters;
535
545
 
536
546
  operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, false, nonExpandable);
537
- if (element.$Collection && (element.$ContainsTarget || level < 2 && target)) {
547
+ if (!root['$cds.autoexpose'] && element.$Collection && (element.$ContainsTarget || level < 2 && target)) {
538
548
  operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions);
539
549
  }
540
550
  pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName);
@@ -544,9 +554,11 @@ module.exports.csdl2openapi = function (
544
554
  if (level < maxLevels)
545
555
  pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable);
546
556
  } else {
547
- operationUpdate(pathItem, element, name, sourceName, target, level, restrictions);
548
- if (element.$Nullable) {
549
- operationDelete(pathItem, element, name, sourceName, target, level, restrictions);
557
+ if (!root['$cds.autoexpose']) {
558
+ operationUpdate(pathItem, element, name, sourceName, target, level, restrictions);
559
+ if (element.$Nullable) {
560
+ operationDelete(pathItem, element, name, sourceName, target, level, restrictions);
561
+ }
550
562
  }
551
563
  pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName);
552
564
  pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPath);
@@ -616,8 +628,10 @@ module.exports.csdl2openapi = function (
616
628
  paths[path] = pathItem;
617
629
 
618
630
  operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, true, nonExpandable);
619
- operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true);
620
- operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true);
631
+ if (!root['$cds.autoexpose']) {
632
+ operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true);
633
+ operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true);
634
+ }
621
635
  if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0)
622
636
  delete paths[path];
623
637
 
@@ -1773,7 +1787,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1773
1787
  title: name,
1774
1788
  enum: members
1775
1789
  };
1776
- const description = type[voc.Core.Description];
1790
+ const description = type[voc.Core.LongDescription];
1777
1791
  if (description) s.description = description;
1778
1792
  schemas[qualifier + '.' + name] = s;
1779
1793
  }
@@ -1789,7 +1803,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1789
1803
  function schemaForTypeDefinition(schemas, qualifier, name, type) {
1790
1804
  const s = getSchema(Object.assign({ $Type: type.$UnderlyingType }, type));
1791
1805
  s.title = name;
1792
- const description = type[voc.Core.Description];
1806
+ const description = type[voc.Core.LongDescription];
1793
1807
  if (description) s.description = description;
1794
1808
  schemas[qualifier + '.' + name] = s;
1795
1809
  }
@@ -1825,11 +1839,11 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1825
1839
  if (property.$Collection && suffix === "" && isCount === true) {
1826
1840
  schemaProperties[`${iName}@${csdl.$Version === '4.0' ? 'odata.' : ''}count`] = ref('count');
1827
1841
  }
1828
- if (property[voc.Core.Permissions] != "Read" && !property[voc.Core.Computed] && property.$ContainsTarget) {
1842
+ if (property[voc.Core.Permissions] != "Read" && !property[voc.Core.Computed] && ( property.$ContainsTarget || property.$OnDelete === 'Cascade') ) {
1829
1843
  if (suffix === SUFFIX.create)
1830
1844
  schemaProperties[iName] = getSchema(property, SUFFIX.create);
1831
- if (suffix === SUFFIX.update && deepUpdate)
1832
- schemaProperties[iName] = getSchema(property, SUFFIX.create);
1845
+ if (suffix === SUFFIX.update)
1846
+ schemaProperties[iName] = getSchema(property, SUFFIX.update);
1833
1847
  }
1834
1848
  } else {
1835
1849
  if (property[voc.Core.Permissions] === "Read" || property[voc.Core.Computed]) {
@@ -1858,7 +1872,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1858
1872
  if (suffix === SUFFIX.create && required.length > 0)
1859
1873
  schemas[schemaName].required = [...new Set(required)];
1860
1874
 
1861
- const description = type[voc.Core.Description];
1875
+ const description = type[voc.Core.LongDescription];
1862
1876
  if (description) {
1863
1877
  schemas[schemaName].description = description;
1864
1878
  }
@@ -2248,9 +2262,9 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
2248
2262
  };
2249
2263
  }
2250
2264
 
2251
- if (!forParameter && element[voc.Core.Description]) {
2265
+ if (!forParameter && element[voc.Core.LongDescription]) {
2252
2266
  if (s.$ref) s = { allOf: [s] };
2253
- s.description = element[voc.Core.Description];
2267
+ s.description = element[voc.Core.LongDescription];
2254
2268
  }
2255
2269
 
2256
2270
  return s;
@@ -2,9 +2,13 @@ const csdl2openapi = require('./csdl2openapi')
2
2
  const cds = require('../../cds')
3
3
 
4
4
  module.exports = function processor(csn, options = {}) {
5
+ const edmOptions = Object.assign({
6
+ odataOpenapiHints: true, // hint to compiler
7
+ to: 'openapi' // hint to cds.compile.to.edm (usually set by CLI, but also do this in programmatic usages)
8
+ }, options)
5
9
 
6
10
  // must not be part of function* otherwise thrown errors are swallowed
7
- const csdl = cds.compile.to.edm(csn, options);
11
+ const csdl = cds.compile.to.edm(csn, edmOptions);
8
12
 
9
13
  if (csdl[Symbol.iterator]) { // generator function means multiple services
10
14
  return _iterate(csdl, csn, options)
@@ -12,10 +16,6 @@ module.exports = function processor(csn, options = {}) {
12
16
  const openApiOptions = toOpenApiOptions(csdl, csn, options)
13
17
  return _getOpenApi(csdl, openApiOptions);
14
18
  }
15
-
16
- // const file = csdl.$EntityContainer.replace(/\.[^.]+$/, '');
17
- // yield [openapi, { file }]; // add file to avoid relative path in filename
18
- // return openapi;
19
19
  }
20
20
 
21
21
  function* _iterate(csdl, csn, options) {
@@ -57,6 +57,6 @@ function servicePath(csdl, csn) {
57
57
  if (csdl.$EntityContainer) {
58
58
  const serviceName = csdl.$EntityContainer.replace(/\.[^.]+$/, '')
59
59
  const service = csn.definitions[serviceName]
60
- return cds.service.path4 ? cds.service.path4(service) : cds.serve.path4(service)
60
+ return cds.service.path4?.(service) || cds.serve.path4(service)
61
61
  }
62
62
  }
@@ -10,8 +10,8 @@ const { build } = require('../../build');
10
10
  const buildConstants = require('../../build/constants');
11
11
 
12
12
  const hdiDeployUtil = require('./hdiDeployUtil');
13
- const cfUtil = require('../../util/cfUtil');
14
- const gitUtil = require('../../util/gitUtil');
13
+ const cfUtil = require('../../util/cf');
14
+ const gitUtil = require('../../util/git');
15
15
  const mtaUtil = require('./mtaUtil');
16
16
 
17
17
  const { bold, info } = require('../../util/term');
@@ -48,7 +48,9 @@ class HanaDeployer {
48
48
  let { model, serviceName, tunnelAddress, vcapFile, undeployWhitelist, hdiOptions, dry } = options;
49
49
 
50
50
  if (model) {
51
- throw 'Specifying a model for hana deployment is not supported.';
51
+ throw `Specifying a CDS model for HANA deployment is not supported.
52
+ 'cds deploy --to hana' performs 'cds build --for hana' which in turn uses the configured HANA build task.
53
+ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
52
54
  }
53
55
 
54
56
  if (dry) {
package/lib/env/schema.js CHANGED
@@ -1,5 +1,4 @@
1
- const { join } = require('path')
2
- const { mergeJSON } = require('../init/util/merge')
1
+ const { merge } = require('../init/merge')
3
2
  const { readJSON } = require('../util/fs')
4
3
 
5
4
  module.exports = async function overlay4(schemaName, cwd = process.cwd()) {
@@ -26,7 +25,7 @@ module.exports = async function overlay4(schemaName, cwd = process.cwd()) {
26
25
 
27
26
  // optional, don't throw if file not found
28
27
  try {
29
- await mergeJSON(result, join(__dirname, 'schemas', schemaName))
28
+ await merge(__dirname, 'schemas', schemaName).into(result)
30
29
  result.description = result.description + ' - overlaid'
31
30
  } catch (err) {
32
31
  if (err.code !== 'ENOENT') throw err
package/lib/index.js CHANGED
@@ -1,33 +1,73 @@
1
+ /** @type { import('./cds') & CdsDk & CdsDkAdd & CdsDkBuild} */
1
2
  const cds = module.exports = require('./cds')
2
- cds.extend (cds.constructor) .with (class {
3
- get import() { return super.import = require('./import/importapi') }
4
- })
5
-
6
- cds.extend (cds.compile.to.constructor) .with (class {
7
- get asyncapi() { return super.asyncapi = require('./compile/asyncapi') }
8
- get openapi() { return super.openapi = require('./compile/openapi') }
9
- get xsuaa(){ return super.xsuaa = require('./compile/to-xsuaa') }
10
- 'edmx-v2'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'v2'}) }
11
- 'edmx-v4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'v4'}) }
12
- 'edmx-w4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'w4'}) }
13
- 'edmx-x4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'x4'}) }
14
- })
15
-
16
- // Compat to cds <=6. Esp. BAS tools need it, see cap/issues#13918
17
- // TODO remove compat w/ cds-dk 8
18
- if (cds.compile.to.constructor.name === 'Object') { // not a class as in cds 7
19
- cds.compile.to.xsuaa = require('./compile/to-xsuaa')
3
+
4
+ class CdsDk {
5
+
6
+ get import() {
7
+ return super.import = require('./import/importapi')
8
+ }
9
+
10
+ get compile() {
11
+ let compile = require(_local('@sap/cds/lib/compile/cds-compile'))
12
+ cds.extend (compile.to.constructor) .with (class {
13
+ get asyncapi() { return super.asyncapi = require('./compile/asyncapi') }
14
+ get openapi() { return super.openapi = require('./compile/openapi') }
15
+ get xsuaa(){ return super.xsuaa = require('./compile/to-xsuaa') }
16
+ 'edmx-v2'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'v2'}) }
17
+ 'edmx-v4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'v4'}) }
18
+ 'edmx-w4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'w4'}) }
19
+ 'edmx-x4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'x4'}) }
20
+ })
21
+ // Compat to cds <=6. Esp. BAS tools need it, see cap/issues#13918
22
+ // TODO remove compat w/ cds-dk 8
23
+ if (compile.to.constructor.name === 'Object') { // not a class as in cds 7
24
+ compile.to.xsuaa = require('./compile/to-xsuaa')
25
+ }
26
+ return super.compile = compile
27
+ }
28
+
29
+ // add overlay4 method to cds.schema to retrieve schema with cds-dk features
30
+ // schema is cds version specific; add cds-dk parts not present in cds, e.g. build
31
+ // failsafe for legacy cds without schema.constructor
32
+ get schema() {
33
+ let schema = require(_local('@sap/cds/lib/env/schemas'))
34
+ cds.extend(schema.constructor) .with (class {
35
+ get overlay4() { return super.overlay4 = require('./env/schema') }
36
+ })
37
+ return super.schema = schema
38
+ }
20
39
  }
21
40
 
22
- // add overlay4 method to cds.schema to retrieve schema with cds-dk features
23
- // schema is cds version specific; add cds-dk parts not present in cds, e.g. build
24
- // failsafe for legacy cds without schema.constructor
25
- cds.extend(cds.schema?.constructor || {}).with(class {
26
- get overlay4() { return super.overlay4 = require('./env/schema') }
27
- })
41
+ cds.extend (cds.constructor) .with (CdsDk)
28
42
 
29
- // set build API, potentially removing the old API facade from sap/cds 7
30
- // delete cds.__proto__?.build //> not required, as its overriden below anyways
31
- cds.extend (cds.constructor) .with (class {
43
+ class CdsDkAdd {
44
+ get add() { return super.add = require('./init/add') }
45
+ }
46
+ class CdsDkBuild {
32
47
  get build() { return super.build = require('./build') }
33
- })
48
+ }
49
+ if (process.argv[2] in { 'add':1, 'init':1 }) {
50
+ cds.extend (cds.constructor) .with (CdsDkAdd)
51
+ } else if (process.argv[2] in { 'build':1, 'deploy':1, 'push':1 }) {
52
+ cds.extend (cds.constructor) .with (CdsDkBuild)
53
+ }
54
+
55
+ const MIN_SUPPORTED_CDS_VERSION = 6
56
+ const [cdsVersion] = cds.version.split('.')
57
+ if (parseInt(cdsVersion) < MIN_SUPPORTED_CDS_VERSION) {
58
+ const [dkVersion] = require('../package.json').version.split('.')
59
+ console.error(`
60
+ This application uses '@sap/cds' version ${cdsVersion}, which is not compatible with the installed '@sap/cds-dk' version ${dkVersion}.
61
+ You can either:
62
+ - update '@sap/cds' to the latest version (recommended)
63
+ - downgrade '@sap/cds-dk' to version ${MIN_SUPPORTED_CDS_VERSION}
64
+ `)
65
+ process.exit(1)
66
+ }
67
+
68
+ function _local (id) {
69
+ return require.resolve (id, {paths:[
70
+ process.cwd(), // project-local module is preferred
71
+ __dirname // otherwise from our own dependencies
72
+ ]})
73
+ }
@@ -0,0 +1,17 @@
1
+ const registered = new Map
2
+
3
+ module.exports = {
4
+ Plugin: require('./plugin'),
5
+ merge: require('./merge').merge, // fluent API
6
+ readProject: require('./projectReader').readProject,
7
+ mvn: {
8
+ add: require('./mvn').add
9
+ },
10
+ registries: {
11
+ mta: require('./registries/mta')
12
+ },
13
+ register: (name, plugin) => {
14
+ registered.set(name, plugin)
15
+ },
16
+ registered
17
+ }
@@ -4,7 +4,7 @@ module.exports = {
4
4
  COMMAND_INIT: 'init',
5
5
  COMMAND_ADD: 'add',
6
6
 
7
- MAVEN_ARCHETYPE_VERSION: '2.4.0',
7
+ MAVEN_ARCHETYPE_VERSION: '2.4.1',
8
8
 
9
9
  OPTIONS: Object.freeze({
10
10
  JAVA: 'java',
@@ -15,6 +15,8 @@ module.exports = {
15
15
  TINY_SAMPLE: 'tiny-sample',
16
16
  SAMPLE: 'sample',
17
17
  PIPELINE: 'pipeline',
18
+ HELM_UNIFIED_RUNTIME: 'helm-unified-runtime',
19
+ HELM: 'helm',
18
20
  MTA: 'mta',
19
21
  CONNECTIVITY: 'connectivity',
20
22
  CF_MANIFEST: 'cf-manifest',
@@ -27,6 +29,7 @@ module.exports = {
27
29
  POSTGRES: 'postgres',
28
30
  SQLITE: 'sqlite',
29
31
  H2: 'h2',
32
+ LIQUIBASE: 'liquibase',
30
33
  LOCAL_MESSAGING: 'local-messaging',
31
34
  FILE_BASED_MESSAGING: 'file-based-messaging',
32
35
  ENTERPRISE_MESSAGING: 'enterprise-messaging',
@@ -35,11 +38,10 @@ module.exports = {
35
38
  APPROUTER: 'approuter',
36
39
  DESTINATION: 'destination',
37
40
  DATA: 'data',
38
- KIBANA: 'kibana',
41
+ APPLICATION_LOGGING: 'application-logging',
39
42
  LINT: 'lint',
40
43
  LINT_GLOBAL: 'lint:global',
41
44
  LINT_DEV: 'lint:dev',
42
- HELM: 'helm',
43
45
  TYPER: 'typer',
44
46
  HTML5_REPO: 'html5-repo',
45
47
  NOTIFICATIONS: 'notifications'