@sap/cds-dk 10.0.7 → 10.1.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 (341) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/bin/add.js +7 -23
  3. package/bin/bind.js +14 -0
  4. package/bin/build.js +21 -34
  5. package/bin/cds.js +1 -1
  6. package/bin/compile/index.js +16 -41
  7. package/bin/completion/completionFs.js +11 -8
  8. package/bin/completion/index.js +603 -80
  9. package/bin/completion/scripts/cds.fish +620 -0
  10. package/bin/completion/scripts/cds.ps1 +403 -0
  11. package/bin/completion/scripts/cds.sh +327 -0
  12. package/bin/completion/scripts/cds.zsh +296 -0
  13. package/bin/completion/templates/cds-tmpl.fish +65 -0
  14. package/bin/completion/templates/cds-tmpl.ps1 +217 -0
  15. package/bin/completion/templates/cds-tmpl.sh +93 -0
  16. package/bin/completion/templates/cds-tmpl.zsh +74 -0
  17. package/bin/deploy/index.js +11 -1
  18. package/bin/deploy/options.js +25 -0
  19. package/{lib → bin}/deploy/to-hana/hana.js +8 -8
  20. package/{lib → bin}/deploy/to-hana/hdiDeployUtil.js +1 -1
  21. package/bin/deploy/{to-hana.js → to-hana/index.js} +1 -1
  22. package/{lib → bin}/deploy/to-hana/mtaUtil.js +1 -1
  23. package/bin/deploy/to-sql.js +0 -2
  24. package/bin/env.js +4 -1
  25. package/bin/export.js +44 -6
  26. package/bin/help/export.md +3 -0
  27. package/bin/help.js +1 -5
  28. package/bin/import.js +9 -0
  29. package/bin/init.js +6 -24
  30. package/bin/inspect.js +8 -0
  31. package/bin/lint.js +5 -3
  32. package/bin/login.js +26 -20
  33. package/bin/minify.js +6 -1
  34. package/bin/pull.js +19 -6
  35. package/bin/push.js +19 -6
  36. package/bin/repl.js +11 -2
  37. package/bin/run.js +12 -1
  38. package/bin/serve.js +13 -2
  39. package/bin/up.js +17 -11
  40. package/{lib → bin}/upgrade/constants.js +1 -1
  41. package/bin/{upgrade.js → upgrade/index.js} +2 -2
  42. package/{lib → bin}/upgrade/preflight/consistency.js +1 -1
  43. package/{lib → bin}/upgrade/preflight/index.js +1 -1
  44. package/{lib → bin}/upgrade/steps/analyze/index.js +1 -1
  45. package/{lib → bin}/upgrade/steps/install.js +1 -1
  46. package/{lib → bin}/upgrade/steps/openrewrite.js +1 -1
  47. package/{lib → bin}/upgrade/steps/removals.js +1 -1
  48. package/{lib → bin}/upgrade/steps/rewrite.js +1 -1
  49. package/{lib → bin}/upgrade/steps/verify.js +1 -1
  50. package/{lib/upgrade/index.js → bin/upgrade/upgrade.js} +2 -2
  51. package/{lib → bin}/upgrade/util/pom.js +2 -2
  52. package/{lib → bin}/upgrade/util/prompt.js +1 -1
  53. package/bin/util/containerize.js +10 -4
  54. package/bin/version.js +10 -1
  55. package/{lib → bin}/watch/hot-reload.js +1 -1
  56. package/bin/{watch.js → watch/index.js} +24 -9
  57. package/{lib → bin}/watch/livereload-connect.js +1 -1
  58. package/{lib → bin}/watch/vite-watch.js +1 -1
  59. package/{lib → bin}/watch/watched.js +2 -2
  60. package/lib/build/constants.js +1 -1
  61. package/lib/build/plugins/fiori/index.js +31 -2
  62. package/lib/build/plugins/internal.js +4 -2
  63. package/lib/build/plugins/mtx-sidecar/index.js +7 -8
  64. package/lib/build/plugins/nodejs/index.js +64 -7
  65. package/lib/build/util.js +2 -4
  66. package/lib/compile/to_asyncapi.js +1 -1
  67. package/lib/env/schema.js +16 -0
  68. package/lib/env/schemas/cds-rc.js +1 -76
  69. package/lib/import/importapi.js +2 -3
  70. package/lib/import/message.js +0 -2
  71. package/lib/init/constants.js +2 -1
  72. package/lib/init/index.js +2 -2
  73. package/lib/init/merge.js +123 -280
  74. package/lib/init/plugin.js +3 -1
  75. package/lib/init/projectReader.js +22 -6
  76. package/lib/init/registries/xs-app.js +3 -5
  77. package/lib/init/template/ai/files/mta.yaml.hbs +1 -1
  78. package/lib/init/template/ai/index.js +14 -2
  79. package/lib/init/template/ams/index.js +2 -2
  80. package/lib/init/template/app-frontend/files/containerize.yaml.hbs +2 -2
  81. package/lib/init/template/app-frontend/index.js +4 -4
  82. package/lib/init/template/application-logging/index.js +2 -2
  83. package/lib/init/template/approuter/files/package.json +1 -1
  84. package/lib/init/template/approuter/index.js +8 -3
  85. package/lib/init/template/attachments/files/package.json.hbs +1 -1
  86. package/lib/init/template/attachments/index.js +2 -2
  87. package/lib/init/template/audit-logging/index.js +2 -2
  88. package/lib/init/template/cloud-logging/files/package.json.hbs +4 -4
  89. package/lib/init/template/cloud-logging/index.js +2 -2
  90. package/lib/init/template/completion/completionSetup.js +36 -39
  91. package/lib/init/template/connectivity/index.js +2 -2
  92. package/lib/init/template/data/as-csv.js +15 -5
  93. package/lib/init/template/data/as-json.js +117 -42
  94. package/lib/init/template/data/index.js +16 -2
  95. package/lib/init/template/destination/index.js +2 -2
  96. package/lib/init/template/dynatrace/files/package.json.hbs +3 -3
  97. package/lib/init/template/dynatrace/index.js +2 -2
  98. package/lib/init/template/enterprise-messaging/index.js +2 -2
  99. package/lib/init/template/enterprise-messaging-shared/index.js +2 -2
  100. package/lib/init/template/extensibility/files/mta.yaml.hbs +11 -0
  101. package/lib/init/template/extensibility/files/xs-security.json.hbs +1 -1
  102. package/lib/init/template/extensibility/index.js +3 -3
  103. package/lib/init/template/github-actions/index.js +2 -2
  104. package/lib/init/template/hana/index.js +3 -2
  105. package/lib/init/template/hana-serverless/files/db/package.json +14 -0
  106. package/lib/init/template/hana-serverless/files/identity.values.yaml.hbs +10 -0
  107. package/lib/init/template/hana-serverless/files/mta.yaml.hbs +64 -0
  108. package/lib/init/template/hana-serverless/files/package.json.hbs +35 -0
  109. package/lib/init/template/hana-serverless/files/src/.hdiconfig +139 -0
  110. package/lib/init/template/hana-serverless/files/undeploy.json +7 -0
  111. package/lib/init/template/hana-serverless/files/values.yaml.hbs +18 -0
  112. package/lib/init/template/hana-serverless/index.js +184 -0
  113. package/lib/init/template/html5-repo/files/containerize.yaml.hbs +2 -2
  114. package/lib/init/template/html5-repo/files/mta.yaml.hbs +5 -0
  115. package/lib/init/template/html5-repo/index.js +18 -14
  116. package/lib/init/template/http/index.js +123 -26
  117. package/lib/init/template/ias/index.js +2 -2
  118. package/lib/init/template/kafka/index.js +2 -2
  119. package/lib/init/template/kyma/index.js +7 -5
  120. package/lib/init/template/malware-scanner/index.js +2 -2
  121. package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
  122. package/lib/init/template/multitenancy/index.js +18 -3
  123. package/lib/init/template/notifications/index.js +2 -2
  124. package/lib/init/template/portal/files/mta.yaml.hbs +4 -0
  125. package/lib/init/template/portal/index.js +13 -8
  126. package/lib/init/template/postgres/index.js +2 -2
  127. package/lib/init/template/redis/index.js +2 -2
  128. package/lib/init/template/sample/files/db/currencies.cds +2 -0
  129. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +1 -1
  130. package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +2 -2
  131. package/lib/init/template/workzone-standard/index.js +5 -5
  132. package/lib/init/template/xsuaa/index.js +20 -2
  133. package/lib/lint/eslintHelp.json +1 -1
  134. package/lib/mtx/auth_manager.js +103 -37
  135. package/lib/mtx/params.js +3 -2
  136. package/lib/mtx/settings_manager.js +45 -28
  137. package/lib/mtx/tenant_action.js +0 -1
  138. package/lib/mtx/util/credentials.js +62 -0
  139. package/node_modules/@cap-js/db-service/CHANGELOG.md +17 -0
  140. package/node_modules/@cap-js/db-service/lib/common/generic-pool.js +4 -7
  141. package/node_modules/@cap-js/db-service/lib/cqn2pql.js +1 -1
  142. package/node_modules/@cap-js/db-service/lib/cqn2sql.js +15 -11
  143. package/node_modules/@cap-js/db-service/lib/cqn4sql.js +119 -19
  144. package/node_modules/@cap-js/db-service/lib/infer/index.js +27 -16
  145. package/node_modules/@cap-js/db-service/lib/recursion-guard.js +40 -0
  146. package/node_modules/@cap-js/db-service/lib/search.js +1 -1
  147. package/node_modules/@cap-js/db-service/package.json +1 -1
  148. package/node_modules/@cap-js/sqlite/CHANGELOG.md +19 -0
  149. package/node_modules/@cap-js/sqlite/lib/SQLiteService.js +110 -14
  150. package/node_modules/@cap-js/sqlite/package.json +3 -3
  151. package/node_modules/@sap/cds/CHANGELOG.md +57 -0
  152. package/node_modules/@sap/cds/app/index.js +5 -4
  153. package/node_modules/@sap/cds/eslint.config.mjs +1 -0
  154. package/node_modules/@sap/cds/lib/compile/minify.js +14 -10
  155. package/node_modules/@sap/cds/lib/env/cds-env.js +1 -1
  156. package/node_modules/@sap/cds/lib/env/cds-requires.js +22 -11
  157. package/node_modules/@sap/cds/lib/env/defaults.js +4 -1
  158. package/node_modules/@sap/cds/lib/env/schemas/cds-rc.js +5 -2
  159. package/node_modules/@sap/cds/lib/plugins.js +9 -5
  160. package/node_modules/@sap/cds/lib/req/spawn.js +1 -1
  161. package/node_modules/@sap/cds/lib/srv/srv-dispatch.js +1 -1
  162. package/node_modules/@sap/cds/lib/srv/srv-models.js +1 -1
  163. package/node_modules/@sap/cds/lib/utils/cds-utils.js +2 -1
  164. package/node_modules/@sap/cds/libx/_runtime/common/generic/assert.js +2 -3
  165. package/node_modules/@sap/cds/libx/_runtime/common/generic/auth/restrict.js +8 -1
  166. package/node_modules/@sap/cds/libx/_runtime/common/generic/crud.js +18 -8
  167. package/node_modules/@sap/cds/libx/_runtime/fiori/lean-draft.js +25 -17
  168. package/node_modules/@sap/cds/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +9 -3
  169. package/node_modules/@sap/cds/libx/_runtime/remote/Service.js +4 -19
  170. package/node_modules/@sap/cds/libx/_runtime/remote/utils/LruCache.js +42 -0
  171. package/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js +14 -4
  172. package/node_modules/@sap/cds/libx/_runtime/remote/utils/cloudSdkProvider.js +2 -9
  173. package/node_modules/@sap/cds/libx/_runtime/remote/utils/destinationClient.js +150 -0
  174. package/node_modules/@sap/cds/libx/_runtime/remote/utils/error.js +13 -0
  175. package/node_modules/@sap/cds/libx/_runtime/remote/utils/fetchClient.js +26 -18
  176. package/node_modules/@sap/cds/libx/_runtime/remote/utils/query.js +34 -23
  177. package/node_modules/@sap/cds/libx/_runtime/remote/utils/token.js +82 -0
  178. package/node_modules/@sap/cds/libx/_runtime/ucl/Service.js +36 -189
  179. package/node_modules/@sap/cds/libx/common/utils/streaming.js +16 -16
  180. package/node_modules/@sap/cds/libx/http/location.js +3 -3
  181. package/node_modules/@sap/cds/libx/odata/middleware/batch.js +16 -10
  182. package/node_modules/@sap/cds/libx/odata/middleware/metadata.js +9 -6
  183. package/node_modules/@sap/cds/libx/odata/middleware/service-document.js +1 -1
  184. package/node_modules/@sap/cds/libx/odata/parse/afterburner.js +19 -3
  185. package/node_modules/@sap/cds/libx/odata/parse/cqn2odata.js +83 -86
  186. package/node_modules/@sap/cds/libx/queue/SchedulingService.js +17 -2
  187. package/node_modules/@sap/cds/libx/queue/processing.js +1 -3
  188. package/node_modules/@sap/cds/libx/rest/RestAdapter.js +3 -7
  189. package/node_modules/@sap/cds/libx/rest/middleware/delete.js +3 -3
  190. package/node_modules/@sap/cds/libx/rest/middleware/parse.js +13 -8
  191. package/node_modules/@sap/cds/libx/rest/middleware/read.js +3 -3
  192. package/node_modules/@sap/cds/libx/rest/middleware/upsert.js +2 -2
  193. package/node_modules/@sap/cds/package.json +1 -1
  194. package/node_modules/@sap/cds-compiler/CHANGELOG.md +75 -8
  195. package/node_modules/@sap/cds-compiler/bin/cdsc.js +2 -2
  196. package/node_modules/@sap/cds-compiler/doc/IncompatibleChanges_v7.md +46 -19
  197. package/node_modules/@sap/cds-compiler/lib/api/main.js +10 -7
  198. package/node_modules/@sap/cds-compiler/lib/api/options.js +8 -2
  199. package/node_modules/@sap/cds-compiler/lib/base/csnRefs.js +5 -2
  200. package/node_modules/@sap/cds-compiler/lib/base/message-registry.js +4 -0
  201. package/node_modules/@sap/cds-compiler/lib/base/optionProcessor.js +12 -0
  202. package/node_modules/@sap/cds-compiler/lib/checks/enricher.js +1 -0
  203. package/node_modules/@sap/cds-compiler/lib/compiler/assert-consistency.js +8 -7
  204. package/node_modules/@sap/cds-compiler/lib/compiler/checks.js +3 -3
  205. package/node_modules/@sap/cds-compiler/lib/compiler/define.js +301 -75
  206. package/node_modules/@sap/cds-compiler/lib/compiler/dictionaries.js +2 -0
  207. package/node_modules/@sap/cds-compiler/lib/compiler/extend.js +40 -26
  208. package/node_modules/@sap/cds-compiler/lib/compiler/populate.js +45 -60
  209. package/node_modules/@sap/cds-compiler/lib/compiler/propagator.js +16 -7
  210. package/node_modules/@sap/cds-compiler/lib/compiler/resolve.js +48 -18
  211. package/node_modules/@sap/cds-compiler/lib/compiler/shared.js +7 -6
  212. package/node_modules/@sap/cds-compiler/lib/compiler/tweak-assocs.js +62 -50
  213. package/node_modules/@sap/cds-compiler/lib/compiler/utils.js +29 -14
  214. package/node_modules/@sap/cds-compiler/lib/edm/edmAnnoPreprocessor.js +6 -5
  215. package/node_modules/@sap/cds-compiler/lib/gen/CdlGrammar.checksum +1 -1
  216. package/node_modules/@sap/cds-compiler/lib/gen/CdlParser.js +1119 -1109
  217. package/node_modules/@sap/cds-compiler/lib/gen/Dictionary.json +19 -3
  218. package/node_modules/@sap/cds-compiler/lib/json/from-csn.js +10 -16
  219. package/node_modules/@sap/cds-compiler/lib/json/to-csn.js +58 -39
  220. package/node_modules/@sap/cds-compiler/lib/main.d.ts +8 -0
  221. package/node_modules/@sap/cds-compiler/lib/main.js +1 -0
  222. package/node_modules/@sap/cds-compiler/lib/model/csnUtils.js +4 -0
  223. package/node_modules/@sap/cds-compiler/lib/parsers/AstBuildingParser.js +2 -1
  224. package/node_modules/@sap/cds-compiler/lib/parsers/XprTree.js +8 -0
  225. package/node_modules/@sap/cds-compiler/lib/render/toCdl.js +22 -1
  226. package/node_modules/@sap/cds-compiler/lib/render/toSql.js +17 -2
  227. package/node_modules/@sap/cds-compiler/lib/render/utils/common.js +6 -1
  228. package/node_modules/@sap/cds-compiler/lib/render/utils/operators.js +27 -0
  229. package/node_modules/@sap/cds-compiler/lib/render/utils/standardDatabaseFunctions.js +125 -3
  230. package/node_modules/@sap/cds-compiler/lib/tool-lib/revealInternalProperties.js +2 -1
  231. package/node_modules/@sap/cds-compiler/lib/transform/db/applyTransformations.js +15 -0
  232. package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +10 -2
  233. package/node_modules/@sap/cds-compiler/lib/transform/db/backlinks.js +22 -6
  234. package/node_modules/@sap/cds-compiler/lib/transform/db/constraints.js +62 -1
  235. package/node_modules/@sap/cds-compiler/lib/transform/db/flattening.js +4 -3
  236. package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +40 -0
  237. package/node_modules/@sap/cds-compiler/lib/transform/effective/flattening.js +17 -1
  238. package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +20 -0
  239. package/node_modules/@sap/cds-compiler/lib/transform/fioriTreeViews.js +12 -1
  240. package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +7 -2
  241. package/node_modules/@sap/cds-compiler/lib/transform/odata/adaptAnnotationRefs.js +11 -5
  242. package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +48 -10
  243. package/node_modules/@sap/cds-compiler/package.json +1 -1
  244. package/node_modules/@sap/cds-mtxs/CHANGELOG.md +49 -0
  245. package/node_modules/@sap/cds-mtxs/bin/cds-mtx-migrate.js +26 -5
  246. package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +37 -16
  247. package/node_modules/@sap/cds-mtxs/lib/utils.js +23 -7
  248. package/node_modules/@sap/cds-mtxs/package.json +1 -1
  249. package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +63 -8
  250. package/node_modules/@sap/cds-mtxs/srv/cf/saas-provisioning-service.js +1 -1
  251. package/node_modules/@sap/cds-mtxs/srv/cf/sms-provisioning-service.js +23 -3
  252. package/node_modules/@sap/cds-mtxs/srv/extensibility/compat/update.js +15 -0
  253. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/annotations.js +2 -2
  254. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/config.js +2 -0
  255. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/index.js +2 -0
  256. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/protected-namespace.js +45 -0
  257. package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +30 -16
  258. package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +49 -10
  259. package/node_modules/@sap/cds-mtxs/srv/model-provider.js +28 -4
  260. package/node_modules/@sap/cds-mtxs/srv/plugins/common.js +19 -12
  261. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +1 -1
  262. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi-ctnr-mgr.js +6 -3
  263. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/serverless.js +271 -0
  264. package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +7 -10
  265. package/node_modules/@sap/cds-mtxs/srv/worker/job-worker-pool.js +212 -0
  266. package/node_modules/@sap/cds-mtxs/srv/worker/job-worker.js +61 -0
  267. package/node_modules/@sap/xsenv/CHANGELOG.md +7 -0
  268. package/node_modules/@sap/xsenv/package.json +10 -7
  269. package/node_modules/body-parser/node_modules/content-type/README.md +2 -0
  270. package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
  271. package/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
  272. package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
  273. package/node_modules/body-parser/node_modules/content-type/package.json +1 -1
  274. package/node_modules/hdb/cfg/VERSION +1 -1
  275. package/node_modules/hdb/lib/protocol/ClientInfo.js +16 -3
  276. package/node_modules/hdb/lib/protocol/Connection.js +1 -0
  277. package/node_modules/hdb/package.json +3 -2
  278. package/node_modules/negotiator/lib/accept.js +54 -0
  279. package/node_modules/negotiator/lib/charset.js +10 -34
  280. package/node_modules/negotiator/lib/encoding.js +9 -30
  281. package/node_modules/negotiator/lib/language.js +15 -36
  282. package/node_modules/negotiator/lib/mediaType.js +16 -134
  283. package/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
  284. package/node_modules/negotiator/node_modules/content-type/README.md +71 -0
  285. package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
  286. package/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
  287. package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
  288. package/node_modules/negotiator/node_modules/content-type/package.json +52 -0
  289. package/node_modules/negotiator/package.json +16 -10
  290. package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
  291. package/node_modules/qs/CHANGELOG.md +15 -0
  292. package/node_modules/qs/README.md +19 -1
  293. package/node_modules/qs/dist/qs.js +21 -21
  294. package/node_modules/qs/eslint.config.mjs +1 -1
  295. package/node_modules/qs/lib/parse.js +3 -4
  296. package/node_modules/qs/lib/stringify.js +23 -8
  297. package/node_modules/qs/lib/utils.js +10 -3
  298. package/node_modules/qs/package.json +4 -4
  299. package/node_modules/qs/test/parse.js +192 -3
  300. package/node_modules/qs/test/stringify.js +317 -0
  301. package/node_modules/qs/test/utils.js +12 -0
  302. package/node_modules/type-is/node_modules/content-type/README.md +2 -0
  303. package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
  304. package/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
  305. package/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
  306. package/node_modules/type-is/node_modules/content-type/package.json +1 -1
  307. package/node_modules/ws/lib/permessage-deflate.js +3 -1
  308. package/node_modules/ws/package.json +1 -1
  309. package/package.json +2 -2
  310. package/bin/completion/scripts/cds-bash.sh +0 -20
  311. package/bin/completion/scripts/cds-fish.fish +0 -13
  312. package/bin/completion/scripts/cds-ps.ps1 +0 -19
  313. package/bin/completion/scripts/cds-zsh.sh +0 -13
  314. package/lib/deploy/index.js +0 -25
  315. package/lib/import/asyncapi/importAsyncAPI.js +0 -33
  316. package/lib/import/asyncapi/index.js +0 -18
  317. package/lib/import/asyncapi/parserContext.js +0 -454
  318. package/lib/import/asyncapi/utils.js +0 -49
  319. package/node_modules/@sap/cds/libx/_runtime/ucl/queries.js +0 -61
  320. package/node_modules/negotiator/HISTORY.md +0 -114
  321. /package/{lib → bin}/upgrade/context.js +0 -0
  322. /package/{lib → bin}/upgrade/migrations/cds10/migrations.json +0 -0
  323. /package/{lib → bin}/upgrade/preflight/cds-version.js +0 -0
  324. /package/{lib → bin}/upgrade/preflight/project-type.js +0 -0
  325. /package/{lib → bin}/upgrade/steps/analyze/classification.js +0 -0
  326. /package/{lib → bin}/upgrade/steps/analyze/detector.js +0 -0
  327. /package/{lib → bin}/upgrade/steps/analyze/evaluator.js +0 -0
  328. /package/{lib → bin}/upgrade/steps/analyze/reporter.js +0 -0
  329. /package/{lib → bin}/upgrade/steps/analyze/setup.js +0 -0
  330. /package/{lib → bin}/upgrade/steps/analyze/utils/detection.js +0 -0
  331. /package/{lib → bin}/upgrade/steps/analyze/utils/files.js +0 -0
  332. /package/{lib → bin}/upgrade/steps/analyze/utils/grep.js +0 -0
  333. /package/{lib → bin}/upgrade/steps/analyze/utils/yaml.js +0 -0
  334. /package/{lib → bin}/upgrade/util/workspaces.js +0 -0
  335. /package/{lib → bin}/watch/esm-resolve-registration.js +0 -0
  336. /package/{lib → bin}/watch/livereload-server.js +0 -0
  337. /package/{lib → bin}/watch/node-watch.js +0 -0
  338. /package/{lib → bin}/watch/open.js +0 -0
  339. /package/{lib → bin}/watch/watcher.js +0 -0
  340. /package/node_modules/@sap/cds-mtxs/srv/worker/{pool.js → model-worker-pool.js} +0 -0
  341. /package/node_modules/@sap/cds-mtxs/srv/worker/{load.js → model-worker.js} +0 -0
