@sap/cds-dk 7.2.0 → 7.3.1

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 (105) hide show
  1. package/bin/activate.js +2 -2
  2. package/bin/add.js +1 -1
  3. package/bin/build.js +6 -3
  4. package/bin/compile/index.js +9 -5
  5. package/bin/env.js +0 -3
  6. package/bin/extend.js +29 -3
  7. package/bin/import.js +7 -3
  8. package/bin/init.js +31 -37
  9. package/bin/push.js +10 -6
  10. package/bin/repl.js +23 -43
  11. package/bin/watch.js +5 -9
  12. package/lib/bind/bindingResolver.js +2 -1
  13. package/lib/bind/index.js +1 -1
  14. package/lib/build/{buildTaskHandler.js → buildPlugin.js} +40 -27
  15. package/lib/build/buildTaskEngine.js +75 -74
  16. package/lib/build/buildTaskFactory.js +39 -32
  17. package/lib/build/buildTaskProvider.js +24 -19
  18. package/lib/build/buildTaskProviderFactory.js +125 -58
  19. package/lib/build/constants.js +6 -4
  20. package/lib/build/index.js +7 -3
  21. package/lib/build/plugins.js +35 -0
  22. package/lib/build/provider/{buildTaskHandlerEdmx.js → edmxBuildPlugin.js} +11 -7
  23. package/lib/build/provider/{buildTaskHandlerFeatureToggles.js → featureToggleBuildPlugin.js} +5 -5
  24. package/lib/build/provider/fiori/index.js +5 -6
  25. package/lib/build/provider/hana/index.js +54 -30
  26. package/lib/build/provider/{buildTaskHandlerInternal.js → internalBuildPlugin.js} +14 -10
  27. package/lib/build/provider/{buildTaskProviderInternal.js → internalBuildTaskProvider.js} +27 -28
  28. package/lib/build/provider/java/index.js +30 -24
  29. package/lib/build/provider/mtx/index.js +4 -4
  30. package/lib/build/provider/mtx/resourcesTarBuilder.js +8 -8
  31. package/lib/build/provider/mtx-extension/index.js +17 -9
  32. package/lib/build/provider/mtx-sidecar/index.js +17 -11
  33. package/lib/build/provider/nodejs/index.js +14 -13
  34. package/lib/build/util.js +5 -0
  35. package/lib/client/auth_manager.js +6 -12
  36. package/lib/client/base_command.js +1 -1
  37. package/lib/client/download_legacy.js +43 -0
  38. package/lib/client/params.js +6 -0
  39. package/lib/client/push.js +41 -1
  40. package/lib/client/settings_manager.js +28 -17
  41. package/lib/compile/openapi/csdl2openapi.js +1 -1
  42. package/lib/env/schema.js +36 -0
  43. package/lib/env/schemas/cds-rc.json +101 -0
  44. package/lib/import/common.js +23 -10
  45. package/lib/import/importapi.js +2 -2
  46. package/lib/import/message.js +3 -1
  47. package/lib/import/odata/v4parser.js +23 -7
  48. package/lib/index.js +11 -0
  49. package/lib/init/constants.js +5 -2
  50. package/lib/init/index.js +2 -3
  51. package/lib/init/template/_merging/registry-mta.js +33 -0
  52. package/lib/init/template/approuter/files/mta.yaml.hbs +1 -1
  53. package/lib/init/template/approuter/index.js +9 -9
  54. package/lib/init/template/connectivity/index.js +5 -4
  55. package/lib/init/template/destination/index.js +2 -5
  56. package/lib/init/template/helm/subcharts/content-deployment/Chart.yaml +4 -4
  57. package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +4 -2
  58. package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +4 -3
  59. package/lib/init/template/helm/subcharts/content-deployment/values.schema.json +9 -83
  60. package/lib/init/template/helm/subcharts/content-deployment/values.yaml +54 -15
  61. package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +4 -4
  62. package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +1 -1
  63. package/lib/init/template/helm/subcharts/service-instance/values.schema.json +0 -17
  64. package/lib/init/template/helm/subcharts/service-instance/values.yaml +28 -0
  65. package/lib/init/template/helm/subcharts/web-application/Chart.yaml +5 -5
  66. package/lib/init/template/helm/subcharts/web-application/templates/_api.tpl +60 -0
  67. package/lib/init/template/helm/subcharts/web-application/templates/_helpers.tpl +34 -73
  68. package/lib/init/template/helm/subcharts/web-application/templates/api-rule.yaml +4 -4
  69. package/lib/init/template/helm/subcharts/web-application/templates/deployment.yaml +96 -17
  70. package/lib/init/template/helm/subcharts/web-application/templates/network-policy.yaml +19 -3
  71. package/lib/init/template/helm/subcharts/web-application/templates/pod-disruption-budget.yaml +3 -3
  72. package/lib/init/template/helm/subcharts/web-application/templates/rbac.yaml +26 -0
  73. package/lib/init/template/helm/subcharts/web-application/templates/secret.yaml +1 -1
  74. package/lib/init/template/helm/subcharts/web-application/templates/service-account.yaml +1 -1
  75. package/lib/init/template/helm/subcharts/web-application/templates/service-binding.yaml +1 -1
  76. package/lib/init/template/helm/subcharts/web-application/templates/service.yaml +21 -3
  77. package/lib/init/template/helm/subcharts/web-application/templates/virtual-service.yaml +36 -0
  78. package/lib/init/template/helm/subcharts/web-application/values.schema.json +535 -142
  79. package/lib/init/template/helm/subcharts/web-application/values.yaml +168 -44
  80. package/lib/init/template/html5-repo/index.js +27 -3
  81. package/lib/init/template/mta/index.js +9 -3
  82. package/lib/init/template/nodejs/files/.vscode/launch.json +0 -3
  83. package/lib/init/template/notifications/files/mta.yaml.hbs +17 -0
  84. package/lib/init/template/notifications/files/notificationtypes.json.hbs +16 -0
  85. package/lib/init/template/notifications/files/package.json.hbs +14 -0
  86. package/lib/init/template/notifications/index.js +52 -0
  87. package/lib/init/template/postgres/files/mta.yaml.hbs +27 -0
  88. package/lib/init/template/postgres/files/package.json.hbs +5 -0
  89. package/lib/init/template/postgres/index.js +52 -0
  90. package/lib/init/util/projectReader.js +0 -1
  91. package/lib/util/pruneAxiosErrors.js +25 -8
  92. package/lib/util/term.js +1 -2
  93. package/lib/watch/livereload-server.js +38 -2
  94. package/lib/watch/node-watch.js +3 -2
  95. package/npm-shrinkwrap.json +334 -335
  96. package/package.json +2 -2
  97. package/lib/init/template/helm/subcharts/content-deployment/templating.md +0 -37
  98. package/lib/init/template/helm/subcharts/content-deployment/values-lint.yaml +0 -5
  99. package/lib/init/template/helm/subcharts/content-deployment/values.md +0 -1011
  100. package/lib/init/template/helm/subcharts/service-instance/templating.md +0 -18
  101. package/lib/init/template/helm/subcharts/service-instance/values-lint.yaml +0 -2
  102. package/lib/init/template/helm/subcharts/service-instance/values.md +0 -186
  103. package/lib/init/template/helm/subcharts/web-application/templating.md +0 -51
  104. package/lib/init/template/helm/subcharts/web-application/values-lint.yaml +0 -8
  105. package/lib/init/template/helm/subcharts/web-application/values.md +0 -1363
