@sap/cds-dk 9.6.0 → 9.7.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 (87) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/bin/add.js +5 -2
  3. package/bin/cds.js +11 -26
  4. package/bin/compile/index.js +3 -2
  5. package/bin/data-products/import.js +3 -0
  6. package/bin/debug.js +76 -16
  7. package/bin/env.js +2 -1
  8. package/bin/export.js +18 -13
  9. package/bin/help/export.md +2 -1
  10. package/bin/import.js +21 -18
  11. package/bin/init.js +8 -1
  12. package/bin/minify.js +11 -12
  13. package/bin/mock.js +17 -9
  14. package/bin/repl.js +2 -2
  15. package/bin/up.js +34 -4
  16. package/bin/version.js +202 -131
  17. package/lib/build/buildTaskEngine.js +4 -0
  18. package/lib/build/buildTaskFactory.js +5 -35
  19. package/lib/build/index.js +10 -10
  20. package/lib/build/plugin.js +6 -3
  21. package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +3 -1
  22. package/lib/build/plugins/helm/files/subcharts/content-deployment/templates/_helpers.tpl +1 -1
  23. package/lib/build/plugins/helm/files/subcharts/content-deployment/templates/job.yaml +8 -0
  24. package/lib/build/plugins/helm/files/subcharts/content-deployment/values.schema.json +18 -0
  25. package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +11 -1
  26. package/lib/build/plugins.js +8 -16
  27. package/lib/build/provider/hana/index.js +16 -19
  28. package/lib/build/provider/internalBuildPlugin.js +28 -4
  29. package/lib/build/provider/internalBuildTaskProvider.js +26 -88
  30. package/lib/build/provider/mtx/index.js +0 -8
  31. package/lib/build/provider/mtx-sidecar/index.js +88 -80
  32. package/lib/build/provider/nodejs/index.js +3 -8
  33. package/lib/build/util.js +52 -87
  34. package/lib/deploy/to-hana/hana.js +117 -109
  35. package/lib/env/schemas/cds-rc.js +0 -4
  36. package/lib/import/odata/v4parser.js +80 -56
  37. package/lib/init/constants.js +5 -2
  38. package/lib/init/index.js +44 -41
  39. package/lib/init/merge.js +7 -2
  40. package/lib/init/projectReader.js +4 -10
  41. package/lib/init/template/ams/index.js +1 -4
  42. package/lib/init/template/attachments/files/package.json.hbs +1 -1
  43. package/lib/init/template/data/index.js +1 -1
  44. package/lib/init/template/extension/index.js +4 -4
  45. package/lib/init/template/hana/files/package.json.hbs +3 -3
  46. package/lib/init/template/handler/index.js +1 -1
  47. package/lib/init/template/helm/index.js +3 -3
  48. package/lib/init/template/helm-unified-runtime/index.js +5 -1
  49. package/lib/init/template/html5-repo/files/mta.yaml.hbs +1 -1
  50. package/lib/init/template/ias/files/mta.yaml.hbs +3 -3
  51. package/lib/init/template/initial/files/.vscode/tasks.json +10 -0
  52. package/lib/init/template/{nodejs/files/README.md → initial/files/readme.md} +2 -3
  53. package/lib/init/template/initial/index.js +15 -0
  54. package/lib/init/template/java/index.js +4 -11
  55. package/lib/init/template/kyma/index.js +21 -20
  56. package/lib/init/template/lint/index.js +3 -1
  57. package/lib/init/template/mta/index.js +0 -5
  58. package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +1 -2
  59. package/lib/init/template/multitenancy/files/values.yaml.hbs +30 -0
  60. package/lib/init/template/nodejs/files/.vscode/tasks.json +1 -14
  61. package/lib/init/template/nodejs/files/package.json.hbs +2 -4
  62. package/lib/init/template/nodejs/index.js +8 -12
  63. package/lib/init/template/sample/files/app/common.cds +1 -1
  64. package/lib/init/template/sample/index.js +5 -6
  65. package/lib/init/template/sqlite/files/package.json.hbs +7 -1
  66. package/lib/init/template/test/index.js +1 -1
  67. package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +6 -0
  68. package/lib/init/template/tiny-sample/files/nodejs/srv/cat-service.cds +5 -0
  69. package/lib/init/template/tiny-sample/index.js +2 -2
  70. package/lib/init/template/workzone-standard/files/mta.yaml.hbs +6 -0
  71. package/lib/init/template/workzone-standard/index.js +13 -3
  72. package/lib/init/validate.js +11 -6
  73. package/lib/util/checksum.js +2 -2
  74. package/lib/util/fs.js +109 -53
  75. package/lib/util/glob.js +2 -1
  76. package/lib/util/term.js +4 -8
  77. package/lib/util/write.js +2 -4
  78. package/lib/watch/livereload-server.js +4 -3
  79. package/lib/watch/node-watch.js +5 -8
  80. package/lib/watch/watched.js +1 -1
  81. package/lib/watch/watcher.js +136 -0
  82. package/npm-shrinkwrap.json +245 -284
  83. package/package.json +2 -3
  84. package/lib/init/template/nodejs/files/.vscode/settings.json +0 -11
  85. package/lib/init/template/tiny-sample/files/nodejs/db/data/my.bookshop-Books.csv +0 -3
  86. package/lib/init/template/tiny-sample/files/nodejs/db/schema.cds +0 -7
  87. package/lib/init/template/tiny-sample/files/nodejs/srv/cat-service.cds.hbs +0 -5