@@ -2,12 +2,8 @@ const cds = require('../cds')
2
2
  const LOG = cds.log('ucl')
3
3
 
4
4
  const { X509Certificate } = require('crypto')
5
- const fs = require('fs').promises
6
- const https = require('https')
7
5
  const sdkProvider = require('../remote/utils/cloudSdkProvider')
8
6
 
9
- const { READ_QUERY, CREATE_MUTATION, UPDATE_MUTATION, DELETE_MUTATION } = require('./queries')
10
-
11
7
  const SSL_CLIENT_VERIFY_HEADER = 'x-ssl-client-verify'
12
8
  const SSL_CLIENT_SUBJECT_HEADER = 'x-ssl-client-subject-dn'
13
9
  const SSL_CLIENT_ISSUER_HEADER = 'x-ssl-client-issuer-dn'
@@ -172,14 +168,15 @@ module.exports = class UCLService extends cds.Service {
172
168
  if (!OPERATION_DEFAULT_STATES[operation])
173
169
  return cds.error(
174
170
  400,
175
- `Invalid operation "${operation}" in tenant mapping notification. Expected one of: ${Object.keys(
176
- OPERATION_DEFAULT_STATES
177
- )
178
- .map(o => `"${o}"`)
179
- .join(', ')}.`
171
+ `Invalid operation "${operation}" in tenant mapping notification. ` +
172
+ `Expected one of: ${Object.keys(OPERATION_DEFAULT_STATES)
173
+ .map(o => `"${o}"`)
174
+ .join(', ')}.`
180
175
  )
181
176
 
182
177
  const locationUrl = req.headers.location
178
+ LOG.debug(`Extracted UCL callback location from header: ${locationUrl}`)
179
+
183
180
  if (locationUrl?.length) return this._dispatchAsyncMappingNotification(req, operation, locationUrl)
184
181
  return this._dispatchSyncMappingNotification(req, operation)
185
182
  }
