@sap/cds-dk 8.9.5 → 9.0.5

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 (109) hide show
  1. package/CHANGELOG.md +101 -2012
  2. package/LICENSE +15 -21
  3. package/bin/bind.js +1 -1
  4. package/bin/build.js +35 -37
  5. package/bin/cds.js +13 -30
  6. package/bin/compile/index.js +2 -2
  7. package/bin/debug.js +27 -7
  8. package/bin/deploy/index.js +6 -23
  9. package/bin/deploy/to-hana.js +4 -2
  10. package/bin/help.js +5 -3
  11. package/bin/init.js +1 -1
  12. package/bin/up.js +45 -12
  13. package/bin/watch.js +45 -63
  14. package/lib/bind/cf.js +2 -1
  15. package/lib/bind/k8s.js +2 -2
  16. package/lib/bind/plugin.js +1 -1
  17. package/lib/bind/shared.js +16 -25
  18. package/lib/build/buildTaskEngine.js +26 -10
  19. package/lib/build/buildTaskFactory.js +3 -2
  20. package/lib/build/buildTaskProvider.js +18 -7
  21. package/lib/build/buildTaskProviderFactory.js +35 -13
  22. package/lib/build/constants.js +4 -0
  23. package/lib/build/index.js +1 -1
  24. package/lib/build/plugin.js +89 -54
  25. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +3 -1
  26. package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +4 -2
  27. package/lib/build/plugins/helm/files/subcharts/web-application/templates/api-rule.yaml +4 -2
  28. package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +18 -1
  29. package/lib/build/plugins/helm/files/subcharts/web-application/templates/service-binding.yaml +0 -1
  30. package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +34 -2
  31. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +9 -2
  32. package/lib/build/plugins/helm/index.js +2 -1
  33. package/lib/build/plugins.js +24 -10
  34. package/lib/build/provider/edmxBuildPlugin.js +1 -11
  35. package/lib/build/provider/fiori/index.js +4 -4
  36. package/lib/build/provider/hana/index.js +12 -5
  37. package/lib/build/provider/hana/template/package.json +1 -1
  38. package/lib/build/provider/internalBuildPlugin.js +1 -1
  39. package/lib/build/provider/internalBuildTaskProvider.js +3 -24
  40. package/lib/build/provider/java/index.js +1 -1
  41. package/lib/build/provider/mtx-extension/index.js +15 -8
  42. package/lib/build/provider/nodejs/index.js +28 -6
  43. package/lib/build/util.js +186 -125
  44. package/lib/deploy/index.js +5 -0
  45. package/lib/deploy/to-hana/hana.js +27 -33
  46. package/lib/deploy/to-hana/hdiDeployUtil.js +2 -2
  47. package/lib/import/odata/v2parser.js +34 -3
  48. package/lib/import/openapi/importOpenAPI.js +4 -0
  49. package/lib/index.js +2 -11
  50. package/lib/init/constants.js +1 -2
  51. package/lib/init/merge.js +101 -77
  52. package/lib/init/mvn.js +3 -3
  53. package/lib/init/projectReader.js +1 -1
  54. package/lib/init/template/ams/files/mta.yaml.hbs +6 -1
  55. package/lib/init/template/ams/files/package.json.hbs +1 -1
  56. package/lib/init/template/approuter/files/mta.yaml.hbs +5 -0
  57. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +1 -1
  58. package/lib/init/template/cloud-logging/files/package.json.hbs +3 -3
  59. package/lib/init/template/data/as-json.js +3 -3
  60. package/lib/init/template/dynatrace/files/mta.yaml.hbs +1 -1
  61. package/lib/init/template/dynatrace/files/package.json.hbs +2 -2
  62. package/lib/init/template/dynatrace/index.js +2 -1
  63. package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +6 -0
  64. package/lib/init/template/enterprise-messaging/index.js +5 -1
  65. package/lib/init/template/extensibility/files/package.json.hbs +1 -1
  66. package/lib/init/template/hana/files/db/package.json +1 -1
  67. package/lib/init/template/hana/files/package.json.hbs +2 -4
  68. package/lib/init/template/hana/index.js +2 -2
  69. package/lib/init/template/handler/index.js +16 -12
  70. package/lib/init/template/helm/index.js +13 -22
  71. package/lib/init/template/helm-unified-runtime/index.js +2 -1
  72. package/lib/init/template/html5-repo/files/values.yaml.hbs +12 -1
  73. package/lib/init/template/html5-repo/index.js +10 -5
  74. package/lib/init/template/http/index.js +1 -1
  75. package/lib/init/template/ias/files/mta.yaml.hbs +1 -1
  76. package/lib/init/template/ias/files/sidecar.package.json.hbs +0 -7
  77. package/lib/init/template/ias/index.js +5 -4
  78. package/lib/init/template/lint/files/package.json +6 -0
  79. package/lib/init/template/lint/index.js +61 -204
  80. package/lib/init/template/mta/files/package.json +1 -1
  81. package/lib/init/template/multitenancy/files/mta.yaml.hbs +2 -2
  82. package/lib/init/template/multitenancy/files/package.json.hbs +1 -1
  83. package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -4
  84. package/lib/init/template/multitenancy/index.js +3 -0
  85. package/lib/init/template/nodejs/files/package.json.hbs +6 -3
  86. package/lib/init/template/postgres/files/package.json.hbs +1 -1
  87. package/lib/init/template/redis/files/package.json.hbs +1 -1
  88. package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +6 -0
  89. package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +1 -0
  90. package/lib/init/template/sample/files/app/browse/fiori-service.cds +3 -2
  91. package/lib/init/template/sample/files/app/common.cds +0 -11
  92. package/lib/init/template/sqlite/files/package.json +1 -1
  93. package/lib/init/template/toggles/files/package.json.hbs +1 -1
  94. package/lib/init/template/typescript/files/package.json +2 -4
  95. package/lib/init/template/workzone-standard/index.js +2 -0
  96. package/lib/init/template/xsuaa/index.js +2 -6
  97. package/lib/lint/Linter.js +203 -331
  98. package/lib/lint/generators.js +52 -46
  99. package/lib/lint/io.js +77 -289
  100. package/lib/util/fs.js +2 -1
  101. package/lib/util/git.js +1 -1
  102. package/lib/util/glob.js +77 -0
  103. package/lib/watch/livereload-server.js +3 -4
  104. package/lib/watch/node-watch.js +3 -4
  105. package/lib/watch/watched.js +1 -1
  106. package/npm-shrinkwrap.json +200 -858
  107. package/package.json +6 -8
  108. package/readme.md +1 -1
  109. package/lib/lint/checks.js +0 -135
