@sap/cds 5.9.6 → 6.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 (381) hide show
  1. package/CHANGELOG.md +266 -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 +90 -53
  25. package/bin/build/provider/mtx/resourcesTarBuilder.js +68 -0
  26. package/bin/build/provider/mtx-sidecar/index.js +80 -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 +19 -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 +9 -10
  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 +56 -21
  37. package/bin/utils/log.js +13 -30
  38. package/bin/version.js +5 -4
  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 +11 -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 +70 -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 +23 -20
  86. package/lib/serve/index.js +51 -54
  87. package/lib/utils/axios.js +8 -12
  88. package/lib/utils/index.js +3 -3
  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 +128 -42
  106. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -3
  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 +10 -45
  109. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -9
  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 +1 -1
  114. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -21
  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 +100 -91
  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 +77 -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 +16 -18
  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 +15 -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 +11 -4
  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 +6 -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 +3 -7
  232. package/libx/_runtime/fiori/generic/index.js +31 -0
  233. package/libx/_runtime/fiori/generic/new.js +2 -4
  234. package/libx/_runtime/fiori/generic/patch.js +4 -8
  235. package/libx/_runtime/fiori/generic/prepare.js +2 -4
  236. package/libx/_runtime/fiori/generic/read.js +137 -162
  237. package/libx/_runtime/fiori/generic/readOverDraft.js +10 -4
  238. package/libx/_runtime/fiori/utils/handler.js +10 -5
  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 +11 -2
  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 +2 -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 +84 -46
  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 +261 -157
  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,5 +1,5 @@
1
1
  /*
2
- * input handler on ApplicationService level
2
+ * Input handler on application service layer
3
3
  *
4
4
  * - remove readonly fields
5
5
  * - remove immutable fields on update
@@ -8,15 +8,15 @@
8
8
  */
9
9
 
10
10
  const cds = require('../../cds')
11
+ const LOG = cds.log('app')
11
12
  const { enrichDataWithKeysFromWhere } = require('../utils/keys')
12
13
  const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
13
- const { checkInputConstraints, checkIfAssocDeep } = require('../../cds-services/util/assert')
14
+ const { checkInputConstraints, assertTargets } = require('../../cds-services/util/assert')
14
15
  const getTemplate = require('../utils/template')
15
16
  const templateProcessor = require('../utils/templateProcessor')
16
17
  const { getDataFromCQN, setDataFromCQN } = require('../utils/data')
17
- const { isMandatory, isReadOnly } = require('../aspects/utils')
18
18
 
