@sap/cds-dk 10.0.6 → 10.1.0

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 (326) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/bin/add.js +7 -23
  3. package/bin/bind.js +10 -0
  4. package/bin/build.js +20 -34
  5. package/bin/cds.js +1 -1
  6. package/bin/compile/index.js +15 -41
  7. package/bin/completion/completionFs.js +11 -8
  8. package/bin/completion/index.js +592 -80
  9. package/bin/completion/scripts/cds.fish +568 -0
  10. package/bin/completion/scripts/cds.ps1 +329 -0
  11. package/bin/completion/scripts/cds.sh +261 -0
  12. package/bin/completion/scripts/cds.zsh +230 -0
  13. package/bin/completion/templates/cds-tmpl.fish +65 -0
  14. package/bin/completion/templates/cds-tmpl.ps1 +208 -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 +7 -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/export.js +35 -5
  25. package/bin/help/export.md +3 -0
  26. package/bin/help.js +1 -5
  27. package/bin/import.js +6 -0
  28. package/bin/init.js +5 -24
  29. package/bin/inspect.js +6 -0
  30. package/bin/login.js +26 -20
  31. package/bin/pull.js +19 -6
  32. package/bin/push.js +19 -6
  33. package/bin/up.js +14 -11
  34. package/{lib → bin}/upgrade/constants.js +1 -1
  35. package/bin/{upgrade.js → upgrade/index.js} +2 -2
  36. package/{lib → bin}/upgrade/preflight/consistency.js +1 -1
  37. package/{lib → bin}/upgrade/preflight/index.js +1 -1
  38. package/{lib → bin}/upgrade/steps/analyze/index.js +1 -1
  39. package/{lib → bin}/upgrade/steps/install.js +1 -1
  40. package/{lib → bin}/upgrade/steps/openrewrite.js +1 -1
  41. package/{lib → bin}/upgrade/steps/removals.js +1 -1
  42. package/{lib → bin}/upgrade/steps/rewrite.js +1 -1
  43. package/{lib → bin}/upgrade/steps/verify.js +1 -1
  44. package/{lib/upgrade/index.js → bin/upgrade/upgrade.js} +2 -2
  45. package/{lib → bin}/upgrade/util/pom.js +2 -2
  46. package/{lib → bin}/upgrade/util/prompt.js +1 -1
  47. package/bin/util/containerize.js +8 -4
  48. package/bin/version.js +10 -1
  49. package/{lib → bin}/watch/hot-reload.js +1 -1
  50. package/bin/{watch.js → watch/index.js} +17 -9
  51. package/{lib → bin}/watch/livereload-connect.js +1 -1
  52. package/{lib → bin}/watch/vite-watch.js +1 -1
  53. package/{lib → bin}/watch/watched.js +2 -2
  54. package/lib/build/constants.js +1 -1
  55. package/lib/build/plugins/fiori/index.js +31 -2
  56. package/lib/build/plugins/internal.js +4 -2
  57. package/lib/build/plugins/mtx-sidecar/index.js +7 -8
  58. package/lib/build/plugins/nodejs/index.js +64 -7
  59. package/lib/compile/to_asyncapi.js +1 -1
  60. package/lib/env/schema.js +16 -0
  61. package/lib/env/schemas/cds-rc.js +1 -76
  62. package/lib/import/importapi.js +2 -3
  63. package/lib/import/message.js +0 -2
  64. package/lib/init/constants.js +2 -1
  65. package/lib/init/index.js +2 -2
  66. package/lib/init/merge.js +123 -280
  67. package/lib/init/plugin.js +3 -1
  68. package/lib/init/projectReader.js +22 -6
  69. package/lib/init/registries/xs-app.js +3 -5
  70. package/lib/init/template/ai/files/mta.yaml.hbs +1 -1
  71. package/lib/init/template/ai/index.js +14 -2
  72. package/lib/init/template/ams/index.js +2 -2
  73. package/lib/init/template/app-frontend/files/containerize.yaml.hbs +2 -2
  74. package/lib/init/template/app-frontend/index.js +4 -4
  75. package/lib/init/template/application-logging/index.js +2 -2
  76. package/lib/init/template/approuter/files/package.json +1 -1
  77. package/lib/init/template/approuter/index.js +8 -3
  78. package/lib/init/template/attachments/files/package.json.hbs +1 -1
  79. package/lib/init/template/attachments/index.js +2 -2
  80. package/lib/init/template/audit-logging/index.js +2 -2
  81. package/lib/init/template/cloud-logging/files/package.json.hbs +4 -4
  82. package/lib/init/template/cloud-logging/index.js +2 -2
  83. package/lib/init/template/completion/completionSetup.js +36 -39
  84. package/lib/init/template/connectivity/index.js +2 -2
  85. package/lib/init/template/data/as-csv.js +15 -5
  86. package/lib/init/template/data/as-json.js +114 -42
  87. package/lib/init/template/data/index.js +16 -2
  88. package/lib/init/template/destination/index.js +2 -2
  89. package/lib/init/template/dynatrace/files/package.json.hbs +3 -3
  90. package/lib/init/template/dynatrace/index.js +2 -2
  91. package/lib/init/template/enterprise-messaging/index.js +2 -2
  92. package/lib/init/template/enterprise-messaging-shared/index.js +2 -2
  93. package/lib/init/template/extensibility/files/mta.yaml.hbs +11 -0
  94. package/lib/init/template/extensibility/files/xs-security.json.hbs +1 -1
  95. package/lib/init/template/extensibility/index.js +3 -3
  96. package/lib/init/template/github-actions/index.js +2 -2
  97. package/lib/init/template/hana/index.js +3 -2
  98. package/lib/init/template/hana-serverless/files/db/package.json +14 -0
  99. package/lib/init/template/hana-serverless/files/identity.values.yaml.hbs +10 -0
  100. package/lib/init/template/hana-serverless/files/mta.yaml.hbs +64 -0
  101. package/lib/init/template/hana-serverless/files/package.json.hbs +35 -0
  102. package/lib/init/template/hana-serverless/files/src/.hdiconfig +139 -0
  103. package/lib/init/template/hana-serverless/files/undeploy.json +7 -0
  104. package/lib/init/template/hana-serverless/files/values.yaml.hbs +18 -0
  105. package/lib/init/template/hana-serverless/index.js +184 -0
  106. package/lib/init/template/html5-repo/files/containerize.yaml.hbs +2 -2
  107. package/lib/init/template/html5-repo/files/mta.yaml.hbs +5 -0
  108. package/lib/init/template/html5-repo/index.js +18 -14
  109. package/lib/init/template/http/index.js +123 -26
  110. package/lib/init/template/ias/index.js +2 -2
  111. package/lib/init/template/kafka/index.js +2 -2
  112. package/lib/init/template/kyma/index.js +7 -5
  113. package/lib/init/template/malware-scanner/index.js +2 -2
  114. package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
  115. package/lib/init/template/multitenancy/index.js +18 -3
  116. package/lib/init/template/nodejs/index.js +4 -2
  117. package/lib/init/template/notifications/index.js +2 -2
  118. package/lib/init/template/portal/files/mta.yaml.hbs +4 -0
  119. package/lib/init/template/portal/index.js +13 -8
  120. package/lib/init/template/postgres/index.js +2 -2
  121. package/lib/init/template/redis/index.js +2 -2
  122. package/lib/init/template/sample/files/db/currencies.cds +2 -0
  123. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +1 -1
  124. package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +2 -2
  125. package/lib/init/template/workzone-standard/index.js +5 -5
  126. package/lib/init/template/xsuaa/index.js +20 -2
  127. package/lib/lint/eslintHelp.json +1 -1
  128. package/lib/mtx/auth_manager.js +103 -37
  129. package/lib/mtx/params.js +3 -2
  130. package/lib/mtx/settings_manager.js +45 -28
  131. package/lib/mtx/tenant_action.js +0 -1
  132. package/lib/mtx/util/credentials.js +62 -0
  133. package/node_modules/@cap-js/openapi/lib/compile/csdl.js +3 -3
  134. package/node_modules/@cap-js/openapi/lib/compile/csdl2openapi.js +111 -103
  135. package/node_modules/@cap-js/openapi/lib/compile/diagram.js +4 -4
  136. package/node_modules/@cap-js/openapi/lib/compile/types.d.ts +3 -1
  137. package/node_modules/@cap-js/openapi/package.json +3 -3
  138. package/node_modules/@sap/cds/CHANGELOG.md +64 -0
  139. package/node_modules/@sap/cds/app/index.js +5 -4
  140. package/node_modules/@sap/cds/eslint.config.mjs +1 -0
  141. package/node_modules/@sap/cds/lib/compile/for/nodejs.js +1 -0
  142. package/node_modules/@sap/cds/lib/compile/minify.js +14 -10
  143. package/node_modules/@sap/cds/lib/env/cds-env.js +1 -1
  144. package/node_modules/@sap/cds/lib/env/cds-requires.js +22 -11
  145. package/node_modules/@sap/cds/lib/env/defaults.js +4 -1
  146. package/node_modules/@sap/cds/lib/env/schemas/cds-rc.js +5 -2
  147. package/node_modules/@sap/cds/lib/plugins.js +9 -5
  148. package/node_modules/@sap/cds/lib/req/spawn.js +1 -1
  149. package/node_modules/@sap/cds/lib/srv/srv-dispatch.js +1 -1
  150. package/node_modules/@sap/cds/lib/srv/srv-models.js +1 -1
  151. package/node_modules/@sap/cds/lib/utils/cds-utils.js +2 -1
  152. package/node_modules/@sap/cds/libx/_runtime/common/generic/assert.js +2 -3
  153. package/node_modules/@sap/cds/libx/_runtime/common/generic/auth/restrict.js +8 -1
  154. package/node_modules/@sap/cds/libx/_runtime/common/generic/crud.js +18 -8
  155. package/node_modules/@sap/cds/libx/_runtime/fiori/lean-draft.js +25 -17
  156. package/node_modules/@sap/cds/libx/_runtime/messaging/common-utils/authorizedRequest.js +3 -2
  157. package/node_modules/@sap/cds/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +9 -3
  158. package/node_modules/@sap/cds/libx/_runtime/remote/Service.js +4 -19
  159. package/node_modules/@sap/cds/libx/_runtime/remote/utils/LruCache.js +42 -0
  160. package/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js +14 -4
  161. package/node_modules/@sap/cds/libx/_runtime/remote/utils/cloudSdkProvider.js +2 -9
  162. package/node_modules/@sap/cds/libx/_runtime/remote/utils/destinationClient.js +150 -0
  163. package/node_modules/@sap/cds/libx/_runtime/remote/utils/error.js +13 -0
  164. package/node_modules/@sap/cds/libx/_runtime/remote/utils/fetchClient.js +26 -18
  165. package/node_modules/@sap/cds/libx/_runtime/remote/utils/query.js +34 -23
  166. package/node_modules/@sap/cds/libx/_runtime/remote/utils/token.js +82 -0
  167. package/node_modules/@sap/cds/libx/_runtime/ucl/Service.js +36 -189
  168. package/node_modules/@sap/cds/libx/common/utils/streaming.js +16 -16
  169. package/node_modules/@sap/cds/libx/http/location.js +3 -3
  170. package/node_modules/@sap/cds/libx/odata/middleware/batch.js +16 -10
  171. package/node_modules/@sap/cds/libx/odata/middleware/metadata.js +9 -6
  172. package/node_modules/@sap/cds/libx/odata/middleware/service-document.js +1 -1
  173. package/node_modules/@sap/cds/libx/odata/parse/afterburner.js +19 -3
  174. package/node_modules/@sap/cds/libx/odata/parse/cqn2odata.js +83 -86
  175. package/node_modules/@sap/cds/libx/queue/SchedulingService.js +17 -2
  176. package/node_modules/@sap/cds/libx/queue/processing.js +1 -3
  177. package/node_modules/@sap/cds/libx/rest/RestAdapter.js +3 -7
  178. package/node_modules/@sap/cds/libx/rest/middleware/delete.js +3 -3
  179. package/node_modules/@sap/cds/libx/rest/middleware/parse.js +13 -8
  180. package/node_modules/@sap/cds/libx/rest/middleware/read.js +3 -3
  181. package/node_modules/@sap/cds/libx/rest/middleware/upsert.js +2 -2
  182. package/node_modules/@sap/cds/package.json +1 -1
  183. package/node_modules/@sap/cds-compiler/CHANGELOG.md +60 -8
  184. package/node_modules/@sap/cds-compiler/bin/cdsc.js +2 -2
  185. package/node_modules/@sap/cds-compiler/doc/IncompatibleChanges_v7.md +46 -19
  186. package/node_modules/@sap/cds-compiler/lib/api/main.js +10 -7
  187. package/node_modules/@sap/cds-compiler/lib/api/options.js +8 -2
  188. package/node_modules/@sap/cds-compiler/lib/base/csnRefs.js +5 -2
  189. package/node_modules/@sap/cds-compiler/lib/base/message-registry.js +4 -0
  190. package/node_modules/@sap/cds-compiler/lib/base/optionProcessor.js +12 -0
  191. package/node_modules/@sap/cds-compiler/lib/checks/enricher.js +1 -0
  192. package/node_modules/@sap/cds-compiler/lib/compiler/assert-consistency.js +8 -7
  193. package/node_modules/@sap/cds-compiler/lib/compiler/checks.js +3 -3
  194. package/node_modules/@sap/cds-compiler/lib/compiler/define.js +301 -75
  195. package/node_modules/@sap/cds-compiler/lib/compiler/dictionaries.js +2 -0
  196. package/node_modules/@sap/cds-compiler/lib/compiler/extend.js +40 -26
  197. package/node_modules/@sap/cds-compiler/lib/compiler/populate.js +45 -60
  198. package/node_modules/@sap/cds-compiler/lib/compiler/propagator.js +16 -7
  199. package/node_modules/@sap/cds-compiler/lib/compiler/resolve.js +41 -15
  200. package/node_modules/@sap/cds-compiler/lib/compiler/shared.js +7 -6
  201. package/node_modules/@sap/cds-compiler/lib/compiler/tweak-assocs.js +62 -50
  202. package/node_modules/@sap/cds-compiler/lib/compiler/utils.js +29 -14
  203. package/node_modules/@sap/cds-compiler/lib/edm/edmAnnoPreprocessor.js +6 -5
  204. package/node_modules/@sap/cds-compiler/lib/gen/CdlGrammar.checksum +1 -1
  205. package/node_modules/@sap/cds-compiler/lib/gen/CdlParser.js +1119 -1109
  206. package/node_modules/@sap/cds-compiler/lib/gen/Dictionary.json +19 -3
  207. package/node_modules/@sap/cds-compiler/lib/json/from-csn.js +10 -16
  208. package/node_modules/@sap/cds-compiler/lib/json/to-csn.js +58 -39
  209. package/node_modules/@sap/cds-compiler/lib/main.d.ts +8 -0
  210. package/node_modules/@sap/cds-compiler/lib/main.js +1 -0
  211. package/node_modules/@sap/cds-compiler/lib/model/csnUtils.js +2 -0
  212. package/node_modules/@sap/cds-compiler/lib/parsers/AstBuildingParser.js +2 -1
  213. package/node_modules/@sap/cds-compiler/lib/parsers/XprTree.js +8 -0
  214. package/node_modules/@sap/cds-compiler/lib/render/toCdl.js +22 -1
  215. package/node_modules/@sap/cds-compiler/lib/render/toSql.js +17 -2
  216. package/node_modules/@sap/cds-compiler/lib/render/utils/common.js +6 -1
  217. package/node_modules/@sap/cds-compiler/lib/render/utils/operators.js +27 -0
  218. package/node_modules/@sap/cds-compiler/lib/render/utils/standardDatabaseFunctions.js +125 -3
  219. package/node_modules/@sap/cds-compiler/lib/tool-lib/revealInternalProperties.js +2 -1
  220. package/node_modules/@sap/cds-compiler/lib/transform/db/applyTransformations.js +3 -0
  221. package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +8 -2
  222. package/node_modules/@sap/cds-compiler/lib/transform/db/backlinks.js +22 -6
  223. package/node_modules/@sap/cds-compiler/lib/transform/db/constraints.js +62 -1
  224. package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +40 -0
  225. package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +1 -0
  226. package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +6 -1
  227. package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +19 -8
  228. package/node_modules/@sap/cds-compiler/package.json +1 -1
  229. package/node_modules/@sap/cds-mtxs/CHANGELOG.md +51 -0
  230. package/node_modules/@sap/cds-mtxs/bin/cds-mtx-migrate.js +32 -48
  231. package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +35 -16
  232. package/node_modules/@sap/cds-mtxs/cds-plugin.js +18 -0
  233. package/node_modules/@sap/cds-mtxs/lib/migration/migration.js +3 -408
  234. package/node_modules/@sap/cds-mtxs/lib/utils.js +19 -4
  235. package/node_modules/@sap/cds-mtxs/package.json +1 -1
  236. package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +6 -7
  237. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/annotations.js +5 -2
  238. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/index.js +6 -5
  239. package/node_modules/@sap/cds-mtxs/srv/extensibility-service.cds +0 -11
  240. package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +34 -35
  241. package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +30 -24
  242. package/node_modules/@sap/cds-mtxs/srv/model-provider.js +19 -4
  243. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +6 -3
  244. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi.js +5 -3
  245. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/srv-mgr.js +3 -2
  246. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/tms.js +17 -0
  247. package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +18 -21
  248. package/node_modules/@sap/xsenv/CHANGELOG.md +7 -0
  249. package/node_modules/@sap/xsenv/package.json +10 -7
  250. package/node_modules/body-parser/node_modules/content-type/README.md +2 -0
  251. package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
  252. package/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
  253. package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
  254. package/node_modules/body-parser/node_modules/content-type/package.json +1 -1
  255. package/node_modules/hdb/cfg/VERSION +1 -1
  256. package/node_modules/hdb/lib/protocol/ClientInfo.js +16 -3
  257. package/node_modules/hdb/lib/protocol/Connection.js +1 -0
  258. package/node_modules/hdb/package.json +3 -2
  259. package/node_modules/negotiator/lib/accept.js +54 -0
  260. package/node_modules/negotiator/lib/charset.js +10 -34
  261. package/node_modules/negotiator/lib/encoding.js +9 -30
  262. package/node_modules/negotiator/lib/language.js +15 -36
  263. package/node_modules/negotiator/lib/mediaType.js +16 -134
  264. package/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
  265. package/node_modules/negotiator/node_modules/content-type/README.md +71 -0
  266. package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
  267. package/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
  268. package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
  269. package/node_modules/negotiator/node_modules/content-type/package.json +52 -0
  270. package/node_modules/negotiator/package.json +16 -10
  271. package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
  272. package/node_modules/qs/CHANGELOG.md +15 -0
  273. package/node_modules/qs/README.md +19 -1
  274. package/node_modules/qs/dist/qs.js +21 -21
  275. package/node_modules/qs/eslint.config.mjs +1 -1
  276. package/node_modules/qs/lib/parse.js +3 -4
  277. package/node_modules/qs/lib/stringify.js +23 -8
  278. package/node_modules/qs/lib/utils.js +10 -3
  279. package/node_modules/qs/package.json +4 -4
  280. package/node_modules/qs/test/parse.js +192 -3
  281. package/node_modules/qs/test/stringify.js +317 -0
  282. package/node_modules/qs/test/utils.js +12 -0
  283. package/node_modules/sax/lib/sax.js +27 -9
  284. package/node_modules/sax/package.json +1 -1
  285. package/node_modules/type-is/node_modules/content-type/README.md +2 -0
  286. package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
  287. package/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
  288. package/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
  289. package/node_modules/type-is/node_modules/content-type/package.json +1 -1
  290. package/node_modules/ws/lib/permessage-deflate.js +3 -1
  291. package/node_modules/ws/package.json +1 -1
  292. package/package.json +5 -5
  293. package/bin/completion/scripts/cds-bash.sh +0 -20
  294. package/bin/completion/scripts/cds-fish.fish +0 -13
  295. package/bin/completion/scripts/cds-ps.ps1 +0 -19
  296. package/bin/completion/scripts/cds-zsh.sh +0 -13
  297. package/lib/deploy/index.js +0 -25
  298. package/lib/import/asyncapi/importAsyncAPI.js +0 -33
  299. package/lib/import/asyncapi/index.js +0 -18
  300. package/lib/import/asyncapi/parserContext.js +0 -372
  301. package/lib/import/asyncapi/utils.js +0 -49
  302. package/lib/init/template/nodejs/files/.gitignore.hbs +0 -34
  303. package/node_modules/@sap/cds/libx/_runtime/ucl/queries.js +0 -61
  304. package/node_modules/@sap/cds-mtxs/lib/migration/extension-project-builder.js +0 -129
  305. package/node_modules/@sap/cds-mtxs/lib/migration/extension-project.js +0 -89
  306. package/node_modules/@sap/cds-mtxs/lib/migration/mtx-adapter.js +0 -230
  307. package/node_modules/negotiator/HISTORY.md +0 -114
  308. /package/{lib → bin}/upgrade/context.js +0 -0
  309. /package/{lib → bin}/upgrade/migrations/cds10/migrations.json +0 -0
  310. /package/{lib → bin}/upgrade/preflight/cds-version.js +0 -0
  311. /package/{lib → bin}/upgrade/preflight/project-type.js +0 -0
  312. /package/{lib → bin}/upgrade/steps/analyze/classification.js +0 -0
  313. /package/{lib → bin}/upgrade/steps/analyze/detector.js +0 -0
  314. /package/{lib → bin}/upgrade/steps/analyze/evaluator.js +0 -0
  315. /package/{lib → bin}/upgrade/steps/analyze/reporter.js +0 -0
  316. /package/{lib → bin}/upgrade/steps/analyze/setup.js +0 -0
  317. /package/{lib → bin}/upgrade/steps/analyze/utils/detection.js +0 -0
  318. /package/{lib → bin}/upgrade/steps/analyze/utils/files.js +0 -0
  319. /package/{lib → bin}/upgrade/steps/analyze/utils/grep.js +0 -0
  320. /package/{lib → bin}/upgrade/steps/analyze/utils/yaml.js +0 -0
  321. /package/{lib → bin}/upgrade/util/workspaces.js +0 -0
  322. /package/{lib → bin}/watch/esm-resolve-registration.js +0 -0
  323. /package/{lib → bin}/watch/livereload-server.js +0 -0
  324. /package/{lib → bin}/watch/node-watch.js +0 -0
  325. /package/{lib → bin}/watch/open.js +0 -0
  326. /package/{lib → bin}/watch/watcher.js +0 -0
