@sap/cds 6.8.4 → 7.0.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 +58 -5
- package/README.md +0 -1
- package/bin/cds-serve.js +50 -3
- package/bin/deploy/to-hana.js +1 -0
- package/bin/serve.js +16 -20
- package/lib/auth/basic-auth.js +6 -4
- package/lib/auth/index.js +4 -3
- package/lib/auth/jwt-auth.js +2 -5
- package/lib/compile/cds-compile.js +34 -89
- package/lib/compile/cdsc.js +11 -0
- package/lib/compile/etc/properties.js +2 -2
- package/lib/compile/for/lean_drafts.js +36 -69
- package/lib/compile/for/nodejs.js +2 -1
- package/lib/compile/load.js +1 -1
- package/lib/compile/minify.js +2 -0
- package/lib/compile/to/csn.js +74 -0
- package/{bin/build/provider/hana/2tabledata.js → lib/compile/to/hdbtabledata.js} +4 -6
- package/lib/compile/to/json.js +1 -1
- package/lib/compile/to/sql.js +8 -6
- package/lib/dbs/cds-deploy.js +174 -114
- package/lib/env/cds-env.js +64 -79
- package/lib/env/cds-requires.js +11 -28
- package/lib/env/defaults.js +13 -3
- package/lib/env/plugins.js +1 -12
- package/lib/env/presets.js +25 -21
- package/lib/index.js +121 -147
- package/lib/{core/reflect.js → linked/models.js} +2 -2
- package/lib/{core/infer.js → linked/queries.js} +2 -0
- package/lib/{core/index.js → linked/types.js} +2 -1
- package/lib/log/cds-error.js +13 -7
- package/lib/log/format/cf.js +1 -1
- package/lib/plugins.js +49 -0
- package/lib/ql/Query.js +0 -9
- package/lib/ql/STREAM.js +0 -1
- package/lib/req/context.js +2 -7
- package/lib/req/request.js +6 -2
- package/lib/req/response.js +23 -10
- package/lib/srv/middlewares/ctx-model.js +1 -1
- package/lib/srv/middlewares/errors.js +1 -1
- package/lib/srv/protocols/_legacy.js +1 -0
- package/lib/srv/protocols/graphql.js +7 -16
- package/lib/srv/protocols/index.js +59 -45
- package/lib/srv/protocols/odata-v2-proxy.js +2 -70
- package/lib/srv/srv-api.js +9 -3
- package/lib/srv/srv-dispatch.js +12 -9
- package/lib/srv/srv-models.js +4 -21
- package/lib/srv/srv-tx.js +15 -12
- package/lib/utils/cds-test.js +14 -9
- package/lib/utils/cds-utils.js +2 -12
- package/lib/utils/check-version.js +17 -0
- package/{bin/build → lib/utils}/csv-reader.js +23 -24
- package/libx/_runtime/auth/index.js +27 -23
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +15 -72
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +0 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +33 -63
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +14 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +5 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +37 -40
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +7 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +101 -38
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/AbstractError.js +5 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +2 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +9 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +15 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +4 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +5 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +1 -123
- package/libx/_runtime/cds-services/services/Service.js +79 -107
- package/libx/_runtime/cds-services/services/utils/columns.js +23 -19
- package/libx/_runtime/cds-services/services/utils/compareJson.js +11 -1
- package/libx/_runtime/cds-services/services/utils/differ.js +7 -2
- package/libx/_runtime/cds-services/util/assert.js +65 -2
- package/libx/_runtime/common/composition/data.js +1 -0
- package/libx/_runtime/common/generic/auth/expand.js +1 -1
- package/libx/_runtime/common/generic/auth/restrict.js +5 -10
- package/libx/_runtime/common/generic/auth/restrictions.js +40 -0
- package/libx/_runtime/common/generic/auth/utils.js +1 -2
- package/libx/_runtime/common/generic/crud.js +32 -16
- package/libx/_runtime/common/generic/etag.js +133 -104
- package/libx/_runtime/common/generic/input.js +6 -21
- package/libx/_runtime/common/generic/put.js +1 -1
- package/libx/_runtime/common/generic/stream.js +52 -0
- package/libx/_runtime/common/generic/temporal.js +25 -8
- package/libx/_runtime/common/i18n/messages.properties +0 -2
- package/libx/_runtime/common/utils/cqn.js +1 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +5 -2
- package/libx/_runtime/common/utils/csn.js +0 -51
- package/libx/_runtime/common/utils/etag.js +30 -0
- package/libx/_runtime/common/utils/keys.js +1 -1
- package/libx/_runtime/common/utils/normalizeTimestamp.js +25 -0
- package/libx/_runtime/common/utils/path.js +1 -1
- package/libx/_runtime/common/utils/resolveView.js +2 -1
- package/libx/_runtime/common/utils/rewriteAsterisks.js +6 -4
- package/libx/_runtime/common/utils/search2cqn4sql.js +12 -16
- package/libx/_runtime/common/utils/stream.js +140 -0
- package/libx/_runtime/common/utils/streamProp.js +29 -12
- package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +0 -2
- package/libx/_runtime/db/generic/index.js +0 -2
- package/libx/_runtime/db/query/delete.js +2 -2
- package/libx/_runtime/db/query/insert.js +2 -2
- package/libx/_runtime/db/query/read.js +2 -2
- package/libx/_runtime/db/query/run.js +2 -2
- package/libx/_runtime/db/query/update.js +2 -2
- package/libx/_runtime/db/sql-builder/BaseBuilder.js +0 -6
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +23 -12
- package/libx/_runtime/db/sql-builder/FunctionBuilder.js +18 -6
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -7
- package/libx/_runtime/db/sql-builder/UpsertBuilder.js +1 -0
- package/libx/_runtime/db/utils/normalizeTimeData.js +7 -3
- package/libx/_runtime/fiori/draft.js +2 -0
- package/libx/_runtime/fiori/generic/activate.js +8 -9
- package/libx/_runtime/fiori/generic/before.js +30 -20
- package/libx/_runtime/fiori/generic/cancel.js +5 -3
- package/libx/_runtime/fiori/generic/delete.js +5 -3
- package/libx/_runtime/fiori/generic/edit.js +7 -7
- package/libx/_runtime/fiori/generic/index.js +10 -16
- package/libx/_runtime/fiori/generic/new.js +5 -3
- package/libx/_runtime/fiori/generic/patch.js +11 -8
- package/libx/_runtime/fiori/generic/prepare.js +13 -6
- package/libx/_runtime/fiori/generic/read.js +12 -6
- package/libx/_runtime/fiori/lean-draft.js +207 -152
- package/libx/_runtime/fiori/utils/delete.js +10 -5
- package/libx/_runtime/fiori/utils/req.js +17 -5
- package/libx/_runtime/fiori/utils/stream.js +36 -0
- package/libx/_runtime/hana/Service.js +12 -9
- package/libx/_runtime/hana/conversion.js +10 -15
- package/libx/_runtime/hana/driver.js +2 -0
- package/libx/_runtime/hana/execute.js +28 -6
- package/libx/_runtime/hana/pool.js +36 -122
- package/libx/_runtime/hana/search2cqn4sql.js +34 -36
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -6
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +3 -1
- package/libx/_runtime/messaging/enterprise-messaging.js +10 -58
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/remote/Service.js +20 -1
- package/libx/_runtime/remote/utils/client.js +3 -5
- package/libx/_runtime/sqlite/Service.js +4 -6
- package/libx/_runtime/sqlite/conversion.js +3 -13
- package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +9 -6
- package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +6 -1
- package/libx/_runtime/sqlite/execute.js +5 -16
- package/libx/odata/afterburner.js +22 -6
- package/libx/odata/grammar.pegjs +6 -1
- package/libx/odata/parser.js +1 -1
- package/libx/rest/RestAdapter.js +16 -9
- package/libx/rest/RestRequest.js +1 -1
- package/libx/rest/middleware/input.js +2 -1
- package/libx/rest/middleware/operation.js +1 -0
- package/libx/rest/middleware/parse.js +3 -2
- package/libx/rest/middleware/payload.js +9 -8
- package/libx/rest/middleware/read.js +1 -0
- package/package.json +9 -16
- package/app/fiori/preview.js +0 -270
- package/app/fiori/routes.js +0 -59
- package/bin/build/buildTaskEngine.js +0 -360
- package/bin/build/buildTaskFactory.js +0 -283
- package/bin/build/buildTaskHandler.js +0 -241
- package/bin/build/buildTaskProvider.js +0 -22
- package/bin/build/buildTaskProviderFactory.js +0 -175
- package/bin/build/cds.js +0 -5
- package/bin/build/constants.js +0 -66
- package/bin/build/index.js +0 -58
- package/bin/build/provider/buildTaskHandlerEdmx.js +0 -82
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +0 -131
- package/bin/build/provider/buildTaskHandlerInternal.js +0 -254
- package/bin/build/provider/buildTaskProviderInternal.js +0 -383
- package/bin/build/provider/fiori/index.js +0 -171
- package/bin/build/provider/hana/2migration.js +0 -179
- package/bin/build/provider/hana/index.js +0 -505
- package/bin/build/provider/hana/migrationtable.js +0 -472
- package/bin/build/provider/hana/template/.hdiconfig-haas +0 -163
- package/bin/build/provider/hana/template/.hdiconfig-hanacloud +0 -137
- package/bin/build/provider/hana/template/.hdinamespace +0 -4
- package/bin/build/provider/hana/template/package.json +0 -12
- package/bin/build/provider/hana/template/undeploy.json +0 -5
- package/bin/build/provider/java/index.js +0 -111
- package/bin/build/provider/java-cf/index.js +0 -1
- package/bin/build/provider/mtx/index.js +0 -268
- package/bin/build/provider/mtx/resourcesTarBuilder.js +0 -95
- package/bin/build/provider/mtx-extension/index.js +0 -131
- package/bin/build/provider/mtx-sidecar/index.js +0 -137
- package/bin/build/provider/node-cf/index.js +0 -1
- package/bin/build/provider/nodejs/index.js +0 -192
- package/bin/build/util.js +0 -299
- package/bin/cds.js +0 -125
- package/bin/deploy/to-hana/cfUtil.js +0 -355
- package/bin/deploy/to-hana/gitUtil.js +0 -57
- package/bin/deploy/to-hana/hana.js +0 -306
- package/bin/deploy/to-hana/hdiDeployUtil.js +0 -153
- package/bin/deploy/to-hana/index.js +0 -16
- package/bin/deploy/to-hana/mtaUtil.js +0 -170
- package/bin/mtx/in-cds.js +0 -17
- package/bin/plugins.js +0 -32
- package/bin/run.js +0 -24
- package/bin/utils/log.js +0 -24
- package/bin/version.js +0 -178
- package/libx/_runtime/audit/Service.js +0 -222
- package/libx/_runtime/audit/generic/personal/access.js +0 -61
- package/libx/_runtime/audit/generic/personal/index.js +0 -56
- package/libx/_runtime/audit/generic/personal/modification.js +0 -132
- package/libx/_runtime/audit/generic/personal/utils.js +0 -186
- package/libx/_runtime/audit/utils/log.js +0 -23
- package/libx/_runtime/audit/utils/v2.js +0 -176
- package/libx/_runtime/db/data-conversion/timestamp.js +0 -9
- package/libx/_runtime/db/generic/integrity.js +0 -455
- package/srv/audit-log.cds +0 -87
- package/srv/mtx.cds +0 -2
- package/srv/mtx.js +0 -8
- /package/lib/{core → linked}/classes.js +0 -0
- /package/lib/{core → linked}/entities.js +0 -0
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const cds = require('./cds'), { log } = cds.exec
|
|
4
|
-
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
5
|
-
const { hasJavaNature, getProperty, redactCredentials, flatten, getDefaultModelOptions } = require('./util')
|
|
6
|
-
const { FILE_EXT_CDS, BUILD_TASK_JAVA_CF, LOG_MODULE_NAMES, BUILD_TASK_JAVA } = require("./constants")
|
|
7
|
-
|
|
8
|
-
class BuildTaskFactory {
|
|
9
|
-
constructor(logger) {
|
|
10
|
-
this._logger = logger || cds.log(LOG_MODULE_NAMES)
|
|
11
|
-
}
|
|
12
|
-
get logger() {
|
|
13
|
-
return this._logger
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// the following order for determining build tasks is used
|
|
17
|
-
// 1. create from command line input, e.g. cds build/all --for hana --src db --model srv --dest db
|
|
18
|
-
// 2. read using cds.env.build.tasks
|
|
19
|
-
// 3. create from cds.env.folders config data
|
|
20
|
-
async getTasks(buildOptions = { root: process.env._TEST_CWD || process.cwd() }) {
|
|
21
|
-
try {
|
|
22
|
-
const providerFactory = new BuildTaskProviderFactory(this._logger, buildOptions)
|
|
23
|
-
const tasks = await this._createTasks(providerFactory)
|
|
24
|
-
buildOptions.target = path.resolve(buildOptions.root, cds.env.build.target)
|
|
25
|
-
|
|
26
|
-
// log build tasks
|
|
27
|
-
this.logger.log(`the following build tasks will be executed`)
|
|
28
|
-
let tasksOutput = " {\n \"build\": {\n \"target\": \"" + cds.env.build.target + "\",\n \"tasks\": ["
|
|
29
|
-
for (let i = 0; i < tasks.length; i++) {
|
|
30
|
-
tasksOutput += "\n " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? "," : "")
|
|
31
|
-
}
|
|
32
|
-
tasksOutput += "\n ]\n }\n }\n"
|
|
33
|
-
this.logger.log(tasksOutput)
|
|
34
|
-
|
|
35
|
-
// for testing purposes
|
|
36
|
-
this.logger.debug("cds.env used for build:")
|
|
37
|
-
this.logger._debug && this.logger.debug(redactCredentials(cds.env))
|
|
38
|
-
|
|
39
|
-
// always resolve tasks for input validation
|
|
40
|
-
if (buildOptions.resolve || buildOptions.cli) {
|
|
41
|
-
const resolvedTasks = providerFactory.resolveTasks(tasks)
|
|
42
|
-
if (buildOptions.resolve) {
|
|
43
|
-
return resolvedTasks
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return tasks
|
|
47
|
-
} catch (e) {
|
|
48
|
-
this.logger.log('')
|
|
49
|
-
// cds CLI layer is doing the logging if invoked using CLI
|
|
50
|
-
if (!buildOptions.cli) {
|
|
51
|
-
log(e, { withStack: true, log: (message) => this.logger.log(message) })
|
|
52
|
-
}
|
|
53
|
-
throw e
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async _createTasks(providerFactory) {
|
|
58
|
-
const buildOptions = providerFactory.buildOptions
|
|
59
|
-
this.logger.debug(`determining build tasks for project [${buildOptions.root}].`)
|
|
60
|
-
|
|
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 = {}
|
|
64
|
-
|
|
65
|
-
let tasks = BuildTaskFactory._getExistingTasks()
|
|
66
|
-
if (tasks.length === 0) {
|
|
67
|
-
tasks = await providerFactory.lookupTasks()
|
|
68
|
-
await providerFactory.applyTaskDefaults(tasks)
|
|
69
|
-
} else {
|
|
70
|
-
// 1. apply default values including task.for and task.use and ensure that for all tasks a provider exists - throwing error otherwise
|
|
71
|
-
await providerFactory.applyTaskDefaults(tasks)
|
|
72
|
-
await providerFactory.lookupTasks(tasks)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 3. filters the list of build tasks and adapts according to given CLI options
|
|
76
|
-
// Note: A new task will be created if invoked using CLI 'cds build --for <xxx>'
|
|
77
|
-
// where <xxx> matches a valid task type like 'hana', 'java' etc.
|
|
78
|
-
const existingTasks = tasks
|
|
79
|
-
tasks = await BuildTaskFactory._applyCliTaskOptions(providerFactory, tasks)
|
|
80
|
-
|
|
81
|
-
if (tasks.length === 0) {
|
|
82
|
-
return tasks
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 2. add dependencies
|
|
86
|
-
await providerFactory.lookupTasks(tasks)
|
|
87
|
-
|
|
88
|
-
if (tasks !== existingTasks && tasks.some(task => !existingTasks.find(existingTask => existingTask === task))) {
|
|
89
|
-
// a different task shall be executed
|
|
90
|
-
await providerFactory.applyTaskDefaults(tasks)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// obligatory task defaults shared by all tasks
|
|
94
|
-
BuildTaskFactory._applyCommonTaskDefaults(tasks, buildOptions)
|
|
95
|
-
|
|
96
|
-
// ensure correct values for optional build task properties, error for missing mandatory properties
|
|
97
|
-
BuildTaskFactory._validateBuildTasks(tasks)
|
|
98
|
-
|
|
99
|
-
this._setDefaultBuildTargetFolder(tasks, buildOptions)
|
|
100
|
-
return tasks
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
static _getExistingTasks() {
|
|
104
|
-
return Array.isArray(getProperty(cds.env, 'build.tasks')) ? JSON.parse(JSON.stringify(cds.env.build.tasks)) : []
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
static _applyCommonTaskDefaults(tasks, buildOptions) {
|
|
108
|
-
const modelPaths = getDefaultModelOptions(buildOptions.root)
|
|
109
|
-
|
|
110
|
-
tasks.forEach(task => {
|
|
111
|
-
this._setTaskModelOptions(task, modelPaths)
|
|
112
|
-
if (!task.src) {
|
|
113
|
-
throw new Error(`Invalid build task definition - value of property 'src' is missing in [${task.for || task.use}].`)
|
|
114
|
-
}
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
static _validateBuildTasks(tasks) {
|
|
119
|
-
tasks.forEach(task => {
|
|
120
|
-
if (!task.src) {
|
|
121
|
-
throw new Error(`Invalid build task definition - value of property 'src' is missing in [${task.for || task.use}].`)
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
_setDefaultBuildTargetFolder(tasks, buildOptions) {
|
|
127
|
-
const task = tasks.find(task => task.for === BUILD_TASK_JAVA_CF || task.for === BUILD_TASK_JAVA)
|
|
128
|
-
const srv = task ? task.src : BuildTaskFactory._getModuleFolder(buildOptions.root, flatten([cds.env.folders.srv])) || "srv"
|
|
129
|
-
|
|
130
|
-
// Java projects use "." as the default build target folder
|
|
131
|
-
if (BuildTaskFactory._hasJavaNature(buildOptions.root, srv) && BuildTaskFactory._adaptBuildTargetSettingForJava(buildOptions.root)) {
|
|
132
|
-
this.logger.debug("using inplace build for java project instead of default staging build")
|
|
133
|
-
}
|
|
134
|
-
buildOptions.target = path.resolve(buildOptions.root, cds.env.build.target)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Returns whether this project is a java project or not.
|
|
139
|
-
* @param {string} projectPath - the absolute project path
|
|
140
|
-
* @param {string} src - the folder name of the service module
|
|
141
|
-
*/
|
|
142
|
-
static _hasJavaNature(projectPath, src) {
|
|
143
|
-
return hasJavaNature([path.join(projectPath, src), projectPath])
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Use inplace build for java projects if build.target has not been configured.
|
|
148
|
-
* @param {string} projectPath
|
|
149
|
-
* @returns {boolean} true if changed, false otherwise
|
|
150
|
-
*/
|
|
151
|
-
static _adaptBuildTargetSettingForJava(projectPath) {
|
|
152
|
-
if (cds.env.build.target !== ".") {
|
|
153
|
-
// filter user settings of cds.env
|
|
154
|
-
const userEnv = cds.env.for("cds", projectPath, false)
|
|
155
|
-
|
|
156
|
-
// use helper as env.build might be undefined
|
|
157
|
-
if (!getProperty(userEnv, "build.target")) {
|
|
158
|
-
cds.env.build.target = "."
|
|
159
|
-
return true
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return false
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
static async _applyCliTaskOptions(providerFactory, tasks) {
|
|
166
|
-
const { buildOptions } = providerFactory
|
|
167
|
-
if (buildOptions.cmdOptions) {
|
|
168
|
-
const options = buildOptions.cmdOptions
|
|
169
|
-
|
|
170
|
-
// filter tasks using either option for, use, src
|
|
171
|
-
tasks = tasks.filter(task => {
|
|
172
|
-
return (!options.use || options.use === task.use)
|
|
173
|
-
&& (!options.for || options.for === task.for)
|
|
174
|
-
&& (!options.src || options.src === task.src)
|
|
175
|
-
})
|
|
176
|
-
if (tasks.length === 0 && (options.for || options.use)) {
|
|
177
|
-
const task = {}
|
|
178
|
-
if ((options.for)) {
|
|
179
|
-
task.for = options.for
|
|
180
|
-
}
|
|
181
|
-
if ((options.use)) {
|
|
182
|
-
task.use = options.use
|
|
183
|
-
}
|
|
184
|
-
if (options.src) {
|
|
185
|
-
task.src = options.src
|
|
186
|
-
}
|
|
187
|
-
tasks.push(task)
|
|
188
|
-
}
|
|
189
|
-
// apply remaining cli options to filtered tasks
|
|
190
|
-
tasks.forEach(task => {
|
|
191
|
-
if (options.dest) {
|
|
192
|
-
task.dest = options.dest
|
|
193
|
-
}
|
|
194
|
-
if (options.opts) {
|
|
195
|
-
const opts = this._scanTaskOptionParams(options.opts)
|
|
196
|
-
task.options = task.options ? Object.assign(task.options, opts) : opts
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
}
|
|
200
|
-
return tasks
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
static _setTaskModelOptions(task, defaultModelPaths) {
|
|
204
|
-
task.options = task.options || {}
|
|
205
|
-
if (!task.options.model || Array.isArray(task.options.model) && task.options.model.length === 0) {
|
|
206
|
-
defaultModelPaths = new Set(defaultModelPaths)
|
|
207
|
-
if (task.src) {
|
|
208
|
-
defaultModelPaths.add(task.src)
|
|
209
|
-
}
|
|
210
|
-
task.options.model = [...defaultModelPaths]
|
|
211
|
-
} else if (!Array.isArray(task.options.model)) {
|
|
212
|
-
task.options.model = [task.options.model]
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
static _stringifyTask(task) {
|
|
217
|
-
// ensures identical order of properties
|
|
218
|
-
const order = ["for", "use", "src", "dest", "options"]
|
|
219
|
-
const keys = Object.keys(task).sort((a, b) => order.indexOf(a) - order.indexOf(b))
|
|
220
|
-
|
|
221
|
-
return keys.reduce((acc, key, idx) => {
|
|
222
|
-
// render either "for" OR "use" value
|
|
223
|
-
return acc + (!key.match("^_") ? (key !== "use" || keys[idx - 1] !== "for" ? (acc !== "{" ? ", " : "") + JSON.stringify(key) + ":" + JSON.stringify(task[key]) : "") : "")
|
|
224
|
-
}, "{") + "}"
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
static _scanTaskOptionParams(optsParams) {
|
|
228
|
-
// need to create new regex every call since a constant would keep the match state
|
|
229
|
-
const quoteRegex = /([\w-]+)=([\w/.]+|\[([\w/,.]+)\])/g
|
|
230
|
-
|
|
231
|
-
// captures a=1 => a:1
|
|
232
|
-
// a=[x,y,z] => a:[x,y,z]
|
|
233
|
-
// a=1,b=[x,y,z] => a:1 b=[x,y,z]
|
|
234
|
-
let match = quoteRegex.exec(optsParams)
|
|
235
|
-
const taskOptions = {}
|
|
236
|
-
|
|
237
|
-
while (match != null) {
|
|
238
|
-
const key = match[1]
|
|
239
|
-
const value = match[3] || match[2]
|
|
240
|
-
const valueArray = value.split(",")
|
|
241
|
-
taskOptions[key] = valueArray.length > 1 ? valueArray.map((entry) => entry.trim()) : value
|
|
242
|
-
match = quoteRegex.exec(optsParams)
|
|
243
|
-
}
|
|
244
|
-
return taskOptions
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* For valid paths remove trailing '/'. Otherwise return as is - important!!
|
|
249
|
-
* @param {*} dir
|
|
250
|
-
*/
|
|
251
|
-
static _normalizePath(dir) {
|
|
252
|
-
return typeof dir === "string" ? dir.replace(/\/$/, '') : dir
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Determines the module folder from the past list that may represent files or folders w or w/o .cds file extension.
|
|
257
|
-
* @param {string} projectPath
|
|
258
|
-
* @param {Array} filesOrFolders
|
|
259
|
-
*/
|
|
260
|
-
static _getModuleFolder(projectPath, filesOrFolders) {
|
|
261
|
-
const resources = [...filesOrFolders]
|
|
262
|
-
filesOrFolders.forEach(fileOrFolder => {
|
|
263
|
-
if (path.extname(fileOrFolder) !== FILE_EXT_CDS) {
|
|
264
|
-
resources.push(fileOrFolder + FILE_EXT_CDS)
|
|
265
|
-
}
|
|
266
|
-
})
|
|
267
|
-
return resources.reduce((acc, resource) => {
|
|
268
|
-
if (!acc) {
|
|
269
|
-
let resourcePath = path.resolve(projectPath, resource)
|
|
270
|
-
if (fs.existsSync(resourcePath)) {
|
|
271
|
-
if (fs.lstatSync(resourcePath).isDirectory()) {
|
|
272
|
-
acc = resource
|
|
273
|
-
} else {
|
|
274
|
-
// represents file
|
|
275
|
-
acc = path.dirname(resource)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
return acc
|
|
280
|
-
}, null)
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
module.exports = BuildTaskFactory
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const fs = require('fs').promises
|
|
3
|
-
const cds = require('./cds')
|
|
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')
|
|
6
|
-
const { hasOptionValue, getProperty, relativePaths, copy, BuildMessage } = require('./util')
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The build task handler creates the build output for a dedicated build task. It is uniquely identified
|
|
10
|
-
* by the build task's <code>use</code> property. It represents the fully qualified node module path
|
|
11
|
-
* of the build task handler implementation.
|
|
12
|
-
* <p>
|
|
13
|
-
* The build task engine defines the following protocol. The methods are invoked in descending order:
|
|
14
|
-
* <ul>
|
|
15
|
-
* <li>init() - optional</li>
|
|
16
|
-
* <li>get priority() - optional</li>
|
|
17
|
-
* <li>async clean()</li>
|
|
18
|
-
* <li>async build()</li>
|
|
19
|
-
* </ul>
|
|
20
|
-
* The reflected CSN can be accessed using the async method <code>model()</code>.
|
|
21
|
-
*/
|
|
22
|
-
class BuildTaskHandler {
|
|
23
|
-
/**
|
|
24
|
-
* @class
|
|
25
|
-
*/
|
|
26
|
-
constructor() {
|
|
27
|
-
if (new.target === BuildTaskHandler) {
|
|
28
|
-
throw new TypeError("Cannot construct BuildTaskHandler instances directly");
|
|
29
|
-
}
|
|
30
|
-
this._written = new Set()
|
|
31
|
-
this._messages = []
|
|
32
|
-
//injected by framework
|
|
33
|
-
this._task
|
|
34
|
-
this._buildOptions
|
|
35
|
-
}
|
|
36
|
-
static get INFO() {
|
|
37
|
-
return SEVERITY_INFO
|
|
38
|
-
}
|
|
39
|
-
static get WARNING() {
|
|
40
|
-
return SEVERITY_WARNING
|
|
41
|
-
}
|
|
42
|
-
static get ERROR() {
|
|
43
|
-
return SEVERITY_ERROR
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Returns the build task executed by this build task handler.
|
|
47
|
-
* @return {object}
|
|
48
|
-
*/
|
|
49
|
-
get task() {
|
|
50
|
-
//injected by framework
|
|
51
|
-
return this._task
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Returns the message object to add build task specific messages. Severity 'Info', 'Warning', and 'Error' are supported.
|
|
56
|
-
* @return {Array}
|
|
57
|
-
*/
|
|
58
|
-
get messages() {
|
|
59
|
-
return this._messages
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Returns the list of files written by this build task handler of current CDS build execution.
|
|
64
|
-
* @return {Array}
|
|
65
|
-
*/
|
|
66
|
-
get files() {
|
|
67
|
-
return [...this._written]
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Returns the priority of this handler as number, where 0 represents the minimum value and
|
|
72
|
-
* Number.MAX_SAFE_INTEGER the maximum value.
|
|
73
|
-
* Positive numbers mean higher and negative numbers lower priority. Build task handlers
|
|
74
|
-
* with higher priority value are executed before handlers with lower priority.
|
|
75
|
-
* <br>
|
|
76
|
-
* Note: Currently not supported for custom build task handlers as they are always executed
|
|
77
|
-
* before the built-in handlers.
|
|
78
|
-
* @return {number} the priority for this handler as integer.
|
|
79
|
-
*/
|
|
80
|
-
get priority() {
|
|
81
|
-
return 1
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Called by the framework immediately after this instance has been created.
|
|
85
|
-
* The instance has already been fully initialized.
|
|
86
|
-
*/
|
|
87
|
-
init() { }
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Called by the framework to create the artifacts of this build task handler.
|
|
91
|
-
*/
|
|
92
|
-
async build() {
|
|
93
|
-
throw new TypeError(OVERRIDE_METHOD_MSG)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Called by the framework immediately before 'build' to delete any output created by this build task handler.
|
|
98
|
-
* <p>
|
|
99
|
-
* Note: The <code>BuildTaskEngine</code> is cleaning the common generation target folder if the build is
|
|
100
|
-
* executed in staging mode, e.g. build.target: "gen".
|
|
101
|
-
*/
|
|
102
|
-
async clean() {
|
|
103
|
-
throw new TypeError(OVERRIDE_METHOD_MSG)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Asynchronously write the given content to a given file path.
|
|
108
|
-
* If the file exists the content is replaced. If the file does not exist, a new file will be created.
|
|
109
|
-
* The file name is stored in the list of files written by this build task handler.
|
|
110
|
-
* @param {string} dest - absolute or relative file path. Relative paths will be resolved to this task's destination path.
|
|
111
|
-
* @param {any} data - If data is of type object the JSON-stringified version is written.
|
|
112
|
-
*/
|
|
113
|
-
write(data) {
|
|
114
|
-
return {
|
|
115
|
-
to: async (dest) => {
|
|
116
|
-
if (!this._hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
|
|
117
|
-
if (!path.isAbsolute(dest)) {
|
|
118
|
-
// relative to build task's destination path
|
|
119
|
-
dest = path.resolve(this.task.dest, dest)
|
|
120
|
-
}
|
|
121
|
-
this.pushFile(dest)
|
|
122
|
-
if (this._hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_DEFAULT)) {
|
|
123
|
-
await fs.mkdir(path.dirname(dest), { recursive: true })
|
|
124
|
-
await fs.writeFile(dest, typeof data === "object" && !Buffer.isBuffer(data) ? JSON.stringify(data, null, 2) : data)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// TODO only works with files due to fs.copyFile, check usages
|
|
132
|
-
/**
|
|
133
|
-
* Copy a file or directory if the build task option 'outputMode' does not have the value 'resultOnly'.
|
|
134
|
-
* The directory can have contents.
|
|
135
|
-
* <p>
|
|
136
|
-
* Note: The file name is stored in the list of files written by this build task handler.
|
|
137
|
-
* </p>
|
|
138
|
-
* @param {string} src The absolute or relative source path of the file or directory to copy.
|
|
139
|
-
* Relative paths will be resolved to this task's source path.
|
|
140
|
-
* @param {string} dest The absolute or relative target path. Relative paths will be resolved to this task's destination path.
|
|
141
|
-
*
|
|
142
|
-
*/
|
|
143
|
-
copy(src) {
|
|
144
|
-
return {
|
|
145
|
-
to: async (dest) => {
|
|
146
|
-
if (!this._hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
|
|
147
|
-
if (!path.isAbsolute(src)) {
|
|
148
|
-
// relative to build task's source path
|
|
149
|
-
src = path.resolve(this.task.src, src)
|
|
150
|
-
}
|
|
151
|
-
if (!path.isAbsolute(dest)) {
|
|
152
|
-
// relative to build task's destination path
|
|
153
|
-
dest = path.resolve(this.task.dest, dest)
|
|
154
|
-
}
|
|
155
|
-
this.pushFile(dest)
|
|
156
|
-
if (this._hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_DEFAULT)) {
|
|
157
|
-
if (fs.cp) { // Node.js >= 16.7
|
|
158
|
-
return fs.cp(src, dest, { recursive: true })
|
|
159
|
-
}
|
|
160
|
-
return copy(src, dest)
|
|
161
|
-
}
|
|
162
|
-
return dest
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Adds the given user message and severity to the list of messages issued by this build task.
|
|
170
|
-
* <p>
|
|
171
|
-
* User messages will be logged after CDS build has been finished based on the log-level that has been set.
|
|
172
|
-
* By default messages with severity <em>warning</em> and <em>error</em> will be logged.
|
|
173
|
-
* @param {string} message the message text
|
|
174
|
-
* @param {string} severity the severity of the message
|
|
175
|
-
*/
|
|
176
|
-
pushMessage(message, severity) {
|
|
177
|
-
this.messages.push(new BuildMessage(message, severity))
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Returns the reflected CSN model using this build task's model settings.
|
|
182
|
-
* @return {object} the reflected CSN
|
|
183
|
-
*/
|
|
184
|
-
async model() {
|
|
185
|
-
const files = this._resolveModel()
|
|
186
|
-
if (!files || files.length === 0) {
|
|
187
|
-
this._logger.log(`no CDS model found for [${this.task.for}] build task [${this.task.src}] - nothing to be done`)
|
|
188
|
-
return null
|
|
189
|
-
}
|
|
190
|
-
this._logger._debug && this._logger.debug(`model: ${relativePaths(this._buildOptions.root, files).join(", ")}`)
|
|
191
|
-
// $location paths are relative to current working dir by default - make sure a given project root folder is taken
|
|
192
|
-
const options = { ...this.options(), cwd: this._buildOptions.root }
|
|
193
|
-
|
|
194
|
-
const model = await cds.load(files, options)
|
|
195
|
-
if (!model) {
|
|
196
|
-
return null
|
|
197
|
-
}
|
|
198
|
-
return model
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
options() {
|
|
202
|
-
return { messages: this._messages }
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Adds the given fully qualified file path to the list of files that are written by this build task.
|
|
207
|
-
* @param {string} filePath
|
|
208
|
-
*/
|
|
209
|
-
pushFile(filePath) {
|
|
210
|
-
this._written.add(filePath)
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Returns a list of CDS model files defining the transitive closure of the CDS model based on the model options
|
|
214
|
-
* defined for this build task.
|
|
215
|
-
*/
|
|
216
|
-
_resolveModel() {
|
|
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
|
|
218
|
-
return cds.resolve(modelPaths, this._buildOptions)
|
|
219
|
-
}
|
|
220
|
-
/** Determines whether the given build option value has been set for this build task.
|
|
221
|
-
* If the value is omitted, the existence of the given property name is checked.
|
|
222
|
-
*/
|
|
223
|
-
_hasBuildOption(qualifiedName, value) {
|
|
224
|
-
return hasOptionValue(this._getBuildOption(qualifiedName), value)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Returns the value of the given build option defined for this build task.
|
|
228
|
-
_getBuildOption(qualifiedName) {
|
|
229
|
-
// build task options overwriting other settings
|
|
230
|
-
let value = getProperty(this.task.options, qualifiedName)
|
|
231
|
-
if (value !== undefined) {
|
|
232
|
-
return value
|
|
233
|
-
}
|
|
234
|
-
value = getProperty(this._buildOptions.for[this.task.for], qualifiedName)
|
|
235
|
-
if (value !== undefined) {
|
|
236
|
-
return value
|
|
237
|
-
}
|
|
238
|
-
return getProperty(this._buildOptions, qualifiedName)
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
module.exports = BuildTaskHandler
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-unused-vars */
|
|
2
|
-
module.exports = class BuildTaskProvider {
|
|
3
|
-
constructor() {
|
|
4
|
-
//injected by framework
|
|
5
|
-
this._plugin = null
|
|
6
|
-
}
|
|
7
|
-
canHandleTask(task) {
|
|
8
|
-
// return this._plugin.provides.includes(task.for || task.use && this._getTaskId(task.use))
|
|
9
|
-
}
|
|
10
|
-
loadHandler(task) {
|
|
11
|
-
// return module.require(`${this._plugin.path}/${task.for || this._getTaskId(task.use)}`)
|
|
12
|
-
}
|
|
13
|
-
async lookupTasks(tasks, options) { }
|
|
14
|
-
async applyTaskDefaults(task, options) {
|
|
15
|
-
// task.for = task.for || this._getTaskId(task.use)
|
|
16
|
-
}
|
|
17
|
-
_getTaskId(use) {
|
|
18
|
-
if (this._plugin && this._plugin.id) {
|
|
19
|
-
return use.substring(this._plugin.id.length + 1)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|