@sap/cds 6.3.1 → 6.4.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 (114) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/apis/cds.d.ts +1 -1
  3. package/apis/core.d.ts +118 -90
  4. package/apis/cqn.d.ts +11 -2
  5. package/apis/internal/inference.d.ts +7 -2
  6. package/apis/ql.d.ts +45 -11
  7. package/apis/serve.d.ts +8 -1
  8. package/apis/services.d.ts +303 -305
  9. package/bin/build/buildTaskEngine.js +28 -36
  10. package/bin/build/buildTaskFactory.js +32 -81
  11. package/bin/build/buildTaskHandler.js +3 -2
  12. package/bin/build/buildTaskProvider.js +2 -2
  13. package/bin/build/buildTaskProviderFactory.js +5 -14
  14. package/bin/build/constants.js +0 -1
  15. package/bin/build/provider/buildTaskHandlerEdmx.js +7 -6
  16. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +6 -5
  17. package/bin/build/provider/buildTaskHandlerInternal.js +9 -30
  18. package/bin/build/provider/buildTaskProviderInternal.js +70 -58
  19. package/bin/build/provider/fiori/index.js +6 -5
  20. package/bin/build/provider/hana/2migration.js +20 -3
  21. package/bin/build/provider/hana/2tabledata.js +1 -0
  22. package/bin/build/provider/hana/index.js +40 -17
  23. package/bin/build/provider/java/index.js +10 -10
  24. package/bin/build/provider/mtx/index.js +25 -16
  25. package/bin/build/provider/mtx/resourcesTarBuilder.js +22 -27
  26. package/bin/build/provider/mtx-extension/index.js +3 -2
  27. package/bin/build/provider/mtx-sidecar/index.js +16 -15
  28. package/bin/build/provider/nodejs/index.js +14 -56
  29. package/bin/build/util.js +56 -16
  30. package/bin/deploy/to-hana/cfUtil.js +4 -1
  31. package/bin/deploy/to-hana/gitUtil.js +1 -1
  32. package/bin/deploy/to-hana/hana.js +45 -38
  33. package/bin/deploy/to-hana/hdiDeployUtil.js +8 -9
  34. package/bin/deploy/to-hana/mtaUtil.js +13 -14
  35. package/bin/mtx/in-cds.js +3 -1
  36. package/bin/serve.js +1 -1
  37. package/bin/version.js +2 -1
  38. package/lib/compile/cds-compile.js +1 -0
  39. package/lib/compile/cdsc.js +1 -0
  40. package/lib/compile/etc/_localized.js +2 -2
  41. package/lib/compile/for/lean_drafts.js +83 -0
  42. package/lib/compile/for/nodejs.js +1 -0
  43. package/lib/compile/minify.js +2 -1
  44. package/lib/compile/parse.js +2 -1
  45. package/lib/compile/to/gql.js +1 -1
  46. package/lib/compile/to/sql.js +11 -1
  47. package/lib/core/entities.js +1 -1
  48. package/lib/core/index.js +8 -9
  49. package/lib/core/infer.js +1 -0
  50. package/lib/dbs/cds-deploy.js +97 -41
  51. package/lib/env/cds-env.js +9 -10
  52. package/lib/env/cds-requires.js +8 -2
  53. package/lib/env/defaults.js +0 -4
  54. package/lib/env/schemas/cds-rc.json +38 -0
  55. package/lib/ql/SELECT.js +10 -4
  56. package/lib/srv/bindings.js +1 -1
  57. package/lib/srv/factory.js +1 -1
  58. package/lib/srv/protocols/index.js +3 -1
  59. package/lib/srv/srv-methods.js +1 -1
  60. package/lib/utils/cds-utils.js +11 -0
  61. package/lib/utils/inflect.js +13 -12
  62. package/lib/utils/tar.js +53 -10
  63. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +2 -2
  64. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
  65. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
  66. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -1
  67. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -15
  68. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -1
  69. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -1
  70. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/UriSyntaxError.js +1 -1
  71. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +6 -1
  72. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/BufferedWriter.js +1 -1
  73. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/ConditionalRequestValidator.js +0 -12
  74. package/libx/_runtime/cds-services/adapter/odata-v4/utils/oDataConfiguration.js +1 -7
  75. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +4 -0
  76. package/libx/_runtime/cds-services/services/Service.js +23 -1
  77. package/libx/_runtime/cds-services/util/assert.js +0 -41
  78. package/libx/_runtime/common/composition/data.js +5 -1
  79. package/libx/_runtime/common/generic/auth/utils.js +3 -3
  80. package/libx/_runtime/common/generic/input.js +4 -24
  81. package/libx/_runtime/common/generic/paging.js +3 -3
  82. package/libx/_runtime/common/utils/csn.js +21 -15
  83. package/libx/_runtime/common/utils/draft.js +2 -1
  84. package/libx/_runtime/common/utils/resolveView.js +25 -4
  85. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -1
  86. package/libx/_runtime/common/utils/rowUUIDGenerator.js +21 -0
  87. package/libx/_runtime/common/utils/templateProcessor.js +12 -15
  88. package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +23 -0
  89. package/libx/_runtime/db/expand/expandCQNToJoin.js +29 -12
  90. package/libx/_runtime/db/generic/input.js +7 -13
  91. package/libx/_runtime/db/sql-builder/UpsertBuilder.js +47 -0
  92. package/libx/_runtime/db/sql-builder/index.js +2 -0
  93. package/libx/_runtime/db/sql-builder/sqlFactory.js +9 -0
  94. package/libx/_runtime/db/utils/columns.js +4 -2
  95. package/libx/_runtime/fiori/generic/read.js +1 -12
  96. package/libx/_runtime/fiori/lean-draft.js +657 -0
  97. package/libx/_runtime/fiori/utils/handler.js +1 -1
  98. package/libx/_runtime/hana/pool.js +16 -1
  99. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -1
  100. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -1
  101. package/libx/_runtime/messaging/enterprise-messaging.js +2 -3
  102. package/libx/_runtime/messaging/outbox/utils.js +109 -70
  103. package/libx/_runtime/messaging/service.js +16 -7
  104. package/libx/_runtime/remote/Service.js +15 -2
  105. package/libx/_runtime/remote/utils/client.js +41 -11
  106. package/libx/_runtime/sqlite/Service.js +3 -0
  107. package/libx/_runtime/sqlite/convertDraftAdminPathExpression.js +56 -0
  108. package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +59 -0
  109. package/libx/_runtime/sqlite/customBuilder/index.js +5 -0
  110. package/libx/_runtime/sqlite/execute.js +1 -1
  111. package/libx/_runtime/types/api.js +2 -2
  112. package/libx/rest/RestAdapter.js +15 -13
  113. package/package.json +1 -1
  114. package/server.js +1 -0
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
- const _cds = require('./cds'), { log } = _cds.exec
3
+ const cds = require('./cds'), { log } = cds.exec
4
4
  const { sortMessagesSeverityAware, deduplicateMessages, CompilationError } = require('@sap/cds-compiler')