19
- const shouldSuppressErrorPropagation = ({ event, value }) => {
19
+ const _shouldSuppressErrorPropagation = (event, value) => {
20
20
  return (
21
21
  event === 'NEW' ||
22
22
  event === 'PATCH' ||
@@ -25,7 +25,7 @@ const shouldSuppressErrorPropagation = ({ event, value }) => {
25
25
  )
26
26
  }
27
27
 
28
- const getSimpleCategory = category => {
28
+ const _getSimpleCategory = category => {
29
29
  if (typeof category === 'object') {
30
30
  category = category.category
31
31
  }
@@ -33,7 +33,7 @@ const getSimpleCategory = category => {
33
33
  return category
34
34
  }
35
35
 
36
- const rowKeysGenerator = eventName => {
36
+ const _rowKeysGenerator = eventName => {
37
37
  if (eventName === 'UPDATE') return
38
38
  return (keyNames, row, template) => {
39
39
  for (const keyName of keyNames) {
@@ -69,8 +69,62 @@ const _getMediaTypeValue = req =>
69
69
  !req._.req.headers['content-type'].match(/json|multipart/i) &&
70
70
  req._.req.headers['content-type']
71
71
 
72
- const _processCategory = ({ row, key, category, isRoot, event, value, req, element }) => {
73
- category = getSimpleCategory(category)
72
+ const _preProcessAssertTarget = (assocInfo, assertMap) => {
73
+ const { element: assoc, row } = assocInfo
74
+ const assocTarget = assoc._target
75
+
76
+ // it is expected that the associated entities be defined in the same service
77
+ if (assoc.parent._service !== assocTarget._service) {
78
+ LOG._warn && LOG.warn('Cross-service checks for the @assert.target constraint are not supported.')
79
+ return
80
+ }
81
+
82
+ const foreignKeys = assoc._foreignKeys
83
+ let mapKey = `${assocTarget.name}(`
84
+ const hasOwn = Object.prototype.hasOwnProperty
85
+ const parentKeys = []
86
+
87
+ foreignKeys.forEach(keyMap => {
88
+ const { childElement, parentElement } = keyMap
89
+
90
+ // don't assert target if the foreign key isn't in the payload
91
+ if (!hasOwn.call(row, parentElement.name)) return
92
+
93
+ const foreignKeyValue = row[parentElement.name]
94
+
95
+ // don't assert target if the foreign key value is null
96
+ if (foreignKeyValue === null) return
97
+
98
+ mapKey += `${childElement.name}=${foreignKeyValue},`
99
+ parentKeys.push({
100
+ [childElement.name]: foreignKeyValue
101
+ })
102
+ })
103
+ mapKey += `)`
104
+
105
+ if (parentKeys.length === 0) return
106
+
107
+ foreignKeys.forEach(keyMap => {
108
+ const clonedAssocInfo = Object.assign({}, assocInfo, { pathSegments: assocInfo.pathSegments.slice(0) })
109
+ const target = {
110
+ key: mapKey,
111
+ entity: assocTarget,
112
+ keys: parentKeys,
113
+ assocInfo: clonedAssocInfo,
114
+ foreignKey: keyMap.parentElement
115
+ }
116
+
117
+ if (!assertMap.targets.has(mapKey)) {
118
+ assertMap.targets.set(mapKey, target)
119
+ }
120
+
121
+ assertMap.allTargets.push(target)
122
+ })
123
+ }
124
+
125
+ const _processCategory = (req, category, value, elementInfo, assertMap) => {
126
+ const { row, key, element, isRoot } = elementInfo
127
+ category = _getSimpleCategory(category)
74
128
 
75
129
  // remember mandatory
76
130
  if (category === 'mandatory') {
@@ -78,6 +132,8 @@ const _processCategory = ({ row, key, category, isRoot, event, value, req, eleme
78
132
  return
79
133
  }
80
134
 
135
+ const event = req.event
136
+
81
137
  // remove readonly & immutable (can also be complex, so do first)
82
138
  if (category === 'readonly' || (category === 'immutable' && event === 'UPDATE')) {
83
139
  if (_isDraftCoreComputed(req, element, event)) {
@@ -95,11 +151,9 @@ const _processCategory = ({ row, key, category, isRoot, event, value, req, eleme
95
151
  value.val = row[key] = cds.utils.uuid()
96
152
  }
97
153
 
98
- // check for forbidden deep operations for association
99
- if (category === 'associationEffective' && (event === 'UPDATE' || event === 'CREATE')) {
100
- if (shouldSuppressErrorPropagation({ event, value })) return
101
- // REVISIT: remove delay_assert_deep_assoc with cds^6
102
- if (!cds.env.features.delay_assert_deep_assoc) checkIfAssocDeep(element, value.val, req)
154
+ // @assert.target
155
+ if ((event === 'UPDATE' || event === 'CREATE') && category === '@assert.target') {
156
+ _preProcessAssertTarget(elementInfo, assertMap)
103
157
  }
104
158
 
105
159
  // set media type from content-type header if streaming
@@ -108,28 +162,26 @@ const _processCategory = ({ row, key, category, isRoot, event, value, req, eleme
108
162
  if (category === 'stream' && isStreaming && mtValue) row[key] = mtValue
109
163
  }
110
164
 
111
- const processorFn = (errors, req) => {
112
- const { event } = req
165
+ const _getProcessorFn = (req, errors, assertMap) => {
166
+ const event = req.event
113
167
 
114
- return ({ row, key, element, plain, isRoot, path }) => {
115
- const categories = plain.categories
168
+ return elementInfo => {
169
+ const { row, key, element, plain, pathSegments } = elementInfo
116
170
  // ugly pointer passing for sonar
117
171
  const value = { mandatory: false, val: row && row[key] }
118
172
 
119
- for (const category of categories) {
120
- _processCategory({ row, key, category, isRoot, event, value, req, element })
173
+ for (const category of plain.categories) {
174
+ _processCategory(req, category, value, elementInfo, assertMap)
121
175
  }
122
176
 
123
- if (shouldSuppressErrorPropagation({ event, value })) {
124
- return
125
- }
177
+ if (_shouldSuppressErrorPropagation(event, value)) return
126
178
 
127
179
  // REVISIT: Convert checkInputConstraints to template mechanism
128
- checkInputConstraints({ element, value: value.val, errors, path, event })
180
+ checkInputConstraints({ element, value: value.val, errors, pathSegments, event })
129
181
  }
130
182
  }
131
183
 
132
- // params: element, target, parent, templateElements
184
+ // params: element, target, parent
133
185
  const _pick = element => {
134
186
  // collect actions to apply
135
187
  const categories = []
@@ -151,25 +203,27 @@ const _pick = element => {
151
203
  categories.push('immutable')
152
204
  }
153
205
 
154
- if (element._isAssociationEffective && !element._target._hasPersistenceSkip) {
155
- categories.push('associationEffective')
156
- }
157
-
158
206
  if (element.key && !DRAFT_COLUMNS_MAP[element.name] && element.isUUID) {
159
207
  categories.push('uuid')
160
208
  }
161
209
 
162
210
  if (element['@Core.IsMediaType']) categories.push('stream')
163
211
 
212
+ if (
213
+ element._isAssociationStrict &&
214
+ !element.on && // managed assoc
215
+ element.is2one &&
216
+ element['@assert.target'] === true
217
+ ) {
218
+ categories.push('@assert.target')
219
+ }
220
+
164
221
  if (categories.length) return { categories }
165
222
  }
166
223
 
167
224
  const _callError = (req, errors) => {
168
- if (errors.length !== 0) {
169
- for (const error of errors) {
170
- req.error(error)
171
- }
172
- }
225
+ if (errors.length === 0) return
226
+ for (const error of errors) req.error(error)
173
227
  }
174
228
 
175
229
  const _isBoundAction = req => !!(req.getUriInfo && req.getUriInfo().getLastSegment().getKind() === 'BOUND.ACTION')
@@ -183,7 +237,7 @@ const _getBoundActionBindingParameter = req => {
183
237
  return (actions && actions[action] && actions[action]['@cds.odata.bindingparameter.name']) || 'in'
184
238
  }
185
239
 
186
- function _handler(req) {
240
+ async function _handler(req) {
187
241
  if (!req.query) return // FIXME: the code below expects req.query to be defined
188
242
  if (!req.target) return
189
243
 
@@ -191,41 +245,44 @@ function _handler(req) {
191
245
  if (template.elements.size === 0) return
192
246
 
193
247
  const errors = []
194
- const args = {
195
- processFn: processorFn(errors, req),
196
- template,
197
- pathOptions: {
198
- rowKeysGenerator: rowKeysGenerator(req.event),
199
- includeKeyValues: true,
200
- path: []
201
- }
248
+ const assertMap = {
249
+ targets: new Map(),
250
+ allTargets: []
251
+ }
252
+
253
+ const pathOptions = {
254
+ rowKeysGenerator: _rowKeysGenerator(req.event),
255
+ includeKeyValues: true,
256
+ pathSegments: []
202
257
  }
258
+
203
259
  if (_isBoundAction(req)) {
204
260
  const pathSegment = _getBoundActionBindingParameter(req)
205
261
  const keys = req._ && req._.params && req._.params[0]
206
- if (pathSegment) {
207
- args.pathOptions.path.push({ key: pathSegment, url: pathSegment })
208
- }
262
+ if (pathSegment) pathOptions.pathSegments.push(pathSegment)
209
263
 
210
264
  if (keys && 'IsActiveEntity' in keys) {
211
- args.pathOptions.extraKeys = { IsActiveEntity: keys.IsActiveEntity }
265
+ pathOptions.extraKeys = { IsActiveEntity: keys.IsActiveEntity }
212
266
  }
213
267
  }
214
268
 
215
269
  const data = getDataFromCQN(req.query) // REVISIT: req.data should point into req.query
216
-
217
270
  enrichDataWithKeysFromWhere(data, req, this)
218
-
219
271
  const arrayData = Array.isArray(data) ? data : [data]
272
+
220
273
  for (const row of arrayData) {
221
- templateProcessor(Object.assign(args, { row }))
274
+ templateProcessor({ processFn: _getProcessorFn(req, errors, assertMap), row, template, pathOptions })
275
+ }
276
+
277
+ if (assertMap.targets.size > 0) {
278
+ await assertTargets(assertMap, errors)
222
279
  }
223
280
 
224
281
  setDataFromCQN(req) // REVISIT: req.data should point into req.query
225
282
  _callError(req, errors)
226
283
  }
227
284
 
228
- const processorFnForActionsFunctions =
285
+ const _getProcessorFnForActionsFunctions =
229
286
  (errors, opName) =>
230
287
  ({ row, key, element }) => {
231
288
  const value = row && row[key]
@@ -236,6 +293,7 @@ const processorFnForActionsFunctions =
236
293
 
237
294
  const _processActionFunctionRow = (row, param, key, errors, event, service) => {
238
295
  const values = Array.isArray(row[key]) ? row[key] : [row[key]]
296
+
239
297
  // unstructured
240
298
  for (const value of values) {
241
299
  checkInputConstraints({ element: param, value, errors, key })
@@ -245,9 +303,10 @@ const _processActionFunctionRow = (row, param, key, errors, event, service) => {
245
303
  const template = getTemplate('app-input-operation', service, param, {
246
304
  pick: _pick
247
305
  })
306
+
248
307
  if (template && template.elements.size) {
249
308
  for (const value of values) {
250
- const args = { processFn: processorFnForActionsFunctions(errors, key), row: value, template }
309
+ const args = { processFn: _getProcessorFnForActionsFunctions(errors, key), row: value, template }
251
310
  templateProcessor(args)
252
311
  }
253
312
  }
@@ -256,6 +315,7 @@ const _processActionFunctionRow = (row, param, key, errors, event, service) => {
256
315
  const _processActionFunction = (row, eventParams, errors, event, service) => {
257
316
  for (const key in eventParams) {
258
317
  let param = eventParams[key]
318
+
259
319
  // .type of action/function behaves different to .type of other csn elements
260
320
  const _type = param.type
261
321
  if (!_type && param.items) param = param.items
@@ -281,27 +341,29 @@ function _actionFunctionHandler(req) {
281
341
  const eventParams = _getEventParameters(req, this)
282
342
  if (!eventParams) return
283
343
 
284
- // REVISIT: find better solution
344
+ // REVISIT: find better solution -> this obviously was because params were not linked in the past
285
345
  // attach aspects, if not yet done
286
- for (const param of Object.values(eventParams)) {
287
- if ('_isMandatory' in param) continue
288
- param._isMandatory = isMandatory(param)
289
- param._isReadOnly = isReadOnly(param)
290
- }
346
+ // for (const param of Object.values(eventParams)) {
347
+ // if ('_isMandatory' in param) continue
348
+ // param._isMandatory = isMandatory(param)
349
+ // param._isReadOnly = isReadOnly(param)
350
+ // }
291
351
 
292
- // REVISIT: find better solution, maybe compiler?
352
+ // REVISIT: find better solution, maybe compiler? -> this obviously was because params were not linked in the past
293
353
  // resolve enums like format, range, etc.
294
- for (const param of Object.values(eventParams)) {
295
- // .type of action/function behaves different to .type of other csn elements
296
- const _type = param.type && this.model && this.model.definitions[param.type]
297
- if (_type) {
298
- param.enum = _type.enum
299
- }
300
- }
354
+ // for (const param of Object.values(eventParams)) {
355
+ // // .type of action/function behaves different to .type of other csn elements
356
+ // const _type = param.type && this.model && this.model.definitions[param.type]
357
+ //
358
+ // if (_type) {
359
+ // param.enum = _type.enum
360
+ // }
361
+ // }
301
362
 
302
363
  const errors = []
303
364
  const data = req.data
304
365
  const arrayData = Array.isArray(data) ? data : [data]
366
+
305
367
  for (const row of arrayData) {
306
368
  _processActionFunction(row, eventParams, errors, req.event, this)
307
369
  }
@@ -314,8 +376,8 @@ _actionFunctionHandler._initial = true
314
376
 
315
377
  module.exports = cds.service.impl(function () {
316
378
  this.before(['CREATE', 'UPDATE', 'NEW', 'PATCH'], '*', _handler)
317
-
318
379
  const operationNames = []
380
+
319
381
  for (const operation of this.operations) {
320
382
  operationNames.push(operation.name.substring(this.name.length + 1))
321
383
  }
@@ -8,10 +8,16 @@ const _handler = function (req) {
8
8
  // target === null if view with parameters
9
9
  if (!req.target || !req.query.SELECT || req.query.SELECT.one) return
10
10
 
11
- let { rows, offset } = req.query.SELECT.limit || {}
12
- rows = rows && 'val' in rows ? rows.val : getDefaultPageSize(req.target)
11
+ _addPaging(req.query, req.target)
12
+ }
13
+
14
+ const _addPaging = function (query, target) {
15
+ let { rows, offset } = query.SELECT.limit || {}
16
+ rows = rows && 'val' in rows ? rows.val : getDefaultPageSize(target)
13
17
  offset = offset && 'val' in offset ? offset.val : 0
14
- req.query.limit(...[Math.min(rows, getMaxPageSize(req.target)), offset])
18
+ query.limit(...[Math.min(rows, getMaxPageSize(target)), offset])
19
+ //Handle nested limits
20
+ if (query.SELECT.from.SELECT) _addPaging(query.SELECT.from, target)
15
21
  }
16
22
 
17
23
  /**
@@ -23,7 +23,7 @@ const _fillStructure = (row, parts, element, category, args) => {
23
23
  }
24
24
  }
25
25
 
26
- const processorFn = req => {
26
+ const _getProcessorFn = req => {
27
27
  const REST = req.constructor.name === 'RestRequest'
28
28
 
29
29
  return ({ row, key, element, plain }) => {
@@ -73,7 +73,7 @@ function _handler(req) {
73
73
  const arrayData = Array.isArray(data) ? data : [data]
74
74
  for (const row of arrayData) {
75
75
  const args = {
76
- processFn: processorFn(req),
76
+ processFn: _getProcessorFn(req),
77
77
  row,
78
78
  template
79
79
  }
@@ -15,8 +15,7 @@ const _getStaticOrders = req => {
15
15
 
16
16
  const ordersFromKeys = []
17
17
 
18
- // implicit sorting?
19
- if (cds.env.features.implicit_sorting !== false && (req.target._isSingleton || query.SELECT.limit)) {
18
+ if (req.target._isSingleton || query.SELECT.limit) {
20
19
  const keys = getAllKeys(entity, true)
21
20
  for (const key of keys) {
22
21
  if (!(key in DRAFT_COLUMNS_MAP) && !defaultOrders.some(o => o.by['='] === key)) {
@@ -27,7 +26,10 @@ const _getStaticOrders = req => {
27
26
 
28
27
  if (entity.query && entity.query.SELECT && entity.query.SELECT.orderBy) {
29
28
  const orderBy = entity.query.SELECT.orderBy
30
- const ordersFromView = orderBy.map(keyName => ({ by: { '=': keyName.ref[0] }, desc: keyName.sort === 'desc' }))
29
+ const ordersFromView = orderBy.map(keyName => ({
30
+ by: { '=': keyName.ref[keyName.ref.length - 1] },
31
+ desc: keyName.sort === 'desc'
32
+ }))
31
33
  return [...ordersFromView, ...defaultOrders, ...ordersFromKeys]
32
34
  }
33
35
 
@@ -44,13 +46,18 @@ const _getStaticOrders = req => {
44
46
  const _handler = function (req) {
45
47
  if (!req.query || !req.query.SELECT || req.query.SELECT.one) return
46
48
 
47
- const select = req.query.SELECT
49
+ let select = req.query.SELECT
48
50
 
49
51
  // do not sort for /$count queries or queries only using aggregations
50
52
  if (select.columns && select.columns.length && select.columns.every(col => col.func)) {
51
53
  return
52
54
  }
53
55
 
56
+ // apply default sort to bottom-most sub-query
57
+ if (select.from && select.from.SELECT) {
58
+ while (select.from.SELECT) select = select.from.SELECT
59
+ }
60
+
54
61
  // "static orders" = the orders not from the query options
55
62
  let staticOrders = _getStaticOrders(req)
56
63
 
@@ -48,11 +48,6 @@ const _handler = function (req) {
48
48
  // REVISIT: stable access
49
49
  const _ = (req.context && req.context._) || req._
50
50
 
51
- if (_isWarningRequired(cds._deprecationWarningForTemporal, _queryOptions)) {
52
- LOG._warn && LOG.warn('query options "sap-valid-from" and "sap-valid-to" are deprecated and will be removed.')
53
- cds._deprecationWarningForTemporal = true
54
- }
55
-
56
51
  // make sure the env vars are reset
57
52
  _['VALID-FROM'] = null
58
53
  _['VALID-TO'] = null
@@ -46,6 +46,7 @@ ASSERT_DATA_TYPE=Value {0} is invalid according to type definition "{1}"
46
46
  ASSERT_ENUM=Value {0} is invalid according to enum declaration {{1}}
47
47
  ASSERT_NOT_NULL=Value is required
48
48
  ASSERT_REFERENCE_INTEGRITY=Reference integrity is violated for association "{0}"
49
+ ASSERT_TARGET="Value doesn't exist"
49
50
  ASSERT_DEEP_ASSOCIATION=It is not allowed to modify sub documents in {0} Association "{1}"
50
51
 
51
52
  # persistence
@@ -70,7 +71,7 @@ DELETABLE=deletable
70
71
  ENTITY_IS_INSERT_ONLY=Entity "{0}" is insert-only
71
72
  ENTITY_IS_READ_ONLY=Entity "{0}" is read-only
72
73
  ENTITY_IS_NOT_CRUD=Entity "{0}" is not {1}
73
- ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via association "{2}"
74
+ ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via navigation "{2}"
74
75
  ENTITY_IS_AUTOEXPOSED=Entity "{0}" is not explicitly exposed as part of the service
75
76
  EXPAND_IS_RESTRICTED=Navigation property "{0}" is not allowed for expand operation
76
77
  EXPAND_COUNT_UNSUPPORTED="$count" is not supported for expand operation
@@ -0,0 +1,69 @@
1
+ const getTemplate = require('./template')
2
+ const templateProcessor = require('./templateProcessor')
3
+
4
+ const BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}={0,1}|[A-Za-z0-9+/]{2}={0,2})$/
5
+
6
+ // convert the standard base64 encoding to the URL-safe variant
7
+ const toBase64url = value =>
8
+ (Buffer.isBuffer(value) ? value.toString('base64') : value).replace(/\//g, '_').replace(/\+/g, '-')
9
+
10
+ const normalizeBase64string = value => {
11
+ if (typeof value !== 'string') return value
12
+ // add last byte(s) and '=' padding in case of shortend base64
13
+ return Buffer.from(value, 'base64').toString('base64')
14
+ }
15
+
16
+ const isInvalidBase64string = value => {
17
+ if (Buffer.isBuffer(value)) return // ok
18
+
19
+ // convert to standard base64 string; let it crash if typeof value !== 'string'
20
+ const base64 = value.replace(/_/g, '/').replace(/-/g, '+')
21
+ const normalized = normalizeBase64string(value)
22
+
23
+ // example of invalid base64 string --> 'WTGTdDsD/k21LnFRb+uNcAi=' <-- '...i=' must be '...g='
24
+ // see https://datatracker.ietf.org/doc/html/rfc4648#section-4
25
+ return !base64.match(BASE64) || base64.replace(/=/g, '') !== normalized.replace(/=/g, '')
26
+ }
27
+
28
+ const _picker = element => {
29
+ const categories = {}
30
+ if (Array.isArray(element)) return
31
+ if (element.type !== 'cds.Binary' && element.type !== 'cds.LargeBinary') return
32
+ categories['convert_binary'] = true
33
+ return categories
34
+ }
35
+
36
+ const _processorFn =
37
+ toBuffer =>
38
+ ({ row, key, plain: categories }) => {
39
+ if (categories['convert_binary'] && row[key] != null) {
40
+ if (toBuffer && typeof row[key] === 'string') row[key] = Buffer.from(row[key], 'base64')
41
+ if (!toBuffer && Buffer.isBuffer(row[key])) row[key] = row[key].toString('base64')
42
+ }
43
+ }
44
+
45
+ const _processBinaryData = (data, srv, definition, toBuffer) => {
46
+ const template = getTemplate('rest-payload', srv, definition, { pick: _picker })
47
+ if (template && template.elements.size) {
48
+ const rows = Array.isArray(data) ? data : [data]
49
+ for (const row of rows) {
50
+ templateProcessor({ processFn: _processorFn(toBuffer), row, template })
51
+ }
52
+ }
53
+ }
54
+
55
+ const base64ToBuffer = (data, srv, definition) => {
56
+ _processBinaryData(data, srv, definition, true)
57
+ }
58
+
59
+ const bufferToBase64 = (data, srv, definition) => {
60
+ _processBinaryData(data, srv, definition, false)
61
+ }
62
+
63
+ module.exports = {
64
+ normalizeBase64string,
65
+ isInvalidBase64string,
66
+ toBase64url,
67
+ base64ToBuffer,
68
+ bufferToBase64
69
+ }
@@ -1,3 +1,7 @@
1
+ const cds = require('../../cds')
2
+ const { SELECT } = cds.ql
3
+ const { setEntityContained } = require('./csn')
4
+
1
5
  const getEntityNameFromDeleteCQN = cqn => {
2
6
  let from
3
7
  if (cqn && cqn.DELETE && cqn.DELETE.from) {
@@ -17,8 +21,7 @@ const getEntityNameFromUpdateCQN = cqn => {
17
21
  }
18
22
 
19
23
  // scope: simple wheres à la "[{ ref: ['foo'] }, '=', { val: 'bar' }, 'and', ... ]"
20
- function where2obj(where, target = null) {
21
- const data = {}
24
+ function where2obj(where, target = null, data = {}) {
22
25
  for (let i = 0; i < where.length; i++) {
23
26
  const whereEl = where[i]
24
27
 
@@ -39,20 +42,34 @@ function where2obj(where, target = null) {
39
42
  return data
40
43
  }
41
44
 
42
- function targetFromPath(path, model) {
43
- const { definitions } = model
44
- let current
45
- for (const r of path) {
46
- if (r.id) {
47
- current = current
48
- ? definitions[current.elements[r.id].target]
49
- : definitions[r.id] || definitions[r.id.replace(/_drafts$/, '')]
45
+ function targetFromPath(from, model) {
46
+ const fromRef = from ? from.ref || [from] : []
47
+ let last = fromRef.length ? model.definitions : {}
48
+ const path = []
49
+ let target
50
+ let isContained
51
+ for (let r of fromRef) {
52
+ isContained = undefined
53
+ path.push(r.operation || r)
54
+ r = (r.id && r.id.replace(/_drafts$/, '')) || r
55
+ if (r.operation) {
56
+ if (last && last.actions) last = last.actions[r.operation]
57
+ else last = last[r.operation]
58
+ } else if (last.elements) {
59
+ last = last.elements[r]
60
+ if (last.isAssociation) {
61
+ isContained = last._isContained && last.target !== last.parent.name
62
+ last = model.definitions[last.target]
63
+ }
50
64
  } else {
51
- const next = current ? current.elements[r] : definitions[r]
52
- current = next.isAssociation ? definitions[next.target] : next
65
+ last = last[r]
66
+ }
67
+ if (last.kind === 'entity') {
68
+ target = last
69
+ setEntityContained(target, model, isContained)
53
70
  }
54
71
  }
55
- return current
72
+ return { last, path, target, isTargetComposition: isContained }
56
73
  }
57
74
 
58
75
  function isPathToDraft(path, model) {
@@ -80,10 +97,18 @@ function isPathToDraft(path, model) {
80
97
  return draft
81
98
  }
82
99
 
100
+ const resolveFromSelect = query => {
101
+ const __protoSelect = Object.getPrototypeOf(SELECT())
102
+ if (!(query instanceof __protoSelect.constructor)) Object.setPrototypeOf(query, __protoSelect)
103
+ const { from } = query.SELECT
104
+ return from.SELECT ? resolveFromSelect(from) : from
105
+ }
106
+
83
107
  module.exports = {
84
108
  getEntityNameFromDeleteCQN,
85
109
  getEntityNameFromUpdateCQN,
86
110
  where2obj,
87
111
  targetFromPath,
88
- isPathToDraft
112
+ isPathToDraft,
113
+ resolveFromSelect
89
114
  }