@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
@@ -76,9 +76,7 @@ const _getColumnsFromTargetType = (targetType, relatedEntity, all = false) => {
76
76
  }))
77
77
  }
78
78
 
79
- const columnNames = Object.values(relatedEntity.elements)
80
- .filter(element => element['@odata.etag'])
81
- .map(element => element.name)
79
+ const columnNames = []
82
80
 
83
81
  const keyNames = Object.keys(relatedEntity.keys).filter(keyName => {
84
82
  const key = relatedEntity.keys[keyName]
@@ -94,6 +92,17 @@ const _getInnerSelect = expandItem => {
94
92
  return expandItem.getOption(QueryOptions.SELECT) || []
95
93
  }
96
94
 
95
+ const _isProxy = (service, targetType, relatedEntity) => {
96
+ // REVISIT still not perfect solution
97
+ if (!cds.env.effective.odata.proxies && !cds.env.effective.odata.xrefs) return
98
+ // proxy => target entity not exposed in service (model.namespace)
99
+ if (targetType.getName() in service.entities()) return
100
+ for (const key of targetType.getProperties().keys()) {
101
+ if (!relatedEntity.keys[key]) return
102
+ }
103
+ return true
104
+ }
105
+
97
106
  /**
98
107
  * Get the selected columns and navigation paths.
99
108
  *
@@ -103,17 +112,14 @@ const _getInnerSelect = expandItem => {
103
112
  * @returns {Array}
104
113
  * @private
105
114
  */
106
- const _getSelectedElements = (expandItem, targetType, relatedEntity, options) => {
107
- if (cds.env.effective.odata.proxies || cds.env.effective.odata.xrefs) {
108
- // proxy target?
109
- let proxy = true
110
- targetType.getProperties().forEach((value, key) => {
111
- if (!relatedEntity.keys[key]) proxy = false
112
- })
113
-
114
- if (proxy) {
115
- return _getColumnsFromTargetType(targetType, relatedEntity)
116
- }
115
+ const _getSelectedElements = (expandItem, targetType, service, options) => {
116
+ const { name: entityName, namespace } = targetType.getFullQualifiedName()
117
+
118
+ // autoexposed entities now used . in csn and _ in edm
119
+ const relatedEntity = findCsnTargetFor(entityName, service.model, namespace)
120
+ // proxy target?
121
+ if (_isProxy(service, targetType, relatedEntity)) {
122
+ return _getColumnsFromTargetType(targetType, relatedEntity)
117
123
  }
118
124
 
119
125
  let innerSelectItems = _getInnerSelect(expandItem)
@@ -151,50 +157,30 @@ const _getSelectedElements = (expandItem, targetType, relatedEntity, options) =>
151
157
  return selectedPaths
152
158
  }
153
159
 
154
- /**
155
- * Nested expands are inner expand items.
156
- *
157
- * @param model
158
- * @param expandItem
159
- * @param targetType
160
- * @returns {Array}
161
- * @private
162
- */
163
- const _getInnerExpandItems = (model, expandItem, targetType) => {
164
- if (!expandItem || !expandItem.getOption(QueryOptions.EXPAND)) {
165
- return []
166
- }
167
-
168
- return expandToCQN(model, expandItem.getOption(QueryOptions.EXPAND), targetType)
169
- }
170
-
171
160
  const _filter = (item, expression) => {
172
161
  if (!expression) return
173
162
  const expressionToCQN = new ExpressionToCQN()
174
163
  item.where = SELECT.from('a').where(expressionToCQN.parse(expression)).SELECT.where
175
164
  }
176
165
 
177
- const _getItemCQN = (model, name, navigationProperty, expandItem, options) => {
166
+ const _getItemCQN = (service, name, navigationProperty, expandItem, options) => {
178
167
  _notSupported(expandItem)
179
168
 
180
169
  const targetType = navigationProperty.getEntityType()
181
- const { name: entityName, namespace } = navigationProperty.getEntityType().getFullQualifiedName()
182
170
 
183
- // autoexposed entities now used . in csn and _ in edm
184
- const relatedEntity = findCsnTargetFor(entityName, model, namespace)
185
- const expand = _getSelectedElements(expandItem, targetType, relatedEntity, options)
171
+ const expand = _getSelectedElements(expandItem, targetType, service, options)
186
172
  const item = {
187
173
  ref: name, // ['structured', 'nested_', nestedAssocToOne] if expand on structured
188
174
  expand
189
175
  }
190
176
 
191
- item.expand.push(..._getInnerExpandItems(model, expandItem, targetType))
192
-
193
177
  if (!expandItem) {
194
178
  // $expand=* can't have own query options -> no limit, orderBy, etc. needed
195
179
  return item
196
180
  }
197
181
 
182
+ item.expand.push(...expandToCQN(expandItem.getOption(QueryOptions.EXPAND), targetType, service, options))
183
+
198
184
  const orderBy = expandItem.getOption(QueryOptions.ORDERBY)
199
185
  if (orderBy) {
200
186
  orderByToCQN(item, orderBy)
@@ -230,7 +216,9 @@ const _name = expandItem =>
230
216
  * @param type
231
217
  * @returns {Array}
232
218
  */
233
- const expandToCQN = (model, expandItems, type, options) => {
219
+ const expandToCQN = (expandItems, type, service, options) => {
220
+ if (!expandItems || !expandItems.length) return []
221
+
234
222
  const allElements = []
235
223
  const isAll = expandItems.some(item => item.isAll())
236
224
 
@@ -238,7 +226,7 @@ const expandToCQN = (model, expandItems, type, options) => {
238
226
  const expandItem = _getExpandItem(isAll, expandItems, name)
239
227
 
240
228
  if (isAll || expandItem) {
241
- const itemCQN = _getItemCQN(model, [name], navigationProperty, expandItem, options)
229
+ const itemCQN = _getItemCQN(service, [name], navigationProperty, expandItem, options)
242
230
  allElements.push(itemCQN)
243
231
  }
244
232
  }
@@ -251,7 +239,7 @@ const expandToCQN = (model, expandItems, type, options) => {
251
239
  const navigationProperty = _getNavigationProperty(pathSegments)
252
240
 
253
241
  if (isAll || expandItem) {
254
- allElements.push(_getItemCQN(model, _name(expandItem), navigationProperty, expandItem))
242
+ allElements.push(_getItemCQN(service, _name(expandItem), navigationProperty, expandItem))
255
243
  }
256
244
  }
257
245
  }
@@ -23,10 +23,7 @@ const parseToCqn = require('../../../../../odata/parseToCqn')
23
23
  * @returns {object} - The CQN object
24
24
  */
25
25
  module.exports = (component, service, target, data, odataReq, upsert) => {
26
- if (
27
- cds.env.features.odata_new_parser &&
28
- !(component in { 'BOUND.ACTION': 1, 'BOUND.FUNCTION': 1, 'FUNCTION.IMPORT': 1, 'ACTION.IMPORT': 1 })
29
- ) {
26
+ if (cds.env.features.odata_new_parser) {
30
27
  return parseToCqn(component, service, target, data, odataReq, upsert)
31
28
  }
32
29
 
@@ -6,7 +6,7 @@ const orderByToCQN = require('./orderByToCQN')
6
6
  const selectToCQN = require('./selectToCQN')
7
7
  const searchToCQN = require('./searchToCQN')
8
8
  const applyToCQN = require('./applyToCQN')
9
- const { convertUrlPathToCqn, getAllKeys, isPathSupported } = require('./utils')
9
+ const { convertUrlPathToCqn, getAllKeys, isPathSupported, getSegmentKeyValue } = require('./utils')
10
10
 
11
11
  const QueryOptions = require('../okra/odata-server').QueryOptions
12
12
  const {
@@ -32,7 +32,7 @@ const SUPPORTED_SEGMENT_KINDS = {
32
32
  [SINGLETON]: 1
33
33
  }
34
34
 
35
- const { _expand } = require('../utils/handlerUtils')
35
+ const expandToCQN = require('./expandToCQN')
36
36
  const { resolveStructuredName } = require('../utils/handlerUtils')
37
37
  const { isStreaming } = require('../utils/stream')
38
38
 
@@ -249,7 +249,8 @@ const _addKeysToSelectIfNoStreaming = (entity, select, streaming) => {
249
249
 
250
250
  const _convertUrlPathToViewCqn = segments => {
251
251
  const args = segments[0].getKeyPredicates().reduce((prev, curr) => {
252
- prev[curr.getEdmRef().getName()] = { val: curr.getText() }
252
+ const { keyName, val } = getSegmentKeyValue(curr)
253
+ prev[keyName.replace(/\//g, '_')] = { val }
253
254
  return prev
254
255
  }, {})
255
256
 
@@ -342,7 +343,7 @@ const readToCQN = (service, target, odataReq) => {
342
343
  const propertyParam = _getPropertyParam(segments)
343
344
  const apply = _apply(uriInfo, queryOptions, entity, service.model)
344
345
  const select = _select(queryOptions, entity)
345
- const expand = _expand(service.model, uriInfo)
346
+ const expand = expandToCQN(uriInfo.getQueryOption(QueryOptions.EXPAND), uriInfo.getFinalEdmType(), service)
346
347
 
347
348
  if (Object.keys(apply).length) {
348
349
  _handleApply(apply, select)
@@ -351,14 +352,6 @@ const readToCQN = (service, target, odataReq) => {
351
352
  if (propertyParam) {
352
353
  select.push(propertyParam)
353
354
 
354
- // add etag property if necessary
355
- if (
356
- entity._etag &&
357
- !(propertyParam.ref && propertyParam.ref.length === 1 && propertyParam.ref[0] === entity._etag)
358
- ) {
359
- select.push({ ref: [entity._etag] })
360
- }
361
-
362
355
  // add keys if no streaming, TODO: what if streaming via to-one
363
356
  _addKeysToSelectIfNoStreaming(entity, select, isStreaming(segments))
364
357
  }
@@ -381,7 +374,14 @@ const readToCQN = (service, target, odataReq) => {
381
374
  // keep target as input because of localized view
382
375
  const cqn = SELECT.from(isView ? _convertUrlPathToViewCqn(segments) : convertUrlPathToCqn(segments, service), select)
383
376
 
384
- if (isCollectionOrToMany && queryOptions && queryOptions[QueryOptions.COUNT]) cqn.SELECT.count = true
377
+ const isCount =
378
+ isCollectionOrToMany &&
379
+ queryOptions &&
380
+ queryOptions[QueryOptions.COUNT] &&
381
+ queryOptions[QueryOptions.COUNT].toUpperCase() === 'TRUE'
382
+ if (isCount) {
383
+ cqn.SELECT.count = true
384
+ }
385
385
 
386
386
  if (Object.keys(apply).length) _extendCqnWithApply(cqn, apply, entity)
387
387
 
@@ -29,13 +29,6 @@ const selectToCQN = (select, keys, entity) => {
29
29
  }
30
30
  }
31
31
 
32
- for (const col in entity.elements) {
33
- const newRef = { ref: [col] }
34
- if (entity.elements[col]['@odata.etag'] && !elements.some(ref => isSameArray(ref.ref, newRef.ref))) {
35
- elements.push(newRef)
36
- }
37
- }
38
-
39
32
  return Array.from(elements)
40
33
  }
41
34
 
@@ -118,10 +118,33 @@ const isPathSupported = (supported, pathSegments) => {
118
118
  }
119
119
  }
120
120
 
121
+ const _parsePrimitiveValue = (edmRef, value) => {
122
+ const typeName = edmRef.getProperty ? edmRef.getProperty().getType().getName() : edmRef.getType().getName()
123
+ return typeName.startsWith('Int') ? Number(value) : typeName === 'Boolean' ? value === 'true' : value
124
+ }
125
+
126
+ const getSegmentKeyValue = segmentParam => {
127
+ const edmRef = segmentParam.getEdmRef()
128
+ const keyName = edmRef.getName()
129
+ if (segmentParam.getAliasValue()) {
130
+ const value = segmentParam.getAliasValue()
131
+ // must be JSON or a string according to
132
+ // https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html#sec_ComplexandCollectionLiterals
133
+ try {
134
+ return { keyName, val: JSON.parse(value) }
135
+ } catch (e) {
136
+ // plain string
137
+ }
138
+ return { keyName, val: _parsePrimitiveValue(edmRef, value) }
139
+ }
140
+ return { keyName, val: _parsePrimitiveValue(edmRef, segmentParam.getText()) }
141
+ }
142
+
121
143
  module.exports = {
122
144
  addLimit,
123
145
  convertUrlPathToCqn,
124
146
  isSameArray,
125
147
  getAllKeys,
126
- isPathSupported
148
+ isPathSupported,
149
+ getSegmentKeyValue
127
150
  }
@@ -343,7 +343,7 @@ class EdmEntityContainer {
343
343
  for (const csdlEntitySet of providerEntitySets) {
344
344
  const config = this._getArtifactConfiguration(this.getNamespace(), csdlEntitySet.name)
345
345
  const entitySet = new EdmEntitySet(this._edm, this, csdlEntitySet, config)
346
- this._entitySetCache[entitySet.getName()] = entitySet
346
+ this._entitySetCache.set(entitySet.getName(), entitySet)
347
347
  this._entitySets.push(entitySet)
348
348
  }
349
349
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  const EdmTypeKind = require('../edm/EdmType').TypeKind
4
4
  const EdmPrimitiveTypeKind = require('../edm/EdmPrimitiveTypeKind')
5
+ const { toBase64url } = require('../../../../../../common/utils/binary')
5
6
 
6
7
  const REGEXP_SINGLE_QUOTE = new RegExp("'", 'g')
7
8
  const REGEXP_TWO_SINGLE_QUOTES = new RegExp("''", 'g')
@@ -24,8 +25,8 @@ class UriHelper {
24
25
 
25
26
  if (edmType === EdmPrimitiveTypeKind.Binary) {
26
27
  // convert the URL-safe base64 encoding to the standard variant (with padding, if necessary)
27
- let val = uriLiteral.substring(uriLiteral.indexOf("'") + 1, uriLiteral.length - 1).replace(/_/g, '/').replace(/-/g, '+')
28
- return val.padEnd(val.length + val.length % 4, '=')
28
+ const val = uriLiteral.substring(uriLiteral.indexOf("'") + 1, uriLiteral.length - 1)
29
+ return Buffer.from(val, 'base64').toString('base64')
29
30
  }
30
31
 
31
32
  if (edmType === EdmPrimitiveTypeKind.Duration || edmType.getKind() === EdmTypeKind.ENUM || edmType.getName().startsWith('Geo')) {
@@ -50,7 +51,7 @@ class UriHelper {
50
51
  if (value === null) return 'null'
51
52
  if (edmType === EdmPrimitiveTypeKind.String) return "'" + value.replace(REGEXP_SINGLE_QUOTE, "''") + "'"
52
53
  if (edmType === EdmPrimitiveTypeKind.Duration) return "duration'" + value + "'"
53
- if (edmType === EdmPrimitiveTypeKind.Binary) return "binary'" + value.replace(/\//g, '_').replace(/\+/g, '-') + "'"
54
+ if (edmType === EdmPrimitiveTypeKind.Binary) return "binary'" + toBase64url(value) + "'"
54
55
  if (edmType.getKind() === EdmTypeKind.DEFINITION) {
55
56
  return UriHelper.toUriLiteral(value, edmType.getUnderlyingType())
56
57
  }
@@ -8,6 +8,7 @@ const ValueConverter = require('./ValueConverter')
8
8
  const ValueValidator = require('../validator/ValueValidator')
9
9
  const JsonContentTypeInfo = require('../format/JsonContentTypeInfo')
10
10
  const IllegalArgumentError = require('../errors/IllegalArgumentError')
11
+ const { isInvalidBase64string } = require('../../../../../../common/utils/binary')
11
12
 
12
13
  const V2_DATE_TIME_OFFSET_REGEXP = new RegExp('^/Date\\((-?\\d{1,15})(?:(\\+|-)(\\d{4}))?\\)/$')
13
14
  const V2_TIME_OF_DAY_REGEXP = new RegExp('^PT(?:(\\d{1,2})H)?(?:(\\d{1,4})M)?(?:(\\d{1,5})(\\.\\d+)?S)?$')
@@ -70,11 +71,9 @@ const COLLECTION_VALIDATION = new RegExp('^' + SRID + 'Collection\\((' + MULTI_G
70
71
  const BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}={2})$/
71
72
 
72
73
  function _getBase64(val) {
73
- // convert url-safe to standard base64 (with padding, if necessary)
74
- val = val.replace(/_/g, '/').replace(/-/g, '+')
75
- val = val.padEnd(val.length + val.length % 4, '=')
76
- if (!val.match(BASE64)) return
77
- return val
74
+ if (isInvalidBase64string(val)) return
75
+ // convert url-safe to standard base64
76
+ return Buffer.from(val, 'base64').toString('base64')
78
77
  }
79
78
 
80
79
  /**
@@ -6,6 +6,7 @@ const EdmTypeKind = require('../edm/EdmType').TypeKind
6
6
  const EdmPrimitiveTypeKind = require('../edm/EdmPrimitiveTypeKind')
7
7
  const JsonContentTypeInfo = require('../format/JsonContentTypeInfo')
8
8
  const IllegalArgumentError = require('../errors/IllegalArgumentError')
9
+ const { toBase64url } = require('../../../../../../common/utils/binary')
9
10
 
10
11
  const PLUS_REGEXP = new RegExp('\\+', 'g')
11
12
  const SLASH_REGEXP = new RegExp('/', 'g')
@@ -189,9 +190,9 @@ class ValueConverter {
189
190
  * @param {Buffer|string} value - value, which should be converted
190
191
  * @returns {string} Base64 string
191
192
  */
192
- convertBinary (value) {
193
- // convert the standard base64 encoding to the URL-safe variant
194
- return (Buffer.isBuffer(value) ? value.toString('base64') : value).replace(/\+/g, '-').replace(/\//g, '_')
193
+ convertBinary (value, maxLength) {
194
+ this._valueValidator.validateBinary(value, maxLength)
195
+ return toBase64url(value)
195
196
  }
196
197
 
197
198
  /**
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { big } = require('@sap/cds-foss')
4
+ const { isInvalidBase64string } = require('../../../../../../common/utils/binary')
4
5
  const IllegalArgumentError = require('../errors/IllegalArgumentError')
5
6
 
6
7
  const YEAR_RE = '(?:-?(?:(?:(?:0\\d{3})|(?:[1-9]\\d{3,}))))'
@@ -86,12 +87,13 @@ class ValueValidator {
86
87
 
87
88
  /**
88
89
  * Validates value of Edm.Binary type.
89
- * @param {Buffer} value - Edm.Binary value
90
+ * @param {Buffer} value - Edm.Binary value as base64 or base64url string
90
91
  * @param {number} maxLength - value of MaxLength facet
91
92
  */
92
93
  validateBinary (value, maxLength) {
93
- if (!Buffer.isBuffer(value)) throw this._valueError(value, 'Edm.Binary', 'Buffer instance')
94
- this._checkMaxLength(value, maxLength, 'Edm.Binary')
94
+ // if it's a Buffer instance, just let it go. Otherwise MUST be base64 or base64url string as per OData spec for edm.Binary
95
+ if (isInvalidBase64string(value)) throw this._valueError(value, 'Edm.Binary', 'Buffer instance or base64/base64url string')
96
+ this._checkMaxLength(Buffer.isBuffer(value) ? value : Buffer.from(value, 'base64'), maxLength, 'Edm.Binary')
95
97
  }
96
98
 
97
99
  /**
@@ -89,6 +89,8 @@ class ResponseHeaderSetter {
89
89
  * @returns {ResponseHeaderSetter} this instance of ResponseHeaderSetter
90
90
  */
91
91
  setLocationHeader (overwrite = false) {
92
+ // to prevent reading empty body in case of e.g. no auth by readAfterWrite
93
+ if (this._response.getHeader(HeaderNames.LOCATION)) return this
92
94
  const uriInfo = this._request.getUriInfo()
93
95
  const data = this._response.getBody()
94
96
  const primitiveValueEncoder = this._request
@@ -29,7 +29,7 @@ class DebugSerializingCommand extends Command {
29
29
  const response = this.getContext().getResponse()
30
30
 
31
31
  if (response.isHeadersSent()) {
32
- logger.warning('Headers already sent')
32
+ logger.debug('Headers already sent')
33
33
  next()
34
34
  } else {
35
35
  // The runtime measurement must be stopped before serializing its output,
@@ -35,7 +35,7 @@ class PresetResponseHeadersCommand extends Command {
35
35
  */
36
36
  execute (next) {
37
37
  if (this._response.isHeadersSent()) {
38
- this._logger.warning('Headers already sent')
38
+ this._logger.debug('Headers already sent')
39
39
  } else {
40
40
  new ResponseHeaderSetter(this._request, this._response, this._version, this._logger).setHeaders(true)
41
41
  }
@@ -34,7 +34,7 @@ class SerializingCommand extends Command {
34
34
  const response = context.getResponse()
35
35
 
36
36
  if (response.isHeadersSent()) {
37
- logger.warning('Headers already sent')
37
+ logger.debug('Headers already sent')
38
38
  return next()
39
39
  }
40
40
 
@@ -35,7 +35,7 @@ class SetResponseHeadersCommand extends Command {
35
35
  */
36
36
  execute (next) {
37
37
  if (this._response.isHeadersSent()) {
38
- this._logger.warning('Headers already sent')
38
+ this._logger.debug('Headers already sent')
39
39
  } else {
40
40
  const responseHeaderSetter = new ResponseHeaderSetter(this._request, this._response, null, this._logger)
41
41
  const responseContract = this._response.getContract()
@@ -8,6 +8,7 @@ const RepresentationKind = commons.format.RepresentationKind.Kinds
8
8
  const UriHelper = require('../utils/UriHelper')
9
9
  const SerializationError = require('../errors/SerializationError')
10
10
  const { appURL } = require('../../../../../../common/utils/vcap')
11
+ const cds = require('../../../../../../../../lib')
11
12
 
12
13
  /**
13
14
  * Context URL construction.
@@ -30,10 +31,10 @@ class ContextURLFactory {
30
31
  const lastSegment = pathSegments[pathSegments.length - 1]
31
32
  const contextUrlInfo = this._parseSegments(pathSegments, providedKeyMap, edm)
32
33
  const contextUrlPrefix = this._buildContextUrlPrefix(contextUrlInfo, pathSegments, request, logger)
33
-
34
+
34
35
  if (lastSegment.getKind() === ResourceKind.SERVICE) return `${contextUrlPrefix}$metadata`
35
36
  if (lastSegment.getKind() === ResourceKind.METADATA) return ''
36
-
37
+
37
38
  const finalEdmType = uriInfo.getFinalEdmType()
38
39
  const structuredType =
39
40
  finalEdmType && (finalEdmType.getKind() === EdmTypeKind.ENTITY || finalEdmType.getKind() === EdmTypeKind.COMPLEX)
@@ -19,8 +19,10 @@ class ErrorJsonSerializer extends ErrorSerializer {
19
19
  let result = {
20
20
  code: this._error.code || 'null',
21
21
  message: this._error.message,
22
- target: this._error.target
22
+ target: this._error.target,
23
23
  }
24
+ // REVISIT: We should also pass stack traces in development
25
+ // if (!cds.env.production) result.stack = this._error.stack
24
26
 
25
27
  if (this._error.details) {
26
28
  result.details = this._error.details.map(d => {
@@ -446,6 +446,7 @@ class SerializerFactory {
446
446
  if (!propertyOrReturnType.isNullable()) throw new SerializationError('Not nullable value must not be null')
447
447
  } else if (type === EdmPrimitiveTypeKind.Binary) {
448
448
  new ValueValidator().validateBinary(value, propertyOrReturnType.getMaxLength())
449
+ value = Buffer.isBuffer(value) ? value : Buffer.from(value, 'base64')
449
450
  response.setHeader(HeaderNames.CONTENT_TYPE, data[MetaProperties.MEDIA_CONTENT_TYPE] || ContentTypes.BINARY)
450
451
  } else if (type === EdmPrimitiveTypeKind.Stream) {
451
452
  if (!value.pipe || typeof value.pipe !== 'function') {
@@ -12,6 +12,7 @@ const QueryOptions = commons.uri.UriInfo.QueryOptions
12
12
  const UriHelper = require('../utils/UriHelper')
13
13
  const NextLinkSerializer = require('./NextLinkSerializer')
14
14
  const SerializationError = require('../errors/SerializationError')
15
+ const { toBase64url } = require('../../../../../../common/utils/binary')
15
16
 
16
17
  /**
17
18
  * JSON serializer for trusted OData resources, i.e., there is no validation.
@@ -209,7 +210,7 @@ class TrustedResourceJsonSerializer {
209
210
  * @private
210
211
  */
211
212
  _serializeEntity (result, entityType, data, expandItems, odataPath, structurePath) {
212
- this._serializeAnnotations(result, data, MetaProperties.ETAG)
213
+ this._serializeAnnotations(result, data, MetaProperties.ETAG, MetaProperties.CONTEXT)
213
214
 
214
215
  this._serializeStructure(result, entityType, data, expandItems, odataPath, structurePath || [])
215
216
 
@@ -472,8 +473,7 @@ class TrustedResourceJsonSerializer {
472
473
  if (type === EdmPrimitiveTypeKind.Decimal || type === EdmPrimitiveTypeKind.Int64) {
473
474
  result = this._formatParams.getIEEE754Setting() ? String(propertyValue) : Number(propertyValue)
474
475
  } else if (type === EdmPrimitiveTypeKind.Binary) {
475
- // convert the standard base64 encoding to the URL-safe variant
476
- result = (Buffer.isBuffer(propertyValue) ? propertyValue.toString('base64') : propertyValue).replace(/\+/g, '-').replace(/\//g, '_')
476
+ result = toBase64url(propertyValue)
477
477
  }
478
478
  break
479
479
  case EdmTypeKind.COMPLEX:
@@ -6,13 +6,11 @@ const { findCsnTargetFor } = require('../../../../common/utils/csn')
6
6
  const { isStreaming } = require('./stream')
7
7
  const { convertStructured } = require('../../../../../common/utils/ucsn')
8
8
  const { deepCopy } = require('../../../../common/utils/copy')
9
+ const { getSegmentKeyValue } = require('../odata-to-cqn/utils')
9
10
 
10
11
  const _isFunctionInvocation = req =>
11
12
  req.getUriInfo().getLastSegment().getFunction || req.getUriInfo().getLastSegment().getFunctionImport
12
13
 
13
- const _getTypeName = edmRef =>
14
- edmRef.getProperty ? edmRef.getProperty().getType().getName() : edmRef.getType().getName()
15
-
16
14
  const _addStructuredProperties = ([structName, property, ...nestedProperties], paramData, value) => {
17
15
  paramData[structName] = paramData[structName] || {}
18
16
  if (nestedProperties.length) {
@@ -23,25 +21,6 @@ const _addStructuredProperties = ([structName, property, ...nestedProperties], p
23
21
  paramData[structName][property] = value
24
22
  }
25
23
 
26
- const _getParamKeyValue = segmentParam => {
27
- const edmRef = segmentParam.getEdmRef()
28
- const typeName = _getTypeName(edmRef)
29
- if (segmentParam.getAliasValue())
30
- // must be JSON or a string according to
31
- // https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html#sec_ComplexandCollectionLiterals
32
- try {
33
- return { keyName: edmRef.getName(), value: JSON.parse(segmentParam.getAliasValue()) }
34
- } catch (e) {
35
- return { keyName: edmRef.getName(), value: segmentParam.getAliasValue() }
36
- }
37
-
38
- return {
39
- keyName: edmRef.getName(),
40
- // Convert any integer type into numeric values.
41
- value: typeName.startsWith('Int') ? Number(segmentParam.getText()) : segmentParam.getText()
42
- }
43
- }
44
-
45
24
  /**
46
25
  * The key predicates or function parameters will contain the keys and values for this request.
47
26
  * Combine all key value pairs into one object.
@@ -54,14 +33,14 @@ const _getParamData = parameters => {
54
33
  const paramData = {}
55
34
 
56
35
  for (const segmentParam of parameters) {
57
- const { keyName, value } = _getParamKeyValue(segmentParam)
36
+ const { keyName, val } = getSegmentKeyValue(segmentParam)
58
37
 
59
38
  if (keyName.includes('/')) {
60
- _addStructuredProperties(keyName.split('/'), paramData, value)
39
+ _addStructuredProperties(keyName.split('/'), paramData, val)
61
40
  continue
62
41
  }
63
42
 
64
- paramData[keyName] = value
43
+ paramData[keyName] = val
65
44
  }
66
45
 
67
46
  return paramData
@@ -83,6 +62,11 @@ const _flattenStructureKeys = structureData => {
83
62
  // works only for custom on condition working on keys with '=' operator
84
63
  // and combination of multiple conditions connected with 'and'
85
64
  const _addKeysToData = (navSourceKeyValues, onCondition, data) => {
65
+ if (onCondition[0].xpr) {
66
+ // REVISIT support for nested xpr?
67
+ return _addKeysToData(navSourceKeyValues, onCondition[0].xpr, data)
68
+ }
69
+
86
70
  const flattenKeys = _flattenStructureKeys(navSourceKeyValues)
87
71
  for (const key in flattenKeys) {
88
72
  // find index of source column
@@ -100,6 +84,33 @@ const _addKeysToData = (navSourceKeyValues, onCondition, data) => {
100
84
  data[target] = flattenKeys[key]
101
85
  }
102
86
  }
87
+
88
+ // get static values from onCond
89
+ for (let i = 0; i < onCondition.length; i++) {
90
+ const first = onCondition[i]
91
+ const compare = onCondition[i + 1]
92
+ const second = onCondition[i + 2]
93
+
94
+ if (compare !== '=') continue
95
+
96
+ if (first && first.ref && second && 'val' in second) {
97
+ // ref = val
98
+ _staticOnCond(data, first, second)
99
+ i += 2
100
+ } else if (second && second.ref && first && 'val' in first) {
101
+ // val = ref
102
+ _staticOnCond(data, second, first)
103
+ i += 2
104
+ }
105
+ }
106
+ }
107
+
108
+ const _staticOnCond = (data, ref, val) => {
109
+ const {
110
+ ref: [alias, target]
111
+ } = ref
112
+ if (alias != 'target') return
113
+ data[target] = val.val
103
114
  }
104
115
 
105
116
  function _entityOrTypeName(navSourceSegment) {