5
5
  const { relativePaths, BuildError, BuildMessage, resolveRequiredSapModels, hasJavaNature } = require('./util')
6
6
  const { OUTPUT_MODE_DEFAULT, SEVERITIES, LOG_LEVELS, LOG_MODULE_NAMES, CDS_MODEL_EXCLUDE_LIST } = require('./constants')
@@ -11,16 +11,8 @@ const COMPILATION_ERROR = 'CompilationError'
11
11
  const COMPILE_MESSAGE = 'CompileMessage'
12
12
 
13
13
  class BuildTaskEngine {
14
- constructor(logger, cds) {
15
- this._cds = cds ? cds : _cds
16
- this._logger = logger || this._cds.log(LOG_MODULE_NAMES)
17
- }
18
-
19
- get cds() {
20
- return this._cds
21
- }
22
- get env() {
23
- return this._cds.env
14
+ constructor(logger) {
15
+ this._logger = logger || cds.log(LOG_MODULE_NAMES)
24
16
  }
25
17
  get logger() {
26
18
  return this._logger
@@ -43,16 +35,16 @@ class BuildTaskEngine {
43
35
  }
44
36
 
45
37
  this.logger.log(`building project [${buildOptions.root}], clean [${clean}]`)
46
- this.logger.log(`cds [${_cds.version}], compiler [${_cds.compiler.version()}], home [${_cds.home}]\n`)
38
+ this.logger.log(`cds [${cds.version}], compiler [${cds.compiler.version()}], home [${cds.home}]\n`)
47
39
 
48
40
  if (!buildOptions.target) {
49
- buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
41
+ buildOptions.target = path.resolve(buildOptions.root, cds.env.build.target)
50
42
  }
51
43
 
52
44
  // Java projects don't have node modules installed on project root level
53
45
  if (!hasJavaNature([buildOptions.root])) {
54
46
  // validate required @sap namespace models - log only
55
- const { unresolved, missing } = this._resolveRequiredSapServices(tasks)
47
+ const { unresolved, missing } = BuildTaskEngine._resolveRequiredSapServices(tasks)
56
48
  if (unresolved.length > 0) {
57
49
  messages.push(new BuildMessage(`Required CDS service models [${unresolved.join(', ')}] cannot be resolved. Make sure to install the missing npm modules.`))
58
50
  }
@@ -155,7 +147,7 @@ class BuildTaskEngine {
155
147
  return handler.clean()
156
148
  }))
157
149
  // check for errors and throw exception
158
- this._resolveHandlerResponse(results, buildOptions)
150
+ BuildTaskEngine._resolveHandlerResponse(results, buildOptions)
159
151
  }
160
152
  }
161
153
 
@@ -182,7 +174,7 @@ class BuildTaskEngine {
182
174
  const results = await this._executePipeline(buildOptions, buildPipeline)
183
175
 
184
176
  // check for errors and throw exception - return results otherwise including any compiler and build status messages
185
- return this._resolveHandlerResponse(results, buildOptions, BuildTaskEngine._getHandlerMessages(handlers))
177
+ return BuildTaskEngine._resolveHandlerResponse(results, buildOptions, BuildTaskEngine._getHandlerMessages(handlers))
186
178
  }
