@sap/cds 5.9.8 → 6.0.3

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 (381) hide show
  1. package/CHANGELOG.md +277 -20
  2. package/apis/services.d.ts +1 -1
  3. package/app/fiori/preview.js +2 -6
  4. package/app/index.js +3 -3
  5. package/bin/build/buildTaskEngine.js +17 -15
  6. package/bin/build/buildTaskFactory.js +29 -19
  7. package/bin/build/buildTaskHandler.js +27 -11
  8. package/bin/build/buildTaskProvider.js +2 -4
  9. package/bin/build/buildTaskProviderFactory.js +11 -16
  10. package/bin/build/constants.js +14 -6
  11. package/bin/build/csv-reader.js +2 -1
  12. package/bin/build/index.js +12 -18
  13. package/bin/build/provider/buildTaskHandlerEdmx.js +3 -39
  14. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +149 -0
  15. package/bin/build/provider/buildTaskHandlerInternal.js +2 -3
  16. package/bin/build/provider/buildTaskProviderInternal.js +108 -239
  17. package/bin/build/provider/fiori/index.js +2 -2
  18. package/bin/build/provider/hana/2migration.js +11 -11
  19. package/bin/build/provider/hana/2tabledata.js +3 -3
  20. package/bin/build/provider/hana/index.js +89 -99
  21. package/bin/build/provider/hana/migrationtable.js +4 -3
  22. package/bin/build/provider/java/index.js +101 -0
  23. package/bin/build/provider/java-cf/index.js +1 -101
  24. package/bin/build/provider/mtx/index.js +83 -41
  25. package/bin/build/provider/mtx/resourcesTarBuilder.js +68 -0
  26. package/bin/build/provider/mtx-sidecar/index.js +110 -0
  27. package/bin/build/provider/node-cf/index.js +1 -308
  28. package/bin/build/provider/nodejs/index.js +189 -0
  29. package/bin/build/util.js +21 -31
  30. package/bin/cds.js +5 -3
  31. package/bin/deploy/to-hana/cfUtil.js +31 -6
  32. package/bin/deploy/to-hana/gitUtil.js +5 -3
  33. package/bin/deploy/to-hana/hana.js +15 -13
  34. package/bin/{build → deploy/to-hana}/mtaUtil.js +10 -9
  35. package/bin/mtx/in-cds.js +19 -7
  36. package/bin/serve.js +49 -22
  37. package/bin/utils/log.js +13 -30
  38. package/bin/version.js +4 -3
  39. package/common.cds +61 -16
  40. package/lib/compile/cdsc.js +3 -2
  41. package/lib/compile/etc/_localized.js +15 -14
  42. package/lib/compile/for/drafts.js +3 -4
  43. package/lib/compile/for/java.js +13 -10
  44. package/lib/compile/for/nodejs.js +8 -8
  45. package/lib/compile/for/odata.js +7 -12
  46. package/lib/compile/for/sql.js +5 -6
  47. package/lib/compile/index.js +5 -4
  48. package/lib/compile/load.js +9 -11
  49. package/lib/compile/minify.js +8 -5
  50. package/lib/compile/parse.js +4 -2
  51. package/lib/compile/resolve.js +18 -15
  52. package/lib/compile/to/edm.js +0 -1
  53. package/lib/compile/to/gql.js +3 -2
  54. package/lib/compile/to/json.js +24 -17
  55. package/lib/connect/bindings.js +3 -2
  56. package/lib/connect/index.js +5 -5
  57. package/lib/core/classes.js +74 -2
  58. package/lib/core/entities.js +52 -3
  59. package/lib/core/reflect.js +2 -1
  60. package/lib/deploy.js +10 -8
  61. package/lib/env/defaults.js +4 -3
  62. package/lib/env/index.js +71 -31
  63. package/lib/env/presets.js +1 -14
  64. package/lib/env/requires.js +71 -20
  65. package/lib/env/serviceBindings.js +147 -0
  66. package/lib/i18n/localize.js +22 -23
  67. package/lib/index.js +148 -144
  68. package/lib/log/errors.js +55 -12
  69. package/lib/log/format/kibana.js +1 -1
  70. package/lib/log/index.js +4 -0
  71. package/lib/ql/SELECT.js +7 -2
  72. package/lib/ql/Whereable.js +8 -2
  73. package/lib/ql/index.js +2 -2
  74. package/lib/req/assert.js +71 -0
  75. package/lib/req/cds-context.js +38 -70
  76. package/lib/req/context.js +34 -21
  77. package/lib/req/request.js +12 -18
  78. package/lib/req/response.js +6 -2
  79. package/lib/req/user.js +30 -22
  80. package/lib/serve/Service-api.js +17 -12
  81. package/lib/serve/Service-dispatch.js +5 -9
  82. package/lib/serve/Service-methods.js +4 -3
  83. package/lib/serve/Transaction.js +24 -21
  84. package/lib/serve/adapters.js +15 -5
  85. package/lib/serve/factory.js +22 -20
  86. package/lib/serve/index.js +51 -54
  87. package/lib/utils/axios.js +8 -12
  88. package/lib/utils/index.js +13 -4
  89. package/lib/utils/resources/index.js +1 -44
  90. package/lib/utils/resources/tar.js +2 -1
  91. package/lib/utils/tests.js +13 -15
  92. package/libx/_runtime/.eslintrc +1 -1
  93. package/libx/_runtime/audit/Service.js +6 -4
  94. package/libx/_runtime/audit/generic/personal/access.js +19 -43
  95. package/libx/_runtime/audit/generic/personal/index.js +40 -34
  96. package/libx/_runtime/audit/generic/personal/modification.js +11 -9
  97. package/libx/_runtime/audit/generic/personal/utils.js +13 -6
  98. package/libx/_runtime/audit/utils/v2.js +6 -3
  99. package/libx/_runtime/auth/index.js +71 -66
  100. package/libx/_runtime/auth/strategies/JWT.js +3 -2
  101. package/libx/_runtime/auth/strategies/mock.js +54 -53
  102. package/libx/_runtime/auth/strategies/xssecUtils.js +3 -4
  103. package/libx/_runtime/auth/strategies/xsuaa.js +3 -2
  104. package/libx/_runtime/auth/utils.js +2 -15
  105. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +127 -41
  106. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +9 -5
  107. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +93 -73
  108. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +25 -45
  109. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +10 -14
  110. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +9 -5
  111. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -2
  112. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +60 -53
  113. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +2 -2
  114. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +21 -26
  115. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +8 -15
  116. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +29 -41
  117. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -4
  118. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -13
  119. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectToCQN.js +0 -7
  120. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +24 -1
  121. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityContainer.js +1 -1
  122. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriHelper.js +4 -3
  123. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +4 -5
  124. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +4 -3
  125. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/validator/ValueValidator.js +5 -3
  126. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/ResponseHeaderSetter.js +2 -0
  127. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DebugSerializingCommand.js +1 -1
  128. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/PresetResponseHeadersCommand.js +1 -1
  129. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SerializingCommand.js +1 -1
  130. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SetResponseHeadersCommand.js +1 -1
  131. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +3 -2
  132. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ErrorJsonSerializer.js +3 -1
  133. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +1 -0
  134. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +3 -3
  135. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +36 -25
  136. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +97 -92
  137. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +382 -0
  138. package/libx/_runtime/cds-services/adapter/odata-v4/utils/oDataConfiguration.js +1 -4
  139. package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +5 -6
  140. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +82 -21
  141. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +3 -11
  142. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +91 -69
  143. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +27 -6
  144. package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +7 -17
  145. package/libx/_runtime/cds-services/services/Service.js +17 -76
  146. package/libx/_runtime/cds-services/services/utils/columns.js +6 -4
  147. package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -53
  148. package/libx/_runtime/cds-services/services/utils/differ.js +15 -19
  149. package/libx/_runtime/cds-services/util/assert.js +107 -34
  150. package/libx/_runtime/cds.js +1 -31
  151. package/libx/_runtime/common/aspects/Association.js +40 -54
  152. package/libx/_runtime/common/aspects/any.js +61 -6
  153. package/libx/_runtime/common/aspects/entity.js +19 -79
  154. package/libx/_runtime/common/composition/data.js +2 -2
  155. package/libx/_runtime/common/composition/delete.js +8 -7
  156. package/libx/_runtime/common/composition/tree.js +10 -10
  157. package/libx/_runtime/common/composition/update.js +3 -2
  158. package/libx/_runtime/common/constants/events.js +13 -0
  159. package/libx/_runtime/common/error/entry.js +9 -3
  160. package/libx/_runtime/common/error/frontend.js +13 -19
  161. package/libx/_runtime/common/error/index.js +8 -3
  162. package/libx/_runtime/common/generic/auth/capabilities.js +2 -1
  163. package/libx/_runtime/common/generic/auth/constants.js +1 -4
  164. package/libx/_runtime/common/generic/auth/requires.js +1 -1
  165. package/libx/_runtime/common/generic/auth/restrict.js +12 -28
  166. package/libx/_runtime/common/generic/auth/restrictions.js +12 -4
  167. package/libx/_runtime/common/generic/auth/utils.js +2 -1
  168. package/libx/_runtime/common/generic/crud.js +9 -60
  169. package/libx/_runtime/common/generic/etag.js +41 -7
  170. package/libx/_runtime/common/generic/input.js +128 -66
  171. package/libx/_runtime/common/generic/paging.js +9 -3
  172. package/libx/_runtime/common/generic/put.js +2 -2
  173. package/libx/_runtime/common/generic/sorting.js +7 -3
  174. package/libx/_runtime/common/generic/temporal.js +0 -5
  175. package/libx/_runtime/common/i18n/messages.properties +2 -1
  176. package/libx/_runtime/common/utils/binary.js +69 -0
  177. package/libx/_runtime/common/utils/cqn.js +39 -14
  178. package/libx/_runtime/common/utils/cqn2cqn4sql.js +93 -59
  179. package/libx/_runtime/common/utils/csn.js +87 -85
  180. package/libx/_runtime/common/utils/dollar.js +8 -7
  181. package/libx/_runtime/common/utils/draft.js +1 -1
  182. package/libx/_runtime/common/utils/foreignKeyPropagations.js +23 -7
  183. package/libx/_runtime/common/utils/generateOnCond.js +2 -1
  184. package/libx/_runtime/common/utils/keys.js +30 -13
  185. package/libx/_runtime/common/utils/postProcessing.js +6 -1
  186. package/libx/_runtime/common/utils/quotingStyles.js +0 -23
  187. package/libx/_runtime/common/utils/resolveStructured.js +23 -26
  188. package/libx/_runtime/common/utils/resolveView.js +4 -1
  189. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -0
  190. package/libx/_runtime/common/utils/search2cqn4sql.js +4 -13
  191. package/libx/_runtime/common/utils/searchToLike.js +9 -13
  192. package/libx/_runtime/common/utils/streamProp.js +35 -0
  193. package/libx/_runtime/common/utils/structured.js +12 -18
  194. package/libx/_runtime/common/utils/template.js +3 -5
  195. package/libx/_runtime/common/utils/templateProcessor.js +22 -14
  196. package/libx/_runtime/common/utils/unionCqnTemplate.js +4 -14
  197. package/libx/_runtime/db/Service.js +2 -1
  198. package/libx/_runtime/db/expand/expand-v2.js +2 -2
  199. package/libx/_runtime/db/expand/expandCQNToJoin.js +7 -6
  200. package/libx/_runtime/db/generic/input.js +14 -17
  201. package/libx/_runtime/db/generic/integrity.js +1 -2
  202. package/libx/_runtime/db/generic/update.js +14 -1
  203. package/libx/_runtime/db/query/read.js +0 -1
  204. package/libx/_runtime/db/query/update.js +1 -1
  205. package/libx/_runtime/db/sql-builder/BaseBuilder.js +1 -1
  206. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +5 -31
  207. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
  208. package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +0 -9
  209. package/libx/_runtime/db/sql-builder/SelectBuilder.js +11 -10
  210. package/libx/_runtime/db/sql-builder/UpdateBuilder.js +2 -2
  211. package/libx/_runtime/db/sql-builder/annotations.js +1 -2
  212. package/libx/_runtime/db/utils/coloredTxCommands.js +5 -0
  213. package/libx/_runtime/db/utils/columns.js +1 -1
  214. package/libx/_runtime/db/utils/propagateForeignKeys.js +10 -2
  215. package/libx/_runtime/extensibility/activate.js +69 -0
  216. package/libx/_runtime/extensibility/add.js +41 -0
  217. package/libx/_runtime/extensibility/addExtension.js +68 -0
  218. package/libx/_runtime/extensibility/defaults.js +39 -0
  219. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformREAD.js +0 -0
  220. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformRESULT.js +2 -2
  221. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformWRITE.js +2 -2
  222. package/libx/_runtime/extensibility/push.js +61 -0
  223. package/libx/_runtime/extensibility/service.js +21 -0
  224. package/libx/_runtime/extensibility/{uiflex/utils.js → utils.js} +39 -3
  225. package/libx/_runtime/extensibility/validation.js +53 -0
  226. package/libx/_runtime/extensibility/views.js +12 -0
  227. package/libx/_runtime/fiori/generic/activate.js +2 -4
  228. package/libx/_runtime/fiori/generic/before.js +17 -29
  229. package/libx/_runtime/fiori/generic/cancel.js +2 -4
  230. package/libx/_runtime/fiori/generic/delete.js +2 -4
  231. package/libx/_runtime/fiori/generic/edit.js +4 -16
  232. package/libx/_runtime/fiori/generic/index.js +31 -0
  233. package/libx/_runtime/fiori/generic/new.js +5 -21
  234. package/libx/_runtime/fiori/generic/patch.js +10 -15
  235. package/libx/_runtime/fiori/generic/prepare.js +13 -22
  236. package/libx/_runtime/fiori/generic/read.js +148 -163
  237. package/libx/_runtime/fiori/generic/readOverDraft.js +10 -4
  238. package/libx/_runtime/fiori/utils/handler.js +10 -22
  239. package/libx/_runtime/fiori/utils/where.js +1 -4
  240. package/libx/_runtime/hana/Service.js +14 -7
  241. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
  242. package/libx/_runtime/hana/dynatrace.js +2 -2
  243. package/libx/_runtime/hana/localized.js +7 -6
  244. package/libx/_runtime/hana/pool.js +9 -6
  245. package/libx/_runtime/hana/search.js +2 -3
  246. package/libx/_runtime/hana/{searchToContains.js → search2Contains.js} +5 -2
  247. package/libx/_runtime/hana/search2cqn4sql.js +20 -17
  248. package/libx/_runtime/index.js +2 -6
  249. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +30 -22
  250. package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -3
  251. package/libx/_runtime/messaging/common-utils/appId.js +9 -0
  252. package/libx/_runtime/messaging/common-utils/authorizedRequest.js +2 -18
  253. package/libx/_runtime/messaging/common-utils/connections.js +1 -1
  254. package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -2
  255. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +305 -231
  256. package/libx/_runtime/messaging/enterprise-messaging-utils/cloudEvents.js +2 -2
  257. package/libx/_runtime/messaging/enterprise-messaging-utils/options-management.js +15 -8
  258. package/libx/_runtime/messaging/enterprise-messaging-utils/options-messaging.js +57 -14
  259. package/libx/_runtime/messaging/enterprise-messaging.js +14 -19
  260. package/libx/_runtime/messaging/file-based.js +3 -1
  261. package/libx/_runtime/messaging/http-utils/token.js +18 -6
  262. package/libx/_runtime/messaging/message-queuing-utils/options-management.js +22 -12
  263. package/libx/_runtime/messaging/message-queuing-utils/options-messaging.js +27 -14
  264. package/libx/_runtime/messaging/message-queuing.js +138 -85
  265. package/libx/_runtime/messaging/outbox/utils.js +13 -7
  266. package/libx/_runtime/messaging/redis-messaging.js +0 -1
  267. package/libx/_runtime/messaging/service.js +4 -1
  268. package/libx/_runtime/remote/Service.js +24 -18
  269. package/libx/_runtime/remote/utils/client.js +90 -48
  270. package/libx/_runtime/remote/utils/data.js +23 -6
  271. package/libx/_runtime/sqlite/Service.js +14 -13
  272. package/libx/_runtime/sqlite/convertAssocToOneManaged.js +2 -0
  273. package/libx/_runtime/sqlite/customBuilder/CustomSelectBuilder.js +1 -0
  274. package/libx/_runtime/sqlite/execute.js +3 -9
  275. package/libx/_runtime/types/api.js +23 -11
  276. package/libx/common/utils/ucsn.js +15 -9
  277. package/libx/odata/afterburner.js +109 -29
  278. package/libx/odata/cqn2odata.js +48 -9
  279. package/libx/odata/grammar.pegjs +263 -156
  280. package/libx/odata/index.js +21 -9
  281. package/libx/odata/parseToCqn.js +8 -5
  282. package/libx/odata/parser.js +1 -1
  283. package/libx/odata/utils.js +13 -3
  284. package/libx/rest/RestAdapter.js +173 -113
  285. package/libx/rest/RestRequest.js +3 -2
  286. package/libx/rest/middleware/create.js +8 -6
  287. package/libx/rest/middleware/delete.js +6 -13
  288. package/libx/rest/middleware/error.js +1 -1
  289. package/libx/rest/middleware/input.js +6 -6
  290. package/libx/rest/middleware/operation.js +8 -3
  291. package/libx/rest/middleware/parse.js +3 -3
  292. package/libx/rest/middleware/payload.js +12 -0
  293. package/libx/rest/middleware/read.js +12 -2
  294. package/libx/rest/middleware/update.js +3 -3
  295. package/package.json +4 -6
  296. package/server.js +3 -44
  297. package/srv/extensibility-service.cds +56 -0
  298. package/srv/extensibility-service.js +1 -0
  299. package/srv/extensions.cds +8 -0
  300. package/srv/model-provider.cds +59 -0
  301. package/srv/model-provider.js +163 -0
  302. package/srv/mtx.cds +2 -0
  303. package/srv/mtx.js +22 -0
  304. package/srv/outbox.cds +2 -0
  305. package/tasks/enterprise-messaging-deploy.js +19 -12
  306. package/lib/serve/Service-compat.js +0 -36
  307. package/libx/_runtime/audit/generic/personal/constants.js +0 -4
  308. package/libx/_runtime/auth/strategies/dwc.js +0 -45
  309. package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +0 -56
  310. package/libx/_runtime/cds-services/adapter/rest/Rest.js +0 -183
  311. package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +0 -67
  312. package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -82
  313. package/libx/_runtime/cds-services/adapter/rest/handlers/delete.js +0 -39
  314. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +0 -63
  315. package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +0 -52
  316. package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +0 -81
  317. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +0 -56
  318. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +0 -33
  319. package/libx/_runtime/cds-services/adapter/rest/to.js +0 -8
  320. package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +0 -50
  321. package/libx/_runtime/cds-services/adapter/rest/utils/data.js +0 -117
  322. package/libx/_runtime/cds-services/adapter/rest/utils/header-checks.js +0 -14
  323. package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +0 -30
  324. package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +0 -250
  325. package/libx/_runtime/cds-services/adapter/rest/utils/result.js +0 -26
  326. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +0 -200
  327. package/libx/_runtime/common/aspects/utils.js +0 -152
  328. package/libx/_runtime/common/toggles/handler.js +0 -21
  329. package/libx/_runtime/common/utils/extensibilityUtils.js +0 -18
  330. package/libx/_runtime/extensibility/mps/index.js +0 -5
  331. package/libx/_runtime/extensibility/mps/service.js +0 -111
  332. package/libx/_runtime/extensibility/mps/tar.js +0 -42
  333. package/libx/_runtime/extensibility/mps/utils.js +0 -11
  334. package/libx/_runtime/extensibility/uiflex/index.js +0 -54
  335. package/libx/_runtime/extensibility/uiflex/service.js +0 -276
  336. package/libx/_runtime/messaging/common-utils/naming-conventions.js +0 -20
  337. package/libx/_runtime/remote/utils/client-types.d.ts +0 -7
  338. package/libx/gql/GraphQLAdapter.js +0 -33
  339. package/libx/gql/constants/adapter.js +0 -69
  340. package/libx/gql/constants/cds.js +0 -18
  341. package/libx/gql/constants/graphql.js +0 -33
  342. package/libx/gql/readme.md +0 -1
  343. package/libx/gql/resolvers/crud/create.js +0 -20
  344. package/libx/gql/resolvers/crud/delete.js +0 -29
  345. package/libx/gql/resolvers/crud/index.js +0 -6
  346. package/libx/gql/resolvers/crud/read.js +0 -30
  347. package/libx/gql/resolvers/crud/update.js +0 -42
  348. package/libx/gql/resolvers/crud/utils/index.js +0 -36
  349. package/libx/gql/resolvers/field.js +0 -5
  350. package/libx/gql/resolvers/index.js +0 -7
  351. package/libx/gql/resolvers/mutation.js +0 -23
  352. package/libx/gql/resolvers/parse/ast/enrich.js +0 -52
  353. package/libx/gql/resolvers/parse/ast/fragment.js +0 -11
  354. package/libx/gql/resolvers/parse/ast/fromObject.js +0 -39
  355. package/libx/gql/resolvers/parse/ast/index.js +0 -3
  356. package/libx/gql/resolvers/parse/ast/meta.js +0 -4
  357. package/libx/gql/resolvers/parse/ast/variable.js +0 -7
  358. package/libx/gql/resolvers/parse/ast2cqn/columns.js +0 -44
  359. package/libx/gql/resolvers/parse/ast2cqn/entries.js +0 -31
  360. package/libx/gql/resolvers/parse/ast2cqn/index.js +0 -8
  361. package/libx/gql/resolvers/parse/ast2cqn/limit.js +0 -6
  362. package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +0 -24
  363. package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +0 -3
  364. package/libx/gql/resolvers/parse/ast2cqn/where.js +0 -70
  365. package/libx/gql/resolvers/parse/utils/index.js +0 -8
  366. package/libx/gql/resolvers/query.js +0 -13
  367. package/libx/gql/resolvers/root.js +0 -34
  368. package/libx/gql/schema/generate.js +0 -18
  369. package/libx/gql/schema/index.js +0 -5
  370. package/libx/gql/schema/mutation.js +0 -76
  371. package/libx/gql/schema/query.js +0 -108
  372. package/libx/gql/schema/typeDefMap.js +0 -45
  373. package/libx/gql/schema/utils/index.js +0 -54
  374. package/libx/gql/utils/index.js +0 -12
  375. package/libx/rest/middleware/auth.js +0 -20
  376. package/libx/rest/middleware/content.js +0 -19
  377. package/srv/flex.cds +0 -21
  378. package/srv/flex.js +0 -1
  379. package/srv/mps.cds +0 -23
  380. package/srv/mps.js +0 -1
  381. package/srv/outbox.js +0 -0