@@ -187,10 +184,14 @@ module.exports = class UCLService extends cds.Service {
187
184
  async _dispatchAsyncMappingNotification(req, operation, locationUrl) {
188
185
  // Get destination based on configured destination name
189
186
  const destinationName = cds.env.requires.ucl.destination
187
+
188
+ LOG.debug(`Callback destination configured: ${destinationName} (${typeof destinationName})`)
190
189
  if (typeof destinationName != 'string' || !destinationName?.length)
191
190
  return cds.error(500, 'UCL Notification includes location but no callback destination was configured')
191
+
192
192
  const cloudSdkConnectivity = sdkProvider.getCloudSdkConnectivity()
193
- const destination = await cloudSdkConnectivity.getDestination(destinationName)
193
+ const destination = await cloudSdkConnectivity.getDestination({ destinationName })
194
+ LOG.debug(`Fetched Destination from destination service: ${destination.name}(${destination.url})`)
194
195
 
195
196
  // Make sure the received callback location matches the configured destination
196
197
  let destinationHost, locationHost
@@ -211,16 +212,28 @@ module.exports = class UCLService extends cds.Service {
211
212
  )
212
213
  }
213
214
 
215
+ const receiverTenantId = req.data?.receiverTenant?.applicationTenantId
216
+ LOG.debug(`Handling '${operation}' asynchronously, as tenant: ${receiverTenantId}`)
217
+
218
+ LOG.debug(`Established destination host for UCL callbacks: ${destinationHost}`)
219
+ LOG.debug(`Established intended UCL callback host from location header: ${locationHost}`)
220
+
214
221
  // Schedule the tenant mapping task
215
- await cds.queued(this).send(operation, req.data, req.headers)
222
+ await cds.tx({ tenant: receiverTenantId }, async () => {
223
+ await cds.queued(this).send(operation, req.data, req.headers)
224
+ })
216
225
 
217
- // Respond 202 Accepted to UCL
218
- req.http.res.status(202)
226
+ LOG.debug(`Successfully dispatched '${operation}' operation for: ${receiverTenantId}`)
227
+
228
+ req.http.res.status(202) // Respond '202: Accepted' to UCL
219
229
  return
220
230
  }
