@cap-js/db-service 1.20.0 → 1.20.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@
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
+ ## [1.20.1](https://github.com/cap-js/cds-dbs/compare/db-service-v1.20.0...db-service-v1.20.1) (2025-05-27)
8
+
9
+
10
+ ### Fixed
11
+
12
+ * **`search`:** do not search on non-projected elements ([#1198](https://github.com/cap-js/cds-dbs/issues/1198)) ([1461673](https://github.com/cap-js/cds-dbs/commit/14616730ba8c27e8ffa30c5962b881badfab991c))
13
+ * current_utctimestamp as default ([#1161](https://github.com/cap-js/cds-dbs/issues/1161)) ([c0cccad](https://github.com/cap-js/cds-dbs/commit/c0cccad921c45db96e14f0e2afeced6af69da4a2))
14
+ * exists within expression is properly detected ([#1156](https://github.com/cap-js/cds-dbs/issues/1156)) ([febe175](https://github.com/cap-js/cds-dbs/commit/febe1755186d291b92edbdf69cebbab68a53d0af))
15
+ * resilience for query re-use scenarios ([#1175](https://github.com/cap-js/cds-dbs/issues/1175)) ([fe9abd5](https://github.com/cap-js/cds-dbs/commit/fe9abd5e4c5e9153c0afad9164f240ae2eadf581))
16
+
7
17
  ## [1.20.0](https://github.com/cap-js/cds-dbs/compare/db-service-v1.19.1...db-service-v1.20.0) (2025-04-17)
8
18
 
9
19
 
package/lib/cqn2sql.js CHANGED
@@ -1102,7 +1102,7 @@ class CQN2SQLRenderer {
1102
1102
 
1103
1103
  let onInsert = this.managed_session_context(element[cdsOnInsert]?.['='])
1104
1104
  || this.managed_session_context(element.default?.ref?.[0])
1105
- || (element.default?.val !== undefined && { val: element.default.val, param: false })
1105
+ || (element.default && { __proto__: element.default, param: false })
1106
1106
  let onUpdate = this.managed_session_context(element[cdsOnUpdate]?.['='])
1107
1107
 
1108
1108
  if (onInsert) onInsert = this.expr(onInsert)
package/lib/cqn4sql.js CHANGED
@@ -5,7 +5,7 @@ cds.infer.target ??= q => q._target || q.target // instanceof cds.entity ? q._ta
5
5
 
6
6
  const infer = require('./infer')
7
7
  const { computeColumnsToBeSearched } = require('./search')
8
- const { prettyPrintRef, isCalculatedOnRead, isCalculatedElement, getImplicitAlias, getModelUtils } = require('./utils')
8
+ const { prettyPrintRef, isCalculatedOnRead, isCalculatedElement, getImplicitAlias, defineProperty, getModelUtils } = require('./utils')
9
9
 
10
10
  /**
11
11
  * For operators of <eqOps>, this is replaced by comparing all leaf elements with null, combined with and.
@@ -845,10 +845,7 @@ function cqn4sql(originalQuery, model) {
845
845
  }
846
846
  const expanded = transformSubquery(subquery)
847
847
  const correlated = _correlate({ ...expanded, as: columnAlias }, outerAlias)
848
- Object.defineProperty(correlated, 'elements', {
849
- value: expanded.elements,
850
- writable: true,
851
- })
848
+ defineProperty(correlated, 'elements', expanded.elements)
852
849
  return correlated
853
850
 
854
851
  function _correlate(subq, outer) {
@@ -1070,7 +1067,7 @@ function cqn4sql(originalQuery, model) {
1070
1067
  else {
1071
1068
  const outerQueries = inferred.outerQueries || []
1072
1069
  outerQueries.push(inferred)
1073
- Object.defineProperty(q, 'outerQueries', { value: outerQueries })
1070
+ defineProperty(q, 'outerQueries', outerQueries)
1074
1071
  }
1075
1072
  const target = cds.infer.target(inferred) // REVISIT: we should reliably use inferred._target instead
1076
1073
  if (isLocalized(target)) q.SELECT.localized = true
@@ -1084,7 +1081,7 @@ function cqn4sql(originalQuery, model) {
1084
1081
  getImplicitAlias(last.id || last),
1085
1082
  inferred.outerQueries,
1086
1083
  )
1087
- Object.defineProperty(q.SELECT.from, 'uniqueSubqueryAlias', { value: uniqueSubqueryAlias })
1084
+ defineProperty(q.SELECT.from, 'uniqueSubqueryAlias', uniqueSubqueryAlias)
1088
1085
  }
1089
1086
  }
1090
1087
 
@@ -1311,7 +1308,7 @@ function cqn4sql(originalQuery, model) {
1311
1308
  const flatForeignKey = getDefinition(element.parent.name)?.elements[fkBaseName]
1312
1309
 
1313
1310
  setElementOnColumns(flatColumn, flatForeignKey || fkElement)
1314
- Object.defineProperty(flatColumn, '_csnPath', { value: csnPath, writable: true })
1311
+ defineProperty(flatColumn, '_csnPath', csnPath)
1315
1312
  flatColumns.push(flatColumn)
1316
1313
  }
1317
1314
  }
@@ -1343,7 +1340,7 @@ function cqn4sql(originalQuery, model) {
1343
1340
  if (column.sort) flatRef.sort = column.sort
1344
1341
  if (columnAlias) flatRef.as = columnAlias
1345
1342
  setElementOnColumns(flatRef, element)
1346
- Object.defineProperty(flatRef, '_csnPath', { value: csnPath, writable: true })
1343
+ defineProperty(flatRef, '_csnPath', csnPath)
1347
1344
  return [flatRef]
1348
1345
 
1349
1346
  function getReplacement(from) {
@@ -1676,7 +1673,7 @@ function cqn4sql(originalQuery, model) {
1676
1673
  const transformedWhere = []
1677
1674
  let transformedFrom = copy(from) // REVISIT: too expensive!
1678
1675
  if (from.$refLinks)
1679
- Object.defineProperty(transformedFrom, '$refLinks', { value: [...from.$refLinks], writable: true })
1676
+ defineProperty(transformedFrom, '$refLinks', [...from.$refLinks])
1680
1677
  if (from.args) {
1681
1678
  transformedFrom.args = []
1682
1679
  from.args.forEach(arg => {
@@ -1924,10 +1921,7 @@ function cqn4sql(originalQuery, model) {
1924
1921
  const refLinkFaker = thing => {
1925
1922
  const { ref } = thing
1926
1923
  const assocHost = getParentEntity(assocRefLink.definition)
1927
- Object.defineProperty(thing, '$refLinks', {
1928
- value: [],
1929
- writable: true,
1930
- })
1924
+ defineProperty(thing, '$refLinks', [])
1931
1925
  let pseudoPath = false
1932
1926
  ref.reduce((prev, res, i) => {
1933
1927
  if (res === '$self') {
@@ -2370,10 +2364,7 @@ function getParentEntity(element) {
2370
2364
  * @param {csn.Element} element
2371
2365
  */
2372
2366
  function setElementOnColumns(col, element) {
2373
- Object.defineProperty(col, 'element', {
2374
- value: element,
2375
- writable: true,
2376
- })
2367
+ defineProperty(col, 'element', element)
2377
2368
  }
2378
2369
 
2379
2370
  const getName = col => col.as || col.ref?.at(-1)
@@ -4,7 +4,7 @@ const cds = require('@sap/cds')
4
4
 
5
5
  const JoinTree = require('./join-tree')
6
6
  const { pseudos } = require('./pseudos')
7
- const { isCalculatedOnRead, getImplicitAlias, getModelUtils } = require('../utils')
7
+ const { isCalculatedOnRead, getImplicitAlias, getModelUtils, defineProperty } = require('../utils')
8
8
  const cdsTypes = cds.linked({
9
9
  definitions: {
10
10
  Timestamp: { type: 'cds.Timestamp' },
@@ -75,7 +75,7 @@ function infer(originalQuery, model) {
75
75
  joinTree: { value: joinTree, writable: true, configurable: true }, // REVISIT: eliminate
76
76
  })
77
77
  // also enrich original query -> writable because it may be inferred again
78
- Object.defineProperty(originalQuery, 'elements', { value: elements, writable: true, configurable: true })
78
+ defineProperty(originalQuery, 'elements', elements)
79
79
  }
80
80
  return inferred
81
81
 
@@ -171,10 +171,7 @@ function infer(originalQuery, model) {
171
171
  * @param {csn.Element} element
172
172
  */
173
173
  function setElementOnColumns(col, element) {
174
- Object.defineProperty(col, 'element', {
175
- value: element,
176
- writable: true,
177
- })
174
+ defineProperty(col, 'element', element)
178
175
  }
179
176
 
180
177
  /**
@@ -245,7 +242,7 @@ function infer(originalQuery, model) {
245
242
  // link $refLinks -> special name resolution rules for orderBy
246
243
  orderBy.forEach(token => {
247
244
  let $baseLink
248
- let rejectJoinRelevantPath
245
+ let needsElementsOfQueryAsBase
249
246
  // first check if token ref is resolvable in query elements
250
247
  if (columns) {
251
248
  const firstStep = token.ref?.[0].id || token.ref?.[0]
@@ -253,14 +250,11 @@ function infer(originalQuery, model) {
253
250
  const columnName = c.as || c.flatName || c.ref?.at(-1).id || c.ref?.at(-1) || c.func
254
251
  return columnName === firstStep
255
252
  })
256
- const needsElementsOfQueryAsBase =
253
+ needsElementsOfQueryAsBase =
257
254
  tokenPointsToQueryElements &&
258
- queryElements[token.ref?.[0]] &&
259
- /* expand on structure can be addressed */ !queryElements[token.ref?.[0]].$assocExpand
255
+ queryElements[firstStep] &&
256
+ /* expand on structure can be addressed */ !queryElements[firstStep].$assocExpand
260
257
 
261
- // if the ref points into the query itself and follows an exposed association
262
- // to a non-fk column, we must reject the ref, as we can't join with the queries own results
263
- rejectJoinRelevantPath = needsElementsOfQueryAsBase
264
258
  if (needsElementsOfQueryAsBase) $baseLink = { definition: { elements: queryElements }, target: inferred }
265
259
  } else {
266
260
  // fallback to elements of query source
@@ -268,7 +262,9 @@ function infer(originalQuery, model) {
268
262
  }
269
263
 
270
264
  inferArg(token, queryElements, $baseLink, { inQueryModifier: true })
271
- if (token.isJoinRelevant && rejectJoinRelevantPath) {
265
+ // if the ref points into the query itself and follows an exposed association
266
+ // to a non-fk column, we must reject the ref, as we can't join with the queries own results
267
+ if (token.isJoinRelevant && needsElementsOfQueryAsBase) {
272
268
  // reverse the array, find the last association and calculate the index of the association in non-reversed order
273
269
  const assocIndex =
274
270
  token.$refLinks.length - 1 - token.$refLinks.reverse().findIndex(link => link.definition.isAssociation)
@@ -406,18 +402,22 @@ function infer(originalQuery, model) {
406
402
  if (arg.param || arg.SELECT) return // parameter references are only resolved into values on execution e.g. :val, :1 or ?
407
403
  if (arg.args) applyToFunctionArgs(arg.args, inferArg, [null, $baseLink, context])
408
404
  if (arg.list) arg.list.forEach(arg => inferArg(arg, null, $baseLink, context))
409
- if (arg.xpr) arg.xpr.forEach(token => inferArg(token, queryElements, $baseLink, { ...context, inXpr: true })) // e.g. function in expression
405
+ if (arg.xpr)
406
+ arg.xpr.forEach((token, i) =>
407
+ inferArg(token, queryElements, $baseLink, { ...context, inXpr: true, inExists: arg.xpr[i - 1] === 'exists' }),
408
+ ) // e.g. function in expression
410
409
 
411
410
  if (!arg.ref) {
412
411
  if (arg.expand && queryElements) queryElements[arg.as] = resolveExpand(arg)
413
412
  return
414
413
  }
415
414
 
416
- // initialize $refLinks
417
- Object.defineProperty(arg, '$refLinks', {
418
- value: [],
419
- writable: true,
420
- })
415
+ // Before the arg is linked, it's meta information should be cleaned up.
416
+ // This may be important if one manipulates the arg object
417
+ // __after__ a query has been fired and re-uses the manipulated query
418
+ defineProperty(arg, '$refLinks', [])
419
+ defineProperty(arg, 'isJoinRelevant', false)
420
+
421
421
  // if any path step points to an artifact with `@cds.persistence.skip`
422
422
  // we must ignore the element from the queries elements
423
423
  let isPersisted = true
@@ -428,7 +428,7 @@ function infer(originalQuery, model) {
428
428
  expandOnTableAlias = arg.ref.length === 1 && arg.ref[0] in sources && (arg.expand || arg.inline)
429
429
  }
430
430
  if (dollarSelfRefs && firstStepIsSelf) {
431
- Object.defineProperty(arg, 'inXpr', { value: true, writable: true })
431
+ defineProperty(arg, 'inXpr', true)
432
432
  dollarSelfRefs.push(arg)
433
433
  return
434
434
  }
@@ -455,7 +455,7 @@ function infer(originalQuery, model) {
455
455
  const nextStep = arg.ref[1]?.id || arg.ref[1]
456
456
  if (isNonForeignKeyNavigation(element, nextStep)) {
457
457
  if (inExists) {
458
- Object.defineProperty($baseLink, 'pathExpressionInsideFilter', { value: true })
458
+ defineProperty($baseLink, 'pathExpressionInsideFilter', true)
459
459
  } else {
460
460
  rejectNonFkNavigation(element, element.on ? $baseLink.definition.name : nextStep)
461
461
  }
@@ -519,7 +519,7 @@ function infer(originalQuery, model) {
519
519
  const nextStep = arg.ref[i + 1]?.id || arg.ref[i + 1]
520
520
  if (isNonForeignKeyNavigation(element, nextStep)) {
521
521
  if (inExists) {
522
- Object.defineProperty($baseLink, 'pathExpressionInsideFilter', { value: true })
522
+ defineProperty($baseLink, 'pathExpressionInsideFilter', true)
523
523
  } else {
524
524
  rejectNonFkNavigation(element, element.on ? $baseLink.definition.name : nextStep)
525
525
  }
@@ -535,7 +535,7 @@ function infer(originalQuery, model) {
535
535
  } else if (id === '$dummy') {
536
536
  // `some.known.element.$dummy` -> no error; used by cds.ql to simulate joins
537
537
  arg.$refLinks.push({ definition: { name: '$dummy', parent: arg.$refLinks[i - 1].target } })
538
- Object.defineProperty(arg, 'isJoinRelevant', { value: true })
538
+ defineProperty(arg, 'isJoinRelevant', true)
539
539
  } else {
540
540
  const notFoundIn = pseudoPath ? arg.ref[i - 1] : getFullPathForLinkedArg(arg)
541
541
  stepNotFoundInPredecessor(id, notFoundIn)
@@ -561,7 +561,7 @@ function infer(originalQuery, model) {
561
561
  const definition = arg.$refLinks[i].definition
562
562
  if ((!definition.target && definition.kind !== 'entity') || (!inFrom && danglingFilter))
563
563
  throw new Error('A filter can only be provided when navigating along associations')
564
- if (!inFrom && !arg.expand) Object.defineProperty(arg, 'isJoinRelevant', { value: true })
564
+ if (!inFrom && !arg.expand)defineProperty(arg, 'isJoinRelevant', true)
565
565
  let skipJoinsForFilter = false
566
566
  step.where.forEach(token => {
567
567
  if (token === 'exists') {
@@ -590,7 +590,7 @@ function infer(originalQuery, model) {
590
590
  if (getDefinition(arg.$refLinks[i].definition.target)?.['@cds.persistence.skip'] === true) isPersisted = false
591
591
  if (!arg.ref[i + 1]) {
592
592
  const flatName = nameSegments.join('_')
593
- Object.defineProperty(arg, 'flatName', { value: flatName, writable: true })
593
+ defineProperty(arg, 'flatName', flatName)
594
594
  // if column is casted, we overwrite it's origin with the new type
595
595
  if (arg.cast) {
596
596
  const base = getElementForCast(arg)
@@ -635,7 +635,7 @@ function infer(originalQuery, model) {
635
635
  })
636
636
 
637
637
  // we need inner joins for the path expressions inside filter expressions after exists predicate
638
- if ($baseLink?.pathExpressionInsideFilter) Object.defineProperty(arg, 'join', { value: 'inner' })
638
+ if ($baseLink?.pathExpressionInsideFilter) defineProperty(arg, 'join', 'inner')
639
639
 
640
640
  // ignore whole expand if target of assoc along path has ”@cds.persistence.skip”
641
641
  if (arg.expand) {
@@ -655,7 +655,7 @@ function infer(originalQuery, model) {
655
655
  ? { ref: [...baseColumn.ref, ...arg.ref], $refLinks: [...baseColumn.$refLinks, ...arg.$refLinks] }
656
656
  : arg
657
657
  if (isColumnJoinRelevant(colWithBase)) {
658
- Object.defineProperty(arg, 'isJoinRelevant', { value: true })
658
+ defineProperty(arg, 'isJoinRelevant', true)
659
659
  joinTree.mergeColumn(colWithBase, originalQuery.outerQueries)
660
660
  }
661
661
  }
@@ -761,7 +761,7 @@ function infer(originalQuery, model) {
761
761
  const res = $leafLink.definition.is2one
762
762
  ? new cds.struct({ elements: inferredExpandSubquery.elements })
763
763
  : new cds.array({ items: new cds.struct({ elements: inferredExpandSubquery.elements }) })
764
- return Object.defineProperty(res, '$assocExpand', { value: true })
764
+ return defineProperty(res, '$assocExpand', true)
765
765
  } else if ($leafLink.definition.elements) {
766
766
  let elements = {}
767
767
  expand.forEach(e => {
@@ -900,13 +900,13 @@ function infer(originalQuery, model) {
900
900
  const calcElementIsJoinRelevant = isColumnJoinRelevant(p)
901
901
  if (calcElementIsJoinRelevant) {
902
902
  if (!calcElement.value.isJoinRelevant)
903
- Object.defineProperty(step, 'isJoinRelevant', { value: true, writable: true })
903
+ defineProperty(step, 'isJoinRelevant',true)
904
904
  joinTree.mergeColumn(p, originalQuery.outerQueries)
905
905
  } else {
906
906
  // we need to explicitly set the value to false in this case,
907
907
  // e.g. `SELECT from booksCalc.Books { ID, author.{name }, author {name } }`
908
908
  // --> for the inline column, the name is join relevant, while for the expand, it is not
909
- Object.defineProperty(step, 'isJoinRelevant', { value: false, writable: true })
909
+ defineProperty(step, 'isJoinRelevant', false)
910
910
  }
911
911
  }
912
912
  }
@@ -1064,7 +1064,6 @@ function infer(originalQuery, model) {
1064
1064
  * @returns {object} a copy of @param base with all annotations of @param from
1065
1065
  * @TODO prototype based
1066
1066
  */
1067
- // REVISIT: TODO: inferred.elements should be linked
1068
1067
  function getCopyWithAnnos(from, base) {
1069
1068
  const result = { ...base }
1070
1069
  // REVISIT: we don't need to and hence should not handle annotations at runtime
@@ -1072,7 +1071,7 @@ function infer(originalQuery, model) {
1072
1071
  if (prop.startsWith('@')) result[prop] = from[prop]
1073
1072
  }
1074
1073
 
1075
- if (from.as && base.name !== from.as) Object.defineProperty(result, 'name', { value: from.as }) // TODO double check if this is needed
1074
+ if (from.as && base.name !== from.as) defineProperty(result, 'name', from.as) // TODO double check if this is needed
1076
1075
  // in subqueries we need the linked element if an outer query accesses it
1077
1076
  return Object.setPrototypeOf(result, base)
1078
1077
  }
package/lib/search.js CHANGED
@@ -79,7 +79,7 @@ const _getSearchableColumns = entity => {
79
79
  const column = entity.elements[columnName]
80
80
  if (column?.isAssociation || columnName.includes('.')) {
81
81
  deepSearchCandidates.push({ ref: columnName.split('.') })
82
- continue;
82
+ continue
83
83
  }
84
84
  cdsSearchColumnMap.set(columnName, annotationValue)
85
85
  }
@@ -93,8 +93,8 @@ const _getSearchableColumns = entity => {
93
93
  // `@cds.search { element1: true }` or `@cds.search { element1 }`
94
94
  if (annotatedColumnValue) return true
95
95
 
96
- // calculated elements are only searchable if requested through `@cds.search`
97
- if(column.value) return false
96
+ // calculated elements are only searchable if requested through `@cds.search`
97
+ if (column.value) return false
98
98
 
99
99
  // if at least one element is explicitly annotated as searchable, e.g.:
100
100
  // `@cds.search { element1: true }` or `@cds.search { element1 }`
@@ -112,16 +112,23 @@ const _getSearchableColumns = entity => {
112
112
 
113
113
  if (deepSearchCandidates.length) {
114
114
  deepSearchCandidates.forEach(c => {
115
- const element = c.ref.reduce((resolveIn, curr, i) => {
116
- const next = resolveIn.elements?.[curr] || resolveIn._target.elements[curr]
117
- if (next?.isAssociation && !c.ref[i + 1]) {
118
- const searchInTarget = _getSearchableColumns(next._target)
119
- searchInTarget.forEach(elementRefInTarget => {
120
- searchableColumns.push({ ref: c.ref.concat(...elementRefInTarget.ref) })
121
- })
115
+ let element = entity
116
+ for (let i = 0; i < c.ref.length; ++i) {
117
+ const curr = c.ref[i]
118
+ const next = element.elements?.[curr] ?? element._target?.elements?.[curr]
119
+
120
+ if (!next) { // e.g. if a search element is not part of a projection
121
+ element = undefined
122
+ break
122
123
  }
123
- return next
124
- }, entity)
124
+
125
+ if (next.isAssociation && i === c.ref.length - 1) {
126
+ _getSearchableColumns(next._target).forEach(r => searchableColumns.push({ ref: c.ref.concat(...r.ref) }))
127
+ }
128
+
129
+ element = next
130
+ }
131
+
125
132
  if (element?.type === DEFAULT_SEARCHABLE_TYPE) {
126
133
  searchableColumns.push({ ref: c.ref })
127
134
  }
@@ -129,9 +136,8 @@ const _getSearchableColumns = entity => {
129
136
  }
130
137
 
131
138
  return searchableColumns.map(column => {
132
- if(column.ref)
133
- return column
134
- return { ref: [ column.name ] }
139
+ if (column.ref) return column
140
+ return { ref: [column.name] }
135
141
  })
136
142
  }
137
143
 
@@ -183,15 +189,16 @@ const computeColumnsToBeSearched = (cqn, entity = { __searchableColumns: [] }) =
183
189
  }
184
190
  })
185
191
  } else {
186
- if(entity.kind === 'entity') {
192
+ if (entity.kind === 'entity') {
187
193
  // first check cache
188
- toBeSearched = entity.own('__searchableColumns') || entity.set('__searchableColumns', _getSearchableColumns(entity))
194
+ toBeSearched =
195
+ entity.own('__searchableColumns') || entity.set('__searchableColumns', _getSearchableColumns(entity))
189
196
  } else {
190
197
  // if we search on a subquery, we don't have a cache
191
198
  toBeSearched = _getSearchableColumns(entity)
192
199
  }
193
200
  toBeSearched = toBeSearched.map(c => {
194
- const column = {ref: [...c.ref]}
201
+ const column = { ref: [...c.ref] }
195
202
  return column
196
203
  })
197
204
  }
package/lib/utils.js CHANGED
@@ -62,6 +62,14 @@ function getImplicitAlias(str, useTechnicalAlias = true) {
62
62
  return index != -1 ? str.substring(index + 1) : str
63
63
  }
64
64
 
65
+ function defineProperty(obj, prop, value) {
66
+ return Object.defineProperty(obj, prop, {
67
+ value,
68
+ writable: true,
69
+ configurable: true,
70
+ })
71
+ }
72
+
65
73
  /**
66
74
  * Shared utility functions which operate dynamically on the model / query.
67
75
  *
@@ -129,5 +137,6 @@ module.exports = {
129
137
  isCalculatedOnRead,
130
138
  isCalculatedElement,
131
139
  getImplicitAlias,
140
+ defineProperty,
132
141
  getModelUtils,
133
142
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@cap-js/db-service",
3
- "version": "1.20.0",
3
+ "version": "1.20.1",
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": {
7
7
  "type": "git",
8
- "url": "https://github.com/cap-js/cds-dbs"
8
+ "url": "git+https://github.com/cap-js/cds-dbs.git"
9
9
  },
10
10
  "bugs": {
11
11
  "url": "https://github.com/cap-js/cds-dbs/issues"