@sap/cds 5.9.8 → 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 +252 -20
  2. package/apis/services.d.ts +1 -1
  3. package/app/fiori/preview.js +2 -6
  4. package/app/index.js +3 -3
  5. package/bin/build/buildTaskEngine.js +17 -15
  6. package/bin/build/buildTaskFactory.js +29 -19
  7. package/bin/build/buildTaskHandler.js +27 -11
  8. package/bin/build/buildTaskProvider.js +2 -4
  9. package/bin/build/buildTaskProviderFactory.js +11 -16
  10. package/bin/build/constants.js +14 -6
  11. package/bin/build/csv-reader.js +2 -1
  12. package/bin/build/index.js +12 -18
  13. package/bin/build/provider/buildTaskHandlerEdmx.js +3 -39
  14. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +149 -0
  15. package/bin/build/provider/buildTaskHandlerInternal.js +2 -3
  16. package/bin/build/provider/buildTaskProviderInternal.js +108 -239
  17. package/bin/build/provider/fiori/index.js +2 -2
  18. package/bin/build/provider/hana/2migration.js +11 -11
  19. package/bin/build/provider/hana/2tabledata.js +3 -3
  20. package/bin/build/provider/hana/index.js +89 -99
  21. package/bin/build/provider/hana/migrationtable.js +4 -3
  22. package/bin/build/provider/java/index.js +101 -0
  23. package/bin/build/provider/java-cf/index.js +1 -101
  24. package/bin/build/provider/mtx/index.js +83 -41
  25. package/bin/build/provider/mtx/resourcesTarBuilder.js +68 -0
  26. package/bin/build/provider/mtx-sidecar/index.js +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 +4 -3
  39. package/common.cds +61 -16
  40. package/lib/compile/cdsc.js +3 -2
  41. package/lib/compile/etc/_localized.js +15 -14
  42. package/lib/compile/for/drafts.js +3 -4
  43. package/lib/compile/for/java.js +13 -10
  44. package/lib/compile/for/nodejs.js +8 -8
  45. package/lib/compile/for/odata.js +7 -12
  46. package/lib/compile/for/sql.js +5 -6
  47. package/lib/compile/index.js +5 -4
  48. package/lib/compile/load.js +9 -11
  49. package/lib/compile/minify.js +8 -5
  50. package/lib/compile/parse.js +4 -2
  51. package/lib/compile/resolve.js +18 -15
  52. package/lib/compile/to/edm.js +0 -1
  53. package/lib/compile/to/gql.js +3 -2
  54. package/lib/compile/to/json.js +24 -17
  55. package/lib/connect/bindings.js +3 -2
  56. package/lib/connect/index.js +5 -5
  57. package/lib/core/classes.js +74 -2
  58. package/lib/core/entities.js +52 -3
  59. package/lib/core/reflect.js +2 -1
  60. package/lib/deploy.js +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 +127 -41
  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 +8 -7
  156. package/libx/_runtime/common/composition/tree.js +10 -10
  157. package/libx/_runtime/common/composition/update.js +3 -2
  158. package/libx/_runtime/common/constants/events.js +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 +7 -3
  174. package/libx/_runtime/common/generic/temporal.js +0 -5
  175. package/libx/_runtime/common/i18n/messages.properties +2 -1
  176. package/libx/_runtime/common/utils/binary.js +69 -0
  177. package/libx/_runtime/common/utils/cqn.js +39 -14
  178. package/libx/_runtime/common/utils/cqn2cqn4sql.js +93 -59
  179. package/libx/_runtime/common/utils/csn.js +87 -85
  180. package/libx/_runtime/common/utils/dollar.js +8 -7
  181. package/libx/_runtime/common/utils/draft.js +1 -1
  182. package/libx/_runtime/common/utils/foreignKeyPropagations.js +23 -7
  183. package/libx/_runtime/common/utils/generateOnCond.js +2 -1
  184. package/libx/_runtime/common/utils/keys.js +30 -13
  185. package/libx/_runtime/common/utils/postProcessing.js +6 -1
  186. package/libx/_runtime/common/utils/quotingStyles.js +0 -23
  187. package/libx/_runtime/common/utils/resolveStructured.js +23 -26
  188. package/libx/_runtime/common/utils/resolveView.js +4 -1
  189. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -0
  190. package/libx/_runtime/common/utils/search2cqn4sql.js +4 -13
  191. package/libx/_runtime/common/utils/searchToLike.js +9 -13
  192. package/libx/_runtime/common/utils/streamProp.js +35 -0
  193. package/libx/_runtime/common/utils/structured.js +12 -18
  194. package/libx/_runtime/common/utils/template.js +3 -5
  195. package/libx/_runtime/common/utils/templateProcessor.js +22 -14
  196. package/libx/_runtime/common/utils/unionCqnTemplate.js +4 -14
  197. package/libx/_runtime/db/Service.js +2 -1
  198. package/libx/_runtime/db/expand/expand-v2.js +2 -2
  199. package/libx/_runtime/db/expand/expandCQNToJoin.js +7 -6
  200. package/libx/_runtime/db/generic/input.js +14 -17
  201. package/libx/_runtime/db/generic/integrity.js +1 -2
  202. package/libx/_runtime/db/generic/update.js +14 -1
  203. package/libx/_runtime/db/query/read.js +0 -1
  204. package/libx/_runtime/db/query/update.js +1 -1
  205. package/libx/_runtime/db/sql-builder/BaseBuilder.js +1 -1
  206. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +5 -31
  207. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
  208. package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +0 -9
  209. package/libx/_runtime/db/sql-builder/SelectBuilder.js +11 -10
  210. package/libx/_runtime/db/sql-builder/UpdateBuilder.js +2 -2
  211. package/libx/_runtime/db/sql-builder/annotations.js +1 -2
  212. package/libx/_runtime/db/utils/coloredTxCommands.js +5 -0
  213. package/libx/_runtime/db/utils/columns.js +1 -1
  214. package/libx/_runtime/db/utils/propagateForeignKeys.js +10 -2
  215. package/libx/_runtime/extensibility/activate.js +69 -0
  216. package/libx/_runtime/extensibility/add.js +41 -0
  217. package/libx/_runtime/extensibility/addExtension.js +68 -0
  218. package/libx/_runtime/extensibility/defaults.js +39 -0
  219. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformREAD.js +0 -0
  220. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformRESULT.js +2 -2
  221. package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformWRITE.js +2 -2
  222. package/libx/_runtime/extensibility/push.js +61 -0
  223. package/libx/_runtime/extensibility/service.js +21 -0
  224. package/libx/_runtime/extensibility/{uiflex/utils.js → utils.js} +39 -3
  225. package/libx/_runtime/extensibility/validation.js +53 -0
  226. package/libx/_runtime/extensibility/views.js +12 -0
  227. package/libx/_runtime/fiori/generic/activate.js +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