@@ -2,9 +2,9 @@ const express = require('express')
2
2
  const cds = require('@sap/cds/lib')
3
3
  const { SELECT, DELETE } = cds.ql
4
4
  const { fs, path, tar, rimraf, read, readdir, mkdirp, write } = cds.utils
5
- const { token: authToken } = require('../lib/utils')
5
+ const { token: authToken, authUrl } = require('../lib/utils')
6
+ const main = require('./config')
6
7
  const linter = require('./extensibility/linter')
7
- const { getMigratedProjects } = require('../lib/migration/migration')
8
8
 
9
9
 
10
10
  const BUILT_IN_NAMESPACES = ['cds.core', 'cds.outbox', 'cds.xt'] // REVISIT: move to a more central place to be consumed also by linter
@@ -20,12 +20,14 @@ const ACTIVE = 2, DRAFT = 1, INACTIVE = 0
20
20
  //const packageJson = require(main.root + '/package.json');
21
21
  const APPID = require('../lib/utils').getAppId()
22
22
 
23
+ const conf = () => ({ ...main.env.requires.extensibility, ...cds.env.requires['cds.xt.ExtensibilityService'] })
24
+
23
25
  const _async = () => {
24
26
  return cds.context.http?.req?.headers?.prefer === 'respond-async'
25
27
  }
