@sap/cds 6.8.4 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/CHANGELOG.md +66 -4
  2. package/README.md +0 -1
  3. package/bin/cds-serve.js +50 -3
  4. package/bin/deploy/to-hana.js +1 -0
  5. package/bin/serve.js +16 -20
  6. package/lib/auth/basic-auth.js +6 -4
  7. package/lib/auth/index.js +4 -3
  8. package/lib/auth/jwt-auth.js +2 -5
  9. package/lib/compile/cds-compile.js +34 -89
  10. package/lib/compile/cdsc.js +11 -0
  11. package/lib/compile/etc/properties.js +2 -2
  12. package/lib/compile/for/lean_drafts.js +36 -69
  13. package/lib/compile/for/nodejs.js +2 -1
  14. package/lib/compile/load.js +3 -3
  15. package/lib/compile/minify.js +2 -0
  16. package/lib/compile/to/csn.js +74 -0
  17. package/{bin/build/provider/hana/2tabledata.js → lib/compile/to/hdbtabledata.js} +4 -6
  18. package/lib/compile/to/json.js +1 -1
  19. package/lib/compile/to/sql.js +8 -6
  20. package/lib/dbs/cds-deploy.js +174 -114
  21. package/lib/env/cds-env.js +64 -79
  22. package/lib/env/cds-requires.js +11 -28
  23. package/lib/env/defaults.js +13 -3
  24. package/lib/env/plugins.js +1 -12
  25. package/lib/env/presets.js +25 -21
  26. package/lib/index.js +121 -147
  27. package/lib/{core/reflect.js → linked/models.js} +2 -2
  28. package/lib/{core/infer.js → linked/queries.js} +2 -0
  29. package/lib/{core/index.js → linked/types.js} +2 -1
  30. package/lib/log/cds-error.js +13 -7
  31. package/lib/log/format/cf.js +1 -1
  32. package/lib/plugins.js +49 -0
  33. package/lib/ql/Query.js +0 -9
  34. package/lib/ql/STREAM.js +0 -1
  35. package/lib/req/context.js +2 -7
  36. package/lib/req/request.js +6 -2
  37. package/lib/req/response.js +23 -10
  38. package/lib/srv/middlewares/ctx-model.js +2 -2
  39. package/lib/srv/middlewares/errors.js +1 -1
  40. package/lib/srv/protocols/_legacy.js +1 -0
  41. package/lib/srv/protocols/graphql.js +7 -16
  42. package/lib/srv/protocols/index.js +59 -45
  43. package/lib/srv/protocols/odata-v2-proxy.js +2 -70
  44. package/lib/srv/protocols/odata-v4.js +9 -4
  45. package/lib/srv/srv-api.js +9 -3
  46. package/lib/srv/srv-dispatch.js +12 -9
  47. package/lib/srv/srv-models.js +4 -21
  48. package/lib/srv/srv-tx.js +15 -12
  49. package/lib/utils/cds-test.js +14 -9
  50. package/lib/utils/cds-utils.js +2 -12
  51. package/lib/utils/check-version.js +17 -0
  52. package/{bin/build → lib/utils}/csv-reader.js +23 -24
  53. package/libx/_runtime/auth/index.js +27 -23
  54. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +15 -72
  55. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
  56. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +0 -2
  57. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +33 -63
  58. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +14 -18
  59. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -5
  60. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +5 -4
  61. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +37 -40
  62. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +7 -1
  63. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +101 -38
  64. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/AbstractError.js +5 -1
  65. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriTokenizer.js +5 -8
  66. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +2 -1
  67. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +9 -8
  68. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
  69. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +15 -11
  70. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +4 -0
  71. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +5 -2
  72. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +1 -123
  73. package/libx/_runtime/cds-services/services/Service.js +79 -107
  74. package/libx/_runtime/cds-services/services/utils/columns.js +23 -19
  75. package/libx/_runtime/cds-services/services/utils/compareJson.js +11 -1
  76. package/libx/_runtime/cds-services/services/utils/differ.js +7 -2
  77. package/libx/_runtime/cds-services/util/assert.js +65 -2
  78. package/libx/_runtime/common/composition/data.js +1 -0
  79. package/libx/_runtime/common/generic/auth/expand.js +1 -1
  80. package/libx/_runtime/common/generic/auth/restrict.js +5 -10
  81. package/libx/_runtime/common/generic/auth/restrictions.js +40 -0
  82. package/libx/_runtime/common/generic/auth/utils.js +1 -2
  83. package/libx/_runtime/common/generic/crud.js +32 -16
  84. package/libx/_runtime/common/generic/etag.js +133 -104
  85. package/libx/_runtime/common/generic/input.js +6 -21
  86. package/libx/_runtime/common/generic/put.js +1 -1
  87. package/libx/_runtime/common/generic/stream.js +52 -0
  88. package/libx/_runtime/common/generic/temporal.js +25 -8
  89. package/libx/_runtime/common/i18n/messages.properties +0 -2
  90. package/libx/_runtime/common/utils/cqn.js +1 -1
  91. package/libx/_runtime/common/utils/cqn2cqn4sql.js +5 -2
  92. package/libx/_runtime/common/utils/csn.js +0 -51
  93. package/libx/_runtime/common/utils/etag.js +30 -0
  94. package/libx/_runtime/common/utils/keys.js +1 -1
  95. package/libx/_runtime/common/utils/normalizeTimestamp.js +25 -0
  96. package/libx/_runtime/common/utils/path.js +1 -1
  97. package/libx/_runtime/common/utils/resolveView.js +2 -1
  98. package/libx/_runtime/common/utils/rewriteAsterisks.js +6 -4
  99. package/libx/_runtime/common/utils/search2cqn4sql.js +12 -16
  100. package/libx/_runtime/common/utils/stream.js +140 -0
  101. package/libx/_runtime/common/utils/streamProp.js +29 -12
  102. package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +0 -2
  103. package/libx/_runtime/db/generic/index.js +0 -2
  104. package/libx/_runtime/db/query/delete.js +2 -2
  105. package/libx/_runtime/db/query/insert.js +2 -2
  106. package/libx/_runtime/db/query/read.js +2 -2
  107. package/libx/_runtime/db/query/run.js +2 -2
  108. package/libx/_runtime/db/query/update.js +2 -2
  109. package/libx/_runtime/db/sql-builder/BaseBuilder.js +0 -6
  110. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +23 -12
  111. package/libx/_runtime/db/sql-builder/FunctionBuilder.js +18 -6
  112. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -0
  113. package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -7
  114. package/libx/_runtime/db/sql-builder/UpsertBuilder.js +1 -0
  115. package/libx/_runtime/db/utils/normalizeTimeData.js +7 -3
  116. package/libx/_runtime/fiori/draft.js +2 -0
  117. package/libx/_runtime/fiori/generic/activate.js +8 -9
  118. package/libx/_runtime/fiori/generic/before.js +30 -20
  119. package/libx/_runtime/fiori/generic/cancel.js +5 -3
  120. package/libx/_runtime/fiori/generic/delete.js +5 -3
  121. package/libx/_runtime/fiori/generic/edit.js +7 -7
  122. package/libx/_runtime/fiori/generic/index.js +10 -16
  123. package/libx/_runtime/fiori/generic/new.js +5 -3
  124. package/libx/_runtime/fiori/generic/patch.js +11 -8
  125. package/libx/_runtime/fiori/generic/prepare.js +13 -6
  126. package/libx/_runtime/fiori/generic/read.js +12 -6
  127. package/libx/_runtime/fiori/lean-draft.js +207 -152
  128. package/libx/_runtime/fiori/utils/delete.js +10 -5
  129. package/libx/_runtime/fiori/utils/req.js +17 -5
  130. package/libx/_runtime/fiori/utils/stream.js +36 -0
  131. package/libx/_runtime/hana/Service.js +12 -9
  132. package/libx/_runtime/hana/conversion.js +10 -15
  133. package/libx/_runtime/hana/driver.js +2 -0
  134. package/libx/_runtime/hana/execute.js +28 -6
  135. package/libx/_runtime/hana/pool.js +36 -122
  136. package/libx/_runtime/hana/search2cqn4sql.js +34 -36
  137. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -6
  138. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +3 -1
  139. package/libx/_runtime/messaging/enterprise-messaging.js +10 -58
  140. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  141. package/libx/_runtime/remote/Service.js +20 -1
  142. package/libx/_runtime/remote/utils/client.js +3 -5
  143. package/libx/_runtime/sqlite/Service.js +4 -6
  144. package/libx/_runtime/sqlite/conversion.js +3 -13
  145. package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +9 -6
  146. package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +6 -1
  147. package/libx/_runtime/sqlite/execute.js +5 -16
  148. package/libx/odata/afterburner.js +22 -6
  149. package/libx/odata/grammar.pegjs +6 -1
  150. package/libx/odata/parser.js +1 -1
  151. package/libx/rest/RestAdapter.js +16 -9
  152. package/libx/rest/RestRequest.js +1 -1
  153. package/libx/rest/middleware/input.js +2 -1
  154. package/libx/rest/middleware/operation.js +1 -0
  155. package/libx/rest/middleware/parse.js +3 -2
  156. package/libx/rest/middleware/payload.js +9 -8
  157. package/libx/rest/middleware/read.js +1 -0
  158. package/package.json +9 -16
  159. package/server.js +1 -1
  160. package/app/fiori/preview.js +0 -270
  161. package/app/fiori/routes.js +0 -59
  162. package/bin/build/buildTaskEngine.js +0 -360
  163. package/bin/build/buildTaskFactory.js +0 -283
  164. package/bin/build/buildTaskHandler.js +0 -241
  165. package/bin/build/buildTaskProvider.js +0 -22
  166. package/bin/build/buildTaskProviderFactory.js +0 -175
  167. package/bin/build/cds.js +0 -5
  168. package/bin/build/constants.js +0 -66
  169. package/bin/build/index.js +0 -58
  170. package/bin/build/provider/buildTaskHandlerEdmx.js +0 -82
  171. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +0 -131
  172. package/bin/build/provider/buildTaskHandlerInternal.js +0 -254
  173. package/bin/build/provider/buildTaskProviderInternal.js +0 -383
  174. package/bin/build/provider/fiori/index.js +0 -171
  175. package/bin/build/provider/hana/2migration.js +0 -179
  176. package/bin/build/provider/hana/index.js +0 -505
  177. package/bin/build/provider/hana/migrationtable.js +0 -472
  178. package/bin/build/provider/hana/template/.hdiconfig-haas +0 -163
  179. package/bin/build/provider/hana/template/.hdiconfig-hanacloud +0 -137
  180. package/bin/build/provider/hana/template/.hdinamespace +0 -4
  181. package/bin/build/provider/hana/template/package.json +0 -12
  182. package/bin/build/provider/hana/template/undeploy.json +0 -5
  183. package/bin/build/provider/java/index.js +0 -111
  184. package/bin/build/provider/java-cf/index.js +0 -1
  185. package/bin/build/provider/mtx/index.js +0 -268
  186. package/bin/build/provider/mtx/resourcesTarBuilder.js +0 -95
  187. package/bin/build/provider/mtx-extension/index.js +0 -131
  188. package/bin/build/provider/mtx-sidecar/index.js +0 -137
  189. package/bin/build/provider/node-cf/index.js +0 -1
  190. package/bin/build/provider/nodejs/index.js +0 -192
  191. package/bin/build/util.js +0 -299
  192. package/bin/cds.js +0 -125
  193. package/bin/deploy/to-hana/cfUtil.js +0 -355
  194. package/bin/deploy/to-hana/gitUtil.js +0 -57
  195. package/bin/deploy/to-hana/hana.js +0 -306
  196. package/bin/deploy/to-hana/hdiDeployUtil.js +0 -153
  197. package/bin/deploy/to-hana/index.js +0 -16
  198. package/bin/deploy/to-hana/mtaUtil.js +0 -170
  199. package/bin/mtx/in-cds.js +0 -17
  200. package/bin/plugins.js +0 -32
  201. package/bin/run.js +0 -24
  202. package/bin/utils/log.js +0 -24
  203. package/bin/version.js +0 -178
  204. package/libx/_runtime/audit/Service.js +0 -222
  205. package/libx/_runtime/audit/generic/personal/access.js +0 -61
  206. package/libx/_runtime/audit/generic/personal/index.js +0 -56
  207. package/libx/_runtime/audit/generic/personal/modification.js +0 -132
  208. package/libx/_runtime/audit/generic/personal/utils.js +0 -186
  209. package/libx/_runtime/audit/utils/log.js +0 -23
  210. package/libx/_runtime/audit/utils/v2.js +0 -176
  211. package/libx/_runtime/db/data-conversion/timestamp.js +0 -9
  212. package/libx/_runtime/db/generic/integrity.js +0 -455
  213. package/srv/audit-log.cds +0 -87
  214. package/srv/mtx.cds +0 -2
  215. package/srv/mtx.js +0 -8
  216. /package/lib/{core → linked}/classes.js +0 -0
  217. /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
- }