221
231
 
222
232
  async _dispatchSyncMappingNotification(req, operation) {
223
- const response = (await this.send(operation, req.data)) ?? {}
233
+ const receiverTenantId = req.data?.receiverTenant?.applicationTenantId
234
+ LOG.debug(`Handling '${operation}' synchronously, as tenant: ${receiverTenantId}`)
235
+
236
+ const response = (await cds.tx({ tenant: receiverTenantId }, async () => this.send(operation, req.data))) ?? {}
224
237
  if (response.error) req.http.res.status(400)
225
238
  else response.state ??= OPERATION_DEFAULT_STATES[operation]
226
239
  return response
@@ -228,8 +241,9 @@ module.exports = class UCLService extends cds.Service {
228
241
 
229
242
  async handleSuccessfulMapping(callbackResult, tenantMapping) {
230
243
  const { operation, operationId } = tenantMapping.data.context
244
+ if (!callbackResult) callbackResult = {}
231
245
 
232
- LOG.debug(`UCL ${operation} operation succeeded:`, callbackResult, tenantMapping)
246
+ LOG.debug(`UCL ${operation} operation succeeded with result:`, callbackResult)
233
247
 
234
248
  // SPII v3 (operationId exists) vs v2
235
249
  const method = operationId ? 'PUT' : 'PATCH'
@@ -242,7 +256,8 @@ module.exports = class UCLService extends cds.Service {
242
256
  const cloudSdkHttpClient = sdkProvider.getCloudSdk()
243
257
  const response = await cloudSdkHttpClient.executeHttpRequest(
244
258
  { destinationName: cds.env.requires.ucl.destination },
245
- { method, url: tenantMapping.headers.location, data }
259
+ { method, url: tenantMapping.headers.location, data },
260
+ { fetchCsrfToken: false }
246
261
  )
247
262
 
248
263
  if (response.status >= 500)
@@ -251,6 +266,8 @@ module.exports = class UCLService extends cds.Service {
251
266
  cds.error(`UCL rejected successful ${operation} operation callback: ${response.data.error}`, {
252
267
  unrecoverable: true
253
268
  })
269
+
270
+ LOG.debug(`UCL Callback completed with status: ${response.status}`)
254
271
  }
255
272
 
256
273
  async handleFailedMapping(callbackError, tenantMapping) {
@@ -264,7 +281,8 @@ module.exports = class UCLService extends cds.Service {
264
281
  const cloudSdkHttpClient = sdkProvider.getCloudSdk()
265
282
  const response = await cloudSdkHttpClient.executeHttpRequest(
266
283
  { destinationName: cds.env.requires.ucl.destination },
267
- { method, url: tenantMapping.headers.location, data: { state: 'ERROR' } }
284
+ { method, url: tenantMapping.headers.location, data: { state: 'ERROR' } },
285
+ { fetchCsrfToken: false }
268
286
  )
269
287
 
270
288
  if (response.status >= 500)
@@ -273,178 +291,7 @@ module.exports = class UCLService extends cds.Service {
273
291
  cds.error(`UCL rejected failed ${operation} operation callback: ${response.data.error}`, {
274
292
  unrecoverable: true
275
293
  })
276
- }
277
-
278
- /*
279
- * the rest is for upserting the application template
280
- */
281
-
282
- async _upsertApplicationTemplate() {
283
- const _getApplicationTemplate = options => {
284
- let applicationTemplate = {
285
- applicationInput: {
286
- providerName: 'SAP',
287
- localTenantID: '{{tenant-id}}',
288
- labels: {
289
- displayName: '{{subdomain}}'
290
- }
291
- },
292
- labels: {
293
- managed_app_provisioning: true,
294
- xsappname: '${xsappname}'
295
- },
296
- placeholders: [
297
- { name: 'subdomain', description: 'The subdomain of the consumer tenant' },
298
- {
299
- name: 'tenant-id',
300
- description: "The tenant id as it's known in the product's domain",
301
- jsonPath: '$.subscribedTenantId'
302
- }
303
- ],
304
- accessLevel: 'GLOBAL'
305
- }
306
- applicationTemplate = cds.utils.merge(applicationTemplate, options.applicationTemplate)
307
-
308
- const pkg = require(cds.root + '/package')
309
- if (!applicationTemplate.name) applicationTemplate.name = pkg.name
310
- if (!applicationTemplate.applicationInput.name) applicationTemplate.applicationInput.name = pkg.name
311
- if (applicationTemplate.labels.xsappname === '${xsappname}')
312
- applicationTemplate.labels.xsappname = options.credentials.xsappname
313
-
314
- return applicationTemplate
315
- }
316
-
317
- this._applicationTemplate = _getApplicationTemplate(cds.env.requires.ucl)
318
- if (!this._applicationTemplate.applicationNamespace) {
319
- cds.error(
320
- 'The UCL service requires a valid `applicationTemplate`, please provide it as described in the documentation.'
321
- )
322
- }
323
-
324
- if (!cds.requires.multitenancy && cds.env.profile !== 'mtx-sidecar')
325
- cds.error(
326
- 'The UCL service requires multitenancy, please enable it in your cds configuration with `cds.requires.multitenancy` or by using the mtx sidecar.'
327
- )
328
- if (!cds.env.requires.ucl.credentials)
329
- cds.error('No credentials found for the UCL service, please bind the service to your app.')
330
-
331
- if (!cds.env.requires.ucl.x509?.cert && !cds.env.requires.ucl.x509?.certPath)
332
- cds.error('UCL requires `x509.cert` or `x509.certPath`.')
333
- if (!cds.env.requires.ucl.x509?.pkey && !cds.env.requires.ucl.x509?.pkeyPath)
334
- cds.error('UCL requires `x509.pkey` or `x509.pkeyPath`.')
335
-
336
- const [cert, key] = await Promise.all([
337
- cds.env.requires.ucl.x509?.cert ??
338
- fs.readFile(cds.utils.path.resolve(cds.root, cds.env.requires.ucl.x509?.certPath)),
339
- cds.env.requires.ucl.x509?.pkey ??
340
- fs.readFile(cds.utils.path.resolve(cds.root, cds.env.requires.ucl.x509?.pkeyPath))
341
- ])
342
-
343
- this.agent = new https.Agent({ cert, key })
344
-
345
- const existingTemplate = await this._readTemplate()
346
- const template = existingTemplate ? await this._updateTemplate(existingTemplate) : await this._createTemplate() // TODO: Make sure return value is correct
347
-
348
- if (!template) cds.error('The UCL service could not create an application template.')
349
-
350
- cds.once('listening', async () => {
351
- const provisioning = await cds.connect.to('cds.xt.SaasProvisioningService')
352
- provisioning.prepend(() => {
353
- provisioning.on('dependencies', async (_, next) => {
354
- const dependencies = await next()
355
- dependencies.push({ xsappname: template.labels.xsappnameCMPClone })
356
- return dependencies
357
- })
358
- })
359
- })
360
- }
361
-
362
- // REVISIT: Replace with fetch (?)
363
- async _request(query, variables) {
364
- // Query GraphQL API
365
-
366
- const opts = {
367
- host: cds.env.requires.ucl.host || 'compass-gateway-sap-mtls.mps.kyma.cloud.sap',
368
- path: cds.env.requires.ucl.path || '/director/graphql',
369
- agent: this.agent,
370
- method: 'POST',
371
- headers: { 'Content-Type': 'application/json' }
372
- }
373
-
374
- return new Promise((resolve, reject) => {
375
- const req = https.request(opts, res => {
376
- const chunks = []
377
-
378
- res.on('data', chunk => {
379
- chunks.push(chunk)
380
- })
381
-
382
- res.on('end', () => {
383
- const response = {
384
- statusCode: res.statusCode,
385
- headers: res.headers,
386
- body: Buffer.concat(chunks).toString()
387
- }
388
-
389
- const body = JSON.parse(response.body)
390
-
391
- if (body.errors) cds.error('Request to UCL service failed with:\n' + JSON.stringify(body.errors, null, 2))
392
-
393
- resolve(body.data)
394
- })
395
- })
396
-
397
- req.on('error', error => {
398
- reject(error)
399
- })
400
-
401
- if (query) {
402
- req.write(JSON.stringify({ query, variables }))
403
- }
404
-
405
- req.end()
406
- })
407
- }
408
-
409
- _handleResponse(result) {
410
- if (result.response && result.response.errors) {
411
- let errorMessage = result.response.errors[0].message
412
- throw new Error(errorMessage)
413
- } else {
414
- return result.result
415
- }
416
- }
417
-
418
- async _readTemplate() {
419
- const xsappname = cds.env.requires.ucl.credentials.xsappname
420
- const variables = { key: 'xsappname', value: `"${xsappname}"` }
421
- const res = await this._request(READ_QUERY, variables)
422
- if (res) return res.applicationTemplates.data[0]
423
- }
424
-
425
- async _createTemplate() {
426
- try {
427
- return this._handleResponse(await this._request(CREATE_MUTATION, { input: this._applicationTemplate }))
428
- } catch (e) {
429
- this._handleResponse(e)
430
- }
431
- }
432
-
433
- async _updateTemplate(template) {
434
- try {
435
- const input = { ...this._applicationTemplate }
436
- delete input.labels
437
- const response = this._handleResponse(await this._request(UPDATE_MUTATION, { id: template.id, input }))
438
- LOG.info('Application template updated successfully.')
439
- return response
440
- } catch (e) {
441
- this._handleResponse(e)
442
- }
443
- }
444
294
 
445
- async _deleteTemplate() {
446
- const template = await this._readTemplate()
447
- if (!template) return
448
- return this._handleResponse(await this._request(DELETE_MUTATION, { id: template.id }))
295
+ LOG.debug(`UCL Callback completed with status: ${response.status}`)
449
296
  }
450
297
  }
@@ -5,7 +5,7 @@ exports.validateMimetypeIsAcceptedOrThrow = (headers, contentType) => {
5
5
  if (!contentType || !headers?.accept) return
6
6
  if (headers.accept.includes('*/*')) return
7
7
  if (headers.accept.includes(contentType)) return
8
- if (headers.accept.includes(contentType.slice(0,contentType.indexOf('/')) + '/*')) return
8
+ if (headers.accept.includes(contentType.slice(0, contentType.indexOf('/')) + '/*')) return
9
9
  const msg = `Content type "${contentType}" is not listed in accept header "${headers.accept}"`
10
10
  cds.error({ status: 406, message: msg })
11
11
  }
@@ -18,7 +18,7 @@ const _mimetypes = {
18
18
  '.css': 'text/css',
19
19
  '.png': 'image/png',
20
20
  '.jpeg': 'image/jpeg',
21
- '.jpg': 'image/jpeg',
21
+ '.jpg': 'image/jpeg'
22
22
  }
23
23
 
24
24
  const { extname } = require('path')
@@ -28,7 +28,7 @@ const _mimetype4 = filename => {
28
28
  return _mimetypes[filetype]
29
29
  }
30
30
 
31
- const _annotation = (def,a) => {
31
+ const _annotation = (def, a) => {
32
32
  if (!def) return
33
33
  if (typeof def[a] === 'string') return def[a]
34
34
  }
@@ -41,32 +41,32 @@ exports.collectStreamMetadata = (result, operation, query) => {
41
41
  const filename =
42
42
  result.$mediaContentDispositionFilename ?? // legacy -> support for odata only?
43
43
  result.filename ??
44
- _annotation (returns, '@Core.ContentDisposition.Filename')
45
- _annotation (element, '@Core.ContentDisposition.Filename')
44
+ _annotation(returns, '@Core.ContentDisposition.Filename') ??
45
+ _annotation(element, '@Core.ContentDisposition.Filename')
46
46
 
47
47
  const disposition =
48
48
  result.$mediaContentDispositionType ?? // legacy -> support for odata only?
49
- _annotation (returns, '@Core.ContentDisposition.Type') ??
50
- _annotation (element, '@Core.ContentDisposition.Type') ??
49
+ _annotation(returns, '@Core.ContentDisposition.Type') ??
50
+ _annotation(element, '@Core.ContentDisposition.Type') ??
51
51
  (filename ? 'attachment' : 'inline')
52
52
 
53
53
  const mimetype =
54
- result['*@odata.mediaContentType'] ?? // compat -> support for odata only?
55
- result.$mediaContentType ?? // legacy -> support for odata only?
54
+ result['*@odata.mediaContentType'] ?? // compat -> support for odata only?
55
+ result.$mediaContentType ?? // legacy -> support for odata only?
56
56
  result.mimetype ??
57
- _mimetype4 (filename) ??
58
- _mimetype4 (result.path) ?? // e.g. for file downloads
59
- _annotation (returns, '@Core.MediaType') ??
60
- _annotation (element, '@Core.MediaType') ??
57
+ _mimetype4(filename) ??
58
+ _mimetype4(result.path) ?? // e.g. for file downloads
59
+ _annotation(returns, '@Core.MediaType') ??
60
+ _annotation(element, '@Core.MediaType') ??
61
61
  'application/octet-stream' // REVISIT: or rather default to undefined?
62
62
 
63
63
  return { mimetype, filename, disposition }
64
64
  }
65
65
 
66
- exports.getReadable = function readable4 (result) {
66
+ exports.getReadable = function readable4(result) {
67
67
  if (result == null) return null
68
68
  if (result instanceof Readable) return result
69
- if (Array.isArray(result)) return readable4 (result[0]) // compat
70
- if (typeof result === 'object' && 'value' in result) return readable4 (result.value)
69
+ if (Array.isArray(result)) return readable4(result[0]) // compat
70
+ if (typeof result === 'object' && 'value' in result) return readable4(result.value)
71
71
  cds.error(500, `Unexpected result type for streaming: Expected stream.Readable or null but got ${typeof result}`)
72
72
  }
@@ -21,10 +21,10 @@ module.exports = (target, srv, result, keys_as_segments) => {
21
21
  return acc
22
22
  }, {})
23
23
 
24
- if (keys_as_segments) {
24
+ if (keys_as_segments) {
25
25
  let location = targetName
26
- for (const k in keyValuePairs) location += `/${keyValuePairs[k]}`
27
- return location
26
+ for (const k in keyValuePairs) location += `/${keyValuePairs[k]}`
27
+ return location
28
28
  }
29
29
 
30
30
  let keys
@@ -33,7 +33,7 @@ const _validateProperty = (name, value, type) => {
33
33
  }
34
34
  }
35
35
 
36
- const _deconstructAndValidateBatchBody = body => {
36
+ const _deconstructAndValidateBatchBody = (body, ct) => {
37
37
  const { requests } = body
38
38
 
39
39
  _validateProperty('requests', requests, 'Array')
@@ -58,6 +58,12 @@ const _deconstructAndValidateBatchBody = body => {
58
58
 
59
59
  const { id, method, url, body, atomicityGroup } = request
60
60
 
61
+ if (atomicityGroup !== undefined) {
62
+ _validateProperty('atomicityGroup', atomicityGroup, 'string')
63
+ if (ct === 'JSON' && !/^[a-zA-Z0-9._~-]+$/.test(atomicityGroup))
64
+ throw _deserializationError('Invalid characters in atomicityGroup')
65
+ }
66
+
61
67
  if (atomicityGroup && atomicityGroups.length && atomicityGroup === atomicityGroups.at(-1)[0]?.atomicityGroup)
62
68
  atomicityGroups.at(-1).push(request)
63
69
  else atomicityGroups.push([request])
@@ -78,8 +84,6 @@ const _deconstructAndValidateBatchBody = body => {
78
84
  throw _deserializationError('A Content-Type header has to be specified for a non JSON body.')
79
85
 
80
86
  if (atomicityGroup) {
81
- _validateProperty('atomicityGroup', atomicityGroup, 'string')
82
-
83
87
  // All request objects with the same value for atomicityGroup MUST be adjacent in the requests array
84
88
  if (atomicityGroup !== previousAtomicityGroup) {
85
89
  if (requestsById[atomicityGroup])
@@ -251,7 +255,7 @@ const _formatResponseMultipart = response => {
251
255
  return [txt]
252
256
  }
253
257
 
254
- const _writeResponseMultipart = (responses, res, boundary) => {
258
+ const _writeResponseMultipart = (responses, res, boundary, ct) => {
255
259
  res.write(`--${boundary}${CRLF}`)
256
260
 
257
261
  const rejected = responses.find(r => r.status === 'fail')
@@ -261,16 +265,18 @@ const _writeResponseMultipart = (responses, res, boundary) => {
261
265
  }
262
266
 
263
267
  const groupId = responses[0].atomicityGroup
264
- if (groupId) res.write(`content-type: multipart/mixed;boundary=${groupId}${CRLF}${CRLF}`)
268
+ const groupBoundary =
269
+ groupId && (ct !== 'JSON' && /^[a-zA-Z0-9.'+_-]{1,70}$/.test(groupId) ? groupId : `changeset_${cds.utils.uuid()}`)
270
+ if (groupBoundary) res.write(`content-type: multipart/mixed;boundary=${groupBoundary}${CRLF}${CRLF}`)
265
271
 
266
272
  for (const response of responses) {
267
273
  for (const each of _formatResponseMultipart(response)) {
268
- if (groupId) res.write(`--${groupId}${CRLF}`)
274
+ if (groupBoundary) res.write(`--${groupBoundary}${CRLF}`)
269
275
  res.write(`${each}${CRLF}`)
270
276
  }
271
277
  }
272
278
 
273
- if (groupId) res.write(`--${groupId}--${CRLF}`)
279
+ if (groupBoundary) res.write(`--${groupBoundary}--${CRLF}`)
274
280
  }
275
281
 
276
282
  /*
@@ -478,7 +484,7 @@ module.exports = adapter => {
478
484
  // 1. Each individual request accessible by its id
479
485
  // 2. Arrays of requests in the same atomicity group
480
486
  // > We will only process requests in atomicity groups
481
- let { requestsById, atomicityGroups } = _deconstructAndValidateBatchBody(body)
487
+ let { requestsById, atomicityGroups } = _deconstructAndValidateBatchBody(body, ct)
482
488
 
483
489
  const only_gets = body.requests.every(r => r.method === 'GET')
484
490
  const max_parallel = only_gets ? cds.env.odata.max_batch_parallelization : 1
@@ -611,7 +617,7 @@ module.exports = adapter => {
611
617
 
612
618
  sendPreludeOnce()
613
619
  if (isJson) _writeResponseJson(responses, res)
614
- else _writeResponseMultipart(responses, res, boundary)
620
+ else _writeResponseMultipart(responses, res, boundary, ct)
615
621
  })
616
622
 
617
623
  if (requestsById[groupId]) requestsById[groupId].promise = promise
@@ -650,7 +656,7 @@ module.exports = adapter => {
650
656
  // NOTE: error middlewares have 4 params
651
657
  // create "subrouter" without the error middlewares for handling subrequests
652
658
  subrouter = Object.create(adapter.router)
653
- subrouter.stack = subrouter.stack.filter(l => l.handle.length === 3)
659
+ subrouter.stack = subrouter.stack.filter(l => l.handle.length !== 4)
654
660
  // combine adapter and global error middlewares to be invoked during error serialization
655
661
  error_mws = adapter.router.stack.filter(l => l.handle.length === 4).map(l => l.handle)
656
662
  error_mws = error_mws.concat(cds.middlewares.after.filter(mw => mw.length === 4).map(mw => mw.bind(adapter)))
@@ -80,8 +80,9 @@ module.exports = adapter => {
80
80
  }
81
81
  }
82
82
 
83
- const { 'cds.xt.ModelProviderService': mps } = cds.services
84
- if (mps) {
83
+ // same check as in ctx-model.js
84
+ if (cds.requires.extensibility || cds.requires.toggles) {
85
+ const mps = await cds.connect.to('cds.xt.ModelProviderService')
85
86
  if (format === 'json') {
86
87
  LOG._warn && LOG.warn('JSON metadata is not supported in case of cds.requires.extensibility: true')
87
88
  const msg = 'JSON metadata is not supported for this service'
@@ -94,12 +95,14 @@ module.exports = adapter => {
94
95
  let edmx = metadataCache.edm
95
96
 
96
97
  if (!edmx) {
97
- // IMPORTANT: Only provide the extended model!
98
- // If model is undefined, MPS has a shortcut to return the prebuilt edmx
99
- edmx = await mps.getEdmx({ tenant, model: cds.context.model, service: service.definition.name })
98
+ // IMPORTANT
99
+ // If MPS is served in process, only provide the extended model. If undefined, MPS has a shortcut to return the prebuilt edmx.
100
+ // If MPS is a remote service, never provide the model. It potentially get's corrupted during serialization.
101
+ const model = mps instanceof cds.ApplicationService ? cds.context.model : undefined
102
+ edmx = await mps.getEdmx({ tenant, model, service: service.definition.name })
100
103
  metadataCache.edm = edmx
101
104
  }
102
- const extBundle = cds.env.requires.extensibility && (await mps.getI18n({ tenant, locale }))
105
+ const extBundle = await mps.getI18n({ tenant, locale })
103
106
  edmx = cds.localize(service.model, locale, edmx, extBundle)
104
107
  metadataCache.xmlEtag[locale] = generateEtag(edmx)
105
108
  res.set('ETag', metadataCache.xmlEtag[locale])
@@ -44,7 +44,7 @@ module.exports = adapter => {
44
44
  }
45
45
 
46
46
  // service.entities does not work because it excludes the texts entities
47
- const srvEntities = service.reflect(d => d.is_entity)
47
+ const srvEntities = service.reflect(d => d.kind === 'entity')
48
48
 
49
49
  const exposedEntities = []
50
50
  for (const e in srvEntities) {
@@ -377,7 +377,7 @@ function _processSegments(from, model, namespace, cqn, protocol) {
377
377
  current = _getDefinition(current, seg, namespace) || _getDefinition(current, seg.replace(/_/g, '.'), namespace)
378
378
 
379
379
  // REVISIT: 404 or 400?
380
- if (!current) throw new cds.error(404, `Invalid resource path "${path}"`)
380
+ if (!current || current.kind === 'event') throw new cds.error(404, `Invalid resource path "${path}"`)
381
381
 
382
382
  if (current.params && current.kind === 'entity') {
383
383
  // > View with params
@@ -802,6 +802,20 @@ const _checkAllKeysProvided = (params, entity) => {
802
802
  cds.error({ status: 400, message: msg })
803
803
  }
804
804
  }
805
+ for (const keyInParam in params) {
806
+ // REVISIT cds^11: entity.keys is used instead of keysOfEntity because it also covers keys excluded
807
+ // from keysOf (e.g. @cds.api.ignore or up_ FK backlinks) that may still appear in request URLs.
808
+ // Reconsider: it's questionable whether @cds.api.ignore-annotated keys should be accepted in URLs,
809
+ // and current Fiori versions may no longer send requests with up_ FK keys.
810
+ const allowed = isView
811
+ ? keyInParam in (entity.params ?? {})
812
+ : entity.keys?.[keyInParam] && !entity.keys[keyInParam].isAssociation
813
+ if (!allowed) {
814
+ // prettier-ignore
815
+ const msg = `${isView ? 'Parameter' : 'Key'} "${keyInParam}" is not a ${isView ? 'parameter' : 'key'} of ${isView ? 'view' : 'entity'} "${entity.name}"`
816
+ cds.error({ status: 400, message: msg })
817
+ }
818
+ }
805
819
  }
806
820
 
807
821
  const _doesNotExistError = (isExpand, refName, { name, kind, _return_of }) => {
@@ -981,8 +995,10 @@ module.exports = (cqn, model, namespace, protocol) => {
981
995
  }
982
996
  }
983
997
 
984
- if (cqn.SELECT.where) {
985
- _processWhere(cqn.SELECT.where, target)
998
+ let _sel = cqn.SELECT
999
+ while (_sel) {
1000
+ if (_sel.where) _processWhere(_sel.where, target)
1001
+ _sel = _sel.from?.SELECT
986
1002
  }
987
1003
 
988
1004
  // one?