@sap/cds-dk 7.0.3 → 7.1.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 (42) hide show
  1. package/bin/bind.js +5 -6
  2. package/bin/build.js +2 -7
  3. package/bin/cds.js +0 -4
  4. package/bin/subscribe.js +4 -4
  5. package/bin/unsubscribe.js +4 -4
  6. package/bin/upgrade.js +4 -4
  7. package/lib/bind/cfKeyProvider.js +9 -10
  8. package/lib/bind/index.js +1 -3
  9. package/lib/build/buildTaskEngine.js +9 -22
  10. package/lib/build/buildTaskFactory.js +18 -27
  11. package/lib/build/index.js +12 -3
  12. package/lib/build/provider/buildTaskProviderInternal.js +23 -15
  13. package/lib/build/provider/mtx/index.js +8 -2
  14. package/lib/build/util.js +13 -0
  15. package/lib/client/activate.js +7 -7
  16. package/lib/client/auth_manager.js +5 -5
  17. package/lib/client/base_command.js +5 -5
  18. package/lib/client/extend.js +2 -2
  19. package/lib/client/helper/logging.js +7 -2
  20. package/lib/client/params.js +2 -3
  21. package/lib/client/pull.js +3 -3
  22. package/lib/client/push.js +3 -3
  23. package/lib/client/settings_manager.js +7 -8
  24. package/lib/client/tenant_action.js +3 -3
  25. package/lib/deploy/to-hana/hana.js +1 -2
  26. package/lib/import/common.js +3 -0
  27. package/lib/import/message.js +2 -1
  28. package/lib/import/odata/v4parser.js +85 -95
  29. package/lib/init/index.js +24 -11
  30. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +1 -1
  31. package/lib/init/template/data/index.js +2 -3
  32. package/lib/init/template/lint/index.js +5 -6
  33. package/lib/init/template/nodejs/index.js +2 -3
  34. package/lib/init/template/pipeline/index.js +1 -2
  35. package/lib/init/util/indent.js +1 -1
  36. package/lib/init/util/merge.js +3 -3
  37. package/lib/init/util/mvn.js +17 -22
  38. package/lib/util/cfUtil.js +1 -2
  39. package/npm-shrinkwrap.json +353 -300
  40. package/package.json +1 -1
  41. package/lib/client/helper/errors.js +0 -26
  42. package/lib/util/version.js +0 -27