@@ -3,6 +3,7 @@
3
3
  /**
4
4
  * @typedef {object} ColumnRef
5
5
  * @property {Array<string>} ref
6
+ * @property {function} func
6
7
  */
7
8
 
8
9
  /**
@@ -17,7 +18,7 @@
17
18
  * @property {*} value
18
19
  * @property {Array} errors
19
20
  * @property {string} [key]
20
- * @property {string[]} [pathSegments]
21
+ * @property {pathSegment[]} [pathSegments]
21
22
  * @property {string} event
22
23
  */
23
24
 
@@ -49,7 +50,7 @@
49
50
  * @typedef {object} TemplateProcessorPathOptions
50
51
  * @property {object} [extraKeys]
51
52
  * @property {function} [rowKeysGenerator]
52
- * @property {pathSegment[]} [path=[]] - Path segments to relate the error message.
53
+ * @property {string[]} [segments=[]] - Path segments to relate the error message.
53
54
  * @property {boolean} [includeKeyValues=false] Indicates whether the key values are included in the path segments
54
55
  * The path segments are used to build the error target (a relative resource path)
55
56
  */
@@ -64,20 +65,14 @@
64
65
  */
65
66
 
66
67
  /**
67
- * @typedef {object} templateProcessorProcessFnArgs
68
+ * @typedef {object} templateElementInfo
68
69
  * @property {object} row
69
70
  * @property {string} key
70
71
  * @property {object} element
71
72
  * @property {boolean} plain
73
+ * @property {entity} target
72
74
  * @property {boolean} isRoot
73
- * @property {Array<pathSegment>} [path]
74
- */
75
-
76
- /**
77
- * @typedef {object} pathSegment
78
- * @property {string} key
79
- * @property {number} idx
80
- * @property {string} url
75
+ * @property {Array<String>} [pathSegments]
81
76
  */