26
28
 
27
29
  const _includeExt = () => {
28
- return (cds.env.requires['cds.xt.ExtensibilityService']?.['check-existing-extensions'] !== false)
30
+ return conf()['check-existing-extensions'] !== false
29
31
  }
30
32
  class DbAdapter {
31
33
 
@@ -64,7 +66,7 @@ class DbAdapter {
64
66
  }
65
67
  }
66
68
 
67
- if (ext.csvs && Object.keys(ext.csvs).length > 0 && cds.env.requires['cds.xt.ExtensibilityService']?.activate?.['skip-csv']) throw Error('CSV deployment is disabled')
69
+ if (ext.csvs && Object.keys(ext.csvs).length > 0 && conf().activate?.['skip-csv']) throw Error('CSV deployment is disabled')
68
70
 
69
71
  // insert extension
70
72
  const tenant = ext.tenant
@@ -74,14 +76,9 @@ class DbAdapter {
74
76
  const tag = ext.ID
75
77
  await cds.tx({ tenant, user: new cds.User.Privileged() }, async tx => {
76
78
  // remove current inactive extension with tag
77
- // use native table names to avoid issues with missing appid
78
- if (tag) await tx.run(DELETE.from('cds_xt_Extensions').where({ tag, activated: { '!=': this.activated(ACTIVE) } }))
79
- try {
80
- await tx.run(INSERT.into('cds_xt_Extensions').entries({ ID, csn, i18n, sources: ext.archive ?? null, activated: this.activated(ext.status), tag, appid: ext.appid ?? APPID, timestamp: new Date().toISOString() }))
81
- } catch (error) {
82
- DEBUG?.('Trying legacy request without appid', error)
83
- await tx.run(INSERT.into('cds_xt_Extensions').entries({ ID, csn, i18n, sources: ext.archive ?? null, activated: this.activated(ext.status), tag, timestamp: new Date().toISOString() }))
84
- }
79
+ if (tag) await tx.run(DELETE.from('cds.xt.Extensions').where({ tag, activated: { '!=': this.activated(ACTIVE) } }))
80
+ // will break with missing appid
81
+ await tx.run(INSERT.into('cds.xt.Extensions').entries({ ID, csn, i18n, sources: ext.archive ?? null, activated: this.activated(ext.status), tag, appid: ext.appid ?? APPID, timestamp: new Date().toISOString() }))
85
82
  })
86
83
  return ID
87
84
  }