@@ -2,13 +2,13 @@ const path = require('path')
2
2
  const fs = require('fs').promises
3
3
  const cds = require('../cds')
4
4
 
5
- const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR, OVERRIDE_METHOD_MSG } = require('./constants')
6
- const { hasOptionValue, getProperty, relativePaths, BuildMessage } = require('./util')
5
+ const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR } = require('./constants')
6
+ const { hasOptionValue, getProperty, relativePaths, BuildMessage, pathExists } = require('./util')
7
7
 
8
8
  /**
9
- * The build task handler creates the build output for a dedicated build task. It is uniquely identified
10
- * by the build task's <code>use</code> property. It represents the fully qualified node module path
11
- * of the build task handler implementation.
9
+ * The build plugin creates the build output for a dedicated build task. It is uniquely identified
10
+ * by the build task's <code>for</code> or <code>use</code>property. The <code>use</code> property represents
11
+ * the fully qualified node module path of the build plugin implementation.
12
12
  * <p>
13
13
  * The build task engine defines the following protocol. The methods are invoked in descending order:
14
14
  * <ul>
@@ -19,17 +19,17 @@ const { hasOptionValue, getProperty, relativePaths, BuildMessage } = require('./
19
19
  * </ul>
20
20
  * The reflected CSN can be accessed using the async method <code>model()</code>.
21
21
  */
