@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
@@ -33,6 +33,9 @@ const notSupportedOps = [['>'], ['<'], ['>='], ['<='], ['*'], ['+'], ['-'], ['/'
33
33
 
34
34
  const allOps = eqOps.concat(eqOps).concat(notEqOps).concat(notSupportedOps)
35
35
 
36
+
37
+ const { depthGuarded, guardEntry } = require('./recursion-guard')
38
+
36
39
  const { pseudos } = require('./infer/pseudos')
37
40
  /**
38
41
  * Transforms a CDL style query into SQL-Like CQN:
@@ -55,7 +58,17 @@ const { pseudos } = require('./infer/pseudos')
55
58
  * @returns {object} transformedQuery the transformed query
56
59
  */
57
60
  function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
61
+ // guardEntry bounds subquery nesting and resets the depth budget per top-level call
62
+ return guardEntry(_cqn4sql)(originalQuery, model, useTechnicalAlias)
63
+ }
64
+
65
+ function _cqn4sql(originalQuery, model, useTechnicalAlias = true) {
58
66
  const getImplicitAlias = str => _getImplicitAlias(str, useTechnicalAlias)
67
+ // guard xpr and inline/expand-on-struct nesting
68
+ // eslint-disable-next-line no-func-assign
69
+ getTransformedTokenStream = depthGuarded(getTransformedTokenStream)
70
+ // eslint-disable-next-line no-func-assign
71
+ nestedProjectionOnStructure = depthGuarded(nestedProjectionOnStructure)
59
72
  let inferred = typeof originalQuery === 'string' ? cds.parse.cql(originalQuery) : cds.ql.clone(originalQuery)
60
73
  const hasCustomJoins =
61
74
  originalQuery.SELECT?.from.args && (!originalQuery.joinTree || originalQuery.joinTree.isInitial)
@@ -69,6 +82,9 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
69
82
  const { where, having } = transformSearch(searchTerm)
70
83
  if (where) inferred.SELECT.where = where
71
84
  else if (having) inferred.SELECT.having = having
85
+ // Defer the ranking ORDER BY to after infer(), where the outer table alias is known and the
86
+ // deep-search sub-select can be correlated to the outer row (see buildSearchRankOrderBy).
87
+ defineProperty(inferred, '$searchRank', searchTerm)
72
88
  }
73
89
  }
74
90
  // query modifiers can also be defined in from ref leaf infix filter
@@ -182,7 +198,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
182
198
  /**
183
199
  * If the target entity is annotated with persistence skip and has an underlying db entity,
184
200
  * we treat it as a runtime view and transform it into a CTE.
185
- *
201
+ *
186
202
  * @param {object} transformedQuery - The query object to be transformed.
187
203
  * @param {string} model - The data model used for inference and transformation.
188
204
  */
@@ -198,10 +214,10 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
198
214
  }
199
215
 
200
216
  /**
201
- * Recursively call cqn4sql for all nested runtime views to calculate cte and
217
+ * Recursively call cqn4sql for all nested runtime views to calculate cte and
202
218
  * add it as a with clause to the transformed query.
203
219
  * Alias the runtime view with a unique alias and update all references to the runtime view to point to the alias.
204
- *
220
+ *
205
221
  * @param {object} rootDefinition - The root definition of the query. This is used to recursively process nested runtime views.
206
222
  * @param {object} transformedQuery - The query object to be transformed.
207
223
  * @param {string} model - The data model used for infer and cqn4sql.
@@ -317,9 +333,29 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
317
333
 
318
334
  // Since all the expressions in the SELECT part of the query have been computed,
319
335
  // one can reference aliases of the queries columns in the orderBy clause.
320
- if (orderBy) {
321
- const transformedOrderBy = getTransformedOrderByGroupBy(orderBy, true)
336
+ let effectiveOrderBy = orderBy
337
+ // Rank by $search relevance — only when the score exists (HANA fuzzy, not opted out); else
338
+ // it would sort by a constant boolean.
339
+ const ranksSearch =
340
+ cds.db?.kind === 'hana' && cds.env.hana?.fuzzy !== false && cds.env.hana?.fuzzy?.ranked_search !== false
341
+ // count queries do not need ranked search
342
+ const isCountQuery = columns?.length === 1 && columns[0].func === 'count'
343
+ const searchRank = ranksSearch && !isCountQuery && inferred.$searchRank && buildSearchRankOrderBy(inferred.$searchRank)
344
+ if (searchRank) {
345
+ // precedence: user ordering, then rank, then the runtime's implicit key ordering
346
+ const implicitAt = (orderBy || []).findIndex(o => o.implicit)
347
+ const at = implicitAt === -1 ? (orderBy?.length ?? 0) : implicitAt
348
+ effectiveOrderBy = [...(orderBy || [])]
349
+ effectiveOrderBy.splice(at, 0, searchRank)
350
+ }
351
+ if (effectiveOrderBy) {
352
+ const transformedOrderBy = getTransformedOrderByGroupBy(effectiveOrderBy, true)
322
353
  if (transformedOrderBy.length) {
354
+ // the rank is the only order-by entry that is a correlated sub-select
355
+ if (searchRank?.$searchRank) {
356
+ const rank = transformedOrderBy.find(o => o.SELECT)
357
+ if (rank) correlateSearchRank(rank, transformedFrom.as)
358
+ }
323
359
  transformedQuery.SELECT.orderBy = transformedOrderBy
324
360
  }
325
361
  }
@@ -383,6 +419,8 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
383
419
  */
