@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
@@ -1,57 +1,14 @@
1
1
  const cds = require('../../cds')
2
-
3
2
  const CHALLENGE = 'Basic realm="Users"'
4
3
 
5
- const _getUser = (users, id) => {
6
- let user
7
-
8
- for (const k in users) {
9
- if (k === id || users[k].ID === id) {
10
- user = users[k]
11
- break
12
- }
13
- }
14
-
15
- if (!user && users['*']) user = { id }
16
-
17
- return user
18
- }
19
-
20
- const _getRoles = user => {
21
- const _roles = ['any', 'identified-user', 'authenticated-user']
22
-
23
- if (user.roles) {
24
- _roles.push(...user.roles)
25
- }
26
-
27
- if (user.jwt) {
28
- const scopes = user.jwt.scope || user.jwt.scopes || []
29
- const aud = user.jwt.aud || []
30
- _roles.push(
31
- ...scopes.map(s => {
32
- for (const each of aud) {
33
- s = s.replace(`${each}.`, '')
34
- }
35
- return s
36
- })
37
- )
38
- }
39
-
40
- if (user.jwt && (user.jwt.grant_type === 'client_credentials' || user.jwt.grant_type === 'client_x509')) {
41
- _roles.push('system-user')
42
- }
43
-
44
- return _roles
45
- }
46
-
47
4
  class MockStrategy {
48
- constructor(users, name = 'mock') {
5
+ constructor({ users, tenants }, name = 'mock') {
49
6
  this.name = name
50
- this.users = users || cds.env.requires.auth.users || {}
7
+ this.users = _init_users(users || cds.env.requires.auth.users || {}, tenants)
51
8
  }
52
9
 
53
10
  authenticate(req) {
54
- const authorization = req.headers.authorization
11
+ const { authorization } = req.headers
55
12
  if (!authorization) return this.fail(CHALLENGE)
56
13
 
57
14
  const [scheme, base64] = authorization.split(' ')
@@ -59,18 +16,62 @@ class MockStrategy {
59
16
  if (!base64) return this.fail(CHALLENGE)
60
17
 
61
18
  const [id, password] = Buffer.from(base64, 'base64').toString().split(':')
62
-
63
- let user = _getUser(this.users, id)
19
+ const user = this.users[id] || ('*' in this.users && { id })
64
20
  if (!user) return this.fail(CHALLENGE)
65
21
  if (user.password && user.password !== password) return this.fail(CHALLENGE)
66
22
 
67
- const _roles = _getRoles(user)
68
- const attr = Object.assign({}, user.userAttributes, user.jwt && user.jwt.userInfo, user.jwt && user.jwt.attributes)
69
- const tenant = user.tenant || (user.jwt && user.jwt.zid) || null
23
+ const { features } = req.headers
24
+ this.success(new cds.User(features ? { ...user, features } : user))
25
+ }
26
+ }
70
27
 
71
- user = new cds.User({ id: user.ID || id, _roles, attr, tenant })
72
- this.success(user)
28
+ // eslint-disable-next-line complexity
29
+ const _init_users = (users, tenants = {}) => {
30
+ if (!users._initialized) {
31
+ Object.defineProperty(users, '_initialized', { value: true })
32
+ for (let [id, user] of Object.entries(users)) {
33
+ if (id !== '*') user.id = user.ID || user.id || id // fill in user ids
34
+ if (id !== user.id) users[user.id] = user
35
+ if (user.jwt) {
36
+ let scopes = user.jwt.scope || user.jwt.scopes
37
+ if (scopes) {
38
+ const aud = user.jwt.aud
39
+ if (aud)
40
+ scopes = scopes.map(s => {
41
+ for (const each of aud) s = s.replace(`${each}.`, '')
42
+ return s
43
+ })
44
+ Array.isArray(user.roles) ? user.roles.push(...scopes) : (user.roles = scopes)
45
+ }
46
+ if (user.jwt.grant_type === 'client_credentials' || user.jwt.grant_type === 'client_x509') {
47
+ user.roles.push('system-user')
48
+ }
49
+ if (!user.tenant && user.jwt.zid) user.tenant = user.jwt.zid
50
+ }
51
+
52
+ // optimization:
53
+ if (user.roles)
54
+ user.roles = user.roles.reduce((p, n) => {
55
+ p[n] = 1
56
+ return p
57
+ }, {})
58
+
59
+ // apply tenant info if any
60
+ if (!user.features) {
61
+ const features = tenants[user.tenant]?.features
62
+ if (features) user.features = features
63
+ }
64
+
65
+ const attr = Object.assign(
66
+ {},
67
+ user.userAttributes,
68
+ user.jwt && user.jwt.userInfo,
69
+ user.jwt && user.jwt.attributes
70
+ )
71
+ if (Object.keys(attr).length > 0) user.attr = attr
72
+ }
73
73
  }
74
+ return users
74
75
  }
75
76
 
76
77
  module.exports = MockStrategy
@@ -25,10 +25,9 @@ const getRoles = (roles, info, credentials) => {
25
25
 
26
26
  if (info && info.checkLocalScope && typeof info.checkLocalScope === 'function') {
27
27
  // > xssec v3
28
- const _roles = roles
29
- roles = new Proxy(_roles, {
30
- get: function (_, role) {
31
- return role in _roles ? _roles[role] : info.checkLocalScope(role)
28
+ roles = new Proxy(roles, {
29
+ get: function (t, role) {
30
+ return role in t ? t[role] : info.checkLocalScope(role)
32
31
  }
33
32
  })
34
33
  }
@@ -22,10 +22,11 @@ class XSUAAStrategy extends JS {
22
22
  // create cds.User
23
23
  user = new cds.User({
24
24
  id: xssecUtils.getUserId(user, info),
25
- tenant: xssecUtils.getTenant(info) || null,
26
- _roles: xssecUtils.getRoles(['any', 'identified-user'], info, credentials),
25
+ roles: xssecUtils.getRoles(['any', 'identified-user'], info, credentials),
27
26
  attr: xssecUtils.getAttrForXSSEC(info)
28
27
  })
28
+ const tenant = xssecUtils.getTenant(info)
29
+ if (tenant) user.tenant = tenant
29
30
  // call "super.success"
30
31
  _success(user, info)
31
32
  }
@@ -1,25 +1,12 @@
1
- const cds = require('../cds')
2
-
3
1
  const UNAUTHORIZED = { statusCode: 401, code: '401', message: 'Unauthorized' }
4
2
  const FORBIDDEN = { statusCode: 403, code: '403', message: 'Forbidden' }
5
3
 
6
4
  const getRequiresAsArray = definition => {
7
- const requires = []
8
-
9
- if (definition['@requires']) {
10
- if (Array.isArray(definition['@requires'])) requires.push(...definition['@requires'])
11
- else requires.push(definition['@requires'])
12
- }
13
-
14
- const { restrict_all_services: restrictAllServices } = cds.env.requires.auth || {}
15
- if (!requires.length && definition.kind === 'service' && restrictAllServices) requires.push('authenticated-user')
16
-
17
- return requires
5
+ const requires = definition['@requires']
6
+ if (requires) return Array.isArray(requires) ? requires : [requires]
18
7
  }
19
8
 
20
9
  const isRestricted = srv => {
21
- const envAuth = cds.env.requires.auth
22
- if (envAuth && envAuth.restrict_all_services) return true
23
10
  if (srv.definition['@requires']) return true
24
11
 
25
12
  const entities = srv.entities
@@ -1,12 +1,13 @@
1
1
  const cds = require('../../../cds')
2
2
  const LOG = cds.log('odata')
3
- const { BASE_TENANT, channelName } = require('../../../common/utils/extensibilityUtils')
4
-
5
- const { SYSTEM_SERVICES, createOdataService, createNewService, getModelHash } = require('./utils/dispatcherUtils')
6
3
 
7
4
  const { normalizeError } = require('../../../common/error/frontend')
8
5
 
9
- class Dispatcher {
6
+ const _run4 = (tenant, query) => (tenant ? cds.tx({ tenant }, tx => tx.run(query)) : query)
7
+ const getError = require('../../../common/error')
8
+
9
+ // REVISIT: this is always active, even without mtx -> do that better
10
+ module.exports = class Dispatcher {
10
11
  /**
11
12
  * Constructs an Dispatcher for cds service.
12
13
  * New OData services will be created.
@@ -18,25 +19,44 @@ class Dispatcher {
18
19
  this._options = service.options
19
20
 
20
21
  this._extMap = new Map()
21
- this._extMap.set(getModelHash(BASE_TENANT, []), createOdataService(service))
22
-
23
- if (cds.requires.extensibility && !SYSTEM_SERVICES.includes(this._serviceName)) {
24
- cds.services['mtx-messaging'].on(channelName(), async msg => {
25
- const tenant = msg.data.tenant
26
- const hash = getModelHash(tenant, [])
27
- for (const entry of this._extMap.entries()) {
28
- if (entry[0].startsWith(hash)) {
29
- this._extMap.delete(entry[0])
30
- }
31
- }
32
- })
33
- }
22
+ this._extMap.set(getModelHash(), createOdataService(service))
23
+ this._intervalMap = new Map()
24
+ this._intervalMap.set(undefined, Date.now())
34
25
 
35
- if (cds._mtxEnabled) {
26
+ if (cds.mtx) {
27
+ cds.mtx._nodejs_models = {}
36
28
  cds.mtx.eventEmitter.on(cds.mtx.events.TENANT_UPDATED, async tenant => {
37
29
  this._extMap.delete(getModelHash(tenant))
30
+ delete cds.mtx._nodejs_models[tenant]
38
31
  })
39
32
  }
33
+
34
+ this._tenantCheckInterval = cds.requires.extensibility && cds.requires.extensibility.tenantCheckInterval
35
+ }
36
+
37
+ _deleteService(tenant) {
38
+ const hash = getModelHash(tenant)
39
+ for (const entry of this._extMap.entries()) {
40
+ if (entry[0].startsWith(hash)) {
41
+ this._extMap.delete(entry[0])
42
+ }
43
+ }
44
+ this._intervalMap.delete(tenant)
45
+ }
46
+
47
+ async _checkTenantExt(tenant, last) {
48
+ try {
49
+ const rs = await _run4(tenant, SELECT(1).from('cds.xt.Extensions').where('timestamp >=', last))
50
+ if (!this._mps) this._mps = await cds.connect.to('cds.xt.ModelProviderService')
51
+ if (rs.length) {
52
+ this._deleteService(tenant)
53
+ this._mps.invalidateCache(tenant)
54
+ } else {
55
+ this._intervalMap.set(tenant, Date.now())
56
+ }
57
+ } catch (_) {
58
+ this._deleteService(tenant)
59
+ }
40
60
  }
41
61
 
42
62
  async _getService4Tenant(req) {
@@ -45,42 +65,46 @@ class Dispatcher {
45
65
  const isExtended = await cds.mtx.isExtended(tenant) // REVISIT: avoid await
46
66
  if (!isExtended) return false
47
67
 
48
- const csn = await cds.mtx.getCsn(tenant)
49
- const model = cds.compile.for.nodejs(csn)
68
+ let model = cds.mtx._nodejs_models[tenant]
69
+ if (!model) {
70
+ const raw = await cds.mtx.getCsn(tenant)
71
+ model = cds.mtx._nodejs_models[tenant] = cds.compile.for.nodejs(raw)
72
+ }
73
+
50
74
  const service = await createNewService(this._serviceName, model, this._options)
51
75
  service._cdsService._isExtended = true
52
76
  return service
53
77
  }
54
78
 
55
79
  async _getService4(tenant, features) {
56
- const csn = await this._mps.getCsn(tenant, features || [], 'nodejs')
57
- const model = cds.compile.for.nodejs(csn)
80
+ const model = await this._mps.getCsn(tenant, features || [], 'nodejs')
58
81
  return createNewService(this._serviceName, model, this._options)
59
82
  }
60
83
 
61
84
  async _getService(tenant, features, hash, req) {
62
- if (cds._mtxEnabled) {
85
+ if (cds.mtx) {
63
86
  const service = await this._getService4Tenant(req)
64
87
 
65
88
  if (service) return service
66
89
 
67
- return this._extMap.get(getModelHash(BASE_TENANT, []))
90
+ return this._extMap.get(getModelHash())
68
91
  }
69
92
 
70
- if (!this._mps) this._mps = await cds.connect.to('cds_r.ModelProviderService')
71
- const hashBase = getModelHash(BASE_TENANT, features)
72
- if (tenant && tenant !== BASE_TENANT && hash !== hashBase) {
93
+ if (!this._mps) this._mps = await cds.connect.to('cds.xt.ModelProviderService')
94
+ const hashBase = getModelHash(undefined, features)
95
+ if (tenant && tenant !== undefined && hash !== hashBase) {
73
96
  const isExtended = cds.requires.extensibility && (await this._mps.isExtended(tenant))
74
97
  if (isExtended) {
75
98
  return this._getService4(tenant, features)
76
99
  } else {
77
100
  if (!this._extMap.has(hashBase)) {
78
- this._extMap.set(hashBase, this._getService4(BASE_TENANT, features))
101
+ this._extMap.set(hashBase, this._getService4(undefined, features))
102
+ this._intervalMap.set(tenant, Date.now())
79
103
  }
80
104
  return this._extMap.get(hashBase)
81
105
  }
82
106
  } else {
83
- return this._getService4(BASE_TENANT, features)
107
+ return this._getService4(undefined, features)
84
108
  }
85
109
  }
86
110
 
@@ -92,11 +116,16 @@ class Dispatcher {
92
116
  // clear map entry
93
117
  this._extMap.delete(hash)
94
118
  // return 503 to client
95
- const { error } = normalizeError(Object.assign(err, { statusCode: 503 }), req)
119
+ err = getError(Object.assign(err, { statusCode: 503 }))
120
+ const { error } = normalizeError(err, req)
96
121
 
97
122
  return res.status(503).send({ error })
98
123
  }
99
124
 
125
+ _hasModelProvider() {
126
+ return 'cds.xt.ModelProviderService' in cds.services || 'cds.xt.ModelProviderService' in cds.requires
127
+ }
128
+
100
129
  /**
101
130
  * Dispatch request in case of extensibility to other odata adapters.
102
131
  *
@@ -107,26 +136,34 @@ class Dispatcher {
107
136
  */
108
137
  async dispatch(req, res) {
109
138
  // here, req is express' req -> req.tenant not available
139
+ // REVISIT: rethink authentication
110
140
  const tenant = req.user && req.user.tenant
111
141
 
112
- if (SYSTEM_SERVICES.includes(this._serviceName) || (!tenant && !cds._mpsEnabled)) {
113
- const service = this._extMap.get(getModelHash(BASE_TENANT, []))
142
+ // single tenant w/o features
143
+ if (!cds.mtx && !this._hasModelProvider()) {
144
+ const service = this._extMap.get(getModelHash())
114
145
  return service.process(req, res)
115
146
  }
116
147
 
117
- // ensure features is an array (some stakeholders set req.features themselves)
118
- const features = req.features
119
- ? Array.isArray(req.features)
120
- ? req.features
121
- : Object.keys(req.features)
122
- .filter(k => req.features[k])
123
- .sort()
124
- : []
148
+ // old mtx does not support feature toggles
149
+ const features = cds.mtx ? [] : _features4(req.features || req.user.features)
125
150
  const hash = getModelHash(tenant, features)
126
151
 
152
+ // check for extensions
153
+ if (cds.requires.extensibility && !this._inCheckTenant) {
154
+ this._inCheckTenant = true
155
+ if (this._intervalMap.has(tenant)) {
156
+ const last = this._intervalMap.get(tenant)
157
+ if (Date.now() - last > this._tenantCheckInterval)
158
+ await this._checkTenantExt(tenant, new Date(last).toISOString())
159
+ }
160
+ this._inCheckTenant = false
161
+ }
162
+
127
163
  // set promise into the map to avoid conflicts
128
164
  if (!this._extMap.has(hash)) {
129
165
  this._extMap.set(hash, this._getService(tenant, features, hash, req))
166
+ this._intervalMap.set(tenant, Date.now())
130
167
  }
131
168
 
132
169
  let service
@@ -151,4 +188,53 @@ class Dispatcher {
151
188
  }
152
189
  }
153
190
 
154
- module.exports = Dispatcher
191
+ // -----------------------------------------------------
192
+ // Private utils...
193
+
194
+ const OData = require('./OData')
195
+ const DEBUG = cds.debug('extensibility')
196
+
197
+ const { alias2ref } = require('../../../common/utils/csn')
198
+
199
+ function createOdataService(service) {
200
+ const name = (service.definition && service.definition.name) || service.name
201
+ const edm = cds.compile.to.edm(service.model, { service: name })
202
+ alias2ref(service, edm)
203
+
204
+ const odataService = new OData(edm, service.model, service.options)
205
+ odataService.addCDSServiceToChannel(service)
206
+
207
+ return odataService
208
+ }
209
+
210
+ async function createNewService(name, model, options) {
211
+ const { constructor: Service, path } = cds.services[name]
212
+ const service = new Service(name, model, { ...options }) // cloning options to be safe
213
+ if (service.init) await service.prepend(service.init)
214
+ if (options.impl) await service.prepend(options.impl)
215
+ if (path) service.path = path
216
+ DEBUG &&
217
+ DEBUG('Created tenant-specific service:', service.name, '= new', Service.name, {
218
+ _handlers: {
219
+ on: service._handlers.on.map(h => ({ on: h.on, handler: () => {} }))
220
+ }
221
+ })
222
+ return createOdataService(service)
223
+ }
224
+
225
+ const getModelHash = (tenant, features) => {
226
+ // ignore tenant in single tenant mode - use default (undefined) hash
227
+ const hash = cds.requires.multitenancy ? `${tenant}:` : 'undefined:'
228
+ return !features ? hash : hash + features.join(';')
229
+ }
230
+
231
+ const _features4 = features => {
232
+ // ensure features is an array
233
+ if (!features) return []
234
+ if (Array.isArray(features)) return features
235
+ if (typeof features === 'string') return features.split(',')
236
+ if (typeof features === 'object')
237
+ return Object.keys(features)
238
+ .filter(k => features[k])
239
+ .sort()
240
+ }
@@ -27,7 +27,6 @@ const _delete = require('./handlers/delete')
27
27
  const _read = require('./handlers/read')
28
28
  const _action = require('./handlers/action')
29
29
  const { normalizeError, isClientError } = require('../../../common/error/frontend')
30
-
31
30
  const { getErrorMessage } = require('../../../common/error/utils')
32
31
 
33
32
  function _log(level, arg) {
@@ -51,7 +50,6 @@ function _log(level, arg) {
51
50
  // reduce 4xx to warning
52
51
  if (isClientError(obj)) {
53
52
  if (!LOG._warn) {
54
- // restore
55
53
  return
56
54
  }
57
55
  level = 'warn'
@@ -264,8 +262,13 @@ class OData {
264
262
 
265
263
  // this._startPerfMeasurementOData(req)
266
264
  this._odataService.process(req, res).catch(err => {
265
+ LOG.warn(err)
267
266
  // REVISIT: use i18n
268
- res.status(500).send({ error: { code: 'null', message: err.message } })
267
+ //do not reply with error, if response already processed (streaming)
268
+ if (!res.headersSent) {
269
+ const { error, statusCode } = normalizeError(err, req)
270
+ res.status(statusCode).send({ error })
271
+ }
269
272
  })
270
273
  }
271
274
  }
@@ -11,11 +11,10 @@ const {
11
11
  } = require('./okra/odata-server')
12
12
 
13
13
  const { findCsnTargetFor } = require('../../../common/utils/csn')
14
-
14
+ const metaInfo = require('./utils/metaInfo')
15
15
  const odataToCQN = require('./odata-to-cqn')
16
16
  const { getData, getParams } = require('./utils/data')
17
17
  const { isCustomOperation } = require('./utils/request')
18
- const { flattenDeepToOneAssociations } = require('../../services/utils/handlerUtils')
19
18
 
20
19
  function _isCorrectCallToViewWithParams(csdlStructuredType) {
21
20
  return (
@@ -55,6 +54,12 @@ function _getTarget(service, segments) {
55
54
  return _getTarget(service, segments)
56
55
  }
57
56
 
57
+ function _add4Odata(query) {
58
+ if (Array.isArray(query))
59
+ for (let i = 0; i < query.length; i++) Object.defineProperty(query[i].SELECT, '_4odata', { value: true })
60
+ else Object.defineProperty(query.SELECT, '_4odata', { value: true })
61
+ }
62
+
58
63
  /**
59
64
  * Class representing an OData request.
60
65
  * @extends cds.Request
@@ -71,86 +76,101 @@ class ODataRequest extends cds.Request {
71
76
  : odataReq.getIncomingRequest()
72
77
  const res = req.res
73
78
 
74
- /*
75
- * target
76
- */
77
- const target = _getTarget(service, [...odataReq.getUriInfo().getPathSegments()])
78
-
79
- /*
80
- * data
81
- */
82
- const data = getData(type, odataReq, service, target)
83
-
84
- /*
85
- * query
86
- */
87
- const operation = isCustomOperation(odataReq.getUriInfo().getPathSegments())
88
- ? odataReq.getUriInfo().getLastSegment().getKind()
89
- : type
90
- const query = odataToCQN(operation, service, target, data, odataReq, upsert)
91
-
92
- /*
93
- * event
94
- */
95
- let event = type
79
+ if (cds.env.features.odata_new_parser) {
80
+ // REVISIT need to resolve target after replacing okra <= maybe just take one from afterburner?
81
+ const target = _getTarget(service, [...odataReq.getUriInfo().getPathSegments()])
82
+ // REVISIT payload after replacing okra
83
+ const data = getData(type, odataReq, service, target)
84
+ const query = odataToCQN(type, service, target, data, odataReq, upsert)
85
+ const headers = Object.assign({}, req.headers, odataReq.getHeaders())
86
+ // REVISIT needed in case of $batch, replace after removing okra
87
+ const method = odataReq.getIncomingRequest().method
88
+ const { user } = req
89
+ const info = metaInfo(query, type, service, data, req, upsert)
90
+ const { event, unbound } = info
91
+ if (event === 'READ') _add4Odata(query)
92
+ const _queryOptions = odataReq.getQueryOptions()
93
+ super({ event, target, data, query: unbound ? {} : query, user, method, headers, req, res, _queryOptions })
94
+ this._metaInfo = info.metadata
95
+ } else {
96
+ /*
97
+ * target
98
+ */
99
+ const target = _getTarget(service, [...odataReq.getUriInfo().getPathSegments()])
100
+
101
+ /*
102
+ * data
103
+ */
104
+ const data = getData(type, odataReq, service, target)
105
+
106
+ /*
107
+ * query
108
+ */
109
+ const operation = isCustomOperation(odataReq.getUriInfo().getPathSegments())
110
+ ? odataReq.getUriInfo().getLastSegment().getKind()
111
+ : type
112
+ const query = odataToCQN(operation, service, target, data, odataReq, upsert)
113
+
114
+ /*
115
+ * event
116
+ */
117
+ let event = type
118
+
119
+ // actions & functions
120
+ const uriInfoLastSegment = odataReq.getUriInfo().getLastSegment()
121
+
122
+ switch (uriInfoLastSegment && uriInfoLastSegment.getKind()) {
123
+ case 'BOUND.ACTION':
124
+ event = uriInfoLastSegment.getAction().getName()
125
+ break
126
+
127
+ case 'ACTION.IMPORT':
128
+ event = uriInfoLastSegment.getActionImport().getName()
129
+ break
130
+
131
+ case 'BOUND.FUNCTION':
132
+ event = uriInfoLastSegment.getFunction().getName()
133
+ break
134
+
135
+ case 'FUNCTION.IMPORT':
136
+ event = uriInfoLastSegment.getFunctionImport().getName()
137
+ break
138
+
139
+ // no default
140
+ }
96
141
 
97
- // actions & functions
98
- const uriInfoLastSegment = odataReq.getUriInfo().getLastSegment()
142
+ // draft
143
+ if (target && target._isDraftEnabled) {
144
+ if (type === 'CREATE') event = 'NEW'
145
+ else if (event === 'draftEdit') event = 'EDIT'
146
+ else if (type === 'UPDATE') event = 'PATCH'
147
+ else if (type === 'DELETE' && data.IsActiveEntity !== true) event = 'CANCEL'
148
+ }
99
149
 
100
- switch (uriInfoLastSegment && uriInfoLastSegment.getKind()) {
101
- case 'BOUND.ACTION':
102
- event = uriInfoLastSegment.getAction().getName()
103
- break
150
+ // mark query as for an OData READ
151
+ if (event === 'READ') Object.defineProperty(query.SELECT, '_4odata', { value: true })
104
152
 
105
- case 'ACTION.IMPORT':
106
- event = uriInfoLastSegment.getActionImport().getName()
107
- break
153
+ /*
154
+ * method, headers
155
+ */
156
+ const method = odataReq.getMethod()
108
157
 
109
- case 'BOUND.FUNCTION':
110
- event = uriInfoLastSegment.getFunction().getName()
111
- break
158
+ // REVISIT: Why do we mix headers of $batch and batched request headers??
159
+ const headers = Object.assign({}, req.headers, odataReq.getHeaders())
112
160
 
113
- case 'FUNCTION.IMPORT':
114
- event = uriInfoLastSegment.getFunctionImport().getName()
115
- break
161
+ /*
162
+ * super
163
+ */
164
+ const { user } = req
116
165
 
117
- // no default
118
- }
166
+ // REVISIT: _model should not be necessary
167
+ const _model = service.model
119
168
 
120
- // draft
121
- if (target && target._isDraftEnabled) {
122
- if (type === 'CREATE') event = 'NEW'
123
- else if (event === 'draftEdit') event = 'EDIT'
124
- else if (type === 'UPDATE') event = 'PATCH'
125
- else if (type === 'DELETE' && data.IsActiveEntity !== 'true') event = 'CANCEL'
169
+ // REVISIT: public API for query options (express style req.query already in use)?
170
+ const _queryOptions = odataReq.getQueryOptions()
171
+ super({ event, target, data, query, user, method, headers, req, res, _model, _queryOptions })
126
172
  }
127
173
 
128
- // mark query as for an OData READ
129
- if (event === 'READ') Object.defineProperty(query.SELECT, '_4odata', { value: true })
130
-
131
- /*
132
- * method, headers
133
- */
134
- const method = odataReq.getMethod()
135
-
136
- // REVISIT: Why do we mix headers of $batch and batched request headers??
137
- const headers = Object.assign({}, req.headers, odataReq.getHeaders())
138
-
139
- /*
140
- * super
141
- */
142
- const { user } = req
143
-
144
- // REVISIT: _model should not be necessary
145
- const _model = service.model
146
-
147
- // REVISIT: public API for query options (express style req.query already in use)?
148
- const _queryOptions = odataReq.getQueryOptions()
149
- super({ event, target, data, query, user, method, headers, req, res, _model, _queryOptions })
150
-
151
- // REVISIT: validate associations for deep insert
152
- flattenDeepToOneAssociations(this, this.model)
153
-
154
174
  /*
155
175
  * req.run
156
176
  */