@sap/cds 6.1.3 → 6.2.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.
- package/CHANGELOG.md +77 -8
- package/apis/cds.d.ts +18 -6
- package/apis/connect.d.ts +1 -1
- package/apis/cqn.d.ts +1 -1
- package/apis/log.d.ts +23 -5
- package/apis/ql.d.ts +128 -61
- package/apis/services.d.ts +11 -0
- package/apis/test.d.ts +61 -0
- package/apis/utils.d.ts +15 -0
- package/app/fiori/preview.js +1 -0
- package/bin/build/buildTaskEngine.js +70 -22
- package/bin/build/buildTaskFactory.js +18 -11
- package/bin/build/buildTaskHandler.js +1 -1
- package/bin/build/buildTaskProviderFactory.js +3 -13
- package/bin/build/constants.js +0 -1
- package/bin/build/index.js +14 -6
- package/bin/build/provider/buildTaskHandlerEdmx.js +2 -3
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +2 -2
- package/bin/build/provider/buildTaskHandlerInternal.js +3 -6
- package/bin/build/provider/buildTaskProviderInternal.js +51 -39
- package/bin/build/provider/fiori/index.js +3 -3
- package/bin/build/provider/hana/2migration.js +1 -1
- package/bin/build/provider/hana/index.js +34 -27
- package/bin/build/provider/java/index.js +6 -7
- package/bin/build/provider/mtx/index.js +20 -18
- package/bin/build/provider/mtx/resourcesTarBuilder.js +8 -11
- package/bin/build/provider/mtx-sidecar/index.js +13 -17
- package/bin/build/provider/nodejs/index.js +8 -7
- package/bin/build/util.js +22 -4
- package/bin/cds.js +8 -4
- package/bin/deploy/to-hana/cfUtil.js +53 -18
- package/bin/mtx/in-cds.js +1 -0
- package/bin/serve.js +37 -30
- package/lib/auth/basic-auth.js +33 -0
- package/lib/auth/dummy-auth.js +7 -0
- package/lib/auth/ias-auth.js +2 -0
- package/lib/auth/index.js +31 -0
- package/lib/auth/jwt-auth.js +3 -0
- package/lib/auth/mocked-users.js +72 -0
- package/lib/auth/passport-basic.js +12 -0
- package/lib/auth/passport-digest.js +14 -0
- package/lib/auth/xsuaa-auth.js +3 -0
- package/lib/compile/cds-compile.js +3 -3
- package/lib/compile/to/cdl.js +5 -1
- package/lib/compile/to/edm.js +8 -0
- package/lib/compile/to/gql.js +1 -0
- package/lib/compile/to/json.js +30 -5
- package/lib/compile/to/sql.js +3 -1
- package/lib/core/index.js +5 -1
- package/lib/dbs/cds-deploy.js +36 -6
- package/lib/env/cds-env.js +15 -5
- package/lib/env/cds-requires.js +51 -58
- package/lib/env/defaults.js +1 -0
- package/lib/env/schemas/cds-package.json +4 -0
- package/lib/env/schemas/cds-rc.json +63 -77
- package/lib/i18n/localize.js +16 -5
- package/lib/index.js +9 -4
- package/lib/log/cds-error.js +4 -6
- package/lib/log/cds-log.js +89 -53
- package/lib/log/service/index.js +1 -0
- package/lib/ql/CREATE.js +2 -5
- package/lib/ql/DELETE.js +1 -1
- package/lib/ql/DROP.js +1 -3
- package/lib/ql/INSERT.js +3 -3
- package/lib/ql/Query.js +10 -23
- package/lib/ql/SELECT.js +1 -2
- package/lib/ql/UPDATE.js +2 -2
- package/lib/ql/Whereable.js +7 -15
- package/lib/ql/cds-ql.js +9 -3
- package/lib/req/cds-context.js +11 -3
- package/lib/req/context.js +29 -23
- package/lib/req/locale.js +9 -5
- package/lib/req/request.js +1 -0
- package/lib/req/user.js +2 -1
- package/lib/srv/cds-connect.js +1 -1
- package/lib/srv/cds-serve.js +21 -14
- package/lib/srv/middlewares/cds-context.js +29 -0
- package/lib/srv/middlewares/ctx-model.js +24 -0
- package/lib/srv/middlewares/errors.js +9 -0
- package/lib/srv/middlewares/index.js +22 -0
- package/lib/srv/middlewares/sap-statistics.js +13 -0
- package/lib/srv/middlewares/trace.js +102 -0
- package/lib/srv/protocols/_legacy.js +42 -0
- package/lib/srv/protocols/graphql.js +39 -0
- package/lib/srv/protocols/hcql.js +37 -0
- package/lib/srv/protocols/index.js +86 -0
- package/lib/srv/protocols/odata-v2-proxy.js +3767 -0
- package/lib/srv/protocols/odata-v2.js +26 -0
- package/lib/srv/protocols/odata-v4.js +16 -0
- package/lib/srv/protocols/rest.js +13 -0
- package/lib/srv/srv-api.js +5 -0
- package/lib/srv/srv-models.js +4 -6
- package/lib/utils/axios.js +3 -2
- package/lib/utils/cds-test.js +27 -21
- package/lib/utils/cds-utils.js +19 -20
- package/lib/utils/tar.js +175 -0
- package/libx/_runtime/audit/generic/personal/utils.js +18 -7
- package/libx/_runtime/audit/utils/v2.js +1 -0
- package/libx/_runtime/auth/index.js +4 -0
- package/libx/_runtime/auth/strategies/ias-auth.js +76 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +8 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +15 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/orderByToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ResourcePathParser.js +9 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriInfo.js +5 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +12 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/BufferedWriter.js +6 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/RequestValidator.js +47 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/util/assert.js +4 -0
- package/libx/_runtime/common/aspects/relation.js +1 -1
- package/libx/_runtime/common/composition/data.js +61 -15
- package/libx/_runtime/common/composition/delete.js +0 -1
- package/libx/_runtime/common/composition/insert.js +0 -1
- package/libx/_runtime/common/composition/tree.js +4 -10
- package/libx/_runtime/common/composition/update.js +44 -21
- package/libx/_runtime/common/generic/auth/capabilities.js +8 -10
- package/libx/_runtime/common/generic/crud.js +1 -2
- package/libx/_runtime/common/generic/etag.js +4 -4
- package/libx/_runtime/common/generic/input.js +4 -4
- package/libx/_runtime/common/generic/paging.js +3 -3
- package/libx/_runtime/common/generic/put.js +3 -3
- package/libx/_runtime/common/generic/sorting.js +4 -4
- package/libx/_runtime/common/generic/temporal.js +3 -3
- package/libx/_runtime/common/i18n/messages.properties +0 -7
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +11 -6
- package/libx/_runtime/common/utils/csn.js +0 -28
- package/libx/_runtime/common/utils/draft.js +8 -1
- package/libx/_runtime/common/utils/path.js +7 -1
- package/libx/_runtime/common/utils/resolveView.js +2 -3
- package/libx/_runtime/db/data-conversion/post-processing.js +3 -44
- package/libx/_runtime/db/generic/input.js +3 -3
- package/libx/_runtime/db/sql-builder/dataTypes.js +4 -0
- package/libx/_runtime/fiori/generic/activate.js +2 -2
- package/libx/_runtime/fiori/generic/before.js +40 -72
- package/libx/_runtime/fiori/generic/cancel.js +2 -2
- package/libx/_runtime/fiori/generic/delete.js +2 -2
- package/libx/_runtime/fiori/generic/edit.js +2 -2
- package/libx/_runtime/fiori/generic/new.js +2 -2
- package/libx/_runtime/fiori/generic/patch.js +49 -37
- package/libx/_runtime/fiori/generic/prepare.js +2 -2
- package/libx/_runtime/fiori/generic/read.js +27 -37
- package/libx/_runtime/fiori/utils/where.js +4 -2
- package/libx/_runtime/hana/Service.js +1 -3
- package/libx/_runtime/hana/conversion.js +3 -0
- package/libx/_runtime/hana/driver.js +33 -3
- package/libx/_runtime/hana/dynatrace.js +1 -0
- package/libx/_runtime/hana/search2Contains.js +12 -1
- package/libx/_runtime/hana/search2cqn4sql.js +10 -27
- package/libx/_runtime/hana/streaming.js +1 -0
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +4 -2
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +1 -0
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +5 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -0
- package/libx/_runtime/messaging/enterprise-messaging.js +62 -3
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/messaging/redis-messaging.js +1 -0
- package/libx/_runtime/remote/Service.js +2 -2
- package/libx/_runtime/remote/utils/client.js +8 -3
- package/libx/_runtime/remote/utils/data.js +7 -2
- package/libx/_runtime/sqlite/Service.js +18 -7
- package/libx/_runtime/sqlite/conversion.js +3 -0
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +3 -3
- package/libx/_runtime/sqlite/localized.js +8 -8
- package/libx/odata/afterburner.js +39 -7
- package/libx/odata/cqn2odata.js +6 -3
- package/libx/odata/grammar.pegjs +66 -18
- package/libx/odata/index.js +3 -2
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +2 -0
- package/libx/rest/RestAdapter.js +62 -43
- package/libx/rest/middleware/parse.js +2 -1
- package/libx/rest/middleware/update.js +1 -1
- package/package.json +2 -2
- package/server.js +5 -4
- package/srv/mtx.cds +1 -1
- package/srv/mtx.js +4 -33
- package/lib/srv/adapters.js +0 -85
- package/lib/utils/resources/index.js +0 -48
- package/lib/utils/resources/tar.js +0 -49
- package/lib/utils/resources/utils.js +0 -11
- package/libx/_runtime/extensibility/activate.js +0 -69
- package/libx/_runtime/extensibility/add.js +0 -50
- package/libx/_runtime/extensibility/addExtension.js +0 -72
- package/libx/_runtime/extensibility/defaults.js +0 -34
- package/libx/_runtime/extensibility/handler/transformREAD.js +0 -121
- package/libx/_runtime/extensibility/handler/transformRESULT.js +0 -51
- package/libx/_runtime/extensibility/handler/transformWRITE.js +0 -64
- package/libx/_runtime/extensibility/linter/allowlist_checker.js +0 -373
- package/libx/_runtime/extensibility/linter/annotations_checker.js +0 -113
- package/libx/_runtime/extensibility/linter/checker_base.js +0 -20
- package/libx/_runtime/extensibility/linter/namespace_checker.js +0 -180
- package/libx/_runtime/extensibility/linter.js +0 -32
- package/libx/_runtime/extensibility/push.js +0 -118
- package/libx/_runtime/extensibility/service.js +0 -38
- package/libx/_runtime/extensibility/token.js +0 -57
- package/libx/_runtime/extensibility/utils.js +0 -131
- package/libx/_runtime/extensibility/validation.js +0 -50
- package/libx/_runtime/extensibility/views.js +0 -12
- package/srv/extensibility-service.cds +0 -60
- package/srv/extensibility-service.js +0 -1
- package/srv/extensions.cds +0 -8
- package/srv/model-provider.cds +0 -61
- package/srv/model-provider.js +0 -143
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const _cds = require('./cds'), { log } = _cds.exec
|
|
4
|
-
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
5
4
|
const { sortMessagesSeverityAware, deduplicateMessages, CompilationError } = require('@sap/cds-compiler')
|
|
6
|
-
const { relativePaths, BuildError, BuildMessage } = require('./util')
|
|
5
|
+
const { relativePaths, BuildError, BuildMessage, resolveRequiredSapModels } = require('./util')
|
|
7
6
|
const { OUTPUT_MODE_DEFAULT, SEVERITIES, LOG_LEVELS, LOG_MODULE_NAMES } = require('./constants')
|
|
7
|
+
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
8
8
|
const BuildTaskHandlerInternal = require('./provider/buildTaskHandlerInternal')
|
|
9
9
|
|
|
10
10
|
const COMPILATION_ERROR = 'CompilationError'
|
|
@@ -27,7 +27,6 @@ class BuildTaskEngine {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async processTasks(tasks, buildOptions, clean = true) {
|
|
30
|
-
const handlers = []
|
|
31
30
|
const startTime = Date.now()
|
|
32
31
|
|
|
33
32
|
if (buildOptions) {
|
|
@@ -49,6 +48,18 @@ class BuildTaskEngine {
|
|
|
49
48
|
buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
|
|
50
49
|
}
|
|
51
50
|
|
|
51
|
+
// validate required @sap namespace models - log only
|
|
52
|
+
const { unresolved, missing } = this._resolveRequiredSapServices(tasks)
|
|
53
|
+
const messages = []
|
|
54
|
+
if (unresolved.length > 0) {
|
|
55
|
+
messages.push(new BuildMessage(`Required CDS service models [${unresolved.join(', ')}] cannot be resolved. Make sure to install the missing npm modules.`))
|
|
56
|
+
}
|
|
57
|
+
if (missing.length > 0) {
|
|
58
|
+
messages.push(new BuildMessage(`Required CDS service models [${missing.join(', ')}] are missing in custom build tasks. Make sure to add the missing models.`))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// create build task handlers
|
|
62
|
+
const handlers = []
|
|
52
63
|
tasks.forEach((task) => {
|
|
53
64
|
if (task) {
|
|
54
65
|
const handler = this._createHandler(task, buildOptions)
|
|
@@ -62,17 +73,22 @@ class BuildTaskEngine {
|
|
|
62
73
|
try {
|
|
63
74
|
await this._executePrepare(handlers, buildOptions)
|
|
64
75
|
await this._executeCleanBuildTasks(handlers, buildOptions, clean)
|
|
76
|
+
|
|
77
|
+
// throwing Exception in case of compilation errors
|
|
65
78
|
const buildResult = await this._executeBuildTasks(handlers, buildOptions)
|
|
66
|
-
|
|
67
|
-
this.
|
|
79
|
+
|
|
80
|
+
await this._writeGenerationLog(handlers, buildOptions)
|
|
81
|
+
this._logBuildOutput(handlers, buildOptions)
|
|
82
|
+
this._logMessages(buildOptions, [...BuildTaskEngine._getHandlerMessages(handlers), ...messages])
|
|
68
83
|
this._logTimer(startTime, Date.now())
|
|
69
84
|
|
|
70
85
|
return buildResult
|
|
71
86
|
} catch (error) {
|
|
72
|
-
|
|
73
|
-
|
|
87
|
+
this._logBuildOutput(handlers, buildOptions)
|
|
88
|
+
|
|
89
|
+
// cds CLI layer logs in case of an exception if invoked from CLI
|
|
74
90
|
if (!buildOptions.cli) {
|
|
75
|
-
this._logMessages(buildOptions, BuildTaskEngine._getErrorMessages([error]))
|
|
91
|
+
this._logMessages(buildOptions, [...BuildTaskEngine._getErrorMessages([error]), ...messages])
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
if (error.name === BuildError.name && error.errors.length > 0 && error.errors[0].constructor.name === COMPILATION_ERROR) {
|
|
@@ -128,7 +144,7 @@ class BuildTaskEngine {
|
|
|
128
144
|
// clean entire build staging folder once
|
|
129
145
|
if (buildOptions.target !== buildOptions.root) {
|
|
130
146
|
this.logger._debug && this.logger.debug(`cleaning staging folder ${buildOptions.target}`)
|
|
131
|
-
await fs.promises.rm(buildOptions.target, {force: true, recursive: true})
|
|
147
|
+
await fs.promises.rm(buildOptions.target, { force: true, recursive: true })
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
const results = await Promise.allSettled(handlers.map((handler) => {
|
|
@@ -249,7 +265,7 @@ class BuildTaskEngine {
|
|
|
249
265
|
return files.map(file => path.relative(buildOptions.root, file))
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
|
|
268
|
+
_logBuildOutput(handlers, buildOptions) {
|
|
253
269
|
// log all generated files
|
|
254
270
|
const files = this._getBuildOutput(handlers, buildOptions)
|
|
255
271
|
if (files.length > 0) {
|
|
@@ -257,18 +273,18 @@ class BuildTaskEngine {
|
|
|
257
273
|
} else {
|
|
258
274
|
this.logger.log('done >')
|
|
259
275
|
}
|
|
276
|
+
}
|
|
260
277
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
).
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
})
|
|
278
|
+
async _writeGenerationLog(handlers, buildOptions) {
|
|
279
|
+
const outputFile = this.env.build.outputfile || process.env.GENERATION_LOG
|
|
280
|
+
if (outputFile) {
|
|
281
|
+
const files = this._getBuildOutput(handlers, buildOptions)
|
|
282
|
+
this.logger.log(`writing generation log to [${outputFile}]\n`)
|
|
283
|
+
try {
|
|
284
|
+
await fs.promises.mkdir(path.dirname(outputFile), { recursive: true }).then(() => fs.promises.writeFile(outputFile, files.join('\n')))
|
|
285
|
+
} catch (error) {
|
|
286
|
+
this.logger.error(`failed to write generation log`)
|
|
287
|
+
this.logger.error(error.stack || error)
|
|
272
288
|
}
|
|
273
289
|
}
|
|
274
290
|
}
|
|
@@ -283,7 +299,7 @@ class BuildTaskEngine {
|
|
|
283
299
|
}
|
|
284
300
|
|
|
285
301
|
_logMessages(buildOptions, messages) {
|
|
286
|
-
if (messages
|
|
302
|
+
if (messages.length > 0) {
|
|
287
303
|
const options = {
|
|
288
304
|
log: this.logger.log,
|
|
289
305
|
"log-level": this._getLogLevel(buildOptions) // ensures that for tests the correct cds.env is used
|
|
@@ -293,6 +309,38 @@ class BuildTaskEngine {
|
|
|
293
309
|
}
|
|
294
310
|
}
|
|
295
311
|
|
|
312
|
+
_resolveRequiredSapServices(tasks) {
|
|
313
|
+
const taskModelPaths = tasks.reduce((acc, task) => {
|
|
314
|
+
const model = task.options?.model
|
|
315
|
+
if (model) {
|
|
316
|
+
if (Array.isArray(model)) {
|
|
317
|
+
model.forEach(m => acc.add(m))
|
|
318
|
+
} else {
|
|
319
|
+
acc.add(model)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return acc
|
|
323
|
+
}, new Set())
|
|
324
|
+
|
|
325
|
+
const srvModelPaths = [...Object.keys(this.env.requires || {}).reduce((acc, srvName) => {
|
|
326
|
+
const model = this.env.requires[srvName]?.model;
|
|
327
|
+
if (model) {
|
|
328
|
+
if (Array.isArray(model)) {
|
|
329
|
+
model.forEach(m => acc.add(m))
|
|
330
|
+
} else {
|
|
331
|
+
acc.add(model)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return acc
|
|
335
|
+
}, new Set())]
|
|
336
|
+
|
|
337
|
+
const unresolved = resolveRequiredSapModels(this.cds, [...taskModelPaths])
|
|
338
|
+
// are the required service models contained in the task's options.model
|
|
339
|
+
const missing = srvModelPaths.filter(m => m.startsWith('@sap/') && !taskModelPaths.has(m) && !unresolved.find(u => u === m))
|
|
340
|
+
|
|
341
|
+
return { unresolved, missing }
|
|
342
|
+
}
|
|
343
|
+
|
|
296
344
|
/**
|
|
297
345
|
* Returns a sorted and flatend list of all messages extracted from the given errors.
|
|
298
346
|
* @param {Array<Error>} errors
|
|
@@ -81,9 +81,15 @@ class BuildTaskFactory {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// 3. filters the list of build tasks and adapts according to given CLI options
|
|
84
|
+
// Note: A new task will be created if invoked using CLI 'cds build --for <xxx>'
|
|
85
|
+
// where <xxx> matches a valid task type like 'hana', 'java' etc.
|
|
84
86
|
const existingTasks = tasks
|
|
85
87
|
tasks = await this._applyCliTaskOptions(providerFactory, tasks)
|
|
86
88
|
|
|
89
|
+
if (tasks.length === 0) {
|
|
90
|
+
return tasks
|
|
91
|
+
}
|
|
92
|
+
|
|
87
93
|
// 2. add dependencies
|
|
88
94
|
await providerFactory.lookupTasks(tasks)
|
|
89
95
|
|
|
@@ -107,8 +113,10 @@ class BuildTaskFactory {
|
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
_applyCommonTaskDefaults(tasks, buildOptions) {
|
|
116
|
+
const modelPaths = this._getDefaultModelOptions(buildOptions.root)
|
|
117
|
+
|
|
110
118
|
tasks.forEach(task => {
|
|
111
|
-
this.
|
|
119
|
+
this._setTaskModelOptions(task, modelPaths)
|
|
112
120
|
if (!task.src) {
|
|
113
121
|
throw new Error(`Invalid build task definition - value of property 'src' is missing in [${task.for || task.use}].`)
|
|
114
122
|
}
|
|
@@ -137,7 +145,7 @@ class BuildTaskFactory {
|
|
|
137
145
|
_getDefaultModelOptions(projectPath) {
|
|
138
146
|
const fts = this.env.features.folders
|
|
139
147
|
const modelPaths = this.cds.resolve(!fts ? '*' : ['*', fts], false)
|
|
140
|
-
return this._pushModelPaths(projectPath,
|
|
148
|
+
return this._pushModelPaths(projectPath, modelPaths)
|
|
141
149
|
}
|
|
142
150
|
|
|
143
151
|
/**
|
|
@@ -206,16 +214,15 @@ class BuildTaskFactory {
|
|
|
206
214
|
return tasks
|
|
207
215
|
}
|
|
208
216
|
|
|
209
|
-
|
|
217
|
+
_setTaskModelOptions(task, defaultModelPaths) {
|
|
210
218
|
task.options = task.options || {}
|
|
211
219
|
if (!task.options.model || Array.isArray(task.options.model) && task.options.model.length === 0) {
|
|
212
|
-
|
|
220
|
+
defaultModelPaths = new Set(defaultModelPaths)
|
|
213
221
|
if (task.src) {
|
|
214
|
-
|
|
222
|
+
defaultModelPaths.add(task.src)
|
|
215
223
|
}
|
|
216
|
-
task.options.model = [...
|
|
217
|
-
}
|
|
218
|
-
else if (!Array.isArray(task.options.model)) {
|
|
224
|
+
task.options.model = [...defaultModelPaths]
|
|
225
|
+
} else if (!Array.isArray(task.options.model)) {
|
|
219
226
|
task.options.model = [task.options.model]
|
|
220
227
|
}
|
|
221
228
|
}
|
|
@@ -251,8 +258,8 @@ class BuildTaskFactory {
|
|
|
251
258
|
return taskOptions
|
|
252
259
|
}
|
|
253
260
|
|
|
254
|
-
_pushModelPaths(projectPath,
|
|
255
|
-
model = new Set(
|
|
261
|
+
_pushModelPaths(projectPath, ...modelPaths) {
|
|
262
|
+
const model = new Set()
|
|
256
263
|
// may contain nested arrays
|
|
257
264
|
modelPaths = BuildTaskFactory._flatten(modelPaths)
|
|
258
265
|
const { roots } = this.env
|
|
@@ -272,7 +279,7 @@ class BuildTaskFactory {
|
|
|
272
279
|
}
|
|
273
280
|
}
|
|
274
281
|
})
|
|
275
|
-
return
|
|
282
|
+
return model
|
|
276
283
|
}
|
|
277
284
|
|
|
278
285
|
static _flatten(modelPaths) {
|
|
@@ -86,7 +86,7 @@ class BuildTaskHandler {
|
|
|
86
86
|
init() { }
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
* Called by the framework to create the
|
|
89
|
+
* Called by the framework to create the artifacts of this build task handler.
|
|
90
90
|
*/
|
|
91
91
|
async build() {
|
|
92
92
|
throw new TypeError(OVERRIDE_METHOD_MSG)
|
|
@@ -55,7 +55,7 @@ class BuildTaskProviderFactory {
|
|
|
55
55
|
}))
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
async lookupTasks(tasks=[]) {
|
|
58
|
+
async lookupTasks(tasks = []) {
|
|
59
59
|
await Promise.all(this.providers.map(async (provider) => {
|
|
60
60
|
const snapShot = tasks
|
|
61
61
|
await this._lookupTasks(provider, tasks)
|
|
@@ -140,21 +140,11 @@ class BuildTaskProviderFactory {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
async _lookupTasks(provider, tasks) {
|
|
143
|
-
|
|
144
|
-
await provider.lookupTasks(tasks, this.buildOptions)
|
|
145
|
-
} catch (e) {
|
|
146
|
-
this.logger.error(`Build task provider ${provider.constructor.name} returned error:\n` + e)
|
|
147
|
-
throw e
|
|
148
|
-
}
|
|
143
|
+
return provider.lookupTasks(tasks, this.buildOptions)
|
|
149
144
|
}
|
|
150
145
|
|
|
151
146
|
async _applyTaskDefaults(provider, tasks) {
|
|
152
|
-
|
|
153
|
-
return Promise.all(tasks.map(task => provider.applyTaskDefaults(task)))
|
|
154
|
-
} catch (e) {
|
|
155
|
-
this.logger.error(`Build task provider ${provider.constructor.name} returned error:\n` + e)
|
|
156
|
-
throw e
|
|
157
|
-
}
|
|
147
|
+
return Promise.all(tasks.map(task => provider.applyTaskDefaults(task)))
|
|
158
148
|
}
|
|
159
149
|
|
|
160
150
|
_loadProviders() {
|
package/bin/build/constants.js
CHANGED
|
@@ -17,7 +17,6 @@ exports.BUILD_TASK_MTX_SIDECAR = "mtx-sidecar"
|
|
|
17
17
|
exports.BUILD_TASK_MTX_EXTENSION = "mtx-extension"
|
|
18
18
|
exports.BUILD_TASKS = [this.BUILD_TASK_JAVA, this.BUILD_TASK_JAVA_CF, this.BUILD_TASK_NODEJS, this.BUILD_TASK_NODE_CF, this.BUILD_TASK_HANA, this.BUILD_TASK_FIORI, this.BUILD_TASK_MTX, this.BUILD_TASK_MTX_SIDECAR, this.BUILD_TASK_MTX_EXTENSION]
|
|
19
19
|
|
|
20
|
-
exports.ODATA_VERSION = "odata.version"
|
|
21
20
|
exports.ODATA_VERSION_V2 = "v2"
|
|
22
21
|
exports.ODATA_VERSION_V4 = "v4"
|
|
23
22
|
|
package/bin/build/index.js
CHANGED
|
@@ -17,7 +17,6 @@ module.exports = Object.assign(build,
|
|
|
17
17
|
*/
|
|
18
18
|
async function build(options = {}) {
|
|
19
19
|
const projectPath = path.resolve(options.project || '.')
|
|
20
|
-
|
|
21
20
|
if (!fs.lstatSync(projectPath).isDirectory()) {
|
|
22
21
|
return Promise.reject(`Project [${projectPath}] does not exist`)
|
|
23
22
|
}
|
|
@@ -25,15 +24,24 @@ async function build(options = {}) {
|
|
|
25
24
|
const cds = require('./cds')
|
|
26
25
|
if (projectPath !== process.cwd()) {
|
|
27
26
|
const env = cds.env.for('cds', projectPath);
|
|
28
|
-
cds.env = env
|
|
29
|
-
cds.root = projectPath
|
|
27
|
+
cds.env = env // REVISIT: not good / fragile
|
|
28
|
+
cds.root = projectPath // REVISIT: not good / fragile
|
|
30
29
|
}
|
|
31
30
|
const logger = options.logger || cds.log(LOG_MODULE_NAMES)
|
|
32
|
-
|
|
33
31
|
const buildOptions = _mergeCliOptions({ root: projectPath }, options)
|
|
32
|
+
const buildTaskFactory = new BuildTaskFactory(logger)
|
|
33
|
+
const buildTaskEngine = new BuildTaskEngine(logger)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
try {
|
|
36
|
+
const tasks = await buildTaskFactory.getTasks(buildOptions)
|
|
37
|
+
return buildTaskEngine.processTasks(tasks, buildOptions)
|
|
38
|
+
} catch (e) {
|
|
39
|
+
// cds CLI layer logs if invoked from CLI
|
|
40
|
+
if (!buildOptions.cli) {
|
|
41
|
+
buildTaskEngine._logMessages(buildOptions, [e])
|
|
42
|
+
}
|
|
43
|
+
throw e
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
function _mergeCliOptions(buildOptions, options) {
|
|
@@ -50,9 +50,8 @@ class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
|
|
|
50
50
|
return Promise.all(promises)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
_isOdataProtocol(
|
|
54
|
-
|
|
55
|
-
return /^odata/.test(_protocol4Service(service))
|
|
53
|
+
_isOdataProtocol(srv) {
|
|
54
|
+
return this.cds.service.protocols.protocol4(srv).startsWith('odata')
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
_options4odata() {
|
|
@@ -72,7 +72,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
|
|
|
72
72
|
return acc
|
|
73
73
|
}, [])
|
|
74
74
|
|
|
75
|
-
// keep existing
|
|
75
|
+
// keep existing behavior and return paths returned by cds.resolve if features are not supported by this project
|
|
76
76
|
if (!fs.existsSync(path.join(this.buildOptions.root, this.ftsName))) {
|
|
77
77
|
return paths
|
|
78
78
|
}
|
|
@@ -106,7 +106,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
|
|
|
106
106
|
const ftCsn = await this.cds.load(ftsPaths[ftName], options)
|
|
107
107
|
const ftPath = path.join(destFts, this.ftsName, ftName)
|
|
108
108
|
|
|
109
|
-
// replace require paths by base model path to ensure precedence of feature
|
|
109
|
+
// replace require paths by base model path to ensure precedence of feature annotations
|
|
110
110
|
// see https://pages.github.tools.sap/cap/docs/cds/compiler-messages#anno-duplicate-unrelated-layer
|
|
111
111
|
ftCsn.requires = [path.join(path.relative(ftPath, destBase), DEFAULT_CSN_FILE_NAME).replace(/\\/g,'/')]
|
|
112
112
|
|
|
@@ -37,7 +37,7 @@ class BuildTaskHandlerInternal extends BuildTaskHandler {
|
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Custom build handlers are executed before internal handlers in order
|
|
40
|
-
* ensure and content cannot be
|
|
40
|
+
* ensure and content cannot be overwritten by mistake.
|
|
41
41
|
*/
|
|
42
42
|
get priority() {
|
|
43
43
|
return BuildTaskHandlerInternal.PRIORITY_MAX_VALUE
|
|
@@ -140,19 +140,16 @@ class BuildTaskHandlerInternal extends BuildTaskHandler {
|
|
|
140
140
|
* or in a separate staging folder which is not part of the build tasks src folder.
|
|
141
141
|
*/
|
|
142
142
|
isStagingBuild() {
|
|
143
|
-
return this.task.src
|
|
143
|
+
return !this.task.src.startsWith(this.task.dest)
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
async copyNativeContent(srcDir, destDir, customFilter) {
|
|
147
|
-
if (!this.isStagingBuild()) {
|
|
148
|
-
return Promise.resolve()
|
|
149
|
-
}
|
|
150
147
|
const files = BuildTaskHandlerInternal._find(srcDir, (src) => {
|
|
151
148
|
// do not copy files that:
|
|
152
149
|
// - are contained in the 'buildOptions.target' folder
|
|
153
150
|
// - are contained in this modules 'dest' folder
|
|
154
151
|
// - are contained in some generation folder
|
|
155
|
-
// - do NOT
|
|
152
|
+
// - do NOT fulfill additional specific filter criteria
|
|
156
153
|
return this._commonStagingBuildFilter(src, destDir) && (!customFilter || customFilter.call(this, src))
|
|
157
154
|
})
|
|
158
155
|
return Promise.all(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const { hasJavaNature, getProperty, isStreamlinedMtx } = require('../util')
|
|
3
|
+
const { hasJavaNature, getProperty, isStreamlinedMtx, BuildError } = require('../util')
|
|
4
4
|
const BuildTaskProvider = require('../buildTaskProvider')
|
|
5
5
|
|
|
6
6
|
const { FILE_EXT_CDS, BUILD_TASK_HANA, BUILD_TASK_FIORI, BUILD_TASK_JAVA, BUILD_TASK_JAVA_CF, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF, BUILD_TASK_MTX,
|
|
@@ -83,9 +83,15 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
83
83
|
}
|
|
84
84
|
if (Array.isArray(db) && db.length > 0) {
|
|
85
85
|
db = BuildTaskProviderInternal._getModuleFolder(projectPath, db) || null
|
|
86
|
+
if (!db && !addRequiredTasks) { // log once
|
|
87
|
+
this.logger.log("No database module found")
|
|
88
|
+
}
|
|
86
89
|
}
|
|
87
90
|
if (Array.isArray(srv) && srv.length > 0) {
|
|
88
91
|
srv = BuildTaskProviderInternal._getModuleFolder(projectPath, srv) || null
|
|
92
|
+
if (!srv && !addRequiredTasks) { // log once
|
|
93
|
+
this.logger.log("No service module found")
|
|
94
|
+
}
|
|
89
95
|
}
|
|
90
96
|
// create required build tasks
|
|
91
97
|
if (addRequiredTasks) {
|
|
@@ -143,7 +149,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
143
149
|
if (this._useHana(projectPath, buildOptions)) {
|
|
144
150
|
this.logger.debug("found HANA database.")
|
|
145
151
|
// legacy build supports dest property
|
|
146
|
-
const compileDest = this.env.
|
|
152
|
+
const compileDest = this.env.data?.dest
|
|
147
153
|
if (compileDest) {
|
|
148
154
|
//../db/src/gen
|
|
149
155
|
// compileDest is relative to src folder in modular build - resolve correctly
|
|
@@ -163,62 +169,72 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
163
169
|
_useHana(projectPath, buildOptions) {
|
|
164
170
|
if (getProperty(buildOptions, "for.hana.skipManifestGeneration") // deprecated fallback for webide fullstack and mtx
|
|
165
171
|
|| getProperty(buildOptions, "for.hana.contentManifest") === false // fallback for webide fullstack and mtx
|
|
166
|
-
|| this.env.
|
|
167
|
-
|| this.env.
|
|
172
|
+
|| this.env.requires.db?.kind === "hana"
|
|
173
|
+
|| this.env.requires.db?.dialect === "hana") {
|
|
168
174
|
|
|
169
175
|
return true
|
|
170
176
|
}
|
|
171
177
|
// false if other db has been defined
|
|
172
|
-
if (this.env.
|
|
178
|
+
if (this.env.requires.db?.kind) {
|
|
173
179
|
return false
|
|
174
180
|
}
|
|
175
181
|
// check whether cds config represents a legacy build system config for which requires.db was not configured
|
|
176
182
|
// Note: compat layer sets requires.db: {}
|
|
177
183
|
const userEnv = this.cds.env.for("cds", projectPath, false)
|
|
178
|
-
return userEnv && (userEnv.
|
|
184
|
+
return userEnv && (userEnv.data?.model || userEnv.service?.model)
|
|
179
185
|
}
|
|
180
186
|
|
|
181
187
|
_createMtxTask(projectPath, src, dest, tasks) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
188
|
+
// MTX build task creation is NOT supported for Java projects
|
|
189
|
+
if (tasks.find(task => task.for === BUILD_TASK_JAVA || task.for === BUILD_TASK_JAVA_CF)) {
|
|
190
|
+
return null
|
|
191
|
+
}
|
|
186
192
|
this.logger.debug("determining mtx type for nodejs")
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
+
|
|
194
|
+
if (isStreamlinedMtx(this.cds)) {
|
|
195
|
+
if (this.env.requires["cds.xt.ModelProviderService"]?.kind === "rest") { // "cds.xt.ModelProviderService": "from-sidecar"
|
|
196
|
+
this.logger.debug("Nodejs Streamlined MTX app with sidecar")
|
|
197
|
+
|
|
198
|
+
const sidecarPath = path.join(projectPath, MTX_SIDECAR_FOLDER)
|
|
199
|
+
if (!fs.existsSync(sidecarPath)) {
|
|
200
|
+
throw new BuildError("CDS build failed", `MTX sidecar directory '${sidecarPath}' not existing. Custom build task configuration necessary if the folder is named differently.`)
|
|
201
|
+
}
|
|
202
|
+
const sidecarEnv = this.env.for("cds", sidecarPath)
|
|
203
|
+
if (sidecarEnv.requires["cds.xt.ModelProviderService"]?.kind === "in-sidecar") {
|
|
204
|
+
return {
|
|
193
205
|
for: BUILD_TASK_MTX_SIDECAR
|
|
194
206
|
}
|
|
195
|
-
this.logger.debug(`${isJava ? "Java" : "Nodejs"} MTX sidecar scenario`)
|
|
196
|
-
} else {
|
|
197
|
-
throw Error(`MTX sidecar module '${MTX_SIDECAR_FOLDER}' not found`)
|
|
198
207
|
}
|
|
199
|
-
|
|
200
|
-
task = {
|
|
201
|
-
for: BUILD_TASK_MTX,
|
|
202
|
-
src
|
|
203
|
-
}
|
|
204
|
-
this.logger.debug("Nodejs MTX scenario without sidecar")
|
|
208
|
+
throw new BuildError("CDS build failed", 'Invalid MTX sidecar configuration. Make sure to add required service "cds.xt.ModelProviderService": "in-sidecar".')
|
|
205
209
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
|
|
211
|
+
if (this.env.requires["cds.xt.ModelProviderService"]?.kind === "in-sidecar") {
|
|
212
|
+
// cds build is executed in sidecar folder
|
|
213
|
+
throw new BuildError("CDS build failed", "Invalid working directory. Make sure to execute 'cds build' in CAP project root directory.")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.logger.debug("Nodejs Streamlined MTX app without sidecar")
|
|
217
|
+
return {
|
|
218
|
+
for: BUILD_TASK_MTX,
|
|
219
|
+
src
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (BuildTaskProviderInternal._isExtension(this.env)) {
|
|
224
|
+
this.logger.debug("Streamlined MTX extension app")
|
|
225
|
+
return {
|
|
209
226
|
for: BUILD_TASK_MTX_EXTENSION
|
|
210
227
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (this.env.requires.multitenancy) {
|
|
231
|
+
this.logger.debug("Nodejs Classic MTX app without sidecar")
|
|
232
|
+
return {
|
|
215
233
|
src: ".",
|
|
216
234
|
for: BUILD_TASK_MTX,
|
|
217
235
|
dest
|
|
218
236
|
}
|
|
219
|
-
this.logger.debug("classic Nodejs MTX scenario")
|
|
220
237
|
}
|
|
221
|
-
return task
|
|
222
238
|
}
|
|
223
239
|
|
|
224
240
|
_createSrvTask(projectPath, src, taskOptions) {
|
|
@@ -238,7 +254,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
238
254
|
_createJavaTask(projectPath, src, taskOptions) {
|
|
239
255
|
this.logger.debug("found implementation technology java")
|
|
240
256
|
// legacy build supports dest property
|
|
241
|
-
const compileDest = this.env.
|
|
257
|
+
const compileDest = this.env.service?.dest
|
|
242
258
|
if (compileDest) {
|
|
243
259
|
// compileDest is relative to src folder in modular build - resolve correctly
|
|
244
260
|
taskOptions.compileDest = path.relative(path.resolve(projectPath, src), path.resolve(projectPath, compileDest))
|
|
@@ -259,10 +275,6 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
259
275
|
}
|
|
260
276
|
}
|
|
261
277
|
|
|
262
|
-
static _isSidecar(env) {
|
|
263
|
-
return env.requires['cds.xt.ModelProviderService']?.kind === "in-sidecar"
|
|
264
|
-
}
|
|
265
|
-
|
|
266
278
|
static _isExtension(env) {
|
|
267
279
|
return !!env.extends
|
|
268
280
|
}
|
|
@@ -3,7 +3,7 @@ const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
|
3
3
|
const URL = require('url')
|
|
4
4
|
const { getProperty, isOldJavaStack, relativePaths } = require('../../util')
|
|
5
5
|
|
|
6
|
-
const {
|
|
6
|
+
const { ODATA_VERSION_V2, BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY, BUILD_TASK_FIORI, BUILD_TASK_JAVA_CF, CDS_CONFIG_PATH_SEP, BUILD_TASK_JAVA } = require('../../constants')
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* With cds 4 service metadata for the UI service binding is no longer created by default.
|
|
@@ -44,14 +44,14 @@ class FioriAppModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
44
44
|
fioriBuildOptions[BUILD_OPTION_OUTPUT_MODE] = OUTPUT_MODE_RESULT_ONLY
|
|
45
45
|
|
|
46
46
|
try {
|
|
47
|
-
const edmxOptions = { version: this.env.
|
|
47
|
+
const edmxOptions = { version: this.env.odata?.version }
|
|
48
48
|
|
|
49
49
|
if (edmxOptions.version !== ODATA_VERSION_V2) {
|
|
50
50
|
const javaTask = this.buildOptions.tasks.find(task => task.for === BUILD_TASK_JAVA_CF || task.for === BUILD_TASK_JAVA)
|
|
51
51
|
|
|
52
52
|
if (javaTask
|
|
53
53
|
&& await isOldJavaStack([javaTask.src, this.buildOptions.root])
|
|
54
|
-
&& !this.env.for("cds", this.buildOptions.root, false).
|
|
54
|
+
&& !this.env.for("cds", this.buildOptions.root, false).odata?.version) {
|
|
55
55
|
|
|
56
56
|
// old java stack
|
|
57
57
|
// default is now v4 and not v2 anymore, so overwrite with v2 if using default
|
|
@@ -97,7 +97,7 @@ function _getNewMigrationEntry(changeset, currentVersion) {
|
|
|
97
97
|
if (changeset && changeset.length > 0) {
|
|
98
98
|
const dropColumns = changeset.some(e => e.drop)
|
|
99
99
|
const manualChange = changeset.some(e => !e.sql)
|
|
100
|
-
const enableDrop = cds.env.
|
|
100
|
+
const enableDrop = cds.env.hana?.journal?.['enable-drop']
|
|
101
101
|
const content = changeset.reduce((acc, e) => {
|
|
102
102
|
if (!acc) {
|
|
103
103
|
acc = `== migration=${currentVersion + 1}\n`
|