@@ -1,5 +1,5 @@
1
- const fs = require('fs')
2
1
  const cds = require('../cds')
2
+ const { exists, isdir } = cds.utils
3
3
  const BuildTaskEngine = require('./buildTaskEngine')
4
4
  const Plugin = require('./plugin')
5
5
  const { BuildError } = require('./util')
@@ -17,28 +17,28 @@ module.exports = { build, register, Plugin, BuildError }
17
17
  * for?: BuildFor | (string & {}),
18
18
  * src?: string,
19
19
  * dest?: string,
20
- * model?: string[]
20
+ * model?: string[],
21
+ * root?: string = cds.root,
21
22
  * } & {[key:string]:unknown}} BuildOptions
22
23
  */
23
24
 
24
25
  /**
25
- * Executes cds build in the directory defined by cds.root.
26
+ * Executes cds build with specified options.
26
27
  *
27
- * @param {BuildOptions} options - command options as defined by build command.
28
+ * @param {BuildOptions} options - command options
28
29
  */
29
- async function build(options = {}) {
30
- if (!fs.existsSync(cds.root) || !cds.utils.isdir(cds.root)) {
31
- throw `Project folder '${cds.root}' does not exist`
30
+ async function build({ root = cds.root, ...options } = {}) {
31
+ if (!exists(root) || !isdir(root)) {
32
+ throw `Project folder '${root}' does not exist`
32
33
  }
33
34
  try {
34
35
  return await new BuildTaskEngine(options).processTasks()
35
36
  } catch (e) {
36
37
  if (e instanceof BuildError || e.constructor.name === 'CompilationError') {
37
38
  cds._log(e.messages.length ? e.messages : e.message, { 'log-level': options['log-level'] || cds.env['log-level'] })
38
- console.log('')
39
+ console.log()
39
40
  // CompilationError.message also includes the detail messages - do not log twice
40
- const message = e.constructor.name === 'CompilationError' ? 'CDS compilation failed' : e.messages.length ? e.message : 'CDS build failed'
41
- throw message
41
+ throw e.constructor.name === 'CompilationError' ? 'CDS compilation failed' : e.messages.length ? e.message : 'CDS build failed'
42
42
  }
43
43
  throw e
44
44
  }
@@ -5,7 +5,10 @@ const cds = require('../cds')
5
5
  const IS_WIN = os.platform() === 'win32';
6
6
 
7
7
  const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR } = require('./constants')
8
- const { hasOptionValue, getProperty, relativePaths, BuildMessage, pathExists, filterFeaturePaths, getFiles } = require('./util')
8
+
9
+ const { find } = require('../util/fs')
10
+ const { hasOptionValue, getProperty, relativePaths, BuildMessage, filterFeaturePaths } = require('./util')
11
+
9
12
  const DEBUG = cds.debug('cli|build')
10
13
 
11
14
  /**
@@ -144,7 +147,7 @@ class Plugin {
144
147
  if (cds.env.build.target === '.'
145
148
  && this.task.src !== this.task.dest
146
149
  && !isSubDirectory(this.task.dest, this.task.src)
147
- && await pathExists(this.task.dest)) {
150
+ && fs.existsSync(this.task.dest)) {
148
151
  return fs.promises.rm(this.task.dest, { force: true, recursive: true })
149
152
  }
150
153
  }
@@ -197,7 +200,7 @@ class Plugin {
197
200
  // list all copied files recursively
198
201
  if (cds.utils.isdir(src)) {
199
202
  await fs.promises.cp(src, dest, { recursive: true })
200
- const files = getFiles(dest)
203
+ const files = await find(dest)
201
204
  files.forEach(file => this.pushFile(file))
202
205
  } else {
203
206
  this.pushFile(dest)
@@ -1,5 +1,7 @@
1
1
  apiVersion: v2
2
2
  description: A Helm Chart for creating a Content Deployment job
3
3
  name: content-deployment
4
+ sources:
5
+ - https://github.tools.sap/unified-runtime/content-deployment
4
6
  type: application
5
- version: 1.8.0
7
+ version: 1.9.0
@@ -33,7 +33,7 @@ If release name contains chart name it will be used as a full name.
33
33
  Define a name for the Job object
34
34
  */}}