82
77
 
83
78
  // Search
@@ -113,4 +108,21 @@
113
108
  * @property {import('../db/Service')} [service]
114
109
  */
115
110
 
111
+ // Assert targets map
112
+
113
+ /**
114
+ * @typedef {object} assertTargetMap
115
+ * @property {Map<string, targetMaps>} targets
116
+ * @property {targetMaps[]} allTargets
117
+ */
118
+
119
+ /**
120
+ * @typedef {object} targetMaps
121
+ * @property {string} key
122
+ * @property {entity} entity
123
+ * @property {object} keys
124
+ * @property {object} foreignKey
125
+ * @property {templateElementInfo} assocInfo
126
+ */
127
+
116
128
  module.exports = {}
@@ -61,32 +61,38 @@ const _processor = ({ row, key, plain: { category }, element }) => {
61
61
  }
62
62
  }
63
63
 
64
- const _cleanup = (row, definition, cleanupNull) => {
64
+ const _cleanup = (row, definition, cleanupNull, cleanupStruct, prefix = []) => {
65
65
  if (!row || !definition) return
66
66
  const elements = definition.elements || definition.params
67
67
  for (const key of Object.keys(row)) {
68
- const element = elements[key]
68
+ if (definition['@open']) continue
69
+ const element = elements[key] || (cleanupStruct && elements[`${prefix.join('_')}_${key}`])
69
70
  if (!element) {
70
- if (!definition['@open']) delete row[key]
71
+ if (cleanupStruct && typeof row[key] === 'object' && !Array.isArray(row[key])) {
72
+ _cleanup( row[key], definition, cleanupNull, cleanupStruct, [...prefix, key])
73
+ } else {
74
+ delete row[key]
75
+ }
71
76
  continue
72
77
  }
73
78
  if (!row[key]) continue
74
79
  if (element.isAssociation) {
75
80
  if (element.is2many) {
76
81
  for (const r of row[key]) {
77
- _cleanup(r, element._target, cleanupNull)
82
+ _cleanup(r, element._target, cleanupNull, cleanupStruct, [])
78
83
  }
79
84
  } else {
80
- _cleanup(row[key], element._target, cleanupNull)
85
+ _cleanup(row[key], element._target, cleanupNull, cleanupStruct, [])
81
86
  }
82
87
  } else if (element.elements) {
83
- _cleanup(row[key], element, cleanupNull)
88
+ _cleanup(row[key], element, cleanupNull, cleanupStruct, prefix)
89
+ if (!Object.keys(row).length) delete row[key]
84
90
  if (cleanupNull && Object.values(row[key]).every(v => v == null)) row[key] = null
85
91
  }
86
92
  }
87
93
  }
88
94
 
89
- function convertStructured(service, definition, data, { cleanupNull = false } = {}) {
95
+ function convertStructured(service, definition, data, { cleanupNull = false, cleanupStruct = false } = {}) {
90
96
  if (!definition) return
91
97
  // REVISIT check `structs` mode only for now as uCSN is not yet available
92
98
  const flatAccess = cds.env.features.compat_flat_access
@@ -95,11 +101,11 @@ function convertStructured(service, definition, data, { cleanupNull = false } =
95
101
  if (template && template.elements.size) {
96
102
  for (let i = 0; i < arrayData.length; i++) {
97
103
  const row = proxifyIfFlattened(definition, arrayData[i])
98
- templateProcessor({ processFn: _processor, row, template, pathOptions: { path: [] } })
104
+ templateProcessor({ processFn: _processor, row, template })
99
105
  }
100
106
  }
101
107
  for (const row of arrayData) {
102
- _cleanup(row, definition, cleanupNull)
108
+ _cleanup(row, definition, cleanupNull, cleanupStruct)
103
109
  }
104
110
  }
105
111
 
@@ -1,6 +1,6 @@
1
1
  const cds = require('../_runtime/cds')
2
2
 
3
- const { where2obj } = require('../_runtime/common/utils/cqn')
3
+ const { where2obj, resolveFromSelect } = require('../_runtime/common/utils/cqn')
4
4
  const { findCsnTargetFor } = require('../_runtime/common/utils/csn')
5
5
 
6
6
  const _addKeysDeep = (keys, keysCollector, ignoreManagedBacklinks) => {
@@ -52,14 +52,38 @@ function _resolveAliasInParams(params, entity) {
52
52
  }
53
53
  }
54
54
 
55
- function _resolveAliasInWhere(where, entity) {
56
- if (!entity._alias2ref) return
57
- for (const w of where) {
58
- if (!w.ref || w.ref.length > 1 || entity.keys[w.ref[0]]) continue
59
- w.ref = entity._alias2ref[w.ref[0]] || w.ref
55
+ function _resolveAliasesInRef(ref, target) {
56
+ if (ref.length === 1) {
57
+ if (target.keys[ref[0]]) return ref
58
+ if (target._alias2ref && target._alias2ref[ref[0]]) return [...target._alias2ref[ref[0]]]
59
+ }
60
+ for (const seg of ref) {
61
+ target = target.elements[seg.id || seg]
62
+ if (!target) return ref
63
+ if (target.isAssociation) {
64
+ target = target._target
65
+ if (seg.where) _resolveAliasesInXpr(seg.where, target)
66
+ }
67
+ }
68
+ return ref
69
+ }
70
+
71
+ function _resolveAliasesInXpr(xpr, target) {
72
+ if (!target || !xpr) return
73
+ for (const el of xpr) {
74
+ if (el.xpr) _resolveAliasesInXpr(el.xpr, target)
75
+ if (el.args) _resolveAliasesInXpr(el.args, target)
76
+ if (el.ref) el.ref = _resolveAliasesInRef(el.ref, target)
60
77
  }
61
78
  }
62
79
 
80
+ function _resolveAliasesInNavigation(cqn, target) {
81
+ if (!target || !cqn) return
82
+ if (cqn.SELECT.from.SELECT) _resolveAliasesInNavigation(cqn.SELECT.from, target)
83
+ if (cqn.SELECT.where) _resolveAliasesInXpr(cqn.SELECT.where, target)
84
+ if (cqn.SELECT.having) _resolveAliasesInXpr(cqn.SELECT.having, target)
85
+ }
86
+
63
87
  function _addDefaultParams(ref, view) {
64
88
  const params = view.params
65
89
  const defaults = params && Object.values(params).filter(p => p.default)
@@ -87,9 +111,8 @@ function addRefToWhereIfNecessary(where, entity) {
87
111
  return 1
88
112
  }
89
113
 
90
- function _processSegments(cqn, model, namespace) {
91
- const from = _resolveFrom(cqn.SELECT.from)
92
- const ref = from.ref
114
+ function _processSegments(from, model, namespace) {
115
+ const { ref } = from
93
116
 
94
117
  let current = model
95
118
  let path
@@ -97,13 +120,14 @@ function _processSegments(cqn, model, namespace) {
97
120
  let keyCount = 0
98
121
  let incompleteKeys
99
122
  let one
123
+ let target
100
124
  for (let i = 0; i < ref.length; i++) {
101
125
  const seg = ref[i].id || ref[i]
102
126
  let params = ref[i].where && where2obj(ref[i].where)
103
127
 
104
128
  if (incompleteKeys) {
105
129
  // > key
106
- keys = keys || _keysOf(current, !cds.env.features.rest_new_adapter && !cds.env.features.rest_new_parser) // if odata skip backlinks as key as they are used from structure
130
+ keys = keys || _keysOf(current, cds.env.features.odata_new_parser) // if odata, skip backlinks as key as they are used from structure
107
131
  let key = keys[keyCount++]
108
132
  one = true
109
133
  const element = current.elements[key]
@@ -118,7 +142,9 @@ function _processSegments(cqn, model, namespace) {
118
142
  .join(',')})`
119
143
  base.where.push({ ref: [key] }, '=', { val })
120
144
  } else {
121
- base.where.push({ ref: [key] }, '=', { val: element._type === 'cds.Integer' ? Number(seg) : seg })
145
+ const val =
146
+ element._type === 'cds.Integer' ? Number(seg) : element._type === 'cds.Boolean' ? seg === 'true' : seg
147
+ base.where.push({ ref: [key] }, '=', { val })
122
148
  }
123
149
  ref[i] = null
124
150
  ref[i - keyCount] = base
@@ -137,9 +163,10 @@ function _processSegments(cqn, model, namespace) {
137
163
 
138
164
  if (current.params && current.kind === 'entity') {
139
165
  // > View with params
166
+ target = current
140
167
  if (ref[i].where) {
141
168
  keyCount += addRefToWhereIfNecessary(ref[i].where, current)
142
- _resolveAliasInWhere(ref[i].where, current)
169
+ _resolveAliasesInXpr(ref[i].where, current)
143
170
  _resolveAliasInParams(params, current)
144
171
  }
145
172
 
@@ -149,10 +176,12 @@ function _processSegments(cqn, model, namespace) {
149
176
  _checkAllKeysProvided(params, current)
150
177
 
151
178
  ref[i].args = {}
152
- for (let j = 0; j < ref[i].where.length; j++) {
153
- const w = ref[i].where[j]
154
- if (w === 'and' || !w.ref) continue
155
- ref[i].args[w.ref[0]] = ref[i].where[j + 2]
179
+
180
+ const where = ref[i].where
181
+ for (let j = 0; j < where.length; j++) {
182
+ const whereElement = where[j]
183
+ if (whereElement === 'and' || !whereElement.ref) continue
184
+ ref[i].args[whereElement.ref[0]] = where[j + 2]
156
185
  j += 2
157
186
  }
158
187
  ref[i].where = undefined
@@ -163,11 +192,12 @@ function _processSegments(cqn, model, namespace) {
163
192
  ref[++i] = null
164
193
  } else if (current.kind === 'entity') {
165
194
  // > entity
195
+ target = current
166
196
  one = !!(ref[i].where || current._isSingleton)
167
197
  incompleteKeys = ref[i].where ? false : i === ref.length - 1 || one ? false : true
168
198
  if (ref[i].where) {
169
199
  keyCount += addRefToWhereIfNecessary(ref[i].where, current)
170
- _resolveAliasInWhere(ref[i].where, current)
200
+ _resolveAliasesInXpr(ref[i].where, current)
171
201
  _resolveAliasInParams(params, current)
172
202
  // in case of Foo(1), params will be {} (before addRefToWhereIfNecessary was called)
173
203
  if (!Object.keys(params).length) params = where2obj(ref[i].where)
@@ -187,14 +217,14 @@ function _processSegments(cqn, model, namespace) {
187
217
  one = !!(current.is2one || ref[i].where)
188
218
  incompleteKeys = one || i === ref.length - 1 ? false : true
189
219
  current = model.definitions[current.target]
220
+ target = current
190
221
  if (ref[i].where) {
191
222
  keyCount += addRefToWhereIfNecessary(ref[i].where, current)
192
- _resolveAliasInWhere(ref[i].where, current)
223
+ _resolveAliasesInXpr(ref[i].where, current)
193
224
  }
194
225
  } else if (current._isStructured) {
195
226
  // > nested property
196
227
  one = true
197
- current = current.elements
198
228
  } else {
199
229
  // > property
200
230
  one = true
@@ -217,15 +247,42 @@ function _processSegments(cqn, model, namespace) {
217
247
  // remove all nulled refs
218
248
  from.ref = ref.filter(r => r)
219
249
 
220
- // one?
221
- if (one) cqn.SELECT.one = true
222
-
223
- // REVISIT: better
224
- // set target (csn definition) for later retrieval
225
- cqn.__target = current
250
+ return { one, current, target }
226
251
  }
227
252
 
228
- const _resolveFrom = from => (from.SELECT ? _resolveFrom(from.SELECT.from) : from)
253
+ const AGGREGATION_DEFAULT = '@Aggregation.default'
254
+
255
+ function _processColumns(cqn, target) {
256
+ if (cqn.SELECT.from.SELECT) _processColumns(cqn.SELECT.from, target)
257
+
258
+ const columns = cqn.SELECT.columns
259
+
260
+ if (!Array.isArray(columns)) return
261
+
262
+ let aggrProp, aggrElem
263
+ for (let i = 0; i < columns.length; i++) {
264
+ if (
265
+ columns[i].func === null &&
266
+ columns[i].args &&
267
+ columns[i].args.length &&
268
+ columns[i].args[0].ref &&
269
+ columns[i].args[0].ref.length
270
+ ) {
271
+ // REVISIT: also support aggregate(Sales/Amount)?
272
+ aggrProp = columns[i].args[0].ref[0]
273
+ aggrElem = target.elements[aggrProp]
274
+ if (
275
+ aggrElem &&
276
+ target[`@Aggregation.CustomAggregate#${aggrProp}`] &&
277
+ aggrElem[AGGREGATION_DEFAULT] &&
278
+ aggrElem[AGGREGATION_DEFAULT]['#']
279
+ ) {
280
+ columns[i].func = aggrElem[AGGREGATION_DEFAULT]['#'].toLowerCase()
281
+ columns[i].as = columns[i].as || aggrProp
282
+ } else throw new Error(`Default aggregation for property '${aggrProp}' not found.`)
283
+ }
284
+ }
285
+ }
229
286
 
230
287
  const _checkAllKeysProvided = (params, entity) => {
231
288
  let keysOfEntity
@@ -267,13 +324,21 @@ function _4service(service) {
267
324
  const { namespace, model } = service
268
325
 
269
326
  return cqn => {
270
- const { ref } = _resolveFrom(cqn.SELECT.from)
327
+ const from = resolveFromSelect(cqn)
328
+ const { ref } = from
271
329
 
272
330
  // REVISIT: shouldn't be necessary
331
+ //Second findCsnTargetFor is required for concat query, where the root is already identified with the first query and subsequent queries already have correct root
273
332
  /*
274
333
  * make first path segment fully qualified
275
334
  */
276
- const root = findCsnTargetFor(ref[0].id || ref[0], model, namespace)
335
+ const root =
336
+ findCsnTargetFor(ref[0].id || ref[0], model, namespace) ||
337
+ findCsnTargetFor(
338
+ ref[0].id?.split('.')[ref[0].id?.split('.').length - 1] || ref[0].split('.')[ref[0].split('.').length - 1],
339
+ model,
340
+ namespace
341
+ )
277
342
  // REVISIT: 404 or 400?
278
343
  if (!root) cds.error(`Invalid resource path "${namespace}.${ref[0].id || ref[0]}"`, { code: 404 })
279
344
  if (ref[0].id) ref[0].id = root.name
@@ -282,7 +347,22 @@ function _4service(service) {
282
347
  /*
283
348
  * key vs. path segments (/Books/1/author/books/2/...) and more
284
349
  */
285
- _processSegments(cqn, model, namespace)
350
+ const { one, current, target } = _processSegments(from, model, namespace)
351
+
352
+ // one?
353
+ if (one) cqn.SELECT.one = true
354
+
355
+ // REVISIT: better
356
+ // set target (csn definition) for later retrieval
357
+ cqn.__target = current
358
+
359
+ // target <=> endpoint entity, all navigation refs must be resolvable accordingly
360
+ if (cds.env.effective.odata.structs) _resolveAliasesInNavigation(cqn, target)
361
+
362
+ /*
363
+ * add default aggregation function (and alias)
364
+ */
365
+ _processColumns(cqn, cqn.__target)
286
366
 
287
367
  return cqn
288
368
  }
@@ -95,8 +95,8 @@ function _args(args) {
95
95
 
96
96
  const _in = (column, /* in */ collection, target, kind, isLambda) => {
97
97
  const ref = _format(column, null, target, kind, isLambda)
98
- // { val: [ 1, 2, 3 ] } or { list: [ { val: 1}, { val: 2}, { val: 3} ] }
99
- const values = collection.val || collection.list
98
+ // { list: [ { val: 1}, { val: 2}, { val: 3} ] }
99
+ const values = collection.list
100
100
  if (values && values.length) {
101
101
  // REVISIT: what about OData `in` operator?
102
102
  const expressions = values.map(value => `${ref}%20eq%20${_format(value, ref, target, kind, isLambda)}`)
@@ -117,7 +117,7 @@ const _odataV2Func = (func, args) => {
117
117
  const _format = (cur, element, target, kind, isLambda) => {
118
118
  if (typeof cur !== 'object') return encodeURIComponent(formatVal(cur, element, target, kind))
119
119
  if (hasValidProps(cur, 'ref'))
120
- return encodeURIComponent(isLambda ? [LAMBDA_VARIABLE, ...cur.ref].join('/') : cur.ref.join('/'))
120
+ return encodeURIComponent(isLambda ? [LAMBDA_VARIABLE, ...cur.ref].join('/') : cur.ref[0].id || cur.ref.join('/'))
121
121
  if (hasValidProps(cur, 'val')) return encodeURIComponent(formatVal(cur.val, element, target, kind))
122
122
  if (hasValidProps(cur, 'xpr')) return `(${_xpr(cur.xpr, target, kind, isLambda)})`
123
123
  // REVISIT: How to detect the types for all functions?
@@ -196,9 +196,24 @@ const _keysOfWhere = (where, kind, target) => {
196
196
  return `/${keys}`
197
197
  }
198
198
 
199
+ if (where.length === 3) {
200
+ const [left, op, right] = where
201
+ if (op === '=' && (('val' in left && right.ref) || (left.ref && 'val' in right))) {
202
+ if ('val' in left) return `(${formatVal(left.val, right.ref.join('/'), target, kind)})`
203
+ return `(${formatVal(right.val, left.ref.join('/'), target, kind)})`
204
+ }
205
+ }
206
+
199
207
  const res = []
200
208
  for (const cur of where) {
201
209
  if (hasValidProps(cur, 'ref')) {
210
+ if (target && target._alias2ref) {
211
+ const alias = target._alias2ref.__2alias[cur.ref.join('/')]
212
+ if (alias) {
213
+ res.push(_format({ ref: [alias] }))
214
+ continue
215
+ }
216
+ }
202
217
  res.push(_format(cur))
203
218
  } else if (hasValidProps(cur, 'val')) {
204
219
  // find previous ref
@@ -228,6 +243,24 @@ function _getQueryTarget(entity, propOrEntity, model) {
228
243
  }
229
244
  }
230
245
 
246
+ const _params = (args, kind, target) => {
247
+ if (!args) {
248
+ throw new Error(`Incorrect call to a view with parameter "${target.name}"`)
249
+ }
250
+ const params = Object.keys(args)
251
+ if (params.length !== Object.keys(target.params).length) {
252
+ throw new Error('KEY_EXPECTED')
253
+ }
254
+ if (params.length === 1) {
255
+ return `(${formatVal(args[params[0]].val, params[0], target, kind)})`
256
+ }
257
+ const _params = []
258
+ for (const p of params) {
259
+ _params.push(`${_format({ ref: [p] })}=${formatVal(args[p].val, p, target, kind)}`)
260
+ }
261
+ return `(${_params.join(',')})`
262
+ }
263
+
231
264
  function _from(from, kind, model) {
232
265
  if (typeof from === 'string') {
233
266
  return { url: _entityUrl(from), queryTarget: model && model.definitions[from] }
@@ -245,6 +278,11 @@ function _from(from, kind, model) {
245
278
  queryTarget = model && _getQueryTarget(queryTarget, id, model)
246
279
  const keys = _keysOfWhere(where, kind, queryTarget)
247
280
  path.push(`${id}${keys}`)
281
+ } else if (hasValidProps(curRef, 'id') && 'args' in curRef) {
282
+ const { args, id } = curRef
283
+ queryTarget = model && _getQueryTarget(queryTarget, id, model)
284
+ const params = _params(args, kind, queryTarget)
285
+ path.push(`${id}${params}`)
248
286
  } else if (typeof curRef === 'string') {
249
287
  queryTarget = model && _getQueryTarget(queryTarget, curRef, model)
250
288
  path.push(curRef)
@@ -288,7 +326,7 @@ const _parseColumns = columns => {
288
326
  let refName = _format(column)
289
327
  if (hasValidProps(column, 'expand')) {
290
328
  // REVISIT: incomplete, see test Foo?$expand=invoices($count=true;$expand=item($search="some"))
291
- if (!columns.some(c => !c.expand)) select.push(refName)
329
+ if (!columns.some(c => !c.expand) && !column.ref[0].id) select.push(refName)
292
330
  const curOptions = getOptions(column).join(';')
293
331
  refName += curOptions ? `(${curOptions})` : ''
294
332
  expand.push(refName)
@@ -429,7 +467,8 @@ const parsers = {
429
467
  orderBy: (cqnPart, url, kind, target, isCount) => !isCount && $orderBy(cqnPart),
430
468
  count: (cqnPart, url, kind, target, isCount) => !isCount && $count(cqnPart, kind),
431
469
  limit: (cqnPart, url, kind, target, isCount) => !isCount && $limit(cqnPart),
432
- one: (cqnPart, url, kind, target, isCount) => !isCount && $one(cqnPart, url, kind)
470
+ one: (cqnPart, url, kind, target, isCount) => !isCount && $one(cqnPart, url, kind),
471
+ ref: (cqnPart, url, kind, target, isCount) => cqnPart[0].where && $where(cqnPart[0].where, target, kind)
433
472
  }
434
473
 
435
474
  function getOptions(cqnPart, url, kind, target, isCount) {
@@ -484,7 +523,7 @@ const _copyData = data => {
484
523
  return copied
485
524
  }
486
525
 
487
- const _update = (cqn, kind, model) => {
526
+ const _update = (cqn, kind, model, method) => {
488
527
  const UPDATE = getProp(cqn, 'UPDATE')
489
528
  const { url, queryTarget } = _from(getProp(UPDATE, 'entity'), kind, model)
490
529
  let keys = ''
@@ -498,7 +537,7 @@ const _update = (cqn, kind, model) => {
498
537
 
499
538
  // TODO: support for .set as well
500
539
  const body = _copyData(UPDATE.data)
501
- return { method: 'PATCH', path: `${url}${keys}`, body }
540
+ return { method: method || 'PATCH', path: `${url}${keys}`, body }
502
541
  }
503
542
 
504
543
  const _delete = (cqn, kind, model) => {
@@ -517,10 +556,10 @@ const _delete = (cqn, kind, model) => {
517
556
  return { method: 'DELETE', path: `${url}${keys}` }
518
557
  }
519
558
 
520
- function cqn2odata(cqn, kind, model) {
559
+ function cqn2odata(cqn, { kind, model, method }) {
521
560
  if (cqn.SELECT) return _select(cqn, kind, model)
522
561
  if (cqn.INSERT) return _insert(cqn, kind, model)
523
- if (cqn.UPDATE) return _update(cqn, kind, model)
562
+ if (cqn.UPDATE) return _update(cqn, kind, model, method)
524
563
  if (cqn.DELETE) return _delete(cqn, kind, model)
525
564
 
526
565
  throw new Error('Unknown CQN object cannot be translated to URL: ' + JSON.stringify(cqn))