@@ -213,7 +210,7 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
213
210
  if (async) { // 202 is set by the job service
214
211
  return
215
212
  }
216
- const res = await _fetchExtensions(req.data.ID)
213
+ const res = await _fetchExtensions(req.data.ID, status)
217
214
  req.results = { ID: res?.tag, csn: res?.csn, i18n: res?.i18n !== '{}' ? res?.i18n : undefined, timestamp: res?.timestamp, appid: res?.appid, status: DbAdapter.status(res?.activated) } // REVISIT: return csvs?
218
215
  })
219
216
 
@@ -379,9 +376,9 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
379
376
  }
380
377
  })
381
378
 
382
- async function _fetchExtensions(ID) {
379
+ async function _fetchExtensions(ID, status) {
383
380
  try {
384
- return !ID ? await SELECT.from('cds.xt.Extensions') : await SELECT.one.from('cds.xt.Extensions').where({ tag: ID })
381
+ return !ID ? await SELECT.from('cds.xt.Extensions') : await SELECT.one.from('cds.xt.Extensions').where(status != undefined ? { tag: ID, activated: DbAdapter.activated(status) } : { tag: ID })
385
382
  } catch (error) {
386
383
  DEBUG?.('Trying legacy request without appid', error)
387
384
  const fields = ['ID', 'csn', 'tag', 'activated', 'timestamp', 'i18n']
@@ -401,25 +398,22 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
401
398
 
402
399
  })
403
400
 
404
- this.on('getMigratedProjects', req => {
405
- const { tagRule, defaultTag } = req.data
406
- const tenant = req.tenant // REVISIT: check if access for arbitrary tenants needed
407
- if (!tenant) req.reject(401, 'User not assigned to any tenant')
408
- return getMigratedProjects(req, tagRule || undefined, defaultTag || undefined, tenant)
409
- })
410
-
411
401
  cds.on('served', () => {
412
- cds.app?.post('/-/cds/login/token', express.urlencoded({ extended: false }), async (req, res) => {
402
+ cds.app?.post('/-/cds/login/grant', express.urlencoded({ extended: false }), async (req, res) => {
413
403
  try {
414
- if (req.method === 'HEAD') return res.status(204).send()
415
-
416
404
  const cred = cds.env.requires.auth.credentials || {}
417
405
  if (!cred.clientid) throw cds.error('missing authentication service binding', { status: 500 })
418
406
 
419
- const query = req.method === 'POST' ? (req.body || {}) : (req.query || {})
407
+ const query = req.body || {}
408
+
409
+ // Endpoint accepts only passcode and refresh_token grant requests.
410
+ const refresh_token = typeof query.refresh_token === 'string' ? query.refresh_token : undefined
411
+ const passcode = typeof query.passcode === 'string' ? query.passcode : undefined
412
+ if (!refresh_token && !passcode)
413
+ throw cds.error('missing passcode or refresh_token', { status: 400 })
420
414
 
421
- const form = query.refresh_token ? { grant_type: 'refresh_token', refresh_token: query.refresh_token } :
422
- query.passcode ? { grant_type: 'password', passcode: query.passcode } : {}
415
+ const form = refresh_token ? { grant_type: 'refresh_token', refresh_token } :
416
+ { grant_type: 'password', passcode }
423
417
  form.scope = `${cred.xsappname}.cds.ExtensionDeveloper`
424
418
  const raw = await authToken(cred, { form, subdomain: query.subdomain })
425
419
  const data = JSON.parse(raw)
@@ -434,7 +428,11 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
434
428
  }
435
429
  })
436
430
 
437
- cds.app?.get('/-/cds/login/authorization-metadata', authMeta)
431
+ cds.app?.get('/-/cds/login/grant-metadata', authMeta)
432
+
433
+ const redirectTo = to => (req, res) => res.redirect(308, to + req.url.slice(req.path.length))
434
+ cds.app?.post('/-/cds/login/token', redirectTo('/-/cds/login/grant'))
435
+ cds.app?.get('/-/cds/login/authorization-metadata', redirectTo('/-/cds/login/grant-metadata'))
438
436
  })
439
437
 
440
438
  const _tenant = function (req) {
@@ -483,7 +481,7 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
483
481
  else await UPDATE('cds.xt.Extensions', { tag, ID: extEntry.ID }).with({ activated: DbAdapter.activated(status) }) // update status
484
482
 
485
483
  // really activate extension
486
- if (status === ACTIVE && !(cds.env.requires['cds.xt.ExtensibilityService']?.activate?.['skip-db'] === true)) {
484
+ if (status === ACTIVE && !(conf().activate?.['skip-db'] === true)) {
487
485
  const { 'cds.xt.DeploymentService': ds } = cds.services
488
486
  if (!ds) {
489
487
  LOG.info('database activation skipped for extension', tag, '- no deployment service')
@@ -503,15 +501,16 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
503
501
  }
504
502
 
505
503
  function _passcodeUrl(c, sub) {
506
- const u = new URL(c.url)
507
- if (sub) u.hostname = u.hostname.replace(/^[^.]+/, sub)
508
- u.pathname = '/passcode'
509
- return u.toString()
504
+ return authUrl(c.url, sub, '/passcode').toString()
510
505
  }
511
506
 
512
507
  function authMeta(req, res) {
513
508
  const cred = cds.env.requires?.auth?.credentials || {}
514
- res.send({ passcode_url: _passcodeUrl(cred, req.query?.subdomain) })
509
+ try {
510
+ res.send({ passcode_url: _passcodeUrl(cred, req.query?.subdomain) })
511
+ } catch (err) {
512
+ res.status(err.status || err.statusCode || 500).json({ error: err.message })
513
+ }
515
514
  }
516
515
 
517
516
  const _getCompilerError = messages => {
@@ -7,14 +7,6 @@ const Jobs = 'cds.xt.Jobs', Tasks = 'cds.xt.Tasks'
7
7
 
8
8
  const { t0_ } = require('../lib/utils')
9
9
 
10
- const {
11
- queueSize = 100, clusterSize = 3, workerSize = 4, poolSize = 1
12
- } = {
13
- ...(cds.env.requires.multitenancy?.jobs ?? {}),
14
- ...(cds.env.requires['cds.xt.SaasProvisioningService']?.jobs ?? {}),
15
- ...(cds.env.requires['cds.xt.SmsProvisioningService']?.jobs ?? {})
16
- }
17
-
18
10
  const RUNNING = 'RUNNING', FINISHED = 'FINISHED', FAILED = 'FAILED', QUEUED = 'QUEUED', TIMEOUT = 'TIMEOUT'
19
11
 
20
12
  // A queue, implemented as a circular buffer for O(1) insert + delete
@@ -41,12 +33,15 @@ class Queue {
41
33
  return value
42
34
  }
43
35
  }
44
- const jobQueue = new Queue(queueSize)
45
- let runningJobs = new Map()
46
36
 
47
37
  module.exports = class JobsService extends cds.ApplicationService {
48
38
 
49
39
  async init() {
40
+
41
+ this._conf = this._config()
42
+ this.jobQueue = new Queue(this._conf.queueSize)
43
+ this.runningJobs = new Map()
44
+
50
45
  if (cds.requires.multitenancy?.diagnostics) _diagnostics4(this)
51
46
  cds.on('listening', () => _scheduled(this))
52
47
 
@@ -57,16 +52,16 @@ module.exports = class JobsService extends cds.ApplicationService {
57
52
  return jobs.map(job => ({ ...job, tasks: job.tasks.sort((a, b) => a.tenant.localeCompare(b.tenant))}))
58
53
  })
59
54
  this.on('config', () => {
60
- const conf = main.requires.extensibility, es = main.requires['cds.xt.ExtensibilityService']
55
+ const conf = main.requires['cds.xt.ExtensibilityService'], ext = main.requires.extensibility
61
56
  const allowlist = 'extension-allowlist', blocklist = 'namespace-blocklist'
62
57
  return {
63
58
  pool: main.requires.db.pool,
64
59
  poolMtx: cds.requires.db.pool,
65
60
  jobs: cds.requires.multitenancy.jobs,
66
61
  extensibility: {
67
- tenantCheckInterval: conf?.tenantCheckInterval,
68
- [allowlist]: conf?.[allowlist] ?? es?.[allowlist],
69
- [blocklist]: conf?.[blocklist] ?? es?.[blocklist]
62
+ tenantCheckInterval: conf?.tenantCheckInterval ?? ext?.tenantCheckInterval,
63
+ [allowlist]: conf?.[allowlist] ?? ext?.[allowlist],
64
+ [blocklist]: conf?.[blocklist] ?? ext?.[blocklist]
70
65
  }
71
66
  }
72
67
  })
@@ -74,6 +69,17 @@ module.exports = class JobsService extends cds.ApplicationService {
74
69
  return super.init()
75
70
  }
76
71
 
72
+ _config() {
73
+ const {
74
+ queueSize = 100, clusterSize = 3, workerSize = 4, poolSize = 1
75
+ } = {
76
+ ...(cds.env.requires.multitenancy?.jobs ?? {}),
77
+ ...(cds.env.requires['cds.xt.SaasProvisioningService']?.jobs ?? {}),
78
+ ...(cds.env.requires['cds.xt.SmsProvisioningService']?.jobs ?? {})
79
+ }
80
+ return { queueSize, clusterSize, workerSize, poolSize }
81
+ }
82
+
77
83
  async enqueue(service, op, clusters, args, onJobDone) {
78
84
  const _inspect = obj => obj && Object.values(obj).filter(Boolean).length > 0 ? inspect(obj, { depth: 5, colors: cds.utils.colors.enabled }) : []
79
85
  const inspected = Object.entries(args).reduce((acc, [k, v]) => {
@@ -112,9 +118,9 @@ module.exports = class JobsService extends cds.ApplicationService {
112
118
  if (tasks.length) {
113
119
  if (cds.services[service]) {
114
120
  const fn = task => cds.services[service].tx({ tenant: task.tenant }, tx => tx[op](task.tenant, ...Object.values(args)))
115
- jobQueue.enqueue({ job_ID, clusters: clustered, fn, onJobDone })
121
+ this.jobQueue.enqueue({ job_ID, clusters: clustered, fn, onJobDone })
116
122
  } else {
117
- jobQueue.enqueue({ job_ID, clusters: clustered, fn: () => {
123
+ this.jobQueue.enqueue({ job_ID, clusters: clustered, fn: () => {
118
124
  LOG.warn('service', service, 'is not available, skipping job')
119
125
  }, onJobDone })
120
126
  }
@@ -186,16 +192,16 @@ module.exports = class JobsService extends cds.ApplicationService {
186
192
  }
187
193
 
188
194
  async pickJob() {
189
- if (jobQueue.size === 0) return
195
+ if (this.jobQueue.size === 0) return
190
196
 
191
- const next = new Set(jobQueue.peek().clusters.flat().map(t => t.tenant).flat())
192
- const running = [...runningJobs.values()].flatMap(j => j.clusters.flat().map(t => t.tenant))
197
+ const next = new Set(this.jobQueue.peek().clusters.flat().map(t => t.tenant).flat())
198
+ const running = [...this.runningJobs.values()].flatMap(j => j.clusters.flat().map(t => t.tenant))
193
199
  if (running.some(t => next.has(t))) return
194
200
 
195
- const job = jobQueue.dequeue()
201
+ const job = this.jobQueue.dequeue()
196
202
  const { job_ID, clusters, fn, onJobDone } = job
197
203
  try {
198
- runningJobs.set(job_ID, job)
204
+ this.runningJobs.set(job_ID, job)
199
205
  await t0_(async () => {
200
206
  await UPDATE(Jobs, { ID: job_ID }).with({ status: RUNNING })
201
207
  await this.emit('jobUpdate', { job: { ID: job_ID, status: RUNNING }})
@@ -207,16 +213,16 @@ module.exports = class JobsService extends cds.ApplicationService {
207
213
  await this.emit('jobUpdate', { job: { ID: job_ID, status: FAILED, error: _errorMessage(e) }})
208
214
  })
209
215
  } finally {
210
- runningJobs.delete(job_ID)
216
+ this.runningJobs.delete(job_ID)
211
217
  }
212
218
  setImmediate(() => this.pickJob())
213
219
  }
214
220
 
215
221
  async _nextJob(clusters, fn, onJobDone) {
216
222
  if (clusters.length > 1) {
217
- await this.limiter(clusterSize, clusters, cluster => this.limiter(workerSize ?? poolSize, Array.from(cluster), fn, true))
223
+ await this.limiter(this._conf.clusterSize, clusters, cluster => this.limiter(this._conf.workerSize ?? this._conf.poolSize, Array.from(cluster), fn, true))
218
224
  } else {
219
- await this.limiter(workerSize ?? poolSize, Array.from(clusters[0]), fn, true)
225
+ await this.limiter(this._conf.workerSize ?? this._conf.poolSize, Array.from(clusters[0]), fn, true)
220
226
  }
221
227
 
222
228
  const { job_ID } = clusters[0][0] // all tasks have the same job ID -> just take the first
@@ -208,8 +208,14 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
208
208
  if (extensions) {
209
209
  const key = crypto.createHash('sha256').update(JSON.stringify({ extensions, models, javaornode })).digest('hex')
210
210
  csn = lru4(extensionCache, key, () => {
211
- const result = cds.extend(csn).with(extensions)
212
- return _delayMinify ? cds.minify(result) : result
211
+ try {
212
+ const result = cds.extend(csn).with(extensions)
213
+ return _delayMinify ? cds.minify(result) : result
214
+ } catch (e) {
215
+ if (!activated || e.code !== 'ERR_CDS_COMPILATION_FAILURE') throw e
216
+ const message = _getCompilerError(e.messages)
217
+ throw cds.error(`Extensions of tenant '${tenant}' are incompatible with the base model: ${message}`, { code: 'ERR_CDS_COMPILATION_FAILURE', status: 422, tenant, messages: e.messages })
218
+ }
213
219
  })
214
220
  }
215
221
 
@@ -334,7 +340,7 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
334
340
  async function _getETag(tenant, activated = true) {
335
341
  if (!main.requires.extensibility || main.requires.multitenancy && !tenant) return BASE_MODEL_ETAG
336
342
  try {
337
- const query = SELECT('max(timestamp) as TS').from('cds_xt_Extensions')
343
+ const query = SELECT('max(timestamp) as TS').from('cds.xt.Extensions')
338
344
  if (activated) query.where('activated=', 'database')
339
345
  const exts = await cds.db.run(query)
340
346
  if (!exts.length || !exts[0].TS) return BASE_MODEL_ETAG
@@ -377,7 +383,7 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
377
383
  }
378
384
 
379
385
  async function getExtCsvs(req) {
380
- if (cds.env.requires['cds.xt.ExtensibilityService']?.activate?.['skip-csv']) return {}
386
+ if (cds.env.requires['cds.xt.ExtensibilityService']?.activate?.['skip-csv'] ?? main.env.requires.extensibility?.activate?.['skip-csv']) return {}
381
387
 
382
388
  const tenant = req.data.tenant || req.tenant
383
389
  if (tenant) cds.context = { tenant }
@@ -410,3 +416,12 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
410
416
  }
411
417
 
412
418
  module.exports.prototype._add_stub_methods = true
419
+
420
+ const _getCompilerError = messages => {
421
+ const defaultMsg = 'Error while compiling extension'
422
+ if (!messages) return defaultMsg
423
+ for (const msg of messages) {
424
+ if (msg.severity === 'Error') return msg.message
425
+ }
426
+ return defaultMsg
427
+ }
@@ -48,7 +48,7 @@ class AbstractContainerManagerClient {
48
48
  if (this.cachedToken && this.cachedToken.expiry >= Date.now() + 30_000) {
49
49
  return `Bearer ${this.cachedToken.access_token}`
50
50
  }
51
- const raw = await token(this)
51
+ const raw = await token(this, { form: { grant_type: 'client_credentials' } })
52
52
  const { access_token, expires_in } = JSON.parse(raw)
53
53
  this.cachedToken = { access_token, expiry: Date.now() + expires_in * 1000 }
54
54
  return `Bearer ${access_token}`
@@ -68,7 +68,7 @@ class AbstractContainerManagerClient {
68
68
  conf.baseURL ??= url.startsWith('http') ? '' : this.sm_url + '/v1/'
69
69
 
70
70
  const { retries, maxRetryAfter } = cds.requires?.multitenancy?.serviceManager ?? cds.requires?.multitenancy?.containerManager ?? {}
71
- return fetchResiliently(conf.baseURL + url, conf, { retries: retries ?? 10, maxRetryAfter: maxRetryAfter ?? 5000, retryUntil, failures })
71
+ return fetchResiliently(conf.baseURL + url, conf, { retriesLeft: retries ?? 10, maxRetryAfter: maxRetryAfter ?? 5000, retryUntil, failures })
72
72
  }
73
73
 
74
74
  _poll = async (location, conf = {}) => {
@@ -89,9 +89,12 @@ class AbstractContainerManagerClient {
89
89
  return new Promise(_next)
90
90
  }
91
91
 
92
+ // base implementation used by srv-mgr
92
93
  _succeeded = (response) => response.data?.state === 'succeeded'
93
94
  _failed = (response) => response.data?.state === 'failed'
94
- _pollError = (response) => response.data.errors[0] ?? response.data.errors
95
+ _pollError = (response) =>
96
+ response.data?.errors?.[0] ?? response.data.errors
97
+ ?? { error: 'Unknown Error', description: `Polling failed with state ${response.data?.state ?? 'unknown'}. Last operation ${response.data?.id}` }
95
98
 
96
99
  static _errorMessage = (e, action, tenant) => {
97
100
  const msg = `Error ${action} tenant ${tenant}: ${e.response?.data?.error ?? e.code ?? e.message ?? 'unknown error'}`
@@ -13,7 +13,7 @@ exports._logDirectory = async () => {
13
13
  await mkdirp(defaultDir)
14
14
  return defaultDir
15
15
  } catch (e) {
16
- if (e.code !== 'EACCES') throw e
16
+ if (e.code !== 'EACCES' && e.code !== 'EROFS' && e.code !== 'ENOENT') throw e
17
17
  LOG?.(`using temporary directory ${TEMP_DIR} for deployment logs`)
18
18
  return join(TEMP_DIR, 'logs')
19
19
  }
@@ -86,9 +86,10 @@ exports.deploy = async (hana, tenant, cwd, options, deployEnv) => {
86
86
  */
87
87
  exports._hdi_env4 = async (t,container,options,deployEnv)=>{
88
88
 
89
+ let vcapFromFile
89
90
  if (process.env.VCAP_SERVICES_FILE_PATH) {
90
91
  try {
91
- process.env.VCAP_SERVICES = await fs.read(process.env.VCAP_SERVICES_FILE_PATH, 'utf-8')
92
+ vcapFromFile = await fs.read(process.env.VCAP_SERVICES_FILE_PATH, 'utf-8')
92
93
  } catch (e) {
93
94
  LOG.warn(`Could not read or parse VCAP_SERVICES_FILE_PATH at ${process.env.VCAP_SERVICES_FILE_PATH}: ${e.message}`)
94
95
  }
@@ -104,7 +105,8 @@ exports._hdi_env4 = async (t,container,options,deployEnv)=>{
104
105
  ...deployEnv // Although VCAP is in here, it will be overwritten
105
106
  }
106
107
 
107
- const { hana=[], 'user-provided':up=[] } = _parse_env (process.env, 'VCAP_SERVICES')
108
+ const vcapEnv = vcapFromFile ? { VCAP_SERVICES: vcapFromFile } : process.env
109
+ const { hana=[], 'user-provided':up=[] } = _parse_env (vcapEnv, 'VCAP_SERVICES')
108
110
  const { hana: customEnvHana=[], 'user-provided':customEnvUp=[] } = _parse_env(deployEnv ?? {}, 'VCAP_SERVICES')
109
111
 
110
112
  const vcapFromEnv = {
@@ -126,6 +126,7 @@ class ServiceManagerClient extends AbstractContainerManagerClient {
126
126
 
127
127
  get = async (tenant, options = {}) => {
128
128
  const { invalidCredentials, retryUntil } = options
129
+ if (invalidCredentials && cacheBindings) delete this._bindingsCache[tenant]
129
130
  try {
130
131
  const previousFailures = this.failures.has(tenant) ? this.failures.get(tenant).count : 0
131
132
  const [binding] = await this._bindings4([tenant], { ...options, tenant, failures: previousFailures, retryUntil })
@@ -292,9 +293,9 @@ class ServiceManagerClient extends AbstractContainerManagerClient {
292
293
  }
293
294
  fetched.push(...directMatches)
294
295
  }
295
- const cacheMisses = Object.fromEntries(fetched.filter(b => b.labels?.tenant_id).map(b => [b.labels.tenant_id[0], b]))
296
- Object.assign(this._bindingsCache, cacheMisses)
297
296
  if (useCache) {
297
+ const cacheMisses = Object.fromEntries(fetched.filter(b => b.labels?.tenant_id).map(b => [b.labels.tenant_id[0], b]))
298
+ Object.assign(this._bindingsCache, cacheMisses)
298
299
  return tenants.map(t => this._bindingsCache[t])
299
300
  }
300
301
  return fetched
@@ -17,6 +17,23 @@ class TMSClient extends AbstractContainerManagerClient {
17
17
  this.tmsHost = credentials.baseurl
18
18
 
19
19
  this.credentialCache = {}
20
+
21
+ // clusterSize > 1 not supported yet for TMS
22
+ const {
23
+ clusterSize
24
+ } = {
25
+ ...(cds.env.requires.multitenancy?.jobs ?? {}),
26
+ ...(cds.env.requires['cds.xt.SaasProvisioningService']?.jobs ?? {}),
27
+ ...(cds.env.requires['cds.xt.SmsProvisioningService']?.jobs ?? {})
28
+ }
29
+
30
+ if (clusterSize && clusterSize > 1) {
31
+ LOG.warn(`Cluster size of ${clusterSize} is not supported for TMS. Defaulting to 1.`)
32
+ }
33
+
34
+ cds.utils.merge(cds.env.requires, { multitenancy: { jobs: { clusterSize: 1 } } })
35
+ cds.utils.merge(cds.env.requires, { 'cds.xt.SaasProvisioningService': { jobs: { clusterSize: 1 } } })
36
+ cds.utils.merge(cds.env.requires, { 'cds.xt.SmsProvisioningService': { jobs: { clusterSize: 1 } } })
20
37
  }
21
38
 
22
39
  static defaultInstance() {
@@ -15,8 +15,6 @@ const resources = new Map()
15
15
 
16
16
  const { deepMerge } = require('../../lib/utils')
17
17
 
18
- const migration = require('../../lib/migration/migration')
19
-
20
18
  if (db?.kind === 'hana') {
21
19
  if (!db.credentials?.sm_url && !db.credentials?.baseurl) cds.error('No Service Manager credentials found. Make sure the application is bound to a BTP Service Manager instance.')
22
20
 
@@ -89,20 +87,24 @@ if (db?.kind === 'hana') {
89
87
  })
90
88
  ds.on ('tenantsByDb', async req => {
91
89
  const tenantsInT0 = await ds.getTenants()
92
- const mtxTenants = await migration.getMissingMtxTenants(tenantsInT0)
93
- const tenants = req.data.tenants ?? [...tenantsInT0, ...mtxTenants]
90
+ const tenants = req.data.tenants ?? [...tenantsInT0]
94
91
  const hana = require('./hana/hdi-ctnr-mgr').defaultInstance() // TODO tms more generic handling -> new functions hana.toTenantId + hana.toDbId
95
92
  const toTenantId = t => t.tenant_id ?? t.labels.tenant_id[0]
96
93
  const smTenants = (await hana.getAll(tenants.length > 0 ? tenants : '*')).filter(Boolean).filter(t => toTenantId(t) !== t0)
94
+ const byDb = {}
97
95
  if (tenants.length !== smTenants.length) {
98
96
  const smSet = new Set(smTenants.map(toTenantId))
99
97
  const inconsistent = tenants.filter(t => !smSet.has(t))
100
98
  if (!inconsistent.length)
101
99
  LOG.warn('Tenants', smTenants.map(toTenantId).join(', '), 'are subscribed in Service Manager but not in t0. Make sure to re-subscribe the tenants.')
102
- else if (inconsistent.length === 1)
100
+ else if (inconsistent.length === 1) {
103
101
  LOG.warn('Warning: Tenant', inconsistent[0], 'does not exist in Service Manager any more and is therefore ignored. Make sure to unsubscribe the tenant.')
104
- else
102
+ byDb['no-db'] = inconsistent
103
+ }
104
+ else {
105
105
  LOG.warn('Warning: Tenants', inconsistent.join(', '), 'do not exist in Service Manager any more and are therefore ignored. Make sure to unsubscribe the tenants.')
106
+ byDb['no-db'] = inconsistent
107
+ }
106
108
  }
107
109
  const tenantToDbUrl = smTenants.reduce((res, t) => {
108
110
  const id = toTenantId(t)
@@ -110,7 +112,7 @@ if (db?.kind === 'hana') {
110
112
  return { ...res, [id]: `${t.credentials.host}:${t.credentials.port}` }
111
113
  }
112
114
  , {})
113
- const byDb = {}
115
+
114
116
  for (const tenant of Object.keys(tenantToDbUrl)) {
115
117
  const dbUrl = tenantToDbUrl[tenant]
116
118
  if (!byDb[dbUrl]) byDb[dbUrl] = new Set
@@ -129,11 +131,6 @@ if (db?.kind === 'hana') {
129
131
  }
130
132
  return byDb
131
133
  })
132
-
133
- // check migration before upgrade
134
- ds.before('upgrade', async (req) => {
135
- await migration.checkMigration(req)
136
- })
137
134
  })
138
135
  })
139
136
 
@@ -178,7 +175,11 @@ async function resources4(out) {
178
175
  throw error
179
176
  }
180
177
  }
181
- if (cache) resources.set(out, _resources4(out).catch(e => { resources.delete(out); throw e }))
178
+ if (cache) {
179
+ const p = _resources4(out).catch(e => { resources.delete(out); throw e })
180
+ resources.set(out, p)
181
+ return p
182
+ }
182
183
  return _resources4(out)
183
184
  }
184
185
  module.exports.resources4 = resources4 // required in abstract provisioning service to prepare shared deployment directory
@@ -323,14 +324,10 @@ async function _deploy (req, _container, { skipExt = false, skipResources = fals
323
324
  if (cacheBindings) {
324
325
  // health-check credentials for DB connection, get uncached if stale
325
326
 
326
- let driver = 'hdb'
327
- const projectPackage = require(cds.root + '/package.json')
328
- const dependencies = {
329
- ...projectPackage.dependencies,
330
- ...(process.env.NODE_ENV !== 'production' && projectPackage.devDependencies),
331
- }
332
- if (dependencies.hdb) driver = 'hdb'
333
- if (dependencies['@sap/hana-client']) driver = '@sap/hana-client'
327
+ let driver
328
+ try { require.resolve('hdb'); driver = 'hdb' } catch { /* continue */ }
329
+ if (!driver) try { require.resolve('@sap/hana-client'); driver = '@sap/hana-client' } catch { /* continue */ }
330
+ if (!driver) cds.error('No HANA client driver found. Add hdb or @sap/hana-client to your sidecar dependencies.')
334
331
 
335
332
  const client = require(driver).createClient(container.credentials)
336
333
  const connect = promisify(client.connect.bind(client))
@@ -5,6 +5,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
6
  The format is based on [Keep a Changelog](http://keepachangelog.com/).
7
7
 
8
+ ## 6.2.2 - 2026-08-11
9
+
10
+ ### Updated
11
+ - Updated `filter-node-package` dependency to 6.2.2
12
+ - Updated `mocha` dependency to 11.8.0
13
+ - Updated `diff` dependency to 9
14
+
8
15
  ## 6.2.1 - 2026-05-13
9
16
 
10
17
  ### Updated
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/xsenv",
3
- "version": "6.2.1",
3
+ "version": "6.2.2",
4
4
  "description": "Utility for easy setup and access of SAP HANA XS Advanced environment variables",
5
5
  "repository": {},
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -23,13 +23,13 @@
23
23
  "prepareRelease": "clean-packages -i"
24
24
  },
25
25
  "devDependencies": {
26
- "@eslint/js": "9.39.4",
26
+ "@eslint/js": "9.39.5",
27
27
  "@eslint/eslintrc": "3.3.5",
28
- "@babel/eslint-parser": "7.28.6",
28
+ "@babel/eslint-parser": "7.29.7",
29
29
  "c8": "11.0.0",
30
- "filter-node-package": "6.2.0",
30
+ "filter-node-package": "6.2.2",
31
31
  "lodash": "4.18.1",
32
- "mocha": "11.7.5",
32
+ "mocha": "11.8.0",
33
33
  "mock-fs": "5.5.0",
34
34
  "node-build": "^3.0.0",
35
35
  "node-style": "2.0.0",
@@ -43,7 +43,10 @@
43
43
  },
44
44
  "overrides": {
45
45
  "mocha": {
46
- "glob": "^13.0.0"
47
- }
46
+ "glob": "^13.0.0",
47
+ "serialize-javascript": "^7.0.0"
48
+ },
49
+ "diff": "^9.0.0",
50
+ "lodash": "4.18.1"
48
51
  }
49
52
  }
@@ -36,6 +36,8 @@ The parser is lenient and does not error. You should validate `type` and `parame
36
36
  #### Options
37
37
 
38
38
  - `parameters` (default: `true`): Set to `false` to skip parameters.
39
+ - `comma` (default: `false`): Set to `true` to stop on a comma. This can be used to parse the media range in an `Accept` header.
40
+ - `start` (default: `0`): Set index to start parsing from.
39
41
 
40
42
  ### contentType.format(obj)
41
43
 
@@ -8,6 +8,7 @@
8
8
  */
9
9
  export interface ContentType {
10
10
  type: string;
11
+ index: number;
11
12
  parameters: Record<string, string>;
12
13
  }
13
14
  /**
@@ -18,7 +19,26 @@ export declare function format(obj: Partial<ContentType>): string;
18
19
  * Options for parsing a `Content-Type` header.
19
20
  */
20
21
  export interface ParseOptions {
22
+ /**
23
+ * Exit early on the first semicolon, returning only the type.
24
+ * This is useful for parsing the MIME from `Content-Type` headers.
25
+ *
26
+ * @default false
27
+ */
21
28
  parameters?: boolean;
29
+ /**
30
+ * Exits early on a comma, returning the first value and parameters.
31
+ * This is useful for parsing `Accept` headers.
32
+ *
33
+ * @default false
34
+ */
35
+ comma?: boolean;
36
+ /**
37
+ * The index to start parsing from.
38
+ *
39
+ * @default 0
40
+ */
41
+ start?: number;
22
42
  }
23
43
  /**
24
44
  * Parse a `Content-Type` header.