@@ -1,7 +1,5 @@
1
1
  const cds = require('../../cds')
2
2
 
3
- const Differ = require('./utils/differ')
4
-
5
3
  const { resolveView, restoreLink, findQueryTarget } = require('../../common/utils/resolveView')
6
4
  const { postProcess } = require('../../common/utils/postProcessing')
7
5
 
@@ -16,21 +14,7 @@ const CRUD = Object.assign({ READ: 1 }, WRITE_EVENTS)
16
14
  * Generic Service Event Handler.
17
15
  */
18
16
  class ApplicationService extends cds.Service {
19
- constructor(name, csn, options) {
20
- // REVISIT: do we still need that -> likely due to legacy test?
21
- // If not we should remove this legacy constructor
22
- if (typeof name === 'object') [name, csn, options] = [csn.service, name, csn]
23
- super(name, csn, options)
24
-
25
- // REVISIT: umbrella calls srv._calculateDiff
26
- this._differ = new Differ(this)
27
- this._calculateDiff = this._differ.calculate
28
- }
29
-
30
17
  init() {
31
- /*
32
- * .before handlers (all with _initial === true)
33
- */
34
18
  require('../../common/generic/auth').call(this, this)
35
19
  require('../../common/generic/etag').call(this, this)
36
20
  require('../../common/generic/input').call(this, this)
@@ -38,21 +22,9 @@ class ApplicationService extends cds.Service {
38
22
  require('../../common/generic/temporal').call(this, this)
39
23
  require('../../common/generic/paging').call(this, this) // > paging must be executed before sorting
40
24
  require('../../common/generic/sorting').call(this, this)
41
-
42
- // draft handlers needed?
43
- // REVISIT: serve 2 fiori
44
- this._2fiori = Object.values(this.entities).some(e => e._isDraftEnabled)
45
- if (this._2fiori) this.registerFioriHandlers()
46
-
47
- // personal data audit logging
48
- this._4audit = cds.env.features.audit_personal_data && Object.values(this.entities).some(e => e._hasPersonalData)
49
- if (this._4audit) this.registerPersonalDataHandlers()
50
-
51
- /*
52
- * .on handlers
53
- */
54
- require('../../common/generic/crud').call(this, this)
55
-
25
+ this.registerFioriHandlers(this)
26
+ this.registerPersonalDataHandlers(this)
27
+ this.registerCrudHandlers(this) // default .on handlers, have to go last
56
28
  return this
57
29
  }
58
30
 
@@ -66,7 +38,6 @@ class ApplicationService extends cds.Service {
66
38
 
67
39
  /**
68
40
  * Registers custom handlers.
69
- *
70
41
  * @param {string | object | Function} serviceImpl - init function to register custom handlers.
71
42
  */
72
43
  impl(serviceImpl) {
@@ -74,43 +45,16 @@ class ApplicationService extends cds.Service {
74
45
  return this.prepend(serviceImpl)
75
46
  }
76
47
 
48
+ registerPersonalDataHandlers() {
49
+ return cds.env.features.audit_personal_data && require('../../audit/generic/personal').impl.call(this)
50
+ }
51
+
77
52
  registerFioriHandlers() {
78
- if (this._draftHandlersRegistered) return
79
- this._draftHandlersRegistered = true
80
-
81
- /*
82
- * .before handlers (all with _initial === true)
83
- */
84
- require('../../fiori/generic/before').call(this, this)
85
-
86
- /*
87
- * .on handlers
88
- */
89
- require('../../fiori/generic/new').call(this, this) // > NEW
90
- require('../../fiori/generic/patch').call(this, this) // > PATCH
91
- require('../../fiori/generic/cancel').call(this, this) // > CANCEL
92
- require('../../fiori/generic/edit').call(this, this) // > EDIT
93
- require('../../fiori/generic/prepare').call(this, this) // > draftPrepare (-> should be PREPARE)
94
- require('../../fiori/generic/activate').call(this, this) // > draftActivate (-> should be ACTIVATE)
95
- require('../../fiori/generic/readOverDraft').call(this, this) // > READ non-draft via navigation
96
- require('../../fiori/generic/read').call(this, this) // > READ
97
- require('../../fiori/generic/delete').call(this, this) // > DELETE
53
+ return require('../../fiori/generic').impl.call(this)
98
54
  }
99
55
 
100
- registerPersonalDataHandlers() {
101
- // register directly if cds.db is already set, otherwise on connect of a DatabaseService
102
- if (cds.db && !this._personalDataHandlersRegistered) {
103
- require('../../audit/generic/personal').call(this, this)
104
- this._personalDataHandlersRegistered = true
105
- } else {
106
- const that = this
107
- cds.on('connect', srv => {
108
- if (srv instanceof cds.DatabaseService && !that._personalDataHandlersRegistered) {
109
- require('../../audit/generic/personal').call(that, that)
110
- that._personalDataHandlersRegistered = true
111
- }
112
- })
113
- }
56
+ registerCrudHandlers() {
57
+ return require('../../common/generic/crud').impl.call(this)
114
58
  }
115
59
 
116
60
  /**
@@ -128,18 +72,18 @@ class ApplicationService extends cds.Service {
128
72
  */
129
73
  getRestrictions(definition, event, user) {
130
74
  let restrictions = getNormalizedRestrictions(definition, this.model.definitions, event)
131
- if ((!restrictions || !restrictions.length) && (event in CRUD || !definition.parent)) {
75
+ if (!restrictions && (event in CRUD || !definition.parent)) {
132
76
  // > unrestricted entity or unbound
133
77
  return null
134
78
  }
135
- if (event in CRUD && restrictions.every(r => r.grant !== '*' && !(r.grant in CRUD))) {
79
+ if (event in CRUD && restrictions.length && restrictions.every(r => r.grant !== '*' && !(r.grant in CRUD))) {
136
80
  // > only bounds are restricted
137
81
  return null
138
82
  }
139
- if (!(event in CRUD) && (!restrictions || !restrictions.length) && definition.parent) {
83
+ if (!(event in CRUD) && !restrictions && definition.parent) {
140
84
  // > bound without own restrictions -> get from parent
141
85
  restrictions = getNormalizedRestrictions(definition.parent, this.model.definitions, event)
142
- if (!restrictions || !restrictions.length) {
86
+ if (!restrictions) {
143
87
  // > unrestricted bound
144
88
  return null
145
89
  }
@@ -152,16 +96,13 @@ class ApplicationService extends cds.Service {
152
96
  // Result is post processed according to the inverse projection in order to reflect the correct result of the original query.
153
97
  async handle(req) {
154
98
  // compat mode
155
- if (req._resolved || cds.env.features.resolve_views === false) return super.handle(req)
156
-
157
- if (req.target && req.target.name && this.definition && req.target.name.startsWith(this.definition.name + '.')) {
158
- return super.handle(req)
159
- }
99
+ if (req._resolved) return super.handle(req)
100
+ if (req.target && req.target.name && req.target.name.startsWith(this.namespace + '.')) return super.handle(req)
160
101
 
161
102
  // req.query can be:
162
103
  // - empty object in case of unbound action/function
163
104
  // - undefined/null in case of plain string queries
164
- if (_isSimpleCqnQuery(req.query) && this.model) {
105
+ if (this.model && _isSimpleCqnQuery(req.query)) {
165
106
  const q = resolveView(req.query, this.model, this)
166
107
  const t = findQueryTarget(q) || req.target
167
108
 
@@ -39,7 +39,7 @@ const getColumns = (
39
39
  return columns
40
40
  }
41
41
 
42
- const getSearchableColumns = entity => {
42
+ const _getSearchableColumns = entity => {
43
43
  const columnsOptions = { removeIgnore: true, filterVirtual: true }
44
44
  const columns = getColumns(entity, columnsOptions)
45
45
  const cdsSearchTerm = '@cds.search'
@@ -121,9 +121,11 @@ const getSearchableColumns = entity => {
121
121
  /**
122
122
  * @returns {import('../../../types/api').ColumnRefs}
123
123
  */
124
- const computeColumnsToBeSearched = (cqn, entity = { _searchableColumns: [] }, alias) => {
124
+ const computeColumnsToBeSearched = (cqn, entity = { __searchableColumns: [] }, alias) => {
125
125
  // if there is a group by clause, only columns in it may be searched
126
- let toBeSearched = [...entity._searchableColumns]
126
+ let toBeSearched =
127
+ entity.own('__searchableColumns') || entity.set('__searchableColumns', _getSearchableColumns(entity))
128
+
127
129
  if (cqn.SELECT.groupBy) toBeSearched = toBeSearched.filter(tbs => cqn.SELECT.groupBy.some(gb => gb.ref[0] === tbs))
128
130
  toBeSearched = toBeSearched.map(c => {
129
131
  const col = { ref: [c] }
@@ -142,6 +144,7 @@ const computeColumnsToBeSearched = (cqn, entity = { _searchableColumns: [] }, al
142
144
  (column.as === '_counted_' || column.as === '$count')
143
145
  )
144
146
  return
147
+
145
148
  toBeSearched.push(column)
146
149
  return
147
150
  }
@@ -162,6 +165,5 @@ const computeColumnsToBeSearched = (cqn, entity = { _searchableColumns: [] }, al
162
165
 
163
166
  module.exports = {
164
167
  getColumns,
165
- getSearchableColumns,
166
168
  computeColumnsToBeSearched
167
169
  }
@@ -265,58 +265,6 @@ const compareJson = (newValue, oldValue, entity) => {
265
265
  return Array.isArray(newValue) ? result : result[0]
266
266
  }
267
267
 
268
- const _isObject = item => item && typeof item === 'object' && !Array.isArray(item) && !Buffer.isBuffer(item)
269
-
270
- const _mergeArrays = (entity, oldValue, newValue) => {
271
- const merged = []
272
- const foundIdxNew = []
273
- const keys = _getKeysOfEntity(entity)
274
- for (const entry of oldValue) {
275
- const idxNew = _getIdxCorrespondingEntryWithSameKeys(newValue, entry, keys)
276
- if (idxNew === -1) merged.push(entry)
277
- else {
278
- foundIdxNew.push(idxNew)
279
- merged.push(mergeJsonDeep(entity, entry, newValue[idxNew]))
280
- }
281
- }
282
- for (let i = 0; i < newValue.length; i++) {
283
- if (!foundIdxNew.includes(i)) merged.push(newValue[i])
284
- }
285
- return merged
286
- }
287
-
288
- const mergeJsonDeep = (entity, oldValue, value) => {
289
- // REVISIT readAfterWrite -> commit -> postProcessing
290
- // Detach result from req.data
291
- const newValue = value ? Object.assign({}, value) : oldValue // if newValue === undefined
292
- if (_isObject(oldValue) && _isObject(newValue)) {
293
- // append to newValue to keep an order of attributes as might be defined in custom handler
294
- Object.keys(oldValue).forEach(key => {
295
- if (!(key in newValue)) {
296
- Object.assign(newValue, { [key]: oldValue[key] })
297
- } else {
298
- const target = entity && entity.elements[key] && entity.elements[key]._target
299
- if (_isObject(newValue[key])) {
300
- newValue[key] = mergeJsonDeep(target, oldValue[key], newValue[key])
301
- } else if (Array.isArray(newValue[key])) {
302
- if (target) {
303
- newValue[key] = _mergeArrays(target, oldValue[key], newValue[key])
304
- }
305
- // Can't merge items without target
306
- }
307
- }
308
- })
309
- }
310
- return newValue
311
- }
312
-
313
- // Signature similar to Object.assign(oldValue, newValue)
314
- const mergeJson = (oldValue, newValue, entity) => {
315
- const result = mergeJsonDeep(entity, oldValue, newValue)
316
- return result
317
- }
318
-
319
268
  module.exports = {
320
- compareJson,
321
- mergeJson
269
+ compareJson
322
270
  }
@@ -1,5 +1,4 @@
1
1
  const cds = require('../../../cds')
2
- const LOG = cds.log('app')
3
2
  const { SELECT } = cds.ql
4
3
 
5
4
  const { compareJson } = require('./compareJson')
@@ -11,7 +10,7 @@ const { cqn2cqn4sql, convertPathExpressionToWhere } = require('../../../common/u
11
10
  const { revertData } = require('../../../common/utils/resolveView')
12
11
  const { removeIsActiveEntityRecursively } = require('../../../fiori/utils/where')
13
12
 
14
- module.exports = class {
13
+ module.exports = class Differ {
15
14
  constructor(srv) {
16
15
  this._srv = srv
17
16
  }
@@ -51,16 +50,7 @@ module.exports = class {
51
50
  }
52
51
 
53
52
  async _diffUpdate(req, providedData) {
54
- if (cds.db) {
55
- // REVISIT: remove try catch with cds^6
56
- try {
57
- await this._addPartialPersistentState(req)
58
- } catch (e) {
59
- // NOTE: unofficial compat flag!
60
- if (cds.env.features.throw_diff_error !== false) throw e
61
- else LOG.error('Unable to calculate diff due to error: ' + e.message, e)
62
- }
63
- }
53
+ if (cds.db) await this._addPartialPersistentState(req)
64
54
  const newQuery = cqn2cqn4sql(req.query, this._srv.model)
65
55
  const combinedData = providedData || Object.assign({}, req.query.UPDATE.data || {}, req.query.UPDATE.with || {})
66
56
  const lastTransition = newQuery.UPDATE._transitions[newQuery.UPDATE._transitions.length - 1]
@@ -93,13 +83,19 @@ module.exports = class {
93
83
  }
94
84
 
95
85
  async calculate(req, providedData) {
96
- // umbrella calls _calculateDiff with srv as this
97
- const that = this._differ || this
98
-
99
- if (req.event === 'CREATE') return that._diffCreate(req, providedData)
86
+ if (req.event === 'CREATE') return this._diffCreate(req, providedData)
100
87
  if (req.target._hasPersistenceSkip) return
101
- if (req.event === 'DELETE') return that._diffDelete(req)
102
- if (req.event === 'UPDATE') return that._diffUpdate(req, providedData)
103
- if (req.event === 'PATCH') return that._diffPatch(req, providedData)
88
+ if (req.event === 'DELETE') return this._diffDelete(req)
89
+ if (req.event === 'UPDATE') return this._diffUpdate(req, providedData)
90
+ if (req.event === 'PATCH') return this._diffPatch(req, providedData)
91
+ }
92
+
93
+ // is used as a req instance method
94
+ static reqDiff(req = this, data) {
95
+ const { _service: d } = req.target
96
+ if (!d) return Promise.resolve([])
97
+ const srv = cds.services[d.name]
98
+ if (!srv) return Promise.resolve([])
99
+ return new Differ(srv).calculate(req, data)
104
100
  }
105
101
  }
@@ -1,3 +1,6 @@
1
+ const cds = require('../../cds')
2
+ const LOG = cds.log('app')
3
+
1
4
  // REVISIT: replace with cds.Request
2
5
  const getEntry = require('../../common/error/entry')
3
6
 
@@ -28,11 +31,13 @@ const _enumValues = element => {
28
31
  return Object.keys(element).map(enumKey => {
29
32
  const enum_ = element[enumKey]
30
33
  const enumValue = enum_ && enum_.val
34
+
31
35
  if (enumValue !== undefined) {
32
36
  if (enumValue['=']) return enumValue['=']
33
37
  if (enum_ && enum_.literal && enum_.literal === 'number') return Number(enumValue)
34
38
  return enumValue
35
39
  }
40
+
36
41
  return enumKey
37
42
  })
38
43
  }
@@ -40,35 +45,41 @@ const _enumValues = element => {
40
45
  // REVISIT: this needs a cleanup!
41
46
  const assertError = (code, element, value, key, pathSegments = []) => {
42
47
  let args
48
+
43
49
  if (typeof code === 'object') {
44
50
  args = code.args
45
51
  code = code.code
46
52
  }
53
+
47
54
  const { name, type, precision, scale } = element
48
- pathSegments = pathSegments.slice(0)
49
- pathSegments.push({ key: name || key })
50
- const path = pathSegments.map(({ key, url }) => url || key).join('/')
55
+ const path = `${pathSegments.join('/')}${pathSegments.length ? '/' : ''}${name || key}`
56
+
57
+ const error = new Error()
58
+ const errorEntry = {
59
+ code,
60
+ message: code,
61
+ target: path,
62
+ args: args || [name || key]
63
+ }
51
64
 
52
- const e = new Error()
53
- const error = Object.assign(e, getEntry({ code, message: code, target: path, args: args || [name || key] }))
54
- Object.assign(error, {
65
+ const assertError = Object.assign(error, getEntry(errorEntry))
66
+ Object.assign(assertError, {
55
67
  entity: element.parent && element.parent.name,
56
68
  element: name, // > REVISIT: when is error.element needed?
57
69
  type: element.items ? element.items._type : type,
58
70
  value
59
71
  })
60
72
 
61
- if (element.enum) error.enum = _enumValues(element)
62
-
63
- if (precision) error.precision = precision
64
- if (scale) error.scale = scale
73
+ if (element.enum) assertError.enum = _enumValues(element)
74
+ if (precision) assertError.precision = precision
75
+ if (scale) assertError.scale = scale
65
76
 
66
77
  if (element.target) {
67
78
  // REVISIT: when does this case apply?
68
- error.target = element.target
79
+ assertError.target = element.target
69
80
  }
70
81
 
71
- return error
82
+ return assertError
72
83
  }
73
84
 
74
85
  const _checkString = value => {
@@ -97,7 +108,8 @@ const _checkBoolean = value => {
97
108
  }
98
109
 
99
110
  const _checkBuffer = value => {
100
- return Buffer.isBuffer(value)
111
+ // REVISIT: Extension parameter in push is an object with buffer data
112
+ return Buffer.isBuffer(value) || value.type === 'Buffer'
101
113
  }
102
114
 
103
115
  const _checkUUID = value => {
@@ -170,7 +182,7 @@ const checkComplexType = ([key, value], elements, ignoreNonModelledData) => {
170
182
  return found || ignoreNonModelledData
171
183
  }
172
184
 
173
- const _checkStaticElementByKey = (definition, key, value, result = [], ignoreNonModelledData = true) => {
185
+ const checkStaticElementByKey = (definition, key, value, result = [], ignoreNonModelledData = true) => {
174
186
  const elementsOrParameters = definition.elements || definition.params
175
187
  if (!elementsOrParameters) return result
176
188
  const elementOrParameter = elementsOrParameters[key]
@@ -217,11 +229,13 @@ const _getEnumElement = element => {
217
229
  const _checkEnumElement = (element, value, errors, key, pathSegments) => {
218
230
  const enumElements = _getEnumElement(element)
219
231
  const enumValues = enumElements && _enumValues(enumElements)
232
+
220
233
  if (enumElements && !enumValues.includes(value)) {
221
234
  const args =
222
235
  typeof value === 'string'
223
236
  ? ['"' + value + '"', enumValues.map(ele => '"' + ele + '"').join(', ')]
224
237
  : [value, enumValues.join(', ')]
238
+
225
239
  errors.push(assertError({ code: ASSERT_ENUM, args }, element, value, key, pathSegments))
226
240
  }
227
241
  }
@@ -244,6 +258,7 @@ const _checkFormatElement = (element, value, errors, key, pathSegments) => {
244
258
  // check for forbidden deep operations for association
245
259
  const checkIfAssocDeep = (element, value, req) => {
246
260
  if (!value) return
261
+
247
262
  if (element.on) {
248
263
  req.error(
249
264
  assertError(
@@ -254,20 +269,24 @@ const checkIfAssocDeep = (element, value, req) => {
254
269
  value
255
270
  )
256
271
  )
257
- } else if (element.is2one) {
272
+
273
+ return
274
+ }
275
+
276
+ if (element.is2one) {
258
277
  // managed to one
259
278
  Object.keys(value).forEach(prop => {
260
279
  if (typeof value[prop] !== 'object') {
261
- const key = element.keys.find(el => el.ref[0] === prop)
262
- if (!key) {
263
- const err = assertError(
264
- { code: ASSERT_DEEP_ASSOCIATION, args: ['managed to-one', element.name] },
265
- element,
266
- value
267
- )
268
- err.target += `.${prop}`
269
- req.error(err)
270
- }
280
+ const key = element.keys.find(element => element.ref[0] === prop)
281
+ if (key) return
282
+
283
+ const err = assertError(
284
+ { code: ASSERT_DEEP_ASSOCIATION, args: ['managed to-one', element.name] },
285
+ element,
286
+ value
287
+ )
288
+ err.target += `.${prop}`
289
+ req.error(err)
271
290
  }
272
291
  })
273
292
  }
@@ -276,18 +295,18 @@ const checkIfAssocDeep = (element, value, req) => {
276
295
  /**
277
296
  * @param {import('../../types/api').InputConstraints} constraints
278
297
  */
279
- const checkInputConstraints = ({ element, value, errors, key, path, event }) => {
298
+ const checkInputConstraints = ({ element, value, errors, key, pathSegments }) => {
280
299
  if (!element) return errors
281
300
 
282
- _checkMandatoryElement(element, value, errors, key, path)
301
+ _checkMandatoryElement(element, value, errors, key, pathSegments)
283
302
 
284
303
  if (value == null) return errors
285
304
 
286
- _checkEnumElement(element, value, errors, key, path)
305
+ _checkEnumElement(element, value, errors, key, pathSegments)
287
306
 
288
- _checkRangeElement(element, value, errors, key, path)
307
+ _checkRangeElement(element, value, errors, key, pathSegments)
289
308
 
290
- _checkFormatElement(element, value, errors, key, path)
309
+ _checkFormatElement(element, value, errors, key, pathSegments)
291
310
 
292
311
  return errors
293
312
  }
@@ -297,9 +316,9 @@ const checkStatic = (definition, data, ignoreNonModelledData = false) => {
297
316
 
298
317
  return data.reduce((result, row) => {
299
318
  return Object.entries(row)
300
- .filter(([key, value]) => value !== null && value !== undefined)
319
+ .filter(([, value]) => value !== null && value !== undefined)
301
320
  .reduce((result, [key, value]) => {
302
- return _checkStaticElementByKey(definition, key, value, result, ignoreNonModelledData)
321
+ return checkStaticElementByKey(definition, key, value, result, ignoreNonModelledData)
303
322
  }, result)
304
323
  }, [])
305
324
  }
@@ -315,12 +334,65 @@ const checkKeys = (entity, data) => {
315
334
  if (row[key] === undefined && !entity.elements[key].isAssociation)
316
335
  result.push(assertError(ASSERT_NOT_NULL, entity.elements[key]))
317
336
  }
337
+
318
338
  return result
319
339
  }, [])
320
340
  }
321
341
 
322
342
  const assertNotNullError = element => assertError(ASSERT_NOT_NULL, element)
323
343
 
344
+ /**
345
+ * Check whether the target entity referenced by the association (the reference's target) exists and assert an error if
346
+ * the the reference's target doesn't exist.
347
+ *
348
+ * In other words, use this annotation to check whether a non-null foreign key input in a table has a corresponding
349
+ * primary key (also known as a parent key) in the associated/referenced target table (also known as a parent table).
350
+ *
351
+ * @param {import('../../types/api').assertTargetMap} assertMap
352
+ * @param {array} errors An array to appends the possible errors.
353
+ * @see {@link https://pages.github.tools.sap/cap/docs/guides/providing-services#assert-target @assert.target} for
354
+ * further information.
355
+ */
356
+ const assertTargets = async (assertMap, errors) => {
357
+ const { targets: targetsMap, allTargets } = assertMap
358
+ if (targetsMap.size === 0) return
359
+
360
+ const targets = Array.from(targetsMap.values())
361
+ const transactions = targets.map(({ keys, entity }) => {
362
+ const where = Object.assign({}, ...keys)
363
+ return cds.db.exists(entity, where).forShareLock()
364
+ })
365
+ const targetsExistsResults = await Promise.allSettled(transactions)
366
+
367
+ targetsExistsResults.forEach((txPromise, index) => {
368
+ const isPromiseRejected = txPromise.status === 'rejected'
369
+ const shouldAssertError = (txPromise.status === 'fulfilled' && txPromise.value === null) || isPromiseRejected
370
+ if (!shouldAssertError) return
371
+
372
+ const target = targets[index]
373
+ const { element } = target.assocInfo
374
+
375
+ if (isPromiseRejected) {
376
+ LOG._debug &&
377
+ LOG.debug(
378
+ `The transaction to check the @assert.target constraint for foreign key "${element.name}" failed`,
379
+ txPromise.reason
380
+ )
381
+
382
+ throw new Error(txPromise.reason.message)
383
+ }
384
+
385
+ allTargets
386
+ .filter(t => t.key === target.key)
387
+ .forEach(target => {
388
+ const { row, pathSegments } = target.assocInfo
389
+ const key = target.foreignKey.name
390
+ const error = assertError('ASSERT_TARGET', target.foreignKey, row[key], key, pathSegments)
391
+ errors.push(error)
392
+ })
393
+ })
394
+ }
395
+
324
396
  module.exports = {
325
397
  CDS_TYPE_CHECKS,
326
398
  checkComplexType,
@@ -329,6 +401,7 @@ module.exports = {
329
401
  checkKeys,
330
402
  assertError,
331
403
  checkIfAssocDeep,
332
- checkStaticElementByKey: _checkStaticElementByKey,
333
- assertNotNullError
404
+ checkStaticElementByKey,
405
+ assertNotNullError,
406
+ assertTargets
334
407
  }
@@ -1,5 +1,5 @@
1
1
  /** @type {import('../../lib')} */
2
- const cds = global.cds || require('../../lib')
2
+ const cds = require('../../lib')
3
3
  module.exports = cds
4
4
 
5
5
  /*
@@ -9,33 +9,3 @@ const { any, entity, Association } = cds.builtin.classes
9
9
  cds.extend(any).with(require('./common/aspects/any'))
10
10
  cds.extend(Association).with(require('./common/aspects/Association'))
11
11
  cds.extend(entity).with(require('./common/aspects/entity'))
12
-
13
- /*
14
- * mtx?
15
- */
16
- Object.defineProperty(cds, '_mtxEnabled', {
17
- get: () => cds.mtx && typeof cds.mtx.in === 'function' && !cds.env.features.streamlined_mtx,
18
- configurable: true
19
- })
20
- Object.defineProperty(cds, '_mpsEnabled', {
21
- get: () =>
22
- cds.requires.extensibility ||
23
- cds.requires.toggles ||
24
- (cds.requires.multitenancy && cds.env.features.streamlined_mtx),
25
- configurable: true
26
- })
27
-
28
- /*
29
- * (lazy) feature flags
30
- */
31
- // referential integrity
32
- // REVISIT: why is _db_foreign_key_constraints necessary?
33
- // REVISIT: Do not access cds.env too early!
34
- Object.defineProperty(cds.env.features, '_db_foreign_key_constraints', {
35
- get: () => {
36
- const { assert_integrity: ai, assert_integrity_type: ait } = cds.env.features
37
- if ((typeof ai === 'string' && ai.match(/individual/i)) || (ait && ait.match(/db/i))) return true
38
- return false
39
- },
40
- configurable: true
41
- })