@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.
- package/CHANGELOG.md +87 -0
- package/apis/cds.d.ts +1 -1
- package/apis/core.d.ts +118 -90
- package/apis/cqn.d.ts +11 -2
- package/apis/internal/inference.d.ts +7 -2
- package/apis/ql.d.ts +45 -11
- package/apis/serve.d.ts +8 -1
- package/apis/services.d.ts +303 -305
- package/bin/build/buildTaskEngine.js +28 -36
- package/bin/build/buildTaskFactory.js +32 -81
- package/bin/build/buildTaskHandler.js +3 -2
- package/bin/build/buildTaskProvider.js +2 -2
- package/bin/build/buildTaskProviderFactory.js +5 -14
- package/bin/build/constants.js +0 -1
- package/bin/build/provider/buildTaskHandlerEdmx.js +7 -6
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +6 -5
- package/bin/build/provider/buildTaskHandlerInternal.js +9 -30
- package/bin/build/provider/buildTaskProviderInternal.js +70 -58
- package/bin/build/provider/fiori/index.js +6 -5
- package/bin/build/provider/hana/2migration.js +20 -3
- package/bin/build/provider/hana/2tabledata.js +1 -0
- package/bin/build/provider/hana/index.js +40 -17
- package/bin/build/provider/java/index.js +10 -10
- package/bin/build/provider/mtx/index.js +25 -16
- package/bin/build/provider/mtx/resourcesTarBuilder.js +22 -27
- package/bin/build/provider/mtx-extension/index.js +3 -2
- package/bin/build/provider/mtx-sidecar/index.js +16 -15
- package/bin/build/provider/nodejs/index.js +14 -56
- package/bin/build/util.js +56 -16
- package/bin/deploy/to-hana/cfUtil.js +4 -1
- package/bin/deploy/to-hana/gitUtil.js +1 -1
- package/bin/deploy/to-hana/hana.js +45 -38
- package/bin/deploy/to-hana/hdiDeployUtil.js +8 -9
- package/bin/deploy/to-hana/mtaUtil.js +13 -14
- package/bin/mtx/in-cds.js +3 -1
- package/bin/serve.js +1 -1
- package/bin/version.js +2 -1
- package/lib/compile/cds-compile.js +1 -0
- package/lib/compile/cdsc.js +1 -0
- package/lib/compile/etc/_localized.js +2 -2
- package/lib/compile/for/lean_drafts.js +83 -0
- package/lib/compile/for/nodejs.js +1 -0
- package/lib/compile/minify.js +2 -1
- package/lib/compile/parse.js +2 -1
- package/lib/compile/to/gql.js +1 -1
- package/lib/compile/to/sql.js +11 -1
- package/lib/core/entities.js +1 -1
- package/lib/core/index.js +8 -9
- package/lib/core/infer.js +1 -0
- package/lib/dbs/cds-deploy.js +97 -41
- package/lib/env/cds-env.js +9 -10
- package/lib/env/cds-requires.js +8 -2
- package/lib/env/defaults.js +0 -4
- package/lib/env/schemas/cds-rc.json +38 -0
- package/lib/ql/SELECT.js +10 -4
- package/lib/srv/bindings.js +1 -1
- package/lib/srv/factory.js +1 -1
- package/lib/srv/protocols/index.js +3 -1
- package/lib/srv/srv-methods.js +1 -1
- package/lib/utils/cds-utils.js +11 -0
- package/lib/utils/inflect.js +13 -12
- package/lib/utils/tar.js +53 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -15
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/UriSyntaxError.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +6 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/BufferedWriter.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/ConditionalRequestValidator.js +0 -12
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/oDataConfiguration.js +1 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +4 -0
- package/libx/_runtime/cds-services/services/Service.js +23 -1
- package/libx/_runtime/cds-services/util/assert.js +0 -41
- package/libx/_runtime/common/composition/data.js +5 -1
- package/libx/_runtime/common/generic/auth/utils.js +3 -3
- package/libx/_runtime/common/generic/input.js +4 -24
- package/libx/_runtime/common/generic/paging.js +3 -3
- package/libx/_runtime/common/utils/csn.js +21 -15
- package/libx/_runtime/common/utils/draft.js +2 -1
- package/libx/_runtime/common/utils/resolveView.js +25 -4
- package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -1
- package/libx/_runtime/common/utils/rowUUIDGenerator.js +21 -0
- package/libx/_runtime/common/utils/templateProcessor.js +12 -15
- package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +23 -0
- package/libx/_runtime/db/expand/expandCQNToJoin.js +29 -12
- package/libx/_runtime/db/generic/input.js +7 -13
- package/libx/_runtime/db/sql-builder/UpsertBuilder.js +47 -0
- package/libx/_runtime/db/sql-builder/index.js +2 -0
- package/libx/_runtime/db/sql-builder/sqlFactory.js +9 -0
- package/libx/_runtime/db/utils/columns.js +4 -2
- package/libx/_runtime/fiori/generic/read.js +1 -12
- package/libx/_runtime/fiori/lean-draft.js +657 -0
- package/libx/_runtime/fiori/utils/handler.js +1 -1
- package/libx/_runtime/hana/pool.js +16 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging.js +2 -3
- package/libx/_runtime/messaging/outbox/utils.js +109 -70
- package/libx/_runtime/messaging/service.js +16 -7
- package/libx/_runtime/remote/Service.js +15 -2
- package/libx/_runtime/remote/utils/client.js +41 -11
- package/libx/_runtime/sqlite/Service.js +3 -0
- package/libx/_runtime/sqlite/convertDraftAdminPathExpression.js +56 -0
- package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +59 -0
- package/libx/_runtime/sqlite/customBuilder/index.js +5 -0
- package/libx/_runtime/sqlite/execute.js +1 -1
- package/libx/_runtime/types/api.js +2 -2
- package/libx/rest/RestAdapter.js +15 -13
- package/package.json +1 -1
- package/server.js +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const
|
|
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
|
|
15
|
-
this.
|
|
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 [${
|
|
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,
|
|
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 } =
|
|
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
|
-
|
|
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
|
|
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:
|
|
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(
|
|
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,
|
|
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 =
|
|
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 =
|
|
269
|
+
const outputFile = cds.env.build.outputfile || process.env.GENERATION_LOG
|
|
283
270
|
if (outputFile) {
|
|
284
|
-
const files =
|
|
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":
|
|
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(
|
|
329
|
-
const 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(
|
|
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"] ||
|
|
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
|
|
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
|
|
10
|
-
this.
|
|
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
|
|
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,
|
|
22
|
+
const providerFactory = new BuildTaskProviderFactory(this._logger, buildOptions)
|
|
30
23
|
const tasks = await this._createTasks(providerFactory)
|
|
31
|
-
buildOptions.target = path.resolve(buildOptions.root,
|
|
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\": \"" +
|
|
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(
|
|
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
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
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 =
|
|
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
|
|
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
|
-
|
|
94
|
+
BuildTaskFactory._applyCommonTaskDefaults(tasks, buildOptions)
|
|
103
95
|
|
|
104
96
|
// ensure correct values for optional build task properties, error for missing mandatory properties
|
|
105
|
-
|
|
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(
|
|
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 =
|
|
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,
|
|
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 (
|
|
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,
|
|
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 (
|
|
151
|
+
static _adaptBuildTargetSettingForJava(projectPath) {
|
|
152
|
+
if (cds.env.build.target !== ".") {
|
|
167
153
|
// filter user settings of cds.env
|
|
168
|
-
const userEnv =
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
10
|
-
this.
|
|
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: [
|
|
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)
|
package/bin/build/constants.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
27
|
+
const result = cds.compile.to.edmx(model, options)
|
|
27
28
|
|
|
28
29
|
if (result) {
|
|
29
|
-
let langs = this.task.options.lang ||
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
}
|