@@ -8,6 +8,6 @@
8
8
  "node": ">=18"
9
9
  },
10
10
  "scripts": {
11
- "start": "node node_modules/@sap/hdi-deploy/deploy.js --use-hdb"
11
+ "start": "node node_modules/@sap/hdi-deploy/deploy.js --use-hdb --parameter com.sap.hana.di.table/try_fast_table_migration=true"
12
12
  }
13
13
  }
@@ -74,7 +74,7 @@ class InternalBuildPlugin extends Plugin {
74
74
  if (typeof src !== "string" || typeof destDir !== "string") {
75
75
  return false
76
76
  }
77
- if (!fs.statSync(src).isDirectory()) {
77
+ if (!cds.utils.isdir(src)) {
78
78
  return true //file
79
79
  }
80
80
  if (src === destDir) {
@@ -102,20 +102,12 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
102
102
  }
103
103
 
104
104
  _createDbTask(src, taskOptions) {
105
- DEBUG?.("determining database kind")
106
105
  if (!src || InternalBuildTaskProvider._isMtxExtension()) {
107
106
  return null
108
107
  }
109
108
  let task = null
110
109
  if (this._useHana()) {
111
110
  DEBUG?.("found HANA database")
112
- // legacy build supports dest property
113
- const compileDest = cds.env.data?.dest
114
- if (compileDest) {
115
- //../db/src/gen
116
- // compileDest is relative to src folder in modular build - resolve correctly
117
- taskOptions.compileDest = path.relative(path.resolve(cds.root, src), path.resolve(cds.root, compileDest))
118
- }
119
111
  task = {
120
112
  src: src,
121
113
  for: BUILD_TASK_HANA,
@@ -135,15 +127,9 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
135
127
  if (cds.env.requires.db?.kind) {
136
128
  return false
137
129
  }
138
- // check whether cds config represents a legacy build system config for which requires.db was not configured
139
- // Note: compat layer sets requires.db: {}
140
- const userEnv = cds.env.for("cds", cds.root, false)
141
- return userEnv && (userEnv.data?.model || userEnv.service?.model)
142
130
  }
143
131
 
144
132
  _createMtxTask(src) {
145
- DEBUG?.("determining MTX architecture")
146
-
147
133
  // preserve order of creation
148
134
  if (InternalBuildTaskProvider._isMtxExtension()) {
149
135
  DEBUG?.("MTX extension app")
@@ -194,7 +180,6 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
194
180
  }
195
181
 
196
182
  _createSrvTask(src, taskOptions) {
197
- DEBUG?.("determining implementation technology")
198
183
  if (!src || InternalBuildTaskProvider._isMtxExtension()) {
199
184
  return null
200
185
  }
@@ -208,13 +193,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
208
193
  }
209
194
 
210
195
  _createJavaTask(src, taskOptions) {
211
- DEBUG?.("found implementation technology Java")
212
- // legacy build supports dest property
213
- const compileDest = cds.env.service?.dest
214
- if (compileDest) {
215
- // compileDest is relative to src folder in modular build - resolve correctly
216
- taskOptions.compileDest = path.relative(path.resolve(cds.root, src), path.resolve(cds.root, compileDest))
217
- }
196
+ DEBUG?.("found Java runtime")
218
197
  return {
219
198
  src: src,
220
199
  for: BUILD_TASK_JAVA,
@@ -223,7 +202,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
223
202
  }
224
203
 
225
204
  _createNodeTask(src, taskOptions) {
226
- DEBUG?.("found implementation technology Nodejs")
205
+ DEBUG?.("found Nodejs runtime")
227
206
  if (!fs.existsSync(path.join(cds.root, 'package.json'))) {
228
207
  throw new BuildError(`No 'package.json' found in project root folder '${cds.root}'`)
229
208
  }
@@ -295,7 +274,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
295
274
  if (!acc) {
296
275
  let resourcePath = path.resolve(cds.root, resource)
297
276
  if (fs.existsSync(resourcePath)) {
298
- if (fs.lstatSync(resourcePath).isDirectory()) {
277
+ if (cds.utils.isdir(resourcePath)) {
299
278
  acc = resource
300
279
  } else {
301
280
  // represents file
@@ -55,7 +55,7 @@ class JavaBuildPlugin extends EdmxBuildPlugin {
55
55
 
56
56
  async _copyNativeContent(src, dest) {
57
57
  return super.copyNativeContent(src, dest, (entry) => {
58
- if (fs.statSync(entry).isDirectory()) {
58
+ if (cds.utils.isdir(entry)) {
59
59
  return true // using common filter for folders
60
60
  } else {
61
61
  const extname = path.extname(entry)
@@ -8,6 +8,8 @@ const { FOLDER_GEN, EXTENSION_POINT_VALIDATION } = require('../../constants')
8
8
  const { BuildError, BuildMessage } = require('../../util')
9
9
  const DEBUG = cds.debug('cli|build')
10
10
 
11
+ const BUILT_IN_NAMESPACES = ['cds.core', 'cds.outbox', 'cds.xt']
12
+
11
13
  class MtxExtensionBuildPlugin extends InternalBuildPlugin {
12
14
  init() {
13
15
  super.init()
@@ -48,6 +50,16 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
48
50
  if (extensionModel.requires) {
49
51
  extensionModel.requires.length = 0
50
52
  }
53
+ if (extensionModel.definitions) {
54
+ for (const [name] of Object.entries(extensionModel.definitions)) {
55
+ for (const namespace of BUILT_IN_NAMESPACES) {
56
+ if (name.startsWith(`${namespace}.`)) {
57
+ delete extensionModel.definitions[name]
58
+ break
59
+ }
60
+ }
61
+ }
62
+ }
51
63
  }
52
64
  }
53
65
 
@@ -93,7 +105,7 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
93
105
  // copy handlers from srv folder
94
106
  const folder = path.join(cds.root, cds.env.folders.srv).replace(/[/\\]$/, '')
95
107
  await this.copyNativeContent(cds.root, destExt, res => {
96
- if (fs.statSync(res).isDirectory()) {
108
+ if (cds.utils.isdir(res)) {
97
109
  return res.startsWith(folder)
98
110
  }
99
111
  if (path.dirname(res).startsWith(folder) && /\.js$/.test(res)) {
@@ -122,19 +134,14 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
122
134
  }
123
135
 
124
136
  _linter() {
125
- let linter
126
137
  try {
127
138
  // Make sure cds-mtxs APIs are loaded, from local mtxs preferrably
128
- linter = require(require.resolve('@sap/cds-mtxs', { paths: [cds.root, __dirname] })).xt?.linter
129
- if (!linter) {
130
- this.pushMessage('MTXS linter cannot be loaded. Update of @sap/cds-dk and @sap/cds-mtxs modules required? Skipping extension model lint step.')
131
- return null // too old mtxs
132
- }
139
+ const mtxs = require(require.resolve('@sap/cds-mtxs', { paths: [cds.root, __dirname] }))
140
+ return mtxs.xt.linter
133
141
  } catch (e) {
134
142
  if (e.code !== 'MODULE_NOT_FOUND') throw e
135
143
  this.pushMessage('MTXS linter cannot be loaded, @sap/cds-mtxs not installed. Skipping extension model lint step.')
136
144
  }
137
- return linter
138
145
  }
139
146
 
140
147
  static _getSaasPkgPath() {
@@ -10,6 +10,12 @@ const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTE
10
10
  const { WARNING } = EdmxBuildPlugin
11
11
  const LOG = cds.log('cli|build'), DEBUG = cds.debug('cli|build')
12
12
 
13
+ /**
14
+ * @param {T | T[]} x
15
+ * @returns {T[]}
16
+ */
17
+ const arrayify = x => Array.isArray(x) ? x : [x]
18
+
13
19
  class NodejsBuildPlugin extends EdmxBuildPlugin {
14
20
  init() {
15
21
  super.init()
@@ -99,7 +105,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
99
105
  // 1. copy all files to 'destSrv' except those contained in the blocklist (including node_modules)
100
106
  // project/srv -> 'gen/srv/srv'
101
107
  await super.copyNativeContent(src, destSrv, (entry) => {
102
- if (fs.statSync(entry).isDirectory()) {
108
+ if (cds.utils.isdir(entry)) {
103
109
  // TODO shall not copy language bundles - return !/(\/|\\)(node_modules|_i18n)(\/|\\)?$/.test(entry)
104
110
  return !/(\/|\\)node_modules(\/|\\)?$/.test(entry)
105
111
  }
@@ -149,7 +155,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
149
155
  srvAllowList = new RegExp(srvAllowList)
150
156
 
151
157
  await super.copyNativeContent(src, dest, (entry) => {
152
- if (fs.statSync(entry).isDirectory()) {
158
+ if (cds.utils.isdir(entry)) {
153
159
  return folders.some(folder => entry.startsWith(folder))
154
160
  }
155
161
  if (/\.js$|\.properties$/.test(entry)) {
@@ -162,17 +168,20 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
162
168
  async _packWorkspaceDependencies(dest) {
163
169
  const wsRoot = findWorkspaceRoot(cds.root)
164
170
  const appPkg = require(path.join(dest, 'package.json'))
171
+ const allWorkspaces = await getWorkspaces(wsRoot, true, false);
165
172
  let workspaces
166
173
  if (this.task.options.workspaces) {
167
- workspaces = Array.isArray(this.task.options.workspaces) ? this.task.options.workspaces : [this.task.options.workspaces]
174
+ const relevantWorkspaces = new Set(arrayify(this.task.options.workspaces))
175
+ workspaces = allWorkspaces
176
+ .filter(ws => relevantWorkspaces.has(ws.workspace))
168
177
  } else {
169
178
  // devDependencies are not considered
170
- workspaces = await getWorkspaces(wsRoot, true, false);
179
+ workspaces = allWorkspaces
171
180
  }
172
181
  if (workspaces.length) {
173
182
  let pkgDescriptors
174
183
  try {
175
- pkgDescriptors = await NodejsBuildPlugin._execNpmPack(dest, wsRoot, workspaces)
184
+ pkgDescriptors = await NodejsBuildPlugin._execNpmPack(dest, wsRoot, workspaces.map(ws => ws.workspace))
176
185
  } catch (e) {
177
186
  DEBUG?.(e)
178
187
  throw new BuildError(`Failed to package npm workspace dependencies\n${e.message}`)
@@ -182,7 +191,13 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
182
191
  for (const pkgDescriptor of pkgDescriptors) {
183
192
  const { name, filename: fileName } = pkgDescriptor
184
193
  const filePath = path.join(dest, fileName)
185
- if (appPkg.dependencies?.[name]) {
194
+ // we pack workspaces that are not directly part of appPkg.dependencies
195
+ // to include transitive dependencies, i.e. we are packing A, which has a dep
196
+ // on workspace B, which has a dep on C. A will not have a direct dependency
197
+ // on C, but it will be included in the build transitively, and therefore
198
+ // has to be added to the package.json as well, so they are available for the
199
+ // packaged B.
200
+ if (appPkg.dependencies?.[name] || workspaces.some(ws => ws.packageName === name)) {
186
201
  appPkg.dependencies[name] = `file:${fileName}`
187
202
  this.pushFile(filePath)
188
203
  changed |= true
@@ -197,6 +212,13 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
197
212
  }
198
213
  }
199
214
 
215
+ /**
216
+ * @param {import('fs').PathLike} dest - destination folder
217
+ * @param {import('fs').PathLike} wsRoot - workspace root folder
218
+ * @param {string[]} workspaces - list of workspace names
219
+ * @returns {Promise<JSON>} - returns a promise that resolves to the result of the command
220
+ * @private
221
+ */
200
222
  static async _execNpmPack(dest, wsRoot, workspaces) {
201
223
  const args = ['pack', '-ws', '--json', `--pack-destination=${dest}`]
202
224
  workspaces.forEach(w => args.push(`-w=${w}`))