@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,254 +0,0 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
- const cds = require('../cds')
4
- const BuildTaskHandler = require('../buildTaskHandler')
5
- const { hasOptionValue } = require('../util')
6
- const { FOLDER_GEN, BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY } = require('../constants')
7
-
8
- class BuildTaskHandlerInternal extends BuildTaskHandler {
9
- /**
10
- * Returns the logger that has been passed the build task engine.
11
- * @returns {object}
12
- */
13
- get logger() {
14
- //injected by framework
15
- return this._logger;
16
- }
17
- /**
18
- * Returns the build options used for this CDS build execution
19
- * @returns {object}
20
- */
21
- get buildOptions() {
22
- return this._buildOptions
23
- }
24
- /**
25
- * Custom build handlers are executed before internal handlers in order
26
- * ensure and content cannot be overwritten by mistake.
27
- */
28
- get priority() {
29
- return BuildTaskHandlerInternal.PRIORITY_MAX_VALUE
30
- }
31
-
32
- async clean() {
33
- // the build results have already been deleted by the BuildTaskEngine if the build.target !== '.'
34
- // make sure that src is not a subfolder of dest
35
- if (this._buildOptions.root === this._buildOptions.target && this.task.src !== this.task.dest && !this._isSubDirectory(this.task.dest, this.task.src)) {
36
- await fs.promises.rm(this.task.dest, { force: true, recursive: true })
37
- }
38
- }
39
-
40
- /**
41
- * Used by the framework to initialize the logger implementation.
42
- * @param {object} logger
43
- */
44
- set logger(logger) {
45
- super.logger = logger;
46
- }
47
- /**
48
- * Sets the build options used for this CDS build execution
49
- * @param {object} options
50
- */
51
- set buildOptions(options) {
52
- super.buildOptions = options
53
- }
54
- /**
55
- * Maximum allowed priority for internal build tasks.
56
- */
57
- static get PRIORITY_MAX_VALUE() {
58
- return 0;
59
- }
60
- /**
61
- * Minimum allowed priority for custom build tasks.
62
- */
63
- static get PRIORITY_MIN_VALUE() {
64
- return Number.MIN_SAFE_INTEGER;
65
- }
66
-
67
- /**
68
- * Called by the framework after {@link #init()}. Handlers may want to perform more elaborate preparation.
69
- * E.g. caching some pre-calculated data that can be used across multiple build tasks. This kind of data
70
- * has to be stored in the handler type specific buildOptions section.
71
- * @returns {Promise<boolean>} A value 'false' indicates that {@link #prepare()} will not be called for other instances
72
- * of this handler type.
73
- * True indicates that {@link #prepare()} will be called for other instances of this of this handler type.
74
- * @deprecated
75
- */
76
- async prepare() {
77
- // cancel subsequent prepare calls for other handlers of the same type by default
78
- return false
79
- }
80
-
81
- /**
82
- * Returns whether cds env has a property with the specified value.
83
- * If the value is omitted the existence of the given property name is checked.
84
- * @param {string} qualifiedName
85
- * @param {any=} value
86
- */
87
- hasCdsEnvOption(qualifiedName, value) {
88
- return hasOptionValue(cds.env.get(qualifiedName), value)
89
- }
90
-
91
- /**
92
- * Determines whether the given build option value has been set for this build task.
93
- * If the value is omitted, the existence of the given property name is checked.
94
- * @param {string} qualifiedName
95
- * @param {any=} value
96
- */
97
- hasBuildOption(qualifiedName, value) {
98
- return hasOptionValue(this._getBuildOption(qualifiedName), value)
99
- }
100
-
101
- /**
102
- * Returns the value of the given build option defined for this build task.
103
- * @param {string} qualifiedName
104
- */
105
- getBuildOption(qualifiedName) {
106
- return super._getBuildOption(qualifiedName)
107
- }
108
-
109
- /**
110
- * Returns a list of CDS model files defining the transitive closure of the CDS model based on the model options
111
- * defined for this build task.
112
- */
113
- resolveModel() {
114
- return this._resolveModel()
115
- }
116
-
117
- /**
118
- * Returns whether the build results of this build plugin are created inplace
119
- * or in a separate staging folder which is not part of the build tasks src folder.
120
- */
121
- isStagingBuild() {
122
- return !this.task.src.startsWith(this.task.dest)
123
- }
124
-
125
- async copyNativeContent(srcDir, destDir, customFilter) {
126
- const files = BuildTaskHandlerInternal._find(srcDir, (src) => {
127
- // do not copy files that:
128
- // - are contained in the 'buildOptions.target' folder
129
- // - are contained in this modules 'dest' folder
130
- // - are contained in some generation folder
131
- // - do NOT fulfill additional specific filter criteria
132
- return this._commonStagingBuildFilter(src, destDir) && (!customFilter || customFilter.call(this, src))
133
- })
134
- return Promise.all(
135
- files.map((srcFile) => {
136
- let relFile = path.relative(srcDir, srcFile)
137
- let destFile = path.join(destDir, relFile)
138
- return this.copy(srcFile).to(destFile)
139
- })
140
- )
141
- }
142
-
143
- async compileToJson(model, csnFile) {
144
- // This will als add a @source prop containing the relative path to the origin .cds source file
145
- // and a parsed _where clause for @restrict.{grant,where} annotations.
146
- // The @source annotation is required for correct custom handler resolution if no @impl annotation has been defined as
147
- // custom service handler implementations are relative to the origin .cds source files.
148
- // For staging builds (task.src !== task.dest) the csn.json file that is served at runtime is copied into a corresponding srv subfolder.
149
- // As a consequence the src folder name has to be included in the @source file name while for inplace builds (task.src === task.dest) this is not the case.
150
- // This ensures that the paths are relative to the cwd when executing cds run.
151
- const jsonOptions = {
152
- cwd: this.buildOptions.root,
153
- src: this.task.src === this.task.dest ? this.task.src : this.buildOptions.root
154
- }
155
- const csnStr = cds.compile.to.json(model, jsonOptions)
156
- if (!this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
157
- await this.write(csnStr).to(csnFile)
158
- }
159
- return csnStr
160
- }
161
-
162
- /**
163
- * Collect and write language bundles into a single i18n.json file.
164
- * @param {Object} model
165
- * @param {string} bundleDest
166
- */
167
- async collectLanguageBundles(model, bundleDest) {
168
- // collect effective i18n properties...
169
- let bundles = {}
170
- const bundleGenerator = cds.localize.bundles4(model)
171
- if (bundleGenerator && bundleGenerator[Symbol.iterator]) {
172
- for (let [locale, bundle] of bundleGenerator) {
173
- // fallback bundle has the name ""
174
- if (typeof locale === 'string') {
175
- bundles[locale] = bundle
176
- }
177
- }
178
- }
179
-
180
- // omit bundles in case the fallback bundle is the only existing entry
181
- const keys = Object.keys(bundles)
182
- if (keys.length === 1 && keys[0] === "" && Object.keys(bundles[keys[0]]).length === 0) {
183
- bundles = {}
184
- }
185
- // copied from ../compile/i18n.js
186
- const { file: base = 'i18n' } = cds.env.i18n
187
- const file = path.join(bundleDest, base + '.json')
188
-
189
- // bundleDest might be null
190
- if (bundleDest && Object.keys(bundles).length > 0) {
191
- if (!this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
192
- await this.write(bundles).to(file)
193
- }
194
- return { file, bundles }
195
- }
196
- return null
197
- }
198
-
199
- _isSubDirectory(parent, child) {
200
- return !path.relative(parent, child).startsWith('..')
201
- }
202
-
203
- _commonStagingBuildFilter(src, destDir) {
204
- if (typeof src !== "string" || typeof destDir !== "string") {
205
- return false
206
- }
207
- if (!fs.statSync(src).isDirectory()) {
208
- return true //file
209
- }
210
- if (src === destDir) {
211
- return false
212
- }
213
- const regex = new RegExp(FOLDER_GEN + "\\b")
214
- if (src === this.buildOptions.target) {
215
- return false
216
- }
217
- return !regex.exec(path.basename(src))
218
- }
219
-
220
- static _find(srcDir, filter) {
221
- const files = []
222
- this._traverseFileSystem(srcDir, files, filter)
223
- return files;
224
- }
225
-
226
- static _traverseFileSystem(srcDir, files, filter) {
227
- let entries = []
228
- try {
229
- entries = fs.readdirSync(srcDir)
230
- } catch (e) {
231
- // ignore if not existing
232
- }
233
- entries.map(subDirEntry => path.join(srcDir, subDirEntry)).forEach((entry) => {
234
- this._handleResource(entry, files, filter)
235
- })
236
- }
237
-
238
- static _handleResource(entry, files, filter) {
239
- if (!filter || filter.call(this, entry)) {
240
- var stats = this._getResourceStatus(entry)
241
- if (stats.isDirectory()) {
242
- this._traverseFileSystem(entry, files, filter)
243
- } else if (stats.isFile() || stats.isSymbolicLink()) {
244
- files.push(entry)
245
- }
246
- }
247
- }
248
-
249
- // for testing purposes
250
- static _getResourceStatus(entry) {
251
- return fs.lstatSync(entry)
252
- }
253
- }
254
- module.exports = BuildTaskHandlerInternal
@@ -1,383 +0,0 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
- const cds = require('../cds')
4
- const { hasJavaNature, getProperty, isStreamlinedMtx, getDefaultModelOptions, BuildError, hasOptionValue } = require('../util')
5
- const BuildTaskProvider = require('../buildTaskProvider')
6
-
7
- 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,
8
- BUILD_TASK_PREFIX, BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION, NODEJS_MODEL_EXCLUDE_LIST,
9
- DEFAULT_BUILT_IN_MODELS } = require("../constants")
10
-
11
- class BuildTaskProviderInternal extends BuildTaskProvider {
12
- constructor(logger) {
13
- super()
14
- this._logger = logger
15
- }
16
- get logger() {
17
- return this._logger
18
- }
19
-
20
- canHandleTask(task) {
21
- return BUILD_TASKS.includes(task.for)
22
- || task.use && task.use.startsWith(BUILD_TASK_PREFIX)
23
- // support different build task implementations of the same build task ID defined by 'for'
24
- //return (BUILD_TASKS.includes(task.for) && !task.use) || (task.use && task.use.startsWith(BUILD_TASK_PREFIX))
25
- }
26
-
27
- loadHandler(task) {
28
- return require(`./${BuildTaskProviderInternal._getForValueFromTask(task)}`)
29
- }
30
-
31
- async lookupTasks(tasks, buildOptions) {
32
- return this._createTasks(tasks, buildOptions, tasks.length > 0)
33
- }
34
-
35
- async applyTaskDefaults(task, buildOptions) {
36
- const taskFor = BuildTaskProviderInternal._getForValueFromTask(task)
37
- const { root: projectPath } = buildOptions
38
- task.for = task.for || taskFor
39
- task.use = task.use || `${BUILD_TASK_PREFIX}/${taskFor}`
40
-
41
- BuildTaskProviderInternal._setDefaultSrcFolder(task)
42
-
43
- // src folder needs to be initialized first
44
- BuildTaskProviderInternal._setDefaultModel(task, projectPath)
45
- }
46
-
47
- async _createTasks(tasks, buildOptions, addRequiredTasks) {
48
- const { root: projectPath } = buildOptions
49
- let db = typeof cds.env.folders.db === "string" ? [BuildTaskProviderInternal._normalizePath(cds.env.folders.db)] : cds.env.folders.db
50
- let srv = typeof cds.env.folders.srv === "string" ? [BuildTaskProviderInternal._normalizePath(cds.env.folders.srv)] : cds.env.folders.srv
51
-
52
- const dbOptions = {
53
- model: []
54
- }
55
- const srvOptions = {
56
- model: []
57
- }
58
- if (Array.isArray(db) && db.length > 0) {
59
- db = BuildTaskProviderInternal._getModuleFolder(projectPath, db) || null
60
- if (!db && !addRequiredTasks) { // log once
61
- this.logger.debug("No database module found")
62
- }
63
- }
64
- if (Array.isArray(srv) && srv.length > 0) {
65
- srv = BuildTaskProviderInternal._getModuleFolder(projectPath, srv) || null
66
- if (!srv && !addRequiredTasks) { // log once
67
- this.logger.debug("No service module found")
68
- }
69
- }
70
- // create required build tasks
71
- if (addRequiredTasks) {
72
- const mtxTask = tasks.find(task => task.for === BUILD_TASK_MTX || task.for === BUILD_TASK_MTX_SIDECAR)
73
- if (mtxTask) {
74
- //restore used tasks as they might have been filtered by 'cds build --for mtx'
75
- if (mtxTask._uses) {
76
- mtxTask._uses.map(use => use.task).forEach(task => {
77
- if (!tasks.includes(task)) {
78
- tasks.push(task)
79
- }
80
- })
81
- }
82
- let dbTask = tasks.find(task => task.for === BUILD_TASK_HANA)
83
- if (!dbTask) {
84
- // db task might be missing if mtx task is enforced by 'cds build --for mtx'
85
- dbTask = this._createDbTask(projectPath, db, dbOptions)
86
- if (dbTask) {
87
- tasks.push(dbTask)
88
- }
89
- }
90
- if (dbTask && (!mtxTask._uses || !mtxTask._uses.map(use => use.task).includes(dbTask))) {
91
- const use = { task: dbTask }
92
- mtxTask._uses ? mtxTask._uses.push(use) : mtxTask._uses = [use]
93
- }
94
- }
95
- } else {
96
- !db && this.logger._debug && this.logger.debug(`project doesn't have a database module '${cds.env.folders.db}'`)
97
- !srv && this.logger._debug && this.logger.debug(`project doesn't have a service module '${cds.env.folders.srv}'`)
98
-
99
- // create hana build task
100
- const dbTask = this._createDbTask(projectPath, db, dbOptions, buildOptions)
101
- if (dbTask) {
102
- tasks.push(dbTask)
103
- }
104
- // create java or node build task
105
- const srvTask = this._createSrvTask(projectPath, srv, srvOptions)
106
- if (srvTask) {
107
- tasks.push(srvTask)
108
- }
109
-
110
- // REVISIT: disable for cds-dk projectReader - causing error due to inconsistent state during project creation
111
- if (buildOptions.resolve !== false) {
112
- // create mtx build task
113
- const mtxTask = this._createMtxTask(projectPath, srv, srv, tasks)
114
- if (mtxTask) {
115
- tasks.push(mtxTask)
116
- }
117
- }
118
- }
119
- }
120
-
121
- _createDbTask(projectPath, src, taskOptions, buildOptions) {
122
- this.logger.debug("determining database kind.")
123
- if (!src || BuildTaskProviderInternal._isMtxExtension()) {
124
- return null
125
- }
126
- let task = null
127
- if (this._useHana(projectPath, buildOptions)) {
128
- this.logger.debug("found HANA database.")
129
- // legacy build supports dest property
130
- const compileDest = cds.env.data?.dest
131
- if (compileDest) {
132
- //../db/src/gen
133
- // compileDest is relative to src folder in modular build - resolve correctly
134
- taskOptions.compileDest = path.relative(path.resolve(projectPath, src), path.resolve(projectPath, compileDest))
135
- }
136
- task = {
137
- src: src,
138
- for: BUILD_TASK_HANA,
139
- options: taskOptions
140
- }
141
- } else {
142
- this.logger.debug("found sqlite database - skipping HANA build task")
143
- }
144
- return task
145
- }
146
-
147
- _useHana(projectPath, buildOptions) {
148
- if (getProperty(buildOptions, "for.hana.skipManifestGeneration") // deprecated fallback for webide fullstack and mtx
149
- || getProperty(buildOptions, "for.hana.contentManifest") === false // fallback for webide fullstack and mtx
150
- || cds.env.requires.db?.kind === "hana"
151
- || cds.env.requires.db?.dialect === "hana") {
152
-
153
- return true
154
- }
155
- // false if other db has been defined
156
- if (cds.env.requires.db?.kind) {
157
- return false
158
- }
159
- // check whether cds config represents a legacy build system config for which requires.db was not configured
160
- // Note: compat layer sets requires.db: {}
161
- const userEnv = cds.env.for("cds", projectPath, false)
162
- return userEnv && (userEnv.data?.model || userEnv.service?.model)
163
- }
164
-
165
- _createMtxTask(projectPath, src, dest, tasks) {
166
- this.logger.debug("determining mtx version of nodejs project")
167
-
168
- // preserve order of creation
169
- if (BuildTaskProviderInternal._isMtxExtension()) {
170
- this.logger.debug("MTX extension app")
171
- return { for: BUILD_TASK_MTX_EXTENSION }
172
- }
173
-
174
- if (isStreamlinedMtx()) {
175
- const sidecarPath = path.join(projectPath, MTX_SIDECAR_FOLDER)
176
- let sidecarEnv
177
- if (fs.existsSync(sidecarPath)) {
178
- sidecarEnv = cds.env.for("cds", sidecarPath)
179
- }
180
- if (
181
- cds.env.profiles?.includes('with-mtx-sidecar') || // new presets
182
- cds.env.requires["cds.xt.ModelProviderService"]?.external // for compatibility with former mtxs presets
183
- ) {
184
- this.logger.debug("MTX app with sidecar")
185
- if (!sidecarEnv) {
186
- throw new BuildError(`MTX sidecar directory '${sidecarPath}' not existing. Custom build task configuration required if the folder is named differently.`)
187
- }
188
- if (!sidecarEnv.requires["cds.xt.ModelProviderService"]?._in_sidecar) {
189
- // correct profile might have been set, but couldn't be resolved
190
- if (sidecarEnv.profiles?.includes('mtx-sidecar')) {
191
- throw new BuildError('MTX configuration cannot be resolved. Make sure an up-to-date version of @sap/cds-mtxs is installed.')
192
- }
193
- throw new BuildError(`Invalid MTX sidecar configuration - profile 'mtx-sidecar' not set.`)
194
- }
195
- return { for: BUILD_TASK_MTX_SIDECAR }
196
- }
197
- if (sidecarEnv?.requires["cds.xt.ModelProviderService"]?._in_sidecar || sidecarEnv?.profiles?.includes('mtx-sidecar')) {
198
- throw new BuildError(`MTX sidecar requires profile 'with-mtx-sidecar' in project root configuration.`)
199
- }
200
-
201
- if (cds.env.requires["cds.xt.ModelProviderService"]?._in_sidecar || cds.env.profiles?.includes('mtx-sidecar')) {
202
- // cds build is executed in sidecar folder
203
- throw new BuildError(`Seems that you are executing 'cds build' in the 'mtx/sidecar' folder. Execute 'cds build' in the project root folder instead.`)
204
- }
205
-
206
- // without sidecar
207
- if (!tasks.some(task => task.for === BUILD_TASK_JAVA || task.for === BUILD_TASK_JAVA_CF)) {
208
- this.logger.debug("Nodejs MTX app without sidecar")
209
- return {
210
- for: BUILD_TASK_MTX,
211
- src
212
- }
213
- }
214
- }
215
- if (!tasks.some(task => task.for === BUILD_TASK_JAVA || task.for === BUILD_TASK_JAVA_CF)) {
216
- if (cds.env.requires.multitenancy) {
217
- this.logger.debug("Nodejs Classic MTX app without sidecar")
218
- return {
219
- src: ".",
220
- for: BUILD_TASK_MTX,
221
- dest
222
- }
223
- }
224
- }
225
- }
226
-
227
- _createSrvTask(projectPath, src, taskOptions) {
228
- this.logger.debug("determining implementation technology")
229
- if (!src || BuildTaskProviderInternal._isMtxExtension()) {
230
- return null
231
- }
232
- let task = null
233
- if (BuildTaskProviderInternal._hasJavaNature(projectPath, src)) {
234
- task = this._createJavaTask(projectPath, src, taskOptions)
235
- } else {
236
- task = this._createNodeTask(src, taskOptions)
237
- }
238
- return task
239
- }
240
-
241
- _createJavaTask(projectPath, src, taskOptions) {
242
- this.logger.debug("found implementation technology java")
243
- // legacy build supports dest property
244
- const compileDest = cds.env.service?.dest
245
- if (compileDest) {
246
- // compileDest is relative to src folder in modular build - resolve correctly
247
- taskOptions.compileDest = path.relative(path.resolve(projectPath, src), path.resolve(projectPath, compileDest))
248
- }
249
- return {
250
- src: src,
251
- for: BUILD_TASK_JAVA,
252
- options: taskOptions
253
- }
254
- }
255
-
256
- _createNodeTask(src, taskOptions) {
257
- this.logger.debug("found implementation technology node")
258
- return {
259
- src: src,
260
- for: BUILD_TASK_NODEJS,
261
- options: taskOptions
262
- }
263
- }
264
-
265
- static _isMtxExtension() {
266
- return !!cds.env.extends
267
- }
268
-
269
- static _setDefaultSrcFolder(task) {
270
- switch (task.for) {
271
- case BUILD_TASK_HANA:
272
- task.src = task.src || this._normalizePath(cds.env.folders.db)
273
- break
274
- case BUILD_TASK_JAVA:
275
- case BUILD_TASK_JAVA_CF:
276
- case BUILD_TASK_NODEJS:
277
- case BUILD_TASK_NODE_CF:
278
- task.src = task.src || this._normalizePath(cds.env.folders.srv)
279
- break
280
- case BUILD_TASK_FIORI:
281
- task.src = task.src || this._normalizePath(cds.env.folders.app)
282
- break
283
- case BUILD_TASK_MTX_SIDECAR:
284
- task.src = task.src || MTX_SIDECAR_FOLDER
285
- break
286
- case BUILD_TASK_MTX_EXTENSION:
287
- task.src = task.src || "."
288
- break
289
- case BUILD_TASK_MTX:
290
- if (isStreamlinedMtx()) {
291
- task.src = task.src || this._normalizePath(cds.env.folders.srv)
292
- } else {
293
- task.src = task.src || "."
294
- }
295
- break
296
- default:
297
- throw new Error(`Unknown build task '${task.use || task.for}'`)
298
- }
299
- }
300
-
301
- static _setDefaultModel(task, projectPath) {
302
- let taskModelPaths = task.options?.model
303
- if (taskModelPaths && !Array.isArray(taskModelPaths)) {
304
- taskModelPaths = [taskModelPaths]
305
- }
306
- task.options = task.options || {}
307
- let defaultModelPaths = []
308
- // add default models to custom build tasks if this hasn't been disabled
309
- if (taskModelPaths?.length) {
310
- if (!hasOptionValue(task.options?.[DEFAULT_BUILT_IN_MODELS], false)) {
311
- // get the built-in models
312
- defaultModelPaths = getDefaultModelOptions(projectPath).filter(p => p.match('@sap/cds'))
313
- }
314
- } else {
315
- defaultModelPaths = getDefaultModelOptions(projectPath)
316
- defaultModelPaths.push(task.src)
317
- if (hasOptionValue(task.options?.[DEFAULT_BUILT_IN_MODELS], false)) {
318
- // all default models except the built-in models
319
- defaultModelPaths = defaultModelPaths.filter(p => !p.match('@sap/cds'))
320
- }
321
- }
322
-
323
- // REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
324
- if (this._hasJavaNature(projectPath, cds.env.folders.srv)) {
325
- defaultModelPaths = defaultModelPaths.filter(p => !NODEJS_MODEL_EXCLUDE_LIST.includes(p))
326
- }
327
- // also add built-in models to custom build tasks already containing model options
328
- if (!taskModelPaths || defaultModelPaths.length) {
329
- task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(defaultModelPaths) : defaultModelPaths)]
330
- }
331
- }
332
-
333
- /**
334
- * Returns whether this project is a java project or not.
335
- * @param {string} projectPath - the absolute project path
336
- * @param {string} srv - the folder name of the service module
337
- */
338
- static _hasJavaNature(projectPath, srv) {
339
- srv = this._getModuleFolder(projectPath, Array.isArray(srv) ? srv : [srv])
340
- return hasJavaNature([projectPath, srv && path.join(projectPath, srv)])
341
- }
342
-
343
- static _getForValueFromTask(task) {
344
- return task.for ? task.for : task.use && task.use.substring(BUILD_TASK_PREFIX.length + 1)
345
- }
346
-
347
- /**
348
- * For valid paths remove trailing '/'. Otherwise return as is - important!!
349
- * @param {*} dir
350
- */
351
- static _normalizePath(dir) {
352
- return typeof dir === "string" ? dir.replace(/\/$/, '') : dir
353
- }
354
-
355
- /**
356
- * Determines the module folder from the past list that may represent files or folders w or w/o .cds file extension.
357
- * @param {string} projectPath
358
- * @param {Array} filesOrFolders
359
- */
360
- static _getModuleFolder(projectPath, filesOrFolders) {
361
- const resources = [...filesOrFolders]
362
- filesOrFolders.forEach(fileOrFolder => {
363
- if (path.extname(fileOrFolder) !== FILE_EXT_CDS) {
364
- resources.push(fileOrFolder + FILE_EXT_CDS)
365
- }
366
- })
367
- return resources.reduce((acc, resource) => {
368
- if (!acc) {
369
- let resourcePath = path.resolve(projectPath, resource)
370
- if (fs.existsSync(resourcePath)) {
371
- if (fs.lstatSync(resourcePath).isDirectory()) {
372
- acc = resource
373
- } else {
374
- // represents file
375
- acc = path.dirname(resource)
376
- }
377
- }
378
- }
379
- return acc
380
- }, null)
381
- }
382
- }
383
- module.exports = BuildTaskProviderInternal