35
35
  {{- define "content-deployment.internal.jobName" -}}
36
- {{- printf "%s-%04d" ((include "content-deployment.internal.fullname" . ) | trunc 59) (mod .Release.Revision 1000) }}
36
+ {{- printf "%s-%04d" ((include "content-deployment.internal.fullname" . ) | trunc 58) (mod .Release.Revision 1000) }}
37
37
  {{- end }}
38
38
 
39
39
  {{/*
@@ -33,6 +33,14 @@ spec:
33
33
  imagePullPolicy: {{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}
34
34
  {{- end }}
35
35
  name: {{ include "content-deployment.internal.name" . }}
36
+ {{- if .Values.command }}
37
+ command:
38
+ {{- toYaml .Values.command | nindent 8 }}
39
+ {{- end }}
40
+ {{- if .Values.args }}
41
+ args:
42
+ {{- toYaml .Values.args | nindent 8 }}
43
+ {{- end }}
36
44
  env:
37
45
  - name: EXIT
38
46
  value: "1"
@@ -546,6 +546,24 @@
546
546
  }
547
547
  }
548
548
  }
549
+ },
550
+ "command": {
551
+ "$id": "#/properties/command",
552
+ "title": "Container command",
553
+ "description": "The command to run in the container. Overrides the default image entrypoint.",
554
+ "type": "array",
555
+ "items": {
556
+ "type": "string"
557
+ }
558
+ },
559
+ "args": {
560
+ "$id": "#/properties/args",
561
+ "title": "Container args",
562
+ "description": "Arguments to pass to the command. Overrides the default image cmd.",
563
+ "type": "array",
564
+ "items": {
565
+ "type": "string"
566
+ }
549
567
  }
550
568
  },
551
569
  "definitions": {
@@ -14,7 +14,7 @@ global:
14
14
  _internal:
15
15
  content-deployment:
16
16
  versions:
17
- 1.8.0: true
17
+ 1.9.0: true
18
18
  # Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
19
19
  # nameOverride: name
20
20
 
@@ -125,3 +125,13 @@ annotations:
125
125
  # operator: In
126
126
  # values:
127
127
  # - key-2
128
+
129
+ ## Container command override. See https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
130
+ # command:
131
+ # - /bin/sh
132
+ # - -c
133
+
134
+ ## Container args override. See https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
135
+ # args:
136
+ # - echo
137
+ # - "Hello World"
@@ -1,11 +1,14 @@
1
1
  // @ts-check
2
2
  const cds = require('../cds')
3
- const Plugin = require('./plugin')
4
3
  const DEBUG = cds.debug('cli|build')
5
4
 
5
+ /** @typedef {typeof import('./plugin')} BuildPlugin */
6
+
6
7
  module.exports = new (class Plugins {
7
- /** @type {Map<string, typeof Plugin>} */
8
+
9
+ /** @type {Map<string, BuildPlugin>} */
8
10
  #plugins = new Map()
11
+
9
12
  get plugins() {
10
13
  return this.#plugins
11
14
  }
@@ -15,27 +18,16 @@ module.exports = new (class Plugins {
15
18
  }
16
19
 
17
20
  /**
18
- * @param {string} id - unique name of the plugin
19
- * @param {typeof Plugin | { prototype?: unknown, impl: string, taskDefaults: { src: string } }} plugin - class extending Plugin
21
+ * @param {string} id - unique ID of the plugin
22
+ * @param {BuildPlugin} plugin - build plugin implementation
20
23
  */
21
24
  register(id, plugin) {
22
- /**
23
- * @param {{prototype?: unknown}} plugin
24
- * @returns {plugin is typeof Plugin}
25
- */
26
- const isNewStylePlugin = plugin => plugin.prototype instanceof Plugin
27
-
28
25
  if (!id || !plugin) {
29
26
  throw new Error(`Invalid parameter passed, build plugin id: ${id}`)
30
27
  }
31
28
  if (this.#plugins.has(id)) {
32
29
  throw new Error(`CDS build plugin ${id} already registered`)
33
30
  }
34
- if(!isNewStylePlugin(plugin)) {
35
- // with cds-dk version 7 the following registration format was supported:
36
- // cds.build.register("cov2ap", { impl: "@cap-js-community/odata-v2-adapter/src/build.js", taskDefaults: { src: "srv" } })
37
- throw `The cds build plugin '${id}' is not compatible with this @sap/cds-dk version. Update the npm package '${plugin.impl || id}' to the latest version.`
38
- }
39
31
  DEBUG?.(`registering build plugin ${id}`)
40
32
  this.#plugins.set(id, plugin)
41
33
  }
@@ -43,4 +35,4 @@ module.exports = new (class Plugins {
43
35
  #registerDefaults() {
44
36
  this.register('helm', require('./plugins/helm'))
45
37
  }
46
- })
38
+ })
@@ -3,7 +3,8 @@ const path = require('path')
3
3
  const cds = require('../../../cds')
4
4
  const { compileToHdbMigration, getJournalEntities, getMigrationTableName } = require('./2migration')
5
5
  const InternalBuildPlugin = require('../internalBuildPlugin')
6
- const { BuildError, relativePaths, BuildMessage, hasOptionValue, getFiles, getWorkspacePaths } = require('../../util')
6
+ const { find } = require('../../../util/fs')
7
+ const { BuildError, relativePaths, BuildMessage, hasOptionValue, getWorkspacePaths } = require('../../util')
7
8
  const { OUTPUT_MODE_NONE, OUTPUT_MODE, CONTENT_PACKAGE_JSON, CONTENT_HDBTABLEDATA, CSV_FILE_DETECTION,
8
9
  CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, OUTPUT_MODE_RESULT, CONTINUE_UNRESOLVED_SCHEMA_CHANGES,
9
10
  CSV_FILE_TARGET, OPTION_WS } = require('../../constants')
@@ -197,14 +198,10 @@ class HanaBuildPlugin extends InternalBuildPlugin {
197
198
 
198
199
  // handle *.csv and *.hdbtabledata located in '<dbSrc>/data' and '<dbSrc>/csv' folder,
199
200
  // subfolders are not supported
200
- const allFiles = csvDirs.reduce((acc, csvDir) => {
201
- return acc.concat(getFiles(csvDir, (entry) => {
202
- if (cds.utils.isdir(entry)) {
203
- return false
204
- }
205
- return regexData.test(entry)
206
- }))
207
- }, [])
201
+ const allFiles = []
202
+ for (const csvDir of csvDirs) {
203
+ allFiles.push(...await find(csvDir, { filter: entry => regexData.test(entry) && !cds.utils.isdir(entry) }))
204
+ }
208
205
 
209
206
  return Promise.all(allFiles.map((file) => {
210
207
  return this.copy(file).to(path.join(this.task.options.compileDest, path.relative(src, file)))
@@ -226,7 +223,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
226
223
  const tableDataDirs = new Set()
227
224
  const destSrcDir = path.join(this.task.dest, "src")
228
225
 
229
- const allCsvFiles = getFiles(destSrcDir, (entry) => {
226
+ const allCsvFiles = await find(destSrcDir, { filter: (entry) => {
230
227
  if (cds.utils.isdir(entry)) {
231
228
  return true
232
229
  }
@@ -234,7 +231,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
234
231
  tableDataDirs.add(path.dirname(entry))
235
232
  }
236
233
  return /\.csv$/.test(entry)
237
- })
234
+ }})
238
235
  if (allCsvFiles.length > 0) {
239
236
  const csvDirs = allCsvFiles.map(path.dirname).reduce((dirs, dir) => {
240
237
  if (!tableDataDirs.has(dir) && !dirs.includes(dir)) { // exclude any dir where a tabledata is present
@@ -554,9 +551,9 @@ class HanaBuildPlugin extends InternalBuildPlugin {
554
551
 
555
552
  async _validateMigrationTableFiles() {
556
553
  const dbSrcDir = path.join(this.task.src, "src")
557
- const migrationTableFiles = getFiles(dbSrcDir, (res) => {
554
+ const migrationTableFiles = await find(dbSrcDir, { filter: (res) => {
558
555
  return fs.statSync(res).isFile() && path.extname(res) === FILE_EXT_HDBMIGRATIONTABLE
559
- })
556
+ }})
560
557
  if (migrationTableFiles.length > 0) {
561
558
  const parser = require('./migrationtable')
562
559
  const resolutionMessages = []
@@ -607,17 +604,17 @@ class HanaBuildPlugin extends InternalBuildPlugin {
607
604
  }
608
605
  }
609
606
  })
610
- const workspaceFiles = [...dbPaths].reduce((acc, src) => {
611
- const files = getFiles(src, (entry) => {
607
+ const workspaceFiles = []
608
+ for (const src of dbPaths) {
609
+ const files = await find(src, { filter: (entry) => {
612
610
  if (entry.match(/(\/|\\)gen(\/|\\)?$/)) {
613
611
  // skip gen folder content
614
612
  return false
615
613
  }
616
614
  return true
617
- })
618
- files.forEach(file => acc.push({ dir: src, filePath: path.relative(src, file), fileName: path.basename(file) }))
619
- return acc
620
- }, [])
615
+ }})
616
+ files.forEach(file => workspaceFiles.push({ dir: src, filePath: path.relative(src, file), fileName: path.basename(file) }))
617
+ }
621
618
 
622
619
  return workspaceFiles
623
620
  }
@@ -2,7 +2,8 @@ const fs = require('fs')
2
2
  const path = require('path')
3
3
  const cds = require('../../cds')
4
4
  const Plugin = require('../plugin')
5
- const { hasOptionValue, getFiles } = require('../util')
5
+ const { find } = require('../../util/fs')
6
+ const { hasOptionValue } = require('../util')
6
7
  const { FOLDER_GEN, DEFAULT_BUILTIN_PRIORITY_MAX } = require('../constants')
7
8
  const TRACE = cds.debug('trace')
8
9
 
@@ -88,14 +89,14 @@ class InternalBuildPlugin extends Plugin {
88
89
  return !regex.exec(path.basename(src))
89
90
  }
90
91
 
91
- const files = getFiles(srcDir, (src) => {
92
+ const files = await find(srcDir, { filter: src => {
92
93
  // do not copy files that:
93
94
  // - from 'cds.env.build.target'
94
95
  // - from 'dest'
95
96
  // - from some generation folder
96
97
  // - do not match filter function ,
97
98
  return commonStagingBuildFilter(src, destDir) && (!customFilter || customFilter.call(this, src))
98
- })
99
+ }})
99
100
  return Promise.all(
100
101
  files.map((srcFile) => {
101
102
  let relFile = path.relative(srcDir, srcFile)
@@ -115,7 +116,7 @@ class InternalBuildPlugin extends Plugin {
115
116
  // This ensures that the paths are relative to the cwd when executing cds run.
116
117
  const jsonOptions = {
117
118
  cwd: cds.root,
118
- src: this.hasBuildOption('flatDeployLayout', true) || this.task.src === this.task.dest ? this.task.src : cds.root
119
+ src: this.task.src === this.task.dest ? this.task.src : cds.root
119
120
  }
120
121
  const csnStr = cds_compile_to_json(model, jsonOptions)
121
122
  await this.write(csnStr).to(csnFile)
@@ -152,10 +153,33 @@ class InternalBuildPlugin extends Plugin {
152
153
  // bundleDest might be null
153
154
  if (bundleDest && Object.keys(bundles).length > 0) {
154
155
  await this.write(bundles).to(file)
156
+ // also collect and write messages from plugins
157
+ await this.collectMessageBundles(bundleDest)
155
158
  return { file, bundles }
156
159
  }
157
160
  return null
158
161
  }
162
+
163
+ /**
164
+ * Collect and write message bundles from CAP plugins into messages.properties files.
165
+ * @param {string} bundleDest
166
+ */
167
+ async collectMessageBundles(bundleDest) {
168
+ const messageBundle = cds.i18n.bundle4('messages')
169
+ const messagesData = messageBundle.translations4?.(cds.env.i18n.languages) ?? {}
170
+
171
+ // Write messages.properties files for each locale
172
+ for (const [locale, messages] of Object.entries(messagesData)) {
173
+ if (Object.keys(messages).length > 0) {
174
+ const fileName = locale ? `messages_${locale}.properties` : 'messages.properties'
175
+ const filePath = path.join(bundleDest, fileName)
176
+ const content = Object.entries(messages)
177
+ .map(([key, value]) => `${key}=${value}`)
178
+ .join('\n') + '\n'
179
+ await this.write(content).to(filePath)
180
+ }
181
+ }
182
+ }
159
183
  }
160
184
 
161
185
  // Emits the 'compile.for.runtime' event, as the produced CSN is for runtime usage.
@@ -1,14 +1,14 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
1
  const cds = require('../../cds')
2
+ const { exists, isdir, path } = cds.utils
4
3
  const { hasJavaNature, BuildError, normalizePath } = require('../util')
5
4
  const BuildTaskProvider = require('../buildTaskProvider')
6
5
  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
6
  BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION } = require("../constants")
8
7
  const ResourcesTarBuilder = require('./mtx/resourcesTarBuilder')
9
8
  const DEBUG = cds.debug('cli|build')
9
+ const ModelProviderService = 'cds.xt.ModelProviderService'
10
10
 
11
- class InternalBuildTaskProvider extends BuildTaskProvider {
11
+ module.exports = class InternalBuildTaskProvider extends BuildTaskProvider {
12
12
  providesTask(key) {
13
13
  return BUILD_TASKS.includes(key.for)
14
14
  }
@@ -29,20 +29,22 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
29
29
  let db = typeof cds.env.folders.db === "string" ? [normalizePath(cds.env.folders.db)] : cds.env.folders.db
30
30
  let srv = typeof cds.env.folders.srv === "string" ? [normalizePath(cds.env.folders.srv)] : cds.env.folders.srv
31
31
 
32
- const dbOptions = {
33
- model: []
34
- }
35
- const srvOptions = {
36
- model: []
32
+ const folder4 = filesOrFolders => {
33
+ const entry = filesOrFolders
34
+ .flatMap(r => path.extname(r) === FILE_EXT_CDS ? [r] : [r, r + FILE_EXT_CDS])
35
+ .find(r => exists(r))
36
+ return entry && (isdir(entry) ? entry : path.dirname(entry))
37
37
  }
38
+ const dbOptions = { model: [] }
39
+ const srvOptions = { model: [] }
38
40
  if (Array.isArray(db) && db.length > 0) {
39
- db = InternalBuildTaskProvider._getModuleFolder(db) || null
41
+ db = folder4(db)
40
42
  if (!db && !dependencies) { // log once
41
43
  DEBUG?.("No database module found")
42
44
  }
43
45
  }
44
46
  if (Array.isArray(srv) && srv.length > 0) {
45
- srv = InternalBuildTaskProvider._getModuleFolder(srv) || null
47
+ srv = folder4(srv)
46
48
  if (!srv && !dependencies) { // log once
47
49
  DEBUG?.("No service module found")
48
50
  }
@@ -130,51 +132,25 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
130
132
  }
131
133
 
132
134
  _createMtxTask(src) {
133
- // preserve order of creation
134
- if (InternalBuildTaskProvider._isMtxExtension()) {
135
- DEBUG?.("MTX extension app")
135
+ const main = cds.env
136
+ if (main.extends) {
136
137
  return { for: BUILD_TASK_MTX_EXTENSION }
137
138
  }
138
-
139
- if (InternalBuildTaskProvider._isMtxs()) {
140
- const sidecarPath = path.join(cds.root, MTX_SIDECAR_FOLDER)
141
- let sidecarEnv
142
- if (fs.existsSync(sidecarPath)) {
143
- sidecarEnv = cds.env.for("cds", sidecarPath)
139
+ const isMtxs = main.requires.toggles || main.requires.multitenancy || main.requires[ModelProviderService]
140
+ if (isMtxs) {
141
+ if (main.requires?.[ModelProviderService]?._in_sidecar) {
142
+ throw new BuildError(`Seems that you are executing 'cds build' in the 'mtx/sidecar' folder. Execute 'cds build' in the project root folder instead.`)
144
143
  }
145
- if (
146
- cds.env.profiles?.includes('with-mtx-sidecar') || // new presets // FIXME: BAD hard-coded dependency to profile
147
- cds.env.requires["cds.xt.ModelProviderService"]?.external // for compatibility with former mtxs presets
148
- ) {
149
- DEBUG?.("MTX app with sidecar")
150
- if (!sidecarEnv) {
151
- throw new BuildError(`MTX sidecar directory '${sidecarPath}' not existing. Custom build task configuration required if the folder is named differently.`)
152
- }
153
- if (!sidecarEnv.requires["cds.xt.ModelProviderService"]?._in_sidecar) {
154
- if (sidecarEnv.profiles?.includes('mtx-sidecar')) {
155
- // profile has been set, but cannot be resolved
156
- throw new BuildError("MTX configuration cannot be resolved. Run the 'npm install' command to install up-to-date versions of @sap/cds-mtxs and @sap/cds.")
157
- }
158
- throw new BuildError(`Invalid MTX sidecar configuration - profile 'mtx-sidecar' not set.`)
144
+ const sidecarPath = path.join(cds.root, MTX_SIDECAR_FOLDER)
145
+ const sidecar = cds.env.for("cds", sidecarPath)
146
+ if (sidecar?.requires[ModelProviderService]?._in_sidecar) {
147
+ if (!exists(sidecarPath)) {
148
+ throw new BuildError(`MTX sidecar directory '${MTX_SIDECAR_FOLDER}' does not exist. Custom build task configuration required if the folder is named differently.`)
159
149
  }
160
150
  return { src: MTX_SIDECAR_FOLDER, for: BUILD_TASK_MTX_SIDECAR }
161
151
  }
162
-
163
- if (sidecarEnv?.requires["cds.xt.ModelProviderService"]?._in_sidecar || sidecarEnv?.profiles?.includes('mtx-sidecar')) {
164
- throw new BuildError(`MTX sidecar requires profile 'with-mtx-sidecar' in project root configuration.`) // FIXME: BAD hard-coded dependency to profile
165
- }
166
- if (cds.env.requires["cds.xt.ModelProviderService"]?._in_sidecar || cds.env.profiles?.includes('mtx-sidecar')) {
167
- // cds build is executed in sidecar folder
168
- throw new BuildError(`Seems that you are executing 'cds build' in the 'mtx/sidecar' folder. Execute 'cds build' in the project root folder instead.`)
169
- }
170
-
171
- // mtxs nodejs app without sidecar
172
- if (!hasJavaNature()) {
173
- DEBUG?.("MTX Nodejs app without sidecar")
174
- return {
175
- for: BUILD_TASK_MTX,
176
- src
177
- }
152
+ if (!hasJavaNature()) { // only Node.js: embedded multitenancy
153
+ return { src, for: BUILD_TASK_MTX }
178
154
  }
179
155
  }
180
156
  }
@@ -203,7 +179,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
203
179
 
204
180
  _createNodeTask(src, taskOptions) {
205
181
  DEBUG?.("found Nodejs runtime")
206
- if (!fs.existsSync(path.join(cds.root, 'package.json'))) {
182
+ if (!exists('package.json')) {
207
183
  throw new BuildError(`No 'package.json' found in project root folder '${cds.root}'`)
208
184
  }
209
185
  return {
@@ -217,16 +193,6 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
217
193
  return !!cds.env.extends
218
194
  }
219
195
 
220
- /**
221
- * Distinguishes whether the Nodejs project is a Streamlined MTX (cds >=6) or an old MTX project.
222
- */
223
- static _isMtxs() {
224
- return cds.env.requires.toggles
225
- || cds.env.profiles.includes('with-mtx-sidecar') // FIXME: BAD hard-coded dependency to profile
226
- || cds.env.requires['cds.xt.ModelProviderService']
227
- || (typeof cds.env.requires.multitenancy === "object")
228
- }
229
-
230
196
  static _setDefaultSrcFolder(task) {
231
197
  switch (task.for) {
232
198
  case BUILD_TASK_HANA:
@@ -258,32 +224,4 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
258
224
  throw new Error(`Unknown build task '${task.for}'`)
259
225
  }
260
226
  }
261
-
262
- /**
263
- * Determines the module folder from the given list that may represent files or folders w or w/o .cds file extension.
264
- * @param {Array} filesOrFolders
265
- */
266
- static _getModuleFolder(filesOrFolders) {
267
- const resources = [...filesOrFolders]
268
- filesOrFolders.forEach(fileOrFolder => {
269
- if (path.extname(fileOrFolder) !== FILE_EXT_CDS) {
270
- resources.push(fileOrFolder + FILE_EXT_CDS)
271
- }
272
- })
273
- return resources.reduce((acc, resource) => {
274
- if (!acc) {
275
- let resourcePath = path.resolve(cds.root, resource)
276
- if (fs.existsSync(resourcePath)) {
277
- if (cds.utils.isdir(resourcePath)) {
278
- acc = resource
279
- } else {
280
- // represents file
281
- acc = path.dirname(resource)
282
- }
283
- }
284
- }
285
- return acc
286
- }, null)
287
- }
288
227
  }
289
- module.exports = InternalBuildTaskProvider
@@ -1,11 +1,9 @@
1
-
2
1
  const fs = require('fs')
3
2
  const path = require('path')
4
3
  const cds = require('../../../cds')
5
4
  const EdmxBuildPlugin = require('../edmxBuildPlugin')
6
5
  const ResourcesTarBuilder = require('./resourcesTarBuilder')
7
6
  const { FOLDER_GEN } = require('../../constants')
8
- const { BuildError } = require('../../util')
9
7
 
10
8
  class MtxBuildPlugin extends EdmxBuildPlugin {
11
9
  get priority() {
@@ -15,12 +13,6 @@ class MtxBuildPlugin extends EdmxBuildPlugin {
15
13
 
16
14
  init() {
17
15
  super.init()
18
-
19
- // this build task only supports nodejs mtxs apps without sidecar
20
- if (cds.env['project-nature'] === 'java') {
21
- throw new BuildError(`@sap/cds-mtx is deprecated and not supported by @sap/cds-dk >= 7. This also applies to the 'mtx' build task in Java projects.
22
- Upgrade to @sap/cds-mtxs following the migration guide https://cap.cloud.sap/docs/guides/multitenancy/old-mtx-migration.`)
23
- }
24
16
  }
25
17
 
26
18
  async build() {