384
420
  function translateAssocsToJoins() {
385
421
  let from
422
+ // guard association-path length
423
+ const joinForBranch = depthGuarded(_joinForBranch)
386
424
  /**
387
425
  * remember already seen aliases, do not create a join for them again
388
426
  */
@@ -406,7 +444,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
406
444
  })
407
445
  return from.args.length > 1 ? from : from.args[0]
408
446
 
409
- function joinForBranch(lhs, node) {
447
+ function _joinForBranch(lhs, node) {
410
448
  const nextAssoc = inferred.joinTree.findNextAssoc(node)
411
449
  if (!nextAssoc || alreadySeen.has(nextAssoc.$refLink.alias)) return lhs.args.length > 1 ? lhs : lhs.args[0]
412
450
 
@@ -643,7 +681,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
643
681
  if (col.cast) ret.cast = resolveEnumCastType(col.cast)
644
682
  return ret
645
683
  }
646
- return copy(col)
684
+ return { ...col }
647
685
  }
648
686
 
649
687
  function handleEmptyColumns(columns) {
@@ -995,11 +1033,11 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
995
1033
  const keyName = k.as || k.ref.join('_')
996
1034
  const fkName = `${elemName}_${keyName}` // e.g., 'head_id'
997
1035
  const fkFullName = `${columnAlias}_${fkName}` // e.g., 'department_head_id'
998
-
1036
+
999
1037
  // Check if this FK is excluded
1000
1038
  if (exclude.some(e => (e.ref?.at(-1) || e.as || e) === fkName)) continue
1001
1039
  if (exclude.some(e => (e.ref?.at(-1) || e.as || e) === fkFullName)) continue
1002
-
1040
+
1003
1041
  const flatColumn = {
1004
1042
  ref: [joinAlias, fkName],
1005
1043
  as: fkFullName,
@@ -1017,7 +1055,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1017
1055
  calcElement.as = fullName
1018
1056
  }
1019
1057
  res.push(calcElement)
1020
- }
1058
+ }
1021
1059
  else {
1022
1060
  // Scalar element
1023
1061
  const flatColumn = {
@@ -1322,7 +1360,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1322
1360
  else if (col.xpr) transformedColumn = { xpr: getTransformedTokenStream(col.xpr) }
1323
1361
  else if (col.func) transformedColumn = { args: getTransformedFunctionArgs(col.args), func: col.func }
1324
1362
  // val
1325
- else transformedColumn = copy(col)
1363
+ else transformedColumn = { ...col }
1326
1364
  if (col.sort) transformedColumn.sort = col.sort
1327
1365
  if (col.nulls) transformedColumn.nulls = col.nulls
1328
1366
  res.push(transformedColumn)
@@ -1397,8 +1435,13 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1397
1435
  if (!exclude.includes(k)) {
1398
1436
  const { index, tableAlias } = inferred.$combinedElements[k][0]
1399
1437
  const element = tableAlias.elements[k]
1400
- // ignore FK for odata csn (but not for subquery sources where FK is not a separate element) / ignore blobs from wildcard expansion
1401
- if ((!tableAlias.SELECT && isManagedAssocInFlatMode(element)) || element.type === 'cds.LargeBinary') continue
1438
+ // ignore FK for odata csn (but not for subquery sources where FK is not a separate element) / ignore blobs and vectors from wildcard expansion
1439
+ if (
1440
+ (!tableAlias.SELECT && isManagedAssocInFlatMode(element)) ||
1441
+ element.type === 'cds.LargeBinary' ||
1442
+ element.type === 'cds.Vector'
1443
+ )
1444
+ continue
1402
1445
  // for wildcard on subquery in from, just reference the elements
1403
1446
  if (tableAlias.SELECT && !element.elements && !element.target) {
1404
1447
  wildcardColumns.push(index ? { ref: [index, k] } : { ref: [k] })
@@ -1461,7 +1504,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1461
1504
  * - `tableAlias` — table alias prepended to the column ref.
1462
1505
  * @param {string[]} [csnPath=[]] - Accumulated CSN element path (used for `_csnPath` metadata on leaf columns).
1463
1506
  * @param {{ exclude?: Array, replace?: Array }} [excludeAndReplace] - Columns to exclude or replace during wildcard expansion.
1464
- * @param {boolean} [isWildcard=false] - Whether this expansion originates from a wildcard; filters out LargeBinary.
1507
+ * @param {boolean} [isWildcard=false] - Whether this expansion originates from a wildcard; filters out LargeBinary and Vector.
1465
1508
  * @returns {object[]} Flat column(s) for the given element.
1466
1509
  */
1467
1510
  function getFlatColumnsFor(column, names, csnPath = [], excludeAndReplace, isWildcard = false) {
@@ -1474,7 +1517,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1474
1517
  const { $refLinks, flatName, isJoinRelevant } = column
1475
1518
  let firstNonJoinRelevantAssoc, stepAfterAssoc
1476
1519
  let element = $refLinks ? $refLinks[$refLinks.length - 1].definition : column
1477
- if (isWildcard && element.type === 'cds.LargeBinary') return []
1520
+ if (isWildcard && (element.type === 'cds.LargeBinary' || element.type === 'cds.Vector')) return []
1478
1521
  if (element.on && !element.keys) return [] // unmanaged doesn't make it into columns
1479
1522
  if (element.virtual === true) return []
1480
1523
 
@@ -1812,8 +1855,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1812
1855
  // reject virtual elements in expressions as they will lead to a sql error down the line
1813
1856
  if (lhsDef?.virtual) throw new Error(`Virtual elements are not allowed in expressions`)
1814
1857
 
1815
- let result = is_regexp(token?.val) ? token : copy(token) // REVISIT: too expensive!
1816
- // REVISIT: required because we copy the token above and lose the not enumerable "param: false"
1858
+ let result = typeof token !== 'object' || is_regexp(token?.val) ? token : { ...token }
1817
1859
  if (typeof token === 'object' && 'val' in token && 'param' in token) Object.defineProperty(result, 'param', { value: token.param })
1818
1860
  if (token.ref) {
1819
1861
  const { definition } = token.$refLinks.at(-1)
@@ -1830,7 +1872,6 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
1830
1872
  const stepToFind = token.ref[1]?.id || token.ref[1]
1831
1873
  const outerAlias = outerQuery.$combinedElements?.[stepToFind]?.[0].index
1832
1874
  if (outerAlias) {
1833
- let result = copy(token)
1834
1875
  result.ref = [outerAlias, token.flatName]
1835
1876
  transformedTokenStream.push(result)
1836
1877
  continue
@@ -2016,7 +2057,7 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
2016
2057
  */
2017
2058
  function getTransformedFrom(from, existingWhere = []) {
2018
2059
  const transformedWhere = []
2019
- let transformedFrom = copy(from) // REVISIT: too expensive!
2060
+ let transformedFrom = { ...from }
2020
2061
  if (from.$refLinks) defineProperty(transformedFrom, '$refLinks', [...from.$refLinks])
2021
2062
  if (from.args) {
2022
2063
  transformedFrom.args = []
@@ -2579,6 +2620,65 @@ function cqn4sql(originalQuery, model, useTechnicalAlias = true) {
2579
2620
  return { xpr: [matchColumns.length === 1 ? matchColumns[0] : { list: matchColumns }, 'in', subquery] }
2580
2621
  }
2581
2622
 
2623
+ /**
2624
+ * Builds the ORDER BY entry ranking rows by $search relevance, sorted desc.
2625
+ *
2626
+ * Flat search: the score is on the outer row.
2627
+ * Deep search: the score lives in a semi-join, so emit a correlated scalar sub-select
2628
+ * (SELECT search(…, true) FROM <same source> WHERE innerKey = <outerAlias>.key) DESC.
2629
+ * Key comparisons are seeded unqualified (infer() binds them to the sub-select's own source);
2630
+ * correlateSearchRank redirects the rhs to the outer alias afterwards.
2631
+ *
2632
+ * @param {object} searchTerm the search term as returned by getSearch (func or xpr shape)
2633
+ * @returns {object|null} an orderBy entry, or null if there is nothing to rank by
2634
+ */
2635
+ function buildSearchRankOrderBy(searchTerm) {
2636
+ if (searchTerm.func) return { func: searchTerm.func, args: [...searchTerm.args, { val: true }], sort: 'desc' }
2637
+ if (!searchTerm.xpr) return null
2638
+
2639
+ const searchSelect = searchTerm.xpr[2]
2640
+ const searchFunc = searchSelect.SELECT.where[0]
2641
+ const innerKeys = searchSelect.SELECT.columns // unqualified pk refs, e.g. [{ ref: ['ID'] }]
2642
+
2643
+ const where = []
2644
+ for (let i = 0; i < innerKeys.length; i++) {
2645
+ if (i) where.push('and')
2646
+ // seeded unqualified on both sides; correlateSearchRank redirects the rhs to the outer row
2647
+ where.push({ ref: [...innerKeys[i].ref] }, '=', { ref: [...innerKeys[i].ref] })
2648
+ }
2649
+
2650
+ const entry = {
2651
+ __proto__: SELECT.from(searchSelect.SELECT.from)
2652
+ // the correlated outer row fans out to many child rows -> MAX makes it a single score
2653
+ .columns({ func: 'max', args: [{ func: searchFunc.func, args: [...searchFunc.args, { val: true }] }] })
2654
+ .where(where),
2655
+ sort: 'desc',
2656
+ }
2657
+ defineProperty(entry, '$searchRank', true)
2658
+ return entry
2659
+ }
2660
+
2661
+ /**
2662
+ * Correlates the (transformed) deep-search ranking sub-select to the outer row.
2663
+ *
2664
+ * buildSearchRankOrderBy seeds its WHERE as `ref = ref` comparisons on the sub-select's own
2665
+ * alias; this rewrites each rhs to `<outerAlias>.<key>`. Driven off the `=` operator (not a
2666
+ * fixed stride) so it holds for any key count.
2667
+ *
2668
+ * @param {object} entry the transformed orderBy entry produced from a `$searchRank` sub-select
2669
+ * @param {string} outerAlias the final table alias of the outer query source
2670
+ */
2671
+ function correlateSearchRank(entry, outerAlias) {
2672
+ const where = entry.SELECT.where
2673
+ for (let i = 1; i < where.length; i++) {
2674
+ // seeded comparisons are exactly `<ref> = <ref>`; rewrite the rhs ref to the outer row
2675
+ if (where[i] === '=' && where[i - 1]?.ref && where[i + 1]?.ref) {
2676
+ const rhs = where[i + 1]
2677
+ rhs.ref = [outerAlias, ...rhs.ref.slice(1)]
2678
+ }
2679
+ }
2680
+ }
2681
+
2582
2682
  /**
2583
2683
  * Calculates the name of the source which can be used to address the given node.
2584
2684
  *
@@ -5,15 +5,19 @@ const cds = require('@sap/cds')
5
5
  const JoinTree = require('./join-tree')
6
6
  const { pseudos } = require('./pseudos')
7
7
  const { isCalculatedOnRead, getImplicitAlias, getModelUtils, defineProperty, hasOwnSkip, isRuntimeView } = require('../utils')
8
+ const { depthGuarded, guardEntry } = require('../recursion-guard')
8
9
  const cdsTypes = cds.builtin.types
9
10
  /**
10
11
  * @param {import('@sap/cds/apis/cqn').Query|string} originalQuery
11
12
  * @param {import('@sap/cds/apis/csn').CSN} [model]
12
13
  * @returns {import('./cqn').Query} = q with .target and .elements
13
14
  */
14
- function infer(originalQuery, model, useTechnicalAlias = true) {
15
+ function _infer(originalQuery, model, useTechnicalAlias = true) {
15
16
  if (!model) throw new Error('Please specify a model')
16
17
  const inferred = originalQuery
18
+ // guard func args / lists / xpr / exists nesting
19
+ // eslint-disable-next-line no-func-assign
20
+ inferArg = depthGuarded(inferArg)
17
21
 
18
22
  const { getDefinition } = getModelUtils(model, originalQuery)
19
23
 
@@ -291,19 +295,23 @@ function infer(originalQuery, model, useTechnicalAlias = true) {
291
295
  */
292
296
  function walkTokenStream(tokenStream, inXpr = false) {
293
297
  let skipJoins
294
- const processToken = t => {
295
- if (t === 'exists') {
296
- // no joins for infix filters along `exists <path>`
297
- skipJoins = true
298
- } else if (t.xpr) {
299
- // don't miss an exists within an expression
300
- t.xpr.forEach(processToken)
301
- } else {
302
- inferArg(t, queryElements, null, { inExists: skipJoins, inXpr, inQueryModifier: true })
303
- skipJoins = false
298
+ const processToken = depthGuarded(walker())
299
+ tokenStream.forEach(processToken)
300
+
301
+ function walker() {
302
+ return t => {
303
+ if (t === 'exists') {
304
+ // no joins for infix filters along `exists <path>`
305
+ skipJoins = true
306
+ } else if (t.xpr) {
307
+ // don't miss an exists within an expression
308
+ t.xpr.forEach(processToken)
309
+ } else {
310
+ inferArg(t, queryElements, null, { inExists: skipJoins, inXpr, inQueryModifier: true })
311
+ skipJoins = false
312
+ }
304
313
  }
305
314
  }
306
- tokenStream.forEach(processToken)
307
315
  }
308
316
  /**
309
317
  * Processes references starting with `$self`, which are intended to target other query elements.
@@ -631,7 +639,7 @@ function infer(originalQuery, model, useTechnicalAlias = true) {
631
639
  } else if (arg.inline && queryElements) {
632
640
  const elements = resolveInline(arg)
633
641
  for (const elName in elements) {
634
- if (queryElements[elName] !== undefined) rejectDuplicatedElement(elName)
642
+ if (queryElements[elName] !== undefined) rejectDuplicatedElement(elName)
635
643
  }
636
644
  Object.assign(queryElements, elements)
637
645
  } else {
@@ -667,7 +675,7 @@ function infer(originalQuery, model, useTechnicalAlias = true) {
667
675
  // ignore whole expand if target of assoc along path has ”@cds.persistence.skip”
668
676
  if (arg.expand) {
669
677
  const { $refLinks } = arg
670
-
678
+
671
679
  const skip = $refLinks.some(link => {
672
680
  const def = getDefinition(link.definition.target)
673
681
  return hasOwnSkip(def) && !isRuntimeView(def)
@@ -1095,7 +1103,7 @@ function infer(originalQuery, model, useTechnicalAlias = true) {
1095
1103
  for (const k in elements) {
1096
1104
  if (!exclude(k)) {
1097
1105
  const element = elements[k]
1098
- if (element.type !== 'cds.LargeBinary') {
1106
+ if (element.type !== 'cds.LargeBinary' && element.type !== 'cds.Vector') {
1099
1107
  queryElements[k] = element
1100
1108
  }
1101
1109
  // only relevant if we actually select the calculated element
@@ -1115,7 +1123,7 @@ function infer(originalQuery, model, useTechnicalAlias = true) {
1115
1123
  }
1116
1124
  if (exclude(name) || name in queryElements) return true
1117
1125
  const element = tableAliases[0].tableAlias.elements[name]
1118
- if (element.type !== 'cds.LargeBinary') queryElements[name] = element
1126
+ if (element.type !== 'cds.LargeBinary' && element.type !== 'cds.Vector') queryElements[name] = element
1119
1127
  if (isCalculatedOnRead(element)) {
1120
1128
  linkCalculatedElement(element)
1121
1129
  }
@@ -1287,4 +1295,7 @@ function getMainAlias (query) {
1287
1295
  return mainAlias
1288
1296
  }
1289
1297
 
1298
+ // guardEntry bounds nested-subquery re-entry (expand, from, set)
1299
+ const infer = guardEntry(_infer)
1300
+
1290
1301
  module.exports = infer
@@ -0,0 +1,40 @@
1
+ 'use strict'
2
+
3
+ const cds = require('@sap/cds')
4
+
5
+ // shared across cqn4sql and infer to guard against stack overflow from user-controlled nesting depth
6
+ const MAX_RECURSION_DEPTH = 100
7
+
8
+ let recursionDepth = 0
9
+
10
+ function enterRecursion() {
11
+ if (++recursionDepth > MAX_RECURSION_DEPTH) throw cds.error(400, `Query exceeds the maximum nesting depth of ${MAX_RECURSION_DEPTH}`)
12
+ }
13
+
14
+ function depthGuarded(fn) {
15
+ return function (...args) {
16
+ enterRecursion()
17
+ try {
18
+ return fn.apply(this, args)
19
+ } finally {
20
+ recursionDepth--
21
+ }
22
+ }
23
+ }
24
+
25
+ // entry points (infer / cqn4sql): outermost call resets the counter, so a thrown
26
+ // depth error can't leave it polluted for the next request
27
+ function guardEntry(fn) {
28
+ return function (...args) {
29
+ const outermost = recursionDepth === 0
30
+ enterRecursion()
31
+ try {
32
+ return fn.apply(this, args)
33
+ } finally {
34
+ if (outermost) recursionDepth = 0
35
+ else recursionDepth--
36
+ }
37
+ }
38
+ }
39
+
40
+ module.exports = { depthGuarded, guardEntry }
@@ -166,7 +166,7 @@ const computeColumnsToBeSearched = (cqn, entity = { __searchableColumns: [] }) =
166
166
  if (
167
167
  cqn.SELECT.columns.length === 1 &&
168
168
  column.func === 'count' &&
169
- (column.as === '_counted_' || column.as === '$count')
169
+ column.as === '$count'
170
170
  ) {
171
171
  return
172
172
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/db-service",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "CDS base database service",
5
5
  "homepage": "https://github.com/cap-js/cds-dbs/tree/main/db-service#cds-base-database-service",
6
6
  "repository": {
@@ -4,6 +4,25 @@
4
4
  - The format is based on [Keep a Changelog](http://keepachangelog.com/).
5
5
  - This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [3.1.0](https://github.com/cap-js/cds-dbs/compare/sqlite-v3.0.2...sqlite-v3.1.0) (2026-09-07)
8
+
9
+
10
+ ### Added
11
+
12
+ * Add support for `cds.Vector` on SQLite and Postgres ([#1676](https://github.com/cap-js/cds-dbs/issues/1676)) ([f0d2203](https://github.com/cap-js/cds-dbs/commit/f0d220324e8a1c7489966545000476bfd33f6b17))
13
+
14
+
15
+ ### Fixed
16
+
17
+ * INSERT.from(SELECT) used non-existent `value` ([#1565](https://github.com/cap-js/cds-dbs/issues/1565)) ([fd98844](https://github.com/cap-js/cds-dbs/commit/fd98844c83a78d6cf2b0b71344d3ee1d88528106))
18
+
19
+
20
+ ### Dependencies
21
+
22
+ * The following workspace dependencies were updated
23
+ * dependencies
24
+ * @cap-js/db-service bumped from ^3.0.1 to ^3.1.0
25
+
7
26
  ## [3.0.2](https://github.com/cap-js/cds-dbs/compare/sqlite-v3.0.1...sqlite-v3.0.2) (2026-07-01)
8
27
 
9
28
 
@@ -14,16 +14,6 @@ const sqliteKeywords = keywords.reduce((prev, curr) => {
14
14
  return prev
15
15
  }, {})
16
16
 
17
- // define date and time functions in js to allow for throwing errors
18
- const isTime = /^\d{1,2}:\d{1,2}:\d{1,2}$/
19
- const hasTimezone = /([+-]\d{1,2}:?\d{0,2}|Z)$/
20
- const toDate = (d, allowTime = false) => {
21
- const date = new Date(allowTime && isTime.test(d) ? `1970-01-01T${d}Z` : hasTimezone.test(d) ? d : d + 'Z')
22
- if (Number.isNaN(date.getTime())) throw new Error(`Value does not contain a valid ${allowTime ? 'time' : 'date'} "${d}"`)
23
- return date
24
- }
25
-
26
-
27
17
  class SQLiteService extends SQLService {
28
18
 
29
19
  get factory() {
@@ -46,6 +36,10 @@ class SQLiteService extends SQLService {
46
36
  dbc.function('hour', deterministic, d => d === null ? null : toDate(d, true).getUTCHours())
47
37
  dbc.function('minute', deterministic, d => d === null ? null : toDate(d, true).getUTCMinutes())
48
38
  dbc.function('second', deterministic, d => d === null ? null : toDate(d, true).getUTCSeconds())
39
+ dbc.function('COSINE_SIMILARITY', deterministic, (a, b) => cosineSimilarity(toFloatArray(a), toFloatArray(b)))
40
+ dbc.function('L2DISTANCE', deterministic, (a, b) => l2Distance(toFloatArray(a), toFloatArray(b)))
41
+ dbc.function('L2NORMALIZE', deterministic, v => v == null ? null : fromFloatArray(l2Normalize(toFloatArray(v)), v))
42
+ dbc.function('VECTOR_EMBEDDING', deterministic, (input, text_type, model_and_version) => input == null ? null : JSON.stringify(hashEmbedding(String(input))))
49
43
  if (database !== ':memory:') dbc.pragma?.('journal_mode = WAL') || dbc.exec('PRAGMA journal_mode = WAL')
50
44
  return dbc
51
45
  } catch (err) {
@@ -184,7 +178,7 @@ class SQLiteService extends SQLService {
184
178
  let ps = await this.prepare(sql)
185
179
  const vals = await this._prepareStreams(values)
186
180
  const { changes } = await ps.run(vals)
187
- return this._return_affected (changes)
181
+ return this._return_affected(changes)
188
182
  }
189
183
 
190
184
  onPlainSQL({ query, data }, next) {
@@ -273,9 +267,9 @@ class SQLiteService extends SQLService {
273
267
  // Reading decimal as string to not loose precision
274
268
  Decimal: cds.env.features.ieee754compatible
275
269
  ? (expr, elem) =>
276
- elem?.scale
277
- ? `CASE WHEN ${expr} IS NULL THEN NULL ELSE format('%.${elem.scale}f', ${expr}) END`
278
- : `CASE WHEN ${expr} IS NULL THEN NULL ELSE rtrim(rtrim(format('%.999f', ${expr}), '0'), '.') END`
270
+ elem?.scale
271
+ ? `CASE WHEN ${expr} IS NULL THEN NULL ELSE format('%.${elem.scale}f', ${expr}) END`
272
+ : `CASE WHEN ${expr} IS NULL THEN NULL ELSE rtrim(rtrim(format('%.999f', ${expr}), '0'), '.') END`
279
273
  : undefined,
280
274
  // Binary is not allowed in json objects
281
275
  Binary: expr => `${expr} || ''`,
@@ -321,4 +315,106 @@ function loadSQLite(driver) {
321
315
  }
322
316
  }
323
317
 
318
+ // define date and time functions in js to allow for throwing errors
319
+ const isTime = d => /^\d{1,2}:\d{1,2}:\d{1,2}$/.test(d)
320
+ const hasTimezone = d => /([+-]\d{1,2}:?\d{0,2}|Z)$/.test(d)
321
+ const toDate = (d, allowTime = false) => {
322
+ const date = new Date(allowTime && isTime(d) ? `1970-01-01T${d}Z` : hasTimezone(d) ? d : d + 'Z')
323
+ if (Number.isNaN(date.getTime())) throw new Error(`Value does not contain a valid ${allowTime ? 'time' : 'date'} "${d}"`)
324
+ return date
325
+ }
326
+
327
+ // Vector functions implemented in JavaScript for SQLite (registered as custom SQL functions)
328
+ function cosineSimilarity(a, b) {
329
+ if (a == null || b == null) return null
330
+ let dot = 0, normA = 0, normB = 0
331
+ for (let i = 0; i < a.length; i++) {
332
+ dot += a[i] * b[i]
333
+ normA += a[i] * a[i]
334
+ normB += b[i] * b[i]
335
+ }
336
+ const denom = Math.sqrt(normA) * Math.sqrt(normB)
337
+ return denom === 0 ? 0 : dot / denom
338
+ }
339
+
340
+ function l2Distance(a, b) {
341
+ if (a == null || b == null) return null
342
+ let sum = 0
343
+ for (let i = 0; i < a.length; i++) {
344
+ const diff = a[i] - b[i]
345
+ sum += diff * diff
346
+ }
347
+ return Math.sqrt(sum)
348
+ }
349
+
350
+ function l2Normalize(v) {
351
+ if (v == null) return null
352
+ let norm = 0
353
+ for (let i = 0; i < v.length; i++) norm += v[i] * v[i]
354
+ if (norm === 0) return v
355
+ norm = Math.sqrt(norm)
356
+ for (let i = 0; i < v.length; i++) v[i] /= norm
357
+ return v
358
+ }
359
+
360
+ /**
361
+ * Deterministic synchronous hash-based embedding function for SQLite.
362
+ * NOTE: If a synchronous embedding library becomes available for Node.js,
363
+ * it can be integrated here to replace the hash-based implementation.
364
+ */
365
+ function hashEmbedding(text, dimensions = 384) {
366
+ if (text == null) return null
367
+ const vector = new Float32Array(dimensions)
368
+ const normalized = text.toLowerCase()
369
+ const ngramSize = 3
370
+
371
+ if (normalized.length >= ngramSize) {
372
+ for (let i = 0; i <= normalized.length - ngramSize; i++)
373
+ project(ngramHash(normalized, i, ngramSize), vector, dimensions)
374
+ } else {
375
+ for (let i = 0; i < normalized.length; i++)
376
+ project(normalized.charCodeAt(i), vector, dimensions)
377
+ }
378
+ return Array.from(l2Normalize(vector))
379
+ }
380
+
381
+ function ngramHash(text, start, len) {
382
+ let hash = 0x811c9dc5
383
+ for (let i = start; i < start + len; i++) {
384
+ hash ^= text.charCodeAt(i)
385
+ hash = Math.imul(hash, 0x01000193)
386
+ }
387
+ return hash
388
+ }
389
+
390
+ function project(hash, vector, dimensions) {
391
+ for (let band = 0; band < 4; band++) {
392
+ const h = rehash(hash, band)
393
+ vector[Math.abs(h % dimensions)] += ((h >>> 16) & 1) === 0 ? 1.0 : -1.0
394
+ }
395
+ }
396
+
397
+ function rehash(hash, band) {
398
+ let h = hash ^ Math.imul(band, 0x9e3779b9)
399
+ h ^= h >>> 16
400
+ h = Math.imul(h, 0x45d9f3b)
401
+ h ^= h >>> 16
402
+ return h
403
+ }
404
+
405
+ // Vector type conversion helpers for SQLite - handle various input formats (Buffer, string, array, typed arrays)
406
+ function toFloatArray(vector) {
407
+ if (vector == null) return null
408
+ if (vector instanceof Float32Array) return Array.from(vector)
409
+ if (Buffer.isBuffer(vector)) return JSON.parse(vector.toString('utf8'))
410
+ if (vector instanceof Uint8Array) return JSON.parse(Buffer.from(vector).toString('utf8'))
411
+ if (typeof vector === 'string') return JSON.parse(vector)
412
+ if (Array.isArray(vector)) return vector
413
+ throw new Error(`Unsupported vector type: ${typeof vector}`)
414
+ }
415
+
416
+ function fromFloatArray(arr, original) {
417
+ return original instanceof Float32Array ? new Float32Array(arr) : JSON.stringify(arr)
418
+ }
419
+
324
420
  module.exports = SQLiteService
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/sqlite",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "CDS database service for SQLite",
5
5
  "homepage": "https://github.com/cap-js/cds-dbs/tree/main/sqlite#cds-database-service-for-sqlite",
6
6
  "repository": {
@@ -26,12 +26,12 @@
26
26
  "test": "cds-test"
27
27
  },
28
28
  "dependencies": {
29
- "@cap-js/db-service": "^3.0.1"
29
+ "@cap-js/db-service": "^3.1.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@sap/cds": "^10",
33
33
  "sql.js": "^1.13.0",
34
- "better-sqlite3": "^12.0.0"
34
+ "better-sqlite3": "^12.0.0 || ^13.0.0"
35
35
  },
36
36
  "peerDependenciesMeta": {
37
37
  "sql.js": {