22
- class BuildTaskHandler {
22
+ class BuildPlugin {
23
23
  /**
24
- * @class
24
+ * @constructor
25
25
  */
26
26
  constructor() {
27
- if (new.target === BuildTaskHandler) {
28
- throw new TypeError("Cannot construct BuildTaskHandler instances directly");
29
- }
30
27
  this._written = new Set()
31
28
  this._messages = []
32
29
  }
30
+ static hasTask() {
31
+ return true
32
+ }
33
33
  static get INFO() {
34
34
  return SEVERITY_INFO
35
35
  }
@@ -47,7 +47,7 @@ class BuildTaskHandler {
47
47
  return this._context
48
48
  }
49
49
  /**
50
- * Returns the build task executed by this build task handler.
50
+ * Returns the build task executed by this build plugin.
51
51
  * @return {object}
52
52
  */
53
53
  get task() {
@@ -56,7 +56,8 @@ class BuildTaskHandler {
56
56
  }
57
57
 
58
58
  /**
59
- * Returns the message object to add build task specific messages. Severity 'Info', 'Warning', and 'Error' are supported.
59
+ * Returns a list of build and compiler messages created by this build plugin.
60
+ * Supported message severities are 'Info', 'Warning', and 'Error'.
60
61
  * @return {Array}
61
62
  */
62
63
  get messages() {
@@ -64,7 +65,7 @@ class BuildTaskHandler {
64
65
  }
65
66
 
66
67
  /**
67
- * Returns the list of files written by this build task handler of current CDS build execution.
68
+ * Returns the list of files written by this build plugin.
68
69
  * @return {Array}
69
70
  */
70
71
  get files() {
@@ -72,14 +73,14 @@ class BuildTaskHandler {
72
73
  }
73
74
 
74
75
  /**
75
- * Returns the priority of this handler as number, where 0 represents the minimum value and
76
+ * Returns the priority of this plugin as number, where 0 represents the minimum value and
76
77
  * Number.MAX_SAFE_INTEGER the maximum value.
77
- * Positive numbers mean higher and negative numbers lower priority. Build task handlers
78
- * with higher priority value are executed before handlers with lower priority.
78
+ * Positive numbers mean higher and negative numbers lower priority. Build plugins
79
+ * with higher priority value are executed before plugins with lower priority.
79
80
  * <br>
80
- * Note: Currently not supported for custom build task handlers as they are always executed
81
- * before the built-in handlers.
82
- * @return {number} the priority for this handler as integer.
81
+ * Note: Currently not supported for custom build plugins as they are always executed
82
+ * before the built-in plugins.
83
+ * @return {number} the priority for this plugin as integer.
83
84
  */
84
85
  get priority() {
85
86
  return 1
@@ -88,29 +89,41 @@ class BuildTaskHandler {
88
89
  * Called by the framework immediately after this instance has been created.
89
90
  * The instance has already been fully initialized.
90
91
  */
91
- init() { }
92
+ init() {
93
+ if (cds.env.build.target === '.') {
94
+ this.task.dest = path.join(this.task.dest, 'gen')
95
+ }
96
+ }
92
97
 
93
98
  /**
94
- * Called by the framework to create the artifacts of this build task handler.
99
+ * @abstract
100
+ * Called by the framework to create the artifacts of this build plugin.
95
101
  */
96
102
  async build() {
97
- throw new TypeError(OVERRIDE_METHOD_MSG)
98
103
  }
99
104
 
100
105
  /**
101
- * Called by the framework immediately before 'build' to delete any output created by this build task handler.
106
+ * Called by the framework immediately before 'build' to delete any output created by this build plugin.
102
107
  * <p>
103
108
  * Note: The <code>BuildTaskEngine</code> is cleaning the common generation target folder if the build is
104
109
  * executed in staging mode, e.g. build.target: "gen".
105
110
  */
106
111
  async clean() {
107
- throw new TypeError(OVERRIDE_METHOD_MSG)
112
+ function isSubDirectory(parent, child) {
113
+ return !path.relative(parent, child).startsWith('..')
114
+ }
115
+ if (cds.env.build.target === '.'
116
+ && this.task.src !== this.task.dest
117
+ && !isSubDirectory(this.task.dest, this.task.src)
118
+ && await pathExists(this.task.dest)) {
119
+ return fs.rm(this.task.dest, { force: true, recursive: true })
120
+ }
108
121
  }
109
122
 
110
123
  /**
111
124
  * Asynchronously write the given content to a given file path.
112
125
  * If the file exists the content is replaced. If the file does not exist, a new file will be created.
113
- * The file name is stored in the list of files written by this build task handler.
126
+ * The file name is stored in the list of files written by this build plugin.
114
127
  * @param {string} dest - absolute or relative file path. Relative paths will be resolved to this task's destination path.
115
128
  * @param {any} data - If data is of type object the JSON-stringified version is written.
116
129
  */
@@ -135,7 +148,7 @@ class BuildTaskHandler {
135
148
  * Copy a file or directory if the build task option 'outputMode' does not have the value 'resultOnly'.
136
149
  * The directory can have contents.
137
150
  * <p>
138
- * Note: The file name is stored in the list of files written by this build task handler.
151
+ * Note: The file name is stored in the list of files written by this build plugin.
139
152
  * </p>
140
153
  * @param {string} src The absolute or relative source path of the file or directory to copy.
141
154
  * Relative paths will be resolved to this task's source path.
@@ -231,4 +244,4 @@ class BuildTaskHandler {
231
244
  return value
232
245
  }
233
246
  }
234
- module.exports = BuildTaskHandler
247
+ module.exports = BuildPlugin
@@ -5,7 +5,7 @@ const { sortMessagesSeverityAware, deduplicateMessages, CompilationError } = cds
5
5
  const { relativePaths, BuildError, resolveRequiredSapModels } = require('./util')
6
6
  const { SEVERITIES, LOG_LEVELS } = require('./constants')
7
7
  const BuildTaskFactory = require('./buildTaskFactory')
8
- const BuildTaskHandlerInternal = require('./provider/buildTaskHandlerInternal')
8
+ const InternalBuildPlugin = require('./provider/internalBuildPlugin')
9
9
 
10
10
  const COMPILATION_ERROR = 'CompilationError'
11
11
  const COMPILE_MESSAGE = 'CompileMessage'
@@ -40,66 +40,66 @@ class BuildTaskEngine {
40
40
  throw new BuildError(`Required CDS models [${unresolved.join(', ')}] cannot be resolved. Make sure up-to-date versions of the missing modules are installed.`)
41
41
  }
42
42
 
43
- // create build task handlers
44
- const handlers = []
43
+ // create build plugins
44
+ const plugins = []
45
45
  tasks.forEach((task) => {
46
46
  if (task) {
47
- const handler = this._createHandler(task)
48
- handlers.push(handler)
47
+ const plugin = this._createPlugin(task)
48
+ plugins.push(plugin)
49
49
  }
50
50
  })
51
51
 
52
52
  try {
53
- await this._executePrepare(handlers)
54
- await this._executeCleanBuildTasks(handlers)
53
+ await this._executePrepare(plugins)
54
+ await this._executeCleanBuildTasks(plugins)
55
55
 
56
56
  // throwing Exception in case of compilation errors
57
- const buildResult = await this._executeBuildTasks(handlers)
57
+ const buildResult = await this._executeBuildTasks(plugins)
58
58
 
59
- await this._writeGenerationLog(handlers)
60
- this._logBuildOutput(handlers)
61
- this._logMessages(BuildTaskEngine._getHandlerMessages(handlers))
59
+ await this._writeGenerationLog(plugins)
60
+ this._logOutput(plugins)
61
+ this._logMessages(BuildTaskEngine._getMessages(plugins))
62
62
  this._logTimer(startTime, Date.now())
63
63
 
64
64
  return buildResult
65
65
  } catch (error) {
66
- this._logBuildOutput(handlers)
66
+ this._logOutput(plugins)
67
67
  throw error
68
68
  }
69
69
  }
70
70
 
71
71
  /**
72
- * BuildTaskHandler#prepare has been deprecated and was never part of the public API.
73
- * Currently only used by internal FioriBuildTaskHandler.
72
+ * BuildPlugin#prepare has been deprecated and was never part of the public API.
73
+ * Currently only used by internal FioriBuildPlugin.
74
74
  * @deprecated
75
- * @param {*} handlers
75
+ * @param {*} plugins
76
76
  * @returns
77
77
  */
78
- async _executePrepare(handlers) {
79
- const handlerGroups = new Map()
78
+ async _executePrepare(plugins) {
79
+ const pluginGroups = new Map()
80
80
 
81
- // group handlers by type
82
- handlers.forEach(handler => {
83
- handlerGroups.has(handler.task.for) ? handlerGroups.get(handler.task.for).push(handler) : handlerGroups.set(handler.task.for, [handler])
81
+ // group plugins by type
82
+ plugins.forEach(plugin => {
83
+ pluginGroups.has(plugin.task.for) ? pluginGroups.get(plugin.task.for).push(plugin) : pluginGroups.set(plugin.task.for, [plugin])
84
84
  })
85
85
 
86
86
  const promises = []
87
- for (let handlerGroup of handlerGroups.values()) {
88
- promises.push(this._doPrepare(handlerGroup))
87
+ for (let pluginGroup of pluginGroups.values()) {
88
+ promises.push(this._doPrepare(pluginGroup))
89
89
  }
90
90
  return Promise.all(promises)
91
91
  }
92
92
 
93
93
  /**
94
94
  * @deprecated
95
- * @param {*} handlerGroup
95
+ * @param {*} pluginGroup
96
96
  */
97
- async _doPrepare(handlerGroup) {
98
- for (let handler of handlerGroup) {
97
+ async _doPrepare(pluginGroup) {
98
+ for (let plugin of pluginGroup) {
99
99
  // prepare has been deprecated
100
- if (handler instanceof BuildTaskHandlerInternal) {
101
- this.logger._debug && this.logger.debug(`preparing, handler [${handler.constructor.name}], src [${relativePaths(cds.root, handler.task.src)}]`)
102
- const result = await handler.prepare()
100
+ if (plugin instanceof InternalBuildPlugin) {
101
+ this.logger._debug && this.logger.debug(`preparing, plugin [${plugin.constructor.name}], src [${relativePaths(cds.root, plugin.task.src)}]`)
102
+ const result = await plugin.prepare()
103
103
  if (result === false) {
104
104
  break
105
105
  }
@@ -107,7 +107,7 @@ class BuildTaskEngine {
107
107
  }
108
108
  }
109
109
 
110
- async _executeCleanBuildTasks(handlers) {
110
+ async _executeCleanBuildTasks(plugins) {
111
111
  if (this.options.clean) {
112
112
  // clean entire build staging folder once
113
113
  if (cds.env.build.target !== '.') {
@@ -116,30 +116,30 @@ class BuildTaskEngine {
116
116
  await fs.promises.rm(target, { force: true, recursive: true })
117
117
  }
118
118
 
119
- const results = await Promise.allSettled(handlers.map((handler) => {
120
- this.logger._debug && this.logger.debug(`cleaning, handler [${handler.constructor.name}], src [${relativePaths(cds.root, handler.task.src)}]`)
121
- return handler.clean()
119
+ const results = await Promise.allSettled(plugins.map((plugin) => {
120
+ this.logger._debug && this.logger.debug(`cleaning, plugin [${plugin.constructor.name}], src [${relativePaths(cds.root, plugin.task.src)}]`)
121
+ return plugin.clean()
122
122
  }))
123
123
  // check for errors and throw exception
124
124
  this._resolveHandlerResponse(results)
125
125
  }
126
126
  }
127
127
 
128
- async _executeBuildTasks(handlers) {
129
- // sort handlers based on priority in
130
- handlers = handlers.sort((a, b) => {
128
+ async _executeBuildTasks(plugins) {
129
+ // sort plugins based on priority in
130
+ plugins = plugins.sort((a, b) => {
131
131
  return a.priority === b.priority ? 0 : a.priority > b.priority ? -1 : 1
132
132
  })
133
- // group handlers with same priority in order to execute in parallel
134
- const buildPipeline = handlers.reduce((acc, handler) => {
133
+ // group plugins with same priority in order to execute in parallel
134
+ const buildPipeline = plugins.reduce((acc, plugin) => {
135
135
  if (acc.length === 0) {
136
- acc.push([handler])
136
+ acc.push([plugin])
137
137
  } else {
138
138
  const currGroup = acc[acc.length - 1]
139
- if (currGroup[0].priority === handler.priority) {
140
- currGroup.push(handler)
139
+ if (currGroup[0].priority === plugin.priority) {
140
+ currGroup.push(plugin)
141
141
  } else {
142
- acc.push([handler])
142
+ acc.push([plugin])
143
143
  }
144
144
  }
145
145
  return acc
@@ -148,20 +148,20 @@ class BuildTaskEngine {
148
148
  const results = await this._executePipeline(buildPipeline)
149
149
 
150
150
  // check for errors and throw exception - return results otherwise including any compiler and build status messages
151
- return this._resolveHandlerResponse(results, BuildTaskEngine._getHandlerMessages(handlers))
151
+ return this._resolveHandlerResponse(results, BuildTaskEngine._getMessages(plugins))
152
152
  }
153
153
 
154
154
  async _executePipeline(pipeline) {
155
155
  let allResults = []
156
156
  for (const group of pipeline) {
157
- const results = await Promise.allSettled(group.map((handler) => {
158
- this.logger._debug && this.logger.debug(`building, handler [${handler.constructor.name}], src [${relativePaths(cds.root, handler.task.src)}]`)
159
- return handler.build()
160
- .then(handlerResult => {
157
+ const results = await Promise.allSettled(group.map((plugin) => {
158
+ this.logger._debug && this.logger.debug(`building, plugin [${plugin.constructor.name}], src [${relativePaths(cds.root, plugin.task.src)}]`)
159
+ return plugin.build()
160
+ .then(pluginResult => {
161
161
  return Promise.resolve({
162
- task: handler.task,
163
- result: handlerResult,
164
- messages: this._sortMessagesUnique(handler.messages)
162
+ task: plugin.task,
163
+ result: pluginResult,
164
+ messages: this._sortMessagesUnique(plugin.messages)
165
165
  })
166
166
  })
167
167
  }))
@@ -170,7 +170,7 @@ class BuildTaskEngine {
170
170
  return allResults
171
171
  }
172
172
 
173
- _resolveHandlerResponse(results, handlerMessages = []) {
173
+ _resolveHandlerResponse(results, pluginMessages = []) {
174
174
  const errors = []
175
175
  const resolvedResults = results.reduce((acc, r) => {
176
176
  if (r.status === 'fulfilled') {
@@ -192,9 +192,9 @@ class BuildTaskEngine {
192
192
 
193
193
  // propagate existing CompilationErrors
194
194
  // merge all existing compilation messages into a single CompilationError
195
- // compiler warning and info messages are returned as handler messages
195
+ // compiler warning and info messages are returned as plugin messages
196
196
  const compileErrors = errors.filter(e => e.constructor.name === COMPILATION_ERROR)
197
- const compileMessages = handlerMessages.filter(message => message.constructor.name === COMPILE_MESSAGE)
197
+ const compileMessages = pluginMessages.filter(message => message.constructor.name === COMPILE_MESSAGE)
198
198
  if (compileErrors.length) {
199
199
  throw new CompilationError(this._sortMessagesUnique(BuildTaskEngine._getErrorMessages(compileErrors), compileMessages))
200
200
  }
@@ -202,31 +202,32 @@ class BuildTaskEngine {
202
202
  return resolvedResults
203
203
  }
204
204
 
205
- _createHandler(task) {
206
- const handler = this.taskFactory.createHandler(task)
207
- handler.init()
205
+ _createPlugin(task) {
206
+ const plugin = this.taskFactory.createPlugin(task)
207
+ plugin.init()
208
208
 
209
- if (!(handler instanceof BuildTaskHandlerInternal) && handler.priority !== 1) {
210
- // Custom build handlers are executed before internal handlers to ensure
209
+ if (!(plugin instanceof InternalBuildPlugin) && plugin.priority !== 1) {
210
+ // Custom build plugins are executed before internal plugins to ensure
211
211
  // that generated content cannot be overwritten by mistake
212
- throw new Error(`Illegal priority for ${handler.constructor.name} encountered for custom handler - in this version only priority value '1' is allowed`)
212
+ throw new Error(`Illegal priority for ${plugin.constructor.name} encountered for custom plugin - in this version only priority value '1' is allowed`)
213
213
  }
214
- this._logTaskHandler(handler)
215
- return handler
214
+ this._logTaskHandler(plugin)
215
+ return plugin
216
216
  }
217
217
 
218
- _logBuildOutput(handlers) {
218
+ _logOutput(plugins) {
219
219
  // log all generated files
220
- const files = BuildTaskEngine._getBuildOutput(handlers)
220
+ const files = BuildTaskEngine._getOutput(plugins)
221
221
  if (files.length > 0) {
222
- this.logger.log(`done > wrote output to:\n ${files.join("\n ")}\n`)
222
+ const term = require('../util/term')
223
+ this.logger.log(`done > wrote output to:\n ${term.secondary(files.join("\n "))}\n`)
223
224
  }
224
225
  }
225
226
 
226
- async _writeGenerationLog(handlers) {
227
+ async _writeGenerationLog(plugins) {
227
228
  const outputFile = cds.env.build.outputfile || process.env.GENERATION_LOG
228
229
  if (outputFile) {
229
- const files = BuildTaskEngine._getBuildOutput(handlers)
230
+ const files = BuildTaskEngine._getOutput(plugins)
230
231
  this.logger.log(`writing generation log to [${outputFile}]\n`)
231
232
  try {
232
233
  await fs.promises.mkdir(path.dirname(outputFile), { recursive: true })
@@ -238,8 +239,8 @@ class BuildTaskEngine {
238
239
  }
239
240
  }
240
241
 
241
- static _getBuildOutput(handlers) {
242
- const files = handlers.reduce((acc, handler) => acc.concat(handler.files), []).sort()
242
+ static _getOutput(plugins) {
243
+ const files = plugins.reduce((acc, plugin) => acc.concat(plugin.files), []).sort()
243
244
  return files.map(file => {
244
245
  if (path.isAbsolute(cds.env.build.target)) {
245
246
  return file
@@ -252,9 +253,9 @@ class BuildTaskEngine {
252
253
  this.logger.log(`build completed in ${end - start} ms\n`)
253
254
  }
254
255
 
255
- _logTaskHandler(handler) {
256
- this.logger._debug && this.logger.debug(`handler ${handler.constructor.name}`)
257
- this.logger._debug && this.logger.debug(`details src [${relativePaths(cds.root, handler.task.src)}], dest [${relativePaths(cds.root, handler.task.dest)}], use [${handler.task.use}], options [${JSON.stringify(handler.task.options)}]`) //NOSONAR
256
+ _logTaskHandler(plugin) {
257
+ this.logger._debug && this.logger.debug(`plugin ${plugin.constructor.name}`)
258
+ this.logger._debug && this.logger.debug(`details src [${relativePaths(cds.root, plugin.task.src)}], dest [${relativePaths(cds.root, plugin.task.dest)}], use [${plugin.task.use}], options [${JSON.stringify(plugin.task.options)}]`) //NOSONAR
258
259
  }
259
260
 
260
261
  _logMessages(messages) {
@@ -303,11 +304,11 @@ class BuildTaskEngine {
303
304
  }
304
305
 
305
306
  /**
306
- * Returns compiler messages and validation messages issued by handlers.
307
- * @param {Array<BuildTaskHandler>} handlers
307
+ * Returns compiler messages and validation messages issued by plugins.
308
+ * @param {Array<BuildPlugin>} plugins
308
309
  */
309
- static _getHandlerMessages(handlers) {
310
- return handlers.reduce((acc, handler) => acc.concat(handler.messages), [])
310
+ static _getMessages(plugins) {
311
+ return plugins.reduce((acc, plugin) => acc.concat(plugin.messages), [])
311
312
  }
312
313
 
313
314
  /**
@@ -4,6 +4,7 @@ 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")
7
+ const term = require('../util/term')
7
8
 
8
9
  class BuildTaskFactory {
9
10
  constructor(options) {
@@ -27,12 +28,11 @@ class BuildTaskFactory {
27
28
  const tasks = await this._createTasks()
28
29
 
29
30
  // 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\": ["
31
+ let tasksOutput = "{\n build: {\n target: " + term.info("'" + cds.env.build.target + "'") + ",\n tasks: [\n"
32
32
  for (let i = 0; i < tasks.length; i++) {
33
- tasksOutput += "\n " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? "," : "")
33
+ tasksOutput += " " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? ",\n" : "\n")
34
34
  }
35
- tasksOutput += "\n ]\n }\n }\n"
35
+ tasksOutput += " ]\n }\n}\n"
36
36
  this.logger.log(tasksOutput)
37
37
 
38
38
  // for testing purposes
@@ -47,8 +47,8 @@ class BuildTaskFactory {
47
47
  return tasks
48
48
  }
49
49
 
50
- createHandler(task) {
51
- return this.providerFactory.createHandler(task)
50
+ createPlugin(task) {
51
+ return this.providerFactory.createPlugin(task)
52
52
  }
53
53
 
54
54
  async _createTasks() {
@@ -65,7 +65,7 @@ class BuildTaskFactory {
65
65
  // 1. apply default values including task.for and task.use and ensure that for all tasks a provider exists - throwing error otherwise
66
66
  await this.providerFactory.applyTaskDefaults(tasks)
67
67
  // ensure that dependencies get wired up before filtering
68
- await this.providerFactory.lookupTasks(tasks)
68
+ await this.providerFactory.lookupTasks(tasks, true)
69
69
  }
70
70
 
71
71
  // 3. filters the list of build tasks and adapts according to given CLI options
@@ -83,7 +83,7 @@ class BuildTaskFactory {
83
83
 
84
84
  // 2. add dependencies
85
85
  existingTasks = [...tasks]
86
- await this.providerFactory.lookupTasks(tasks)
86
+ await this.providerFactory.lookupTasks(tasks, true)
87
87
  if (tasks.length > existingTasks.length) {
88
88
  const newTasks = tasks.filter(task => !existingTasks.includes(task))
89
89
  // a dependant task was added
@@ -93,9 +93,6 @@ class BuildTaskFactory {
93
93
  // obligatory task defaults shared by all tasks
94
94
  BuildTaskFactory._applyCommonTaskDefaults(tasks)
95
95
 
96
- // ensure correct values for optional build task properties, error for missing mandatory properties
97
- BuildTaskFactory._validateBuildTasks(tasks)
98
-
99
96
  this._setDefaultBuildTargetFolder(tasks)
100
97
  return tasks
101
98
  }
@@ -115,14 +112,6 @@ class BuildTaskFactory {
115
112
  })
116
113
  }
117
114
 
118
- static _validateBuildTasks(tasks) {
119
- tasks.forEach(task => {
120
- if (!task.src) {
121
- throw new Error(`Invalid build task definition - value of property 'src' is missing in [${task.for || task.use}].`)
122
- }
123
- })
124
- }
125
-
126
115
  _setDefaultBuildTargetFolder(tasks) {
127
116
  const task = tasks.find(task => task.for === BUILD_TASK_JAVA_CF || task.for === BUILD_TASK_JAVA)
128
117
  const srv = task ? task.src : BuildTaskFactory._getModuleFolder(flatten([cds.env.folders.srv])) || "srv"
@@ -161,19 +150,13 @@ class BuildTaskFactory {
161
150
  })
162
151
  if (resultTasks.length === 0) {
163
152
  if (options.for || options.use) {
164
- const task = {}
165
- if ((options.for)) {
166
- task.for = options.for
167
- }
168
- if ((options.use)) {
169
- task.use = options.use
170
- }
153
+ const task = this.providerFactory.getTask(options.for ? { for: options.for } : { use: options.use })
171
154
  if (options.src) {
172
155
  task.src = options.src
173
156
  }
174
157
  resultTasks.push(task)
175
158
  }
176
- } else if (resultTasks.length < tasks.length) {
159
+ } else if (resultTasks.length <= tasks.length) {
177
160
  // return the same array as long as it contains a subset of the given tasks
178
161
  tasks.length = 0
179
162
  resultTasks.forEach(task => tasks.push(task))
@@ -213,12 +196,36 @@ class BuildTaskFactory {
213
196
  static _stringifyTask(task) {
214
197
  // ensures identical order of properties
215
198
  const order = ["for", "use", "src", "dest", "options"]
216
- const keys = Object.keys(task).sort((a, b) => order.indexOf(a) - order.indexOf(b))
199
+ const keys = Object.keys(task).filter(key => order.includes(key)).sort((a, b) => order.indexOf(a) - order.indexOf(b))
217
200
 
218
- return keys.reduce((acc, key, idx) => {
219
- // render either "for" OR "use" value
220
- return acc + (!key.match("^_") ? (key !== "use" || keys[idx - 1] !== "for" ? (acc !== "{" ? ", " : "") + JSON.stringify(key) + ":" + JSON.stringify(task[key]) : "") : "")
221
- }, "{") + "}"
201
+ return keys.reduce((acc, key, i) => {
202
+ const prefix = acc !== '{' ? ', ' : (i === 0 ? ' ' : '')
203
+ if (!key.startsWith('_')) {
204
+ // render either "for" OR "use" value
205
+ if (key in { src: 1, for: 1 } || (!task.for && key === 'use')) {
206
+ return `${acc}${prefix}${key}: ${term.info(`'${task[key]}'`)}`
207
+ } else if (key === 'options') {
208
+ const options = Object.entries(task.options)
209
+ .map(([key, value]) => {
210
+ if (Array.isArray(value)) {
211
+ return `${key}: [${value.map(v => term.info(`'${v}'`)).join(', ')}]`
212
+ } else if (typeof value === 'object') {
213
+ const nested = Object.entries(value)
214
+ .map(([key, value]) => `${key}: ${term.info(`'${value}'`)}`)
215
+ .join(', ')
216
+ return `${key}: { ${nested} }`
217
+ } else {
218
+ return `${key}: ${term.info(`'${value}'`)}`
219
+ }
220
+ })
221
+ .join(', ')
222
+ return `${acc}${prefix}${key}: { ${options} }`
223
+ } else if (key !== 'use') {
224
+ return `${acc}${prefix}${key}: ${term.info(`'${task[key]}'`)}`
225
+ }
226
+ }
227
+ return acc
228
+ }, '{') + '}'
222
229
  }
223
230
 
224
231
  static _scanTaskOptionParams(optsParams) {
@@ -1,22 +1,27 @@
1
1
  /* eslint-disable no-unused-vars */
2
+ /**
3
+ * @abstract
4
+ */
2
5
  module.exports = class BuildTaskProvider {
3
- constructor() {
4
- //injected by framework
5
- this._plugin = null
6
- }
7
- canHandleTask(task) {
8
- // return this._plugin.provides.includes(task.for || task.use && this._getTaskId(task.use))
9
- }
10
- loadHandler(task) {
11
- // return module.require(`${this._plugin.path}/${task.for || this._getTaskId(task.use)}`)
12
- }
13
- async lookupTasks(tasks) { }
14
- async applyTaskDefaults(task) {
15
- // task.for = task.for || this._getTaskId(task.use)
16
- }
17
- _getTaskId(use) {
18
- if (this._plugin && this._plugin.id) {
19
- return use.substring(this._plugin.id.length + 1)
20
- }
21
- }
6
+ /**
7
+ * @param {object} task
8
+ */
9
+ providesTask(key) { }
10
+ /**
11
+ * @returns {object} task
12
+ */
13
+ getTask(key) { return key }
14
+ /**
15
+ * @param {object} task
16
+ */
17
+ getPluginClass(task) { }
18
+ /**
19
+ * @param {Array} tasks
20
+ * @param {boolean} dependencies
21
+ */
22
+ async lookupTasks(tasks, dependencies) { }
23
+ /**
24
+ * @param {object} task
25
+ */
26
+ async applyTaskDefaults(task) { }
22
27
  }