187
179
 
188
180
  async _executePipeline(buildOptions, pipeline) {
@@ -195,7 +187,7 @@ class BuildTaskEngine {
195
187
  return Promise.resolve({
196
188
  task: handler.task,
197
189
  result: handlerResult,
198
- messages: this._sortCompilationErrorsUnique(buildOptions, handler.messages)
190
+ messages: BuildTaskEngine._sortCompilationErrorsUnique(buildOptions, handler.messages)
199
191
  })
200
192
  })
201
193
  }))
@@ -204,7 +196,7 @@ class BuildTaskEngine {
204
196
  return allResults
205
197
  }
206
198
 
207
- _resolveHandlerResponse(results, buildOptions, handlerMessages = []) {
199
+ static _resolveHandlerResponse(results, buildOptions, handlerMessages = []) {
208
200
  const errors = []
209
201
  const resolvedResults = results.reduce((acc, r) => {
210
202
  if (r.status === 'fulfilled') {
@@ -228,7 +220,7 @@ class BuildTaskEngine {
228
220
  // 1. compiler warnings are returned as handler messages
229
221
  const compileMessages = handlerMessages.filter(message => message.constructor.name === COMPILE_MESSAGE)
230
222
  if (compileErrors.length > 0) {
231
- const compileError = new CompilationError(this._sortCompilationErrorsUnique(buildOptions, BuildTaskEngine._getErrorMessages(compileErrors), compileMessages))
223
+ const compileError = new CompilationError(BuildTaskEngine._sortCompilationErrorsUnique(buildOptions, BuildTaskEngine._getErrorMessages(compileErrors), compileMessages))
232
224
  buildErrors.push(compileError)
233
225
  }
234
226
 
@@ -245,7 +237,7 @@ class BuildTaskEngine {
245
237
 
246
238
  _createHandler(task, buildOptions) {
247
239
  try {
248
- const providerFactory = new BuildTaskProviderFactory(this._logger, this._cds, buildOptions)
240
+ const providerFactory = new BuildTaskProviderFactory(this._logger, buildOptions)
249
241
  const handler = providerFactory.createHandler(task)
250
242
  handler.init()
251
243
 
@@ -263,14 +255,9 @@ class BuildTaskEngine {
263
255
  }
264
256
  }
265
257
 
266
- _getBuildOutput(handlers, buildOptions) {
267
- const files = handlers.reduce((acc, handler) => acc.concat(handler.files), []).sort()
268
- return files.map(file => path.relative(buildOptions.root, file))
269
- }
270
-
271
258
  _logBuildOutput(handlers, buildOptions) {
272
259
  // log all generated files
273
- const files = this._getBuildOutput(handlers, buildOptions)
260
+ const files = BuildTaskEngine._getBuildOutput(handlers, buildOptions)
274
261
  if (files.length > 0) {
275
262
  this.logger.log(`done > wrote output to:\n ${files.join("\n ")}\n`)
276
263
  } else {
@@ -279,9 +266,9 @@ class BuildTaskEngine {
279
266
  }
280
267
 
281
268
  async _writeGenerationLog(handlers, buildOptions) {
282
- const outputFile = this.env.build.outputfile || process.env.GENERATION_LOG
269
+ const outputFile = cds.env.build.outputfile || process.env.GENERATION_LOG
283
270
  if (outputFile) {
284
- const files = this._getBuildOutput(handlers, buildOptions)
271
+ const files = BuildTaskEngine._getBuildOutput(handlers, buildOptions)
285
272
  this.logger.log(`writing generation log to [${outputFile}]\n`)
286
273
  try {
287
274
  await fs.promises.mkdir(path.dirname(outputFile), { recursive: true }).then(() => fs.promises.writeFile(outputFile, files.join('\n')))
@@ -292,6 +279,11 @@ class BuildTaskEngine {
292
279
  }
293
280
  }
294
281
 
282
+ static _getBuildOutput(handlers, buildOptions) {
283
+ const files = handlers.reduce((acc, handler) => acc.concat(handler.files), []).sort()
284
+ return files.map(file => path.relative(buildOptions.root, file))
285
+ }
286
+
295
287
  _logTimer(start, end) {
296
288
  this.logger.log(`build completed in ${end - start} ms\n`)
297
289
  }
@@ -305,14 +297,14 @@ class BuildTaskEngine {
305
297
  if (messages.length > 0) {
306
298
  const options = {
307
299
  log: this.logger.log,
308
- "log-level": this._getLogLevel(buildOptions) // ensures that for tests the correct cds.env is used
300
+ "log-level": BuildTaskEngine._getLogLevel(buildOptions) // ensures that for tests the correct cds.env is used
309
301
  }
310
302
  deduplicateMessages(messages)
311
303
  log(messages, options)
312
304
  }
313
305
  }
314
306
 
315
- _resolveRequiredSapServices(tasks) {
307
+ static _resolveRequiredSapServices(tasks) {
316
308
  const taskModelPaths = tasks.reduce((acc, task) => {
317
309
  const model = task.options?.model
318
310
  if (model) {
@@ -325,8 +317,8 @@ class BuildTaskEngine {
325
317
  return acc
326
318
  }, new Set())
327
319
 
328
- const srvModelPaths = [...Object.keys(this.env.requires || {}).reduce((acc, srvName) => {
329
- const model = this.env.requires[srvName]?.model;
320
+ const srvModelPaths = [...Object.keys(cds.env.requires || {}).reduce((acc, srvName) => {
321
+ const model = cds.env.requires[srvName]?.model;
330
322
  if (model) {
331
323
  if (Array.isArray(model)) {
332
324
  model.forEach(m => acc.add(m))
@@ -337,7 +329,7 @@ class BuildTaskEngine {
337
329
  return acc
338
330
  }, new Set())]
339
331
 
340
- const unresolved = resolveRequiredSapModels(this.cds, [...taskModelPaths])
332
+ const unresolved = resolveRequiredSapModels([...taskModelPaths])
341
333
  // are the required service models contained in the task's options.model
342
334
  const missing = srvModelPaths.filter(m => m.startsWith('@sap/') && !CDS_MODEL_EXCLUDE_LIST.includes(m) && !taskModelPaths.has(m) && !unresolved.find(u => u === m))
343
335
 
@@ -376,7 +368,7 @@ class BuildTaskEngine {
376
368
  * @param {object} buildOptions
377
369
  * @param {...Error} messages
378
370
  */
379
- _sortCompilationErrorsUnique(buildOptions, ...messages) {
371
+ static _sortCompilationErrorsUnique(buildOptions, ...messages) {
380
372
  const logLevelIdx = LOG_LEVELS.indexOf(this._getLogLevel(buildOptions))
381
373
  // flatten
382
374
  messages = messages.reduce((acc, m) => acc.concat(m), [])
@@ -392,8 +384,8 @@ class BuildTaskEngine {
392
384
  * Return user defined log level or default value 'warn'
393
385
  * @param {string} buildOptions
394
386
  */
395
- _getLogLevel(buildOptions) {
396
- return buildOptions["log-level"] || this.env["log-level"]
387
+ static _getLogLevel(buildOptions) {
388
+ return buildOptions["log-level"] || cds.env["log-level"]
397
389
  }
398
390
  }
399
391
  module.exports = BuildTaskEngine
@@ -1,38 +1,31 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
- const _cds = require('./cds'), { log } = _cds.exec
3
+ const cds = require('./cds'), { log } = cds.exec
4
4
  const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
5
- const { hasJavaNature, getProperty, redactCredentials } = require('./util')
5
+ const { hasJavaNature, getProperty, redactCredentials, flatten, getDefaultModelOptions } = require('./util')
6
6
  const { FILE_EXT_CDS, BUILD_TASK_JAVA_CF, LOG_MODULE_NAMES, BUILD_TASK_JAVA } = require("./constants")
7
7
 
8
8
  class BuildTaskFactory {
9
- constructor(logger, cds) {
10
- this._cds = cds ? cds : _cds
11
- this._logger = logger || this._cds.log(LOG_MODULE_NAMES)
12
- }
13
- get cds() {
14
- return this._cds
15
- }
16
- get env() {
17
- return this._cds.env
9
+ constructor(logger) {
10
+ this._logger = logger || cds.log(LOG_MODULE_NAMES)
18
11
  }
19
12
  get logger() {
20
13
  return this._logger
21
14
  }
22
15
 
23
16
  // the following order for determining build tasks is used
24
- // 1. create from commandline input, e.g. cds build/all --for hana --src db --model srv --dest db
17
+ // 1. create from command line input, e.g. cds build/all --for hana --src db --model srv --dest db
25
18
  // 2. read using cds.env.build.tasks
26
19
  // 3. create from cds.env.folders config data
27
20
  async getTasks(buildOptions = { root: process.env._TEST_CWD || process.cwd() }) {
28
21
  try {
29
- const providerFactory = new BuildTaskProviderFactory(this._logger, this._cds, buildOptions)
22
+ const providerFactory = new BuildTaskProviderFactory(this._logger, buildOptions)
30
23
  const tasks = await this._createTasks(providerFactory)
31
- buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
24
+ buildOptions.target = path.resolve(buildOptions.root, cds.env.build.target)
32
25
 
33
26
  // log build tasks
34
27
  this.logger.log(`the following build tasks will be executed`)
35
- let tasksOutput = " {\n \"build\": {\n \"target\": \"" + this.env.build.target + "\",\n \"tasks\": ["
28
+ let tasksOutput = " {\n \"build\": {\n \"target\": \"" + cds.env.build.target + "\",\n \"tasks\": ["
36
29
  for (let i = 0; i < tasks.length; i++) {
37
30
  tasksOutput += "\n " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? "," : "")
38
31
  }
@@ -41,7 +34,7 @@ class BuildTaskFactory {
41
34
 
42
35
  // for testing purposes
43
36
  this.logger.debug("cds.env used for build:")
44
- this.logger._debug && this.logger.debug(redactCredentials(this.env))
37
+ this.logger._debug && this.logger.debug(redactCredentials(cds.env))
45
38
 
46
39
  // always resolve tasks for input validation
47
40
  if (buildOptions.resolve || buildOptions.cli) {
@@ -65,12 +58,11 @@ class BuildTaskFactory {
65
58
  const buildOptions = providerFactory.buildOptions
66
59
  this.logger.log(`determining build tasks for project [${buildOptions.root}].`)
67
60
 
68
- // clear model cache - see https://github.tools.sap/cap/cds/pull/181
69
- // Required as cds.serve is invoking cds.resolve('*') which caused cds to cache the current model state
70
- // which in turn screwed-up all subsequent tests - see ./lib/compile/resolve.js#L67 and ./lib/compile/resolve.js#L58
71
- this.cds.resolve.cache = {}
61
+ // clearing model cache (details https://github.tools.sap/cap/cds/pull/181) is no longer required
62
+ // because of changes https://github.tools.sap/cap/cds/pull/1121
63
+ // cds.resolve.cache = {}
72
64
 
73
- let tasks = this._getExistingTasks()
65
+ let tasks = BuildTaskFactory._getExistingTasks()
74
66
  if (tasks.length === 0) {
75
67
  tasks = await providerFactory.lookupTasks()
76
68
  await providerFactory.applyTaskDefaults(tasks)
@@ -84,7 +76,7 @@ class BuildTaskFactory {
84
76
  // Note: A new task will be created if invoked using CLI 'cds build --for <xxx>'
85
77
  // where <xxx> matches a valid task type like 'hana', 'java' etc.
86
78
  const existingTasks = tasks
87
- tasks = await this._applyCliTaskOptions(providerFactory, tasks)
79
+ tasks = await BuildTaskFactory._applyCliTaskOptions(providerFactory, tasks)
88
80
 
89
81
  if (tasks.length === 0) {
90
82
  return tasks
@@ -99,21 +91,21 @@ class BuildTaskFactory {
99
91
  }
100
92
 
101
93
  // obligatory task defaults shared by all tasks
102
- this._applyCommonTaskDefaults(tasks, buildOptions)
94
+ BuildTaskFactory._applyCommonTaskDefaults(tasks, buildOptions)
103
95
 
104
96
  // ensure correct values for optional build task properties, error for missing mandatory properties
105
- this._validateBuildTasks(tasks)
97
+ BuildTaskFactory._validateBuildTasks(tasks)
106
98
 
107
99
  this._setDefaultBuildTargetFolder(tasks, buildOptions)
108
100
  return tasks
109
101
  }
110
102
 
111
- _getExistingTasks() {
112
- return Array.isArray(getProperty(this.env, 'build.tasks')) ? JSON.parse(JSON.stringify(this.env.build.tasks)) : []
103
+ static _getExistingTasks() {
104
+ return Array.isArray(getProperty(cds.env, 'build.tasks')) ? JSON.parse(JSON.stringify(cds.env.build.tasks)) : []
113
105
  }
114
106
 
115
- _applyCommonTaskDefaults(tasks, buildOptions) {
116
- const modelPaths = this._getDefaultModelOptions(buildOptions.root)
107
+ static _applyCommonTaskDefaults(tasks, buildOptions) {
108
+ const modelPaths = getDefaultModelOptions(buildOptions.root)
117
109
 
118
110
  tasks.forEach(task => {
119
111
  this._setTaskModelOptions(task, modelPaths)
@@ -123,7 +115,7 @@ class BuildTaskFactory {
123
115
  })
124
116
  }
125
117
 
126
- _validateBuildTasks(tasks) {
118
+ static _validateBuildTasks(tasks) {
127
119
  tasks.forEach(task => {
128
120
  if (!task.src) {
129
121
  throw new Error(`Invalid build task definition - value of property 'src' is missing in [${task.for || task.use}].`)
@@ -133,19 +125,13 @@ class BuildTaskFactory {
133
125
 
134
126
  _setDefaultBuildTargetFolder(tasks, buildOptions) {
135
127
  const task = tasks.find(task => task.for === BUILD_TASK_JAVA_CF || task.for === BUILD_TASK_JAVA)
136
- const srv = task ? task.src : BuildTaskFactory._getModuleFolder(buildOptions.root, BuildTaskFactory._flatten([this.env.folders.srv])) || "srv"
128
+ const srv = task ? task.src : BuildTaskFactory._getModuleFolder(buildOptions.root, flatten([cds.env.folders.srv])) || "srv"
137
129
 
138
130
  // Java projects use "." as the default build target folder
139
- if (this._hasJavaNature(buildOptions.root, srv) && this._adaptBuildTargetSettingForJava(buildOptions.root)) {
131
+ if (BuildTaskFactory._hasJavaNature(buildOptions.root, srv) && BuildTaskFactory._adaptBuildTargetSettingForJava(buildOptions.root)) {
140
132
  this.logger.debug("using inplace build for java project instead of default staging build")
141
133
  }
142
- buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
143
- }
144
-
145
- _getDefaultModelOptions(projectPath) {
146
- const fts = this.env.features.folders
147
- const modelPaths = this.cds.resolve(!fts ? '*' : ['*', fts], false)
148
- return this._pushModelPaths(projectPath, modelPaths)
134
+ buildOptions.target = path.resolve(buildOptions.root, cds.env.build.target)
149
135
  }
150
136
 
151
137
  /**
@@ -153,7 +139,7 @@ class BuildTaskFactory {
153
139
  * @param {string} projectPath - the absolute project path
154
140
  * @param {string} src - the folder name of the service module
155
141
  */
156
- _hasJavaNature(projectPath, src) {
142
+ static _hasJavaNature(projectPath, src) {
157
143
  return hasJavaNature([path.join(projectPath, src), projectPath])
158
144
  }
159
145
 
@@ -162,21 +148,21 @@ class BuildTaskFactory {
162
148
  * @param {string} projectPath
163
149
  * @returns {boolean} true if changed, false otherwise
164
150
  */
165
- _adaptBuildTargetSettingForJava(projectPath) {
166
- if (this.env.build.target !== ".") {
151
+ static _adaptBuildTargetSettingForJava(projectPath) {
152
+ if (cds.env.build.target !== ".") {
167
153
  // filter user settings of cds.env
168
- const userEnv = this.env.for("cds", projectPath, false)
154
+ const userEnv = cds.env.for("cds", projectPath, false)
169
155
 
170
156
  // use helper as env.build might be undefined
171
157
  if (!getProperty(userEnv, "build.target")) {
172
- this.env.build.target = "."
158
+ cds.env.build.target = "."
173
159
  return true
174
160
  }
175
161
  }
176
162
  return false
177
163
  }
178
164
 
179
- async _applyCliTaskOptions(providerFactory, tasks) {
165
+ static async _applyCliTaskOptions(providerFactory, tasks) {
180
166
  const { buildOptions } = providerFactory
181
167
  if (buildOptions.cmdOptions) {
182
168
  const options = buildOptions.cmdOptions
@@ -206,7 +192,7 @@ class BuildTaskFactory {
206
192
  task.dest = options.dest
207
193
  }
208
194
  if (options.opts) {
209
- const opts = BuildTaskFactory._scanTaskOptionParams(options.opts)
195
+ const opts = this._scanTaskOptionParams(options.opts)
210
196
  task.options = task.options ? Object.assign(task.options, opts) : opts
211
197
  }
212
198
  })
@@ -214,7 +200,7 @@ class BuildTaskFactory {
214
200
  return tasks
215
201
  }
216
202
 
217
- _setTaskModelOptions(task, defaultModelPaths) {
203
+ static _setTaskModelOptions(task, defaultModelPaths) {
218
204
  task.options = task.options || {}
219
205
  if (!task.options.model || Array.isArray(task.options.model) && task.options.model.length === 0) {
220
206
  defaultModelPaths = new Set(defaultModelPaths)
@@ -258,41 +244,6 @@ class BuildTaskFactory {
258
244
  return taskOptions
259
245
  }
260
246
 
261
- _pushModelPaths(projectPath, ...modelPaths) {
262
- const model = new Set()
263
- // may contain nested arrays
264
- modelPaths = BuildTaskFactory._flatten(modelPaths)
265
- const { roots } = this.env
266
- modelPaths.forEach(m => {
267
- if (m && !model.has(m) && !model.has(m + "/")) {
268
- // filter root model paths that do not exist
269
- // other entries are added as is, e.g. reuse model entries
270
- if (roots.includes(m)) {
271
- const dir = path.resolve(projectPath, m)
272
- if (fs.existsSync(dir)) {
273
- model.add(BuildTaskFactory._normalizePath(m))
274
- } else if (fs.existsSync(dir + FILE_EXT_CDS)) { //might be cds file name, compability to old build configs
275
- model.add(m)
276
- }
277
- } else {
278
- model.add(m)
279
- }
280
- }
281
- })
282
- return model
283
- }
284
-
285
- static _flatten(modelPaths) {
286
- return modelPaths.reduce((acc, m) => {
287
- if (Array.isArray(m)) {
288
- acc = acc.concat(BuildTaskFactory._flatten(m))
289
- } else if (m) {
290
- acc.push(m)
291
- }
292
- return acc
293
- }, [])
294
- }
295
-
296
247
  /**
297
248
  * For valid paths remove trailing '/'. Otherwise return as is - important!!
298
249
  * @param {*} dir
@@ -1,5 +1,6 @@
1
1
  const path = require('path')
2
2
  const fs = require('fs').promises
3
+ const cds = require('./cds')
3
4
 
4
5
  const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_DEFAULT, OUTPUT_MODE_RESULT_ONLY, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR, OVERRIDE_METHOD_MSG } = require('./constants')
5
6
  const { hasOptionValue, getProperty, relativePaths, BuildMessage } = require('./util')
@@ -190,7 +191,7 @@ class BuildTaskHandler {
190
191
  // $location paths are relative to current working dir by default - make sure a given project root folder is taken
191
192
  const options = { ...this.options(), cwd: this._buildOptions.root }
192
193
 
193
- const model = await this._cds.load(files, options)
194
+ const model = await cds.load(files, options)
194
195
  if (!model) {
195
196
  return null
196
197
  }
@@ -214,7 +215,7 @@ class BuildTaskHandler {
214
215
  */
215
216
  _resolveModel() {
216
217
  const modelPaths = Array.isArray(this.task.options.model) && this.task.options.model.length > 0 ? this.task.options.model : !Array.isArray(this.task.options.model) && this.task.options.model || this.task.src
217
- return this._cds.resolve(modelPaths, this._buildOptions)
218
+ return cds.resolve(modelPaths, this._buildOptions)
218
219
  }
219
220
  /** Determines whether the given build option value has been set for this build task.
220
221
  * If the value is omitted, the existence of the given property name is checked.
@@ -10,8 +10,8 @@ module.exports = class BuildTaskProvider {
10
10
  loadHandler(task) {
11
11
  // return module.require(`${this._plugin.path}/${task.for || this._getTaskId(task.use)}`)
12
12
  }
13
- async lookupTasks(tasks) { }
14
- async applyTaskDefaults(task) {
13
+ async lookupTasks(tasks, options) { }
14
+ async applyTaskDefaults(task, options) {
15
15
  // task.for = task.for || this._getTaskId(task.use)
16
16
  }
17
17
  _getTaskId(use) {
@@ -1,24 +1,17 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
- const _cds = require('./cds')
3
+ const cds = require('./cds')
4
4
  const { OUTPUT_MODE_DEFAULT, LOG_MODULE_NAMES } = require("./constants")
5
5
  const BuildTaskProviderInternal = require('./provider/buildTaskProviderInternal')
6
6
  const BuildTaskProvider = require('./buildTaskProvider')
7
7
 
8
8
  class BuildTaskProviderFactory {
9
- constructor(logger, cds, buildOptions) {
10
- this._cds = cds ? cds : _cds
11
- this._logger = logger || this._cds.log(LOG_MODULE_NAMES)
9
+ constructor(logger, buildOptions) {
10
+ this._logger = logger || cds.log(LOG_MODULE_NAMES)
12
11
  buildOptions.for = buildOptions.for || {}
13
12
  buildOptions.outputMode = buildOptions.outputMode || OUTPUT_MODE_DEFAULT
14
13
  this._buildOptions = buildOptions
15
14
  }
16
- get cds() {
17
- return this._cds
18
- }
19
- get env() {
20
- return this._cds.env
21
- }
22
15
  get logger() {
23
16
  return this._logger
24
17
  }
@@ -80,7 +73,6 @@ class BuildTaskProviderFactory {
80
73
 
81
74
  const handler = new BuildTaskHandlerClass()
82
75
  handler._task = resolvedTask
83
- handler._cds = this.cds
84
76
  handler._logger = this.logger
85
77
  handler._buildOptions = this.buildOptions
86
78
  this.logger._debug && this.logger.debug(`created BuildTaskHandler [${resolvedTask.use}]`)
@@ -144,7 +136,7 @@ class BuildTaskProviderFactory {
144
136
  }
145
137
 
146
138
  async _applyTaskDefaults(provider, tasks) {
147
- return Promise.all(tasks.map(task => provider.applyTaskDefaults(task)))
139
+ return Promise.all(tasks.map(task => provider.applyTaskDefaults(task, this.buildOptions)))
148
140
  }
149
141
 
150
142
  _loadProviders() {
@@ -154,7 +146,6 @@ class BuildTaskProviderFactory {
154
146
 
155
147
  _createProvider(clazz, plugin) {
156
148
  const provider = new clazz()
157
- provider._cds = this.cds
158
149
  provider._logger = this.logger
159
150
  provider._plugin = plugin
160
151
  return provider
@@ -174,7 +165,7 @@ class DefaultBuildTaskProvider extends BuildTaskProvider {
174
165
  throw new Error(`Invalid build task definition [${task.for}] - property 'use' missing`)
175
166
  }
176
167
  try {
177
- return require(require.resolve(task.use, { paths: [this._cds.root] }))
168
+ return require(require.resolve(task.use, { paths: [cds.root] }))
178
169
  }
179
170
  catch (e) {
180
171
  throw new Error(`Build task could not be resolved - module [${task.use}] cannot be loaded:\n` + e)
@@ -62,4 +62,3 @@ exports.LOG_LEVEL_DEBUG = "debug"
62
62
  exports.LOG_LEVELS = [exports.LOG_LEVEL_ERROR, exports.LOG_LEVEL_WARN, exports.LOG_LEVEL_INFO, exports.LOG_LEVEL_DEBUG]
63
63
  exports.LOG_MODULE_NAMES = "cds|build"
64
64
  exports.OVERRIDE_METHOD_MSG = "Must override method"
65
- exports.SEMVER_REGEX = /^(\D*)(\d+\.)?(\d+\.)?(\*|\d+)/
@@ -1,4 +1,5 @@
1
1
  const path = require('path')
2
+ const cds = require('../cds')
2
3
  const BuildTaskHandlerFeatureToggles = require('./buildTaskHandlerFeatureToggles')
3
4
  const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY } = require('../constants')
4
5
 
@@ -7,7 +8,7 @@ class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
7
8
  const promises = []
8
9
 
9
10
  // generate edmx for services only that have the odata protocol
10
- const serviceNames = this.cds.reflect(model).services
11
+ const serviceNames = cds.reflect(model).services
11
12
  .filter(service => this._isOdataProtocol(service))
12
13
  .map(service => service.name)
13
14
 
@@ -23,10 +24,10 @@ class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
23
24
  }
24
25
  this.logger._debug && this.logger.debug(`compiling edmx files using OData version ${options.version}`)
25
26
 
26
- const result = this.cds.compile.to.edmx(model, options)
27
+ const result = cds.compile.to.edmx(model, options)
27
28
 
28
29
  if (result) {
29
- let langs = this.task.options.lang || this.env.i18n.languages
30
+ let langs = this.task.options.lang || cds.env.i18n.languages
30
31
  if (langs.split) { // string to array
31
32
  langs = langs.split(',')
32
33
  }
@@ -36,7 +37,7 @@ class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
36
37
  for (let [content, key] of result) {
37
38
  const serviceName = key.file ? key.file : key.name
38
39
  this._result.services.add(serviceName)
39
- const locResult = this.cds.localize(model, langs, content)
40
+ const locResult = cds.localize(model, langs, content)
40
41
  if (locResult[Symbol.iterator]) { // multi result
41
42
  for (let [localizedContent, { lang }] of locResult) {
42
43
  promises.push(this._writeEdmxForLang(localizedContent, serviceName, lang, edmxDest))
@@ -51,12 +52,12 @@ class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
51
52
  }
52
53
 
53
54
  _isOdataProtocol(srv) {
54
- return this.cds.service.protocols.protocol4(srv).startsWith('odata')
55
+ return cds.service.protocols.protocol4(srv).startsWith('odata')
55
56
  }
56
57
 
57
58
  _options4odata() {
58
59
  const o = this.options()
59
- o.version = this.env.odata.version
60
+ o.version = cds.env.odata.version
60
61
  return o
61
62
  }
62
63
 
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
+ const cds = require('../cds')
3
4
  const { DEFAULT_CSN_FILE_NAME } = require('../constants')
4
5
  const BuildTaskHandlerInternal = require('./buildTaskHandlerInternal')
5
6
 
@@ -16,7 +17,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
16
17
  }
17
18
 
18
19
  get ftsName() {
19
- return path.dirname(this.env.features.folders || 'fts/*')
20
+ return path.dirname(cds.env.features.folders || 'fts/*')
20
21
  }
21
22
 
22
23
  async compileAll(csn, destBase, destFts) {
@@ -25,7 +26,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
25
26
 
26
27
  if (sources.features) {
27
28
  // create base model as the given CSN is containing all features
28
- dictionary.base = await this.cds.load(sources.base, this.options())
29
+ dictionary.base = await cds.load(sources.base, this.options())
29
30
  } else {
30
31
  // CSN already represents the base model as no features exist
31
32
  dictionary.base = csn
@@ -43,7 +44,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
43
44
  }
44
45
 
45
46
  async collectAllLanguageBundles(dictionary, paths, destBase, destFts) {
46
- const i18nFolder = this.env.i18n.folders?.[0] || 'i18n'
47
+ const i18nFolder = cds.env.i18n.folders?.[0] || 'i18n'
47
48
  // create language bundle for base model
48
49
  const i18n = await this.collectLanguageBundles(dictionary.base, path.join(destBase, i18nFolder))
49
50
  if (i18n) {
@@ -104,7 +105,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
104
105
 
105
106
  // create feature models
106
107
  for (const ftName in ftsPaths) {
107
- const ftCsn = await this.cds.load(ftsPaths[ftName], options)
108
+ const ftCsn = await cds.load(ftsPaths[ftName], options)
108
109
  const ftPath = path.join(destFts, this.ftsName, ftName)
109
110
 
110
111
  // replace require paths by base model path to ensure precedence of feature annotations
@@ -121,7 +122,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
121
122
  async _validateFeature(ftPath) {
122
123
  // features must not have other than base model dependencies, cross feature dependencies are not supported
123
124
  // do not pass options.messages in order to avoid duplicate compiler messages
124
- return this.cds.load([ftPath])
125
+ return cds.load([ftPath])
125
126
  // version 2.13.9 of compileSources does not read the requires definition of parsed CSNs
126
127
  // require('@sap/cds-compiler').compileSources({ '../..csn.json': baseCsn, 'feature.csn': ftCsn }, this.options())
127
128
  }