package/bin/bind.js CHANGED
@@ -54,7 +54,6 @@ module.exports = Object.assign(cds_bind, {
54
54
  const os = require('os');
55
55
  const IS_WIN = os.platform() === 'win32';
56
56
 
57
- const { CliError } = require('../lib/client/helper/errors');
58
57
  const { bind, parseProfile } = require('../lib/bind');
59
58
 
60
59
 
@@ -70,26 +69,26 @@ async function cds_bind(args, options) {
70
69
 
71
70
  // Check if cds command was bind. Don't abort in case of deploy
72
71
  if (process.env.CDS_ENV && process.argv[2] === 'bind') {
73
- throw new CliError('Option --profile is no longer supported. Use --for instead to specify the profile to use when storing connection settings.');
72
+ throw 'Option --profile is no longer supported. Use --for instead to specify the profile to use when storing connection settings.';
74
73
  }
75
74
 
76
75
  if (!options.to) {
77
- throw new CliError(`Use option --to or -2 to specify the target instance, e.g. cds bind --to myInstance:myService`);
76
+ throw `Use option --to or -2 to specify the target instance, e.g. cds bind --to myInstance:myService`;
78
77
  }
79
78
 
80
79
  if (args.length > 1) {
81
- throw new CliError(`Too many arguments: Please specify only one or no service.`);
80
+ throw `Too many arguments: Please specify only one or no service.`;
82
81
  }
83
82
 
84
83
  options.serviceArg = args[0]
85
84
  options.targets = options.to.split(/,/g);
86
85
 
87
86
  if (options.targets.length >= 2 && options.serviceArg) {
88
- throw new CliError(`Service argument cannot be specified together with multiple targets ('--to') services. Use one service per call or omit the service argument.`);
87
+ throw `Service argument cannot be specified together with multiple targets ('--to') services. Use one service per call or omit the service argument.`;
89
88
  }
90
89
 
91
90
  if (options.targets.length >= 2 && options.kind) {
92
- throw new CliError(`The option '--kind' cannot be specified together with multiple targets ('--to') services. Use one service per call or omit the '--kind' option.`);
91
+ throw `The option '--kind' cannot be specified together with multiple targets ('--to') services. Use one service per call or omit the '--kind' option.`;
93
92
  }
94
93
 
95
94
  await bind({
package/bin/build.js CHANGED
@@ -96,19 +96,14 @@ async function build([project], options = {}) {
96
96
  cds.env = cds.env.for('cds', cds.root);
97
97
  delete options.project // avoid that relative project paths are resolved twice
98
98
 
99
- options.cli = true // avoid that errors are logged twice
100
-
101
- const { CliError } = require('../lib/client/helper/errors')
102
99
  const { build } = require('../lib/build')
103
-
104
100
  const [major] = cds.version.split('.')
105
101
  if (Number(major) < 6) {
106
- throw new CliError("This application uses @sap/cds version < 6, which is not compatible with the installed @sap/cds-dk version >= 7. Update @sap/cds to version >= 6.")
102
+ throw "This application uses @sap/cds version < 6, which is not compatible with the installed @sap/cds-dk version >= 7. Update @sap/cds to version >= 6."
107
103
  }
108
104
  if (options.clean === "false") {
109
- throw new CliError("cds build option '--clean' is deprecated - build output folders are always cleaned before build")
105
+ throw "cds build option '--clean' is deprecated - build output folders are always cleaned before build"
110
106
  }
111
-
112
107
  if (typeof options["options-model"] === "string") {
113
108
  options.opts = "model=[" + options["options-model"].split(",").map((entry) => entry.trim()) + "]"
114
109
  delete options["options-model"]
package/bin/cds.js CHANGED
@@ -54,11 +54,7 @@ const cli = { //NOSONAR
54
54
  return await task.apply(this, args)
55
55
  }
56
56
  } catch (e) {
57
- const { BuildError } = require('../lib/build')
58
- const { CliError } = require('../lib/client/helper/errors')
59
57
  process.exitCode ??= 1
60
- if (e.messages?.length) return cds._log(e.messages, { 'log-level': cds.env.log.levels.cli })
61
- else if (e instanceof CliError || e instanceof BuildError) return console.error(e.message)
62
58
  if (cds.watched) throw e // bin/watched.js handles errors
63
59
  else return console.error(e)
64
60
  }
package/bin/subscribe.js CHANGED
@@ -46,19 +46,19 @@ module.exports = Object.assign(subscribe, {
46
46
 
47
47
 
48
48
  async function subscribe([tenant], options = {}) {
49
- const { CliError } = require('../lib/client/helper/errors');
49
+ const { getMessage } = require('../lib/client/helper/logging');
50
50
  if (!tenant) {
51
- throw new CliError('Tenant not given.', { command: 'subscribe' });
51
+ throw getMessage('Tenant not given.', { command: 'subscribe' });
52
52
  }
53
53
  const libOptions = { tenant };
54
54
  if (options.local) {
55
55
  libOptions.local = true;
56
56
  delete options.local;
57
57
  if (options.user) {
58
- throw new CliError('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
58
+ throw getMessage('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
59
59
  }
60
60
  if (options.to) {
61
- throw new CliError('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
61
+ throw getMessage('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
62
62
  }
63
63
  }
64
64
  const [username, password] = options.user?.split(':') ?? [];
@@ -47,19 +47,19 @@ module.exports = Object.assign(unsubscribe, {
47
47
 
48
48
 
49
49
  async function unsubscribe([tenant], options = {}) {
50
- const { CliError } = require('../lib/client/helper/errors');
50
+ const { getMessage } = require('../lib/client/helper/logging');
51
51
  if (!tenant) {
52
- throw new CliError('Tenant not given.', { command: 'unsubscribe' });
52
+ throw getMessage('Tenant not given.', { command: 'unsubscribe' });
53
53
  }
54
54
  const libOptions = { tenant };
55
55
  if (options.local) {
56
56
  libOptions.local = true;
57
57
  delete options.local;
58
58
  if (options.user) {
59
- throw new CliError('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
59
+ throw getMessage('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
60
60
  }
61
61
  if (options.from) {
62
- throw new CliError('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'unsubscribe' });
62
+ throw getMessage('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'unsubscribe' });
63
63
  }
64
64
  }
65
65
  const [username, password] = options.user?.split(':') ?? [];
package/bin/upgrade.js CHANGED
@@ -47,19 +47,19 @@ module.exports = Object.assign(upgrade, {
47
47
 
48
48
 
49
49
  async function upgrade([tenant], options = {}) {
50
- const { CliError } = require('../lib/client/helper/errors');
50
+ const { getMessage } = require('../lib/client/helper/logging');
51
51
  if (!tenant) {
52
- throw new CliError('Tenant not given.', { command: 'upgrade' });
52
+ throw getMessage('Tenant not given.', { command: 'upgrade' });
53
53
  }
54
54
  const libOptions = { tenant };
55
55
  if (options.local) {
56
56
  libOptions.local = true;
57
57
  delete options.local;
58
58
  if (options.user) {
59
- throw new CliError('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'upgrade' });
59
+ throw getMessage('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'upgrade' });
60
60
  }
61
61
  if (options.at) {
62
- throw new CliError('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'upgrade' });
62
+ throw getMessage('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'upgrade' });
63
63
  }
64
64
  }
65
65
  const [username, password] = options.user?.split(':') ?? [];
@@ -7,7 +7,6 @@ const axios = require('axios');
7
7
  require('../util/pruneAxiosErrors');
8
8
  const { URL } = require('url');
9
9
  const { bold, highlight } = require('../util/term');
10
- const { CliError } = require('../client/helper/errors');
11
10
 
12
11
  class CFKeyProvider {
13
12
  async getCfSpaceInfo() {
@@ -21,13 +20,13 @@ class CFKeyProvider {
21
20
  const { org, space } = target;
22
21
  const orgs = await BatchRequest.req(targetWithAuth, `/v3/organizations?names=${encodeURIComponent(encodeURIComponent(org))}`);
23
22
  if (!(orgs && orgs.resources.length === 1)) {
24
- throw new CliError(`CF org ${org} not found!`);
23
+ throw `CF org ${org} not found!`;
25
24
  }
26
25
 
27
26
  const orgGuid = orgs.resources[0].guid;
28
27
  const spaces = await BatchRequest.req(targetWithAuth, `/v3/spaces?names=${encodeURIComponent(encodeURIComponent(space))}&organization_guids=${encodeURIComponent(encodeURIComponent(orgGuid))}`)
29
28
  if (!(spaces && spaces.resources.length === 1)) {
30
- throw new CliError(`CF space ${space} not found in org ${org}!`);
29
+ throw `CF space ${space} not found in org ${org}!`;
31
30
  }
32
31
 
33
32
  const spaceGuid = spaces.resources[0].guid;
@@ -81,7 +80,7 @@ class CFKeyProvider {
81
80
  try {
82
81
  instanceObj = await this.getInstance({ names: instance, space_guids: spaceGuid });
83
82
  } catch (error) {
84
- throw new CliError(`Service instance "${instance}" not found.`);
83
+ throw `Service instance "${instance}" not found.`;
85
84
  }
86
85
  switch (instanceObj.type) {
87
86
  case 'managed':
@@ -89,7 +88,7 @@ class CFKeyProvider {
89
88
  case 'user-provided':
90
89
  return this._resolveUserProvidedService(instanceObj, instance, org, space);
91
90
  default:
92
- throw new CliError(`Service type ${instanceObj.type} not supported`)
91
+ throw `Service type ${instanceObj.type} not supported`;
93
92
  }
94
93
  }
95
94
 
@@ -100,7 +99,7 @@ class CFKeyProvider {
100
99
  } catch (error) {
101
100
  let message = `No service key ${highlight(key)} found for service instance ${highlight(instance)}.\n\n`;
102
101
  message += `Use ${bold(`cf create-service-key ${instanceObj.name} ${key} [-c ...]`)} to create the required service key.`;
103
- throw new CliError(message);
102
+ throw message;
104
103
  }
105
104
  const planObj = await this.getPlans({ guids: instanceObj.relationships.service_plan.data.guid });
106
105
  const offeringObj = await this.getOfferings({ guids: planObj.relationships.service_offering.data.guid });
@@ -151,10 +150,10 @@ class CFKeyProvider {
151
150
 
152
151
  // if no api endpoint is configured the currently logged in endpoint will be used
153
152
  if (apiEndpoint && apiEndpoint !== this.target.apiEndpoint) {
154
- name = `${name || instance}:${key || instance + '-key'}`
153
+ name = `${name || instance}:${key || instance + '-key'}`;
155
154
  let message = `Current Cloud Foundry API endpoint ${highlight(this.target.apiEndpoint)} differs from API endpoint ${highlight(apiEndpoint)} for service binding ${highlight(name)}.\n\n`;
156
155
  message += `Use ${bold(`cf login -a ${apiEndpoint}`)} to log in to the target API endpoint.`;
157
- throw new CliError(message)
156
+ throw message;
158
157
  }
159
158
  }
160
159
  }
@@ -224,9 +223,9 @@ class BatchRequest {
224
223
  if (filteredResources.length === 1) {
225
224
  filter.resolve(filteredResources[0]);
226
225
  } else if (filteredResources.length === 0) {
227
- filter.reject(new CliError(`Couldn't find resource for url "${this.url}" with filter "${fmt(filter.filter)}"`));
226
+ filter.reject(`Couldn't find resource for url "${this.url}" with filter "${fmt(filter.filter)}"`);
228
227
  } else {
229
- filter.reject(new CliError(`Found more than one resources for url "${this.url}" with filter "${fmt(filter.filter)}"`));
228
+ filter.reject(`Found more than one resources for url "${this.url}" with filter "${fmt(filter.filter)}"`);
230
229
  }
231
230
  }
232
231
  }
package/lib/bind/index.js CHANGED
@@ -1,7 +1,5 @@
1
1
  const cds = require('../cds');
2
2
 
3
- const { CliError } = require('../client/helper/errors');
4
-
5
3
  const BindingResolver = require('./bindingResolver');
6
4
  const { determineKinds, getRequiresNameFromKind, checkIsJavaProject, platformText, bindingText, logger } = require('./bindingUtil');
7
5
  const { highlight, bold, info } = require('../util/term');
@@ -31,7 +29,7 @@ async function bind(options) {
31
29
  on = 'cf';
32
30
  break;
33
31
  default:
34
- throw new CliError(`Invalid value '${options.on}' for option --on.`);
32
+ throw `Invalid value '${options.on}' for option --on.`;
35
33
  }
36
34
 
37
35
  const onText = { 'cf': 'Cloud Foundry', 'k8s': 'Kubernetes' }[on];
@@ -27,7 +27,6 @@ class BuildTaskEngine {
27
27
 
28
28
  async processTasks(tasks) {
29
29
  const startTime = Date.now()
30
- const messages = []
31
30
 
32
31
  this.logger.log(`building project [${cds.root}], clean [${this.buildOptions.clean}]`)
33
32
  this.logger.log(`cds-dk [${require('../../package.json').version}], cds [${cds.version}], compiler [${cds.compiler.version()}], home [${cds.home}]\n`)
@@ -64,18 +63,12 @@ class BuildTaskEngine {
64
63
 
65
64
  await this._writeGenerationLog(handlers)
66
65
  this._logBuildOutput(handlers)
67
- this._logMessages([...BuildTaskEngine._getHandlerMessages(handlers), ...messages])
66
+ this._logMessages(BuildTaskEngine._getHandlerMessages(handlers))
68
67
  this._logTimer(startTime, Date.now())
69
68
 
70
69
  return buildResult
71
70
  } catch (error) {
72
71
  this._logBuildOutput(handlers)
73
-
74
- // cds CLI layer logs in case of an exception if invoked from CLI
75
- if (!this.buildOptions.cli) {
76
- this._logMessages([...BuildTaskEngine._getErrorMessages([error]), ...messages])
77
- }
78
-
79
72
  throw error
80
73
  }
81
74
  }
@@ -215,22 +208,16 @@ class BuildTaskEngine {
215
208
  }
216
209
 
217
210
  _createHandler(task) {
218
- try {
219
- const handler = this.providerFactory.createHandler(task)
220
- handler.init()
211
+ const handler = this.providerFactory.createHandler(task)
212
+ handler.init()
221
213
 
222
- if (!(handler instanceof BuildTaskHandlerInternal) && handler.priority !== 1) {
223
- // Custom build handlers are executed before internal handlers to ensure
224
- // that generated content cannot be overwritten by mistake
225
- throw new Error(`Illegal priority for ${handler.constructor.name} encountered for custom handler - in this version only priority value '1' is allowed`)
226
- }
227
- this._logTaskHandler(handler)
228
-
229
- return handler
230
- } catch (error) {
231
- log(error, { log: this.logger.log })
232
- throw error
214
+ if (!(handler instanceof BuildTaskHandlerInternal) && handler.priority !== 1) {
215
+ // Custom build handlers are executed before internal handlers to ensure
216
+ // that generated content cannot be overwritten by mistake
217
+ throw new Error(`Illegal priority for ${handler.constructor.name} encountered for custom handler - in this version only priority value '1' is allowed`)
233
218
  }
219
+ this._logTaskHandler(handler)
220
+ return handler
234
221
  }
235
222
 
236
223
  _logBuildOutput(handlers) {
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
- const cds = require('../cds'), { _log:log } = cds
3
+ const cds = require('../cds')
4
4
  const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
5
5
  const { hasJavaNature, getProperty, redactCredentials, flatten, getDefaultModelOptions } = require('./util')
6
6
  const { FILE_EXT_CDS, BUILD_TASK_JAVA_CF, BUILD_TASK_JAVA } = require("./constants")
@@ -24,36 +24,27 @@ class BuildTaskFactory {
24
24
  // 2. read using cds.env.build.tasks
25
25
  // 3. create from cds.env.folders config data
26
26
  async getTasks() {
27
- try {
28
- const tasks = await this._createTasks()
27
+ const tasks = await this._createTasks()
29
28
 
30
- // log build tasks
31
- this.logger.log(`the following build tasks will be executed`)
32
- let tasksOutput = " {\n \"build\": {\n \"target\": \"" + cds.env.build.target + "\",\n \"tasks\": ["
33
- for (let i = 0; i < tasks.length; i++) {
34
- tasksOutput += "\n " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? "," : "")
35
- }
36
- tasksOutput += "\n ]\n }\n }\n"
37
- this.logger.log(tasksOutput)
29
+ // log build tasks
30
+ this.logger.log(`the following build tasks will be executed`)
31
+ let tasksOutput = " {\n \"build\": {\n \"target\": \"" + cds.env.build.target + "\",\n \"tasks\": ["
32
+ for (let i = 0; i < tasks.length; i++) {
33
+ tasksOutput += "\n " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? "," : "")
34
+ }
35
+ tasksOutput += "\n ]\n }\n }\n"
36
+ this.logger.log(tasksOutput)
38
37
 
39
- // for testing purposes
40
- this.logger.debug("cds.env used for build:")
41
- this.logger._debug && this.logger.debug(redactCredentials(cds.env))
38
+ // for testing purposes
39
+ this.logger.debug("cds.env used for build:")
40
+ this.logger._debug && this.logger.debug(redactCredentials(cds.env))
42
41
 
43
- // always resolve tasks for input validation
44
- const resolvedTasks = this.providerFactory.resolveTasks(tasks)
45
- if (this.buildOptions.resolve) {
46
- return resolvedTasks
47
- }
48
- return tasks
49
- } catch (e) {
50
- this.logger.log('')
51
- // cds CLI layer is doing the logging if invoked using CLI
52
- if (!this.buildOptions.cli) {
53
- log(e, { withStack: true, log: (message) => this.logger.log(message) })
54
- }
55
- throw e
42
+ // always resolve tasks for input validation
43
+ const resolvedTasks = this.providerFactory.resolveTasks(tasks)
44
+ if (this.buildOptions.resolve) {
45
+ return resolvedTasks
56
46
  }
47
+ return tasks
57
48
  }
58
49
 
59
50
  async _createTasks() {
@@ -14,8 +14,17 @@ module.exports = { build, BuildTaskFactory, BuildTaskEngine, BuildTaskHandler, B
14
14
  */
15
15
  async function build(options = {}) {
16
16
  if (!fs.existsSync(cds.root) || !fs.lstatSync(cds.root).isDirectory()) {
17
- const { CliError } = require('../client/helper/errors')
18
- throw new CliError(`Project folder '${cds.root}' does not exist`)
17
+ throw `Project folder '${cds.root}' does not exist`
18
+ }
19
+ try {
20
+ return await new BuildTaskEngine(options).processTasks()
21
+ } catch (e) {
22
+ if (e instanceof BuildError || e.constructor.name === 'CompilationError') {
23
+ cds._log(e.messages.length ? [...e.messages, ''] : e.message + '\n', { 'log-level': options['log-level'] || cds.env['log-level'] })
24
+ // CompilationError.message also includes the detail messages - do not log twice
25
+ const message = e.constructor.name === 'CompilationError' ? 'CDS compilation failed' : e.messages.length ? e.message : 'CDS build failed'
26
+ throw message
27
+ }
28
+ throw e
19
29
  }
20
- return await new BuildTaskEngine(options).processTasks()
21
30
  }
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
  const cds = require('../../cds')
4
- const { hasJavaNature, getDefaultModelOptions, BuildError, hasOptionValue } = require('../util')
4
+ const { hasJavaNature, getDefaultModelOptions, BuildError, hasOptionValue, isClassicMtx } = require('../util')
5
5
  const BuildTaskProvider = require('../buildTaskProvider')
6
6
 
7
7
  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,
@@ -12,6 +12,11 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
12
12
  constructor(logger) {
13
13
  super()
14
14
  this._logger = logger
15
+ // ensure that classic mtx is not used in combination with cds-dk@7
16
+ if (isClassicMtx()) {
17
+ throw new BuildError(`@sap/cds-mtx is deprecated and not supported by @sap/cds-dk >= 7.
18
+ Upgrade to @sap/cds-mtxs following the migration guide https://cap.cloud.sap/docs/guides/multitenancy/old-mtx-migration or install @sap/cds-dk version 6 instead.`)
19
+ }
15
20
  }
16
21
  get logger() {
17
22
  return this._logger
@@ -65,7 +70,8 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
65
70
  this.logger.debug("No service module found")
66
71
  }
67
72
  }
68
- // create required build tasks
73
+
74
+ // order of creation is relevant
69
75
  if (addRequiredTasks) {
70
76
  const mtxTask = tasks.find(task => task.for === BUILD_TASK_MTX || task.for === BUILD_TASK_MTX_SIDECAR)
71
77
  if (mtxTask) {
@@ -80,12 +86,15 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
80
86
  let dbTask = tasks.find(task => task.for === BUILD_TASK_HANA)
81
87
  if (!dbTask) {
82
88
  // db task might be missing if mtx task is enforced by 'cds build --for mtx'
83
- dbTask = this._createDbTask(db, dbOptions)
89
+ dbTask = cds.env.build.tasks?.find(task => task.for === BUILD_TASK_HANA)
90
+ if (!dbTask) {
91
+ dbTask = this._createDbTask(db, dbOptions)
92
+ }
84
93
  if (dbTask) {
85
94
  tasks.push(dbTask)
86
95
  }
87
96
  }
88
- if (dbTask && (!mtxTask._uses || !mtxTask._uses.map(use => use.task).includes(dbTask))) {
97
+ if (dbTask && !mtxTask._uses?.map(use => use.task).includes(dbTask)) {
89
98
  const use = { task: dbTask }
90
99
  mtxTask._uses ? mtxTask._uses.push(use) : mtxTask._uses = [use]
91
100
  }
@@ -106,7 +115,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
106
115
  }
107
116
 
108
117
  // create mtx build task
109
- const mtxTask = this._createMtxTask(srv, tasks)
118
+ const mtxTask = this._createMtxTask(srv)
110
119
  if (mtxTask) {
111
120
  tasks.push(mtxTask)
112
121
  }
@@ -153,7 +162,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
153
162
  return userEnv && (userEnv.data?.model || userEnv.service?.model)
154
163
  }
155
164
 
156
- _createMtxTask(src, tasks) {
165
+ _createMtxTask(src) {
157
166
  this.logger.debug("determining MTX architecture")
158
167
 
159
168
  // preserve order of creation
@@ -177,26 +186,26 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
177
186
  throw new BuildError(`MTX sidecar directory '${sidecarPath}' not existing. Custom build task configuration required if the folder is named differently.`)
178
187
  }
179
188
  if (!sidecarEnv.requires["cds.xt.ModelProviderService"]?._in_sidecar) {
180
- // correct profile might have been set, but couldn't be resolved
181
189
  if (sidecarEnv.profiles?.includes('mtx-sidecar')) {
182
- throw new BuildError('MTX configuration cannot be resolved. Make sure an up-to-date version of @sap/cds-mtxs is installed.')
190
+ // profile has been set, but cannot be resolved
191
+ throw new BuildError('MTX configuration cannot be resolved. Make sure up-to-date versions of @sap/cds-mtxs and @sap/cds are installed.')
183
192
  }
184
193
  throw new BuildError(`Invalid MTX sidecar configuration - profile 'mtx-sidecar' not set.`)
185
194
  }
186
195
  return { for: BUILD_TASK_MTX_SIDECAR }
187
196
  }
197
+
188
198
  if (sidecarEnv?.requires["cds.xt.ModelProviderService"]?._in_sidecar || sidecarEnv?.profiles?.includes('mtx-sidecar')) {
189
199
  throw new BuildError(`MTX sidecar requires profile 'with-mtx-sidecar' in project root configuration.`)
190
200
  }
191
-
192
201
  if (cds.env.requires["cds.xt.ModelProviderService"]?._in_sidecar || cds.env.profiles?.includes('mtx-sidecar')) {
193
202
  // cds build is executed in sidecar folder
194
203
  throw new BuildError(`Seems that you are executing 'cds build' in the 'mtx/sidecar' folder. Execute 'cds build' in the project root folder instead.`)
195
204
  }
196
205
 
197
- // mtxs with nodejs, but without sidecar
198
- if (!tasks.some(task => task.for === BUILD_TASK_JAVA || task.for === BUILD_TASK_JAVA_CF)) {
199
- this.logger.debug("MTX app without sidecar")
206
+ // mtxs nodejs app without sidecar
207
+ if (!BuildTaskProviderInternal._hasJavaNature(src)) {
208
+ this.logger.debug("MTX Nodejs app without sidecar")
200
209
  return {
201
210
  for: BUILD_TASK_MTX,
202
211
  src
@@ -278,7 +287,6 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
278
287
  task.src = task.src || "."
279
288
  break
280
289
  case BUILD_TASK_MTX:
281
- require('../../util/version').checkMtx(cds)
282
290
  // mtxs with nodejs, but without sidecar
283
291
  task.src = task.src || this._normalizePath(cds.env.folders.srv)
284
292
  break
@@ -310,7 +318,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
310
318
  }
311
319
 
312
320
  // REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
313
- if (this._hasJavaNature(cds.env.folders.srv)) {
321
+ if (this._hasJavaNature()) {
314
322
  defaultModelPaths = defaultModelPaths.filter(p => !NODEJS_MODEL_EXCLUDE_LIST.includes(p))
315
323
  }
316
324
  // also add built-in models to custom build tasks already containing model options
@@ -323,7 +331,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
323
331
  * Returns whether this project is a java project or not.
324
332
  * @param {string} srv - the folder name of the service module
325
333
  */
326
- static _hasJavaNature(srv) {
334
+ static _hasJavaNature(srv = cds.env.folders.srv) {
327
335
  srv = this._getModuleFolder(Array.isArray(srv) ? srv : [srv])
328
336
  return hasJavaNature([cds.root, srv && path.join(cds.root, srv)])
329
337
  }
@@ -5,6 +5,7 @@ const cds = require('../../../cds')
5
5
  const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
6
6
  const ResourcesTarProvider = require('./resourcesTarBuilder')
7
7
  const { FOLDER_GEN } = require('../../constants')
8
+ const { BuildError } = require('../../util')
8
9
 
9
10
  class MtxModuleBuilder extends BuildTaskHandlerEdmx {
10
11
  get priority() {
@@ -13,12 +14,17 @@ class MtxModuleBuilder extends BuildTaskHandlerEdmx {
13
14
  }
14
15
  init() {
15
16
  super.init()
17
+
18
+ // this build task only supports nodejs mtxs apps without sidecar
19
+ if (cds.env['project-nature'] === 'java') {
20
+ 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.
21
+ Upgrade to @sap/cds-mtxs following the migration guide https://cap.cloud.sap/docs/guides/multitenancy/old-mtx-migration or install @sap/cds-dk version 6 instead.`)
22
+ }
16
23
  }
17
24
 
18
25
  async build() {
19
- // Non-sidecar scenario: model-provider is implemented by the Nodejs app itself (default for Nodejs).
20
26
  // Only create resources TAR, compiled CSN(s) are created by the Nodejs app build task.
21
- const dest = cds.env.build.target !== "." ? this.task.dest : path.join(this.task.dest, FOLDER_GEN)
27
+ const dest = cds.env.build.target !== '.' ? this.task.dest : path.join(this.task.dest, FOLDER_GEN)
22
28
  const model = await this.model()
23
29
  if (!model) {
24
30
  return
package/lib/build/util.js CHANGED
@@ -177,6 +177,18 @@ function getI18nDefaultFolder() {
177
177
  return cds.env.i18n.folders[0] ?? 'i18n'
178
178
  }
179
179
 
180
+ function isClassicMtx() {
181
+ function _hasMtxDependency() {
182
+ try {
183
+ return !!require(path.join(cds.root, 'package.json'))?.dependencies?.['@sap/cds-mtx']
184
+ } catch (e) {
185
+ return false
186
+ }
187
+ }
188
+ return /true/i.test(process.env.OLD_MTX) || _hasMtxDependency()
189
+ }
190
+
191
+
180
192
  /**
181
193
  * Return gnu-style error string for location `loc`:
182
194
  * - 'File:Line:Col' without `loc.end`
@@ -266,6 +278,7 @@ module.exports = {
266
278
  flatten,
267
279
  copy,
268
280
  getI18nDefaultFolder,
281
+ isClassicMtx,
269
282
  BuildMessage,
270
283
  BuildError
271
284
  }
@@ -5,7 +5,7 @@ const axios = require('axios');
5
5
  const cds = require('../cds');
6
6
  const DEBUG = cds.debug('cli');
7
7
  const { collectFileContent, collectFiles, toUnixPath } = require('./helper/fs_helper');
8
- const { CliError } = require('./helper/errors');
8
+ const { getMessage } = require('./helper/logging');
9
9
 
10
10
  const AuthManager = require('./auth_manager');
11
11
  const BaseCommand = require('./base_command');
@@ -30,7 +30,7 @@ async function checkFinished(jobId, statusUrl, params, finisher) {
30
30
  finisher.finished = true;
31
31
  clearInterval(finisher.timer);
32
32
  if (status === JOB_STATUS.FAILED) {
33
- return finisher.reject(new CliError(`Job ${jobId} failed`, { error }));
33
+ return finisher.reject(getMessage(`Job ${jobId} failed`, { error }));
34
34
  }
35
35
  console.log('Extension active');
36
36
  finisher.resolve();
@@ -58,7 +58,7 @@ module.exports = class Activate extends BaseCommand {
58
58
  }
59
59
 
60
60
  if (!await this.checkProject(params.get('projectFolder'))) {
61
- throw new CliError(params.get('projectFolder') + ' is not a valid extension project');
61
+ throw params.get('projectFolder') + ' is not a valid extension project';
62
62
  }
63
63
 
64
64
  try {
@@ -133,7 +133,7 @@ module.exports = class Activate extends BaseCommand {
133
133
  try {
134
134
  pkgJson = await fs.readFile(path.join(absoluteFolder, 'package.json'), 'utf-8');
135
135
  } catch (error) {
136
- throw new CliError('No package.json file found', { error });
136
+ throw getMessage('No package.json file found', { error });
137
137
  }
138
138
  allFiles.set('package.json', pkgJson);
139
139
 
@@ -182,11 +182,11 @@ module.exports = class Activate extends BaseCommand {
182
182
  const { jobID: jobId, statusPath } = response.data;
183
183
 
184
184
  if (jobId === undefined) {
185
- throw new CliError('Activation failed: did not receive job ID');
185
+ throw 'Activation failed: did not receive job ID';
186
186
  }
187
187
 
188
188
  if (!statusPath) {
189
- throw new CliError(`Job ${jobId} failed: did not receive job-status path`);
189
+ throw `Job ${jobId} failed: did not receive job-status path`;
190
190
  }
191
191
 
192
192
  DEBUG?.(`Job ID: ${jobId}`);
@@ -199,7 +199,7 @@ module.exports = class Activate extends BaseCommand {
199
199
  finished: false,
200
200
  timer: null
201
201
  };
202
- finisher.timer = setInterval(checkFinished.bind(undefined, jobId, statusUrl, params, finisher), 250).unref();
202
+ finisher.timer = setInterval(checkFinished.bind(undefined, jobId, statusUrl, params, finisher), 250);
203
203
  });
204
204
  });
205
205
  }