@sap/cds 6.7.2 → 6.8.2

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 (106) hide show
  1. package/CHANGELOG.md +53 -1
  2. package/README.md +1 -0
  3. package/_i18n/i18n.properties +9 -6
  4. package/_i18n/i18n_ar.properties +6 -6
  5. package/_i18n/i18n_cs.properties +6 -6
  6. package/_i18n/i18n_da.properties +6 -6
  7. package/_i18n/i18n_de.properties +6 -6
  8. package/_i18n/i18n_en.properties +6 -6
  9. package/_i18n/i18n_es.properties +6 -6
  10. package/_i18n/i18n_fi.properties +6 -6
  11. package/_i18n/i18n_fr.properties +6 -6
  12. package/_i18n/i18n_hu.properties +6 -6
  13. package/_i18n/i18n_it.properties +6 -6
  14. package/_i18n/i18n_ja.properties +6 -6
  15. package/_i18n/i18n_ko.properties +6 -6
  16. package/_i18n/i18n_ms.properties +6 -6
  17. package/_i18n/i18n_nl.properties +6 -6
  18. package/_i18n/i18n_no.properties +6 -6
  19. package/_i18n/i18n_pl.properties +6 -6
  20. package/_i18n/i18n_pt.properties +6 -6
  21. package/_i18n/i18n_ro.properties +6 -6
  22. package/_i18n/i18n_ru.properties +6 -6
  23. package/_i18n/i18n_sv.properties +6 -6
  24. package/_i18n/i18n_th.properties +6 -6
  25. package/_i18n/i18n_tr.properties +8 -8
  26. package/_i18n/i18n_zh_CN.properties +3 -3
  27. package/_i18n/i18n_zh_TW.properties +6 -6
  28. package/apis/core.d.ts +30 -31
  29. package/apis/csn.d.ts +1 -1
  30. package/apis/ql.d.ts +69 -39
  31. package/apis/serve.d.ts +4 -3
  32. package/apis/services.d.ts +20 -7
  33. package/bin/build/buildTaskEngine.js +1 -1
  34. package/bin/build/index.js +1 -1
  35. package/bin/build/provider/buildTaskProviderInternal.js +9 -6
  36. package/bin/build/provider/hana/index.js +11 -4
  37. package/bin/build/provider/mtx-extension/index.js +13 -1
  38. package/bin/build/provider/mtx-sidecar/index.js +3 -3
  39. package/bin/build/provider/nodejs/index.js +23 -0
  40. package/bin/plugins.js +2 -1
  41. package/bin/version.js +3 -2
  42. package/common.cds +3 -2
  43. package/lib/auth/index.js +3 -0
  44. package/lib/auth/mocked-users.js +13 -0
  45. package/lib/compile/etc/_localized.js +3 -0
  46. package/lib/compile/for/lean_drafts.js +0 -1
  47. package/lib/core/entities.js +7 -3
  48. package/lib/dbs/cds-deploy.js +36 -12
  49. package/lib/env/cds-env.js +47 -14
  50. package/lib/env/cds-requires.js +16 -7
  51. package/lib/env/defaults.js +2 -2
  52. package/lib/env/schemas/cds-rc.json +1 -8
  53. package/lib/index.js +1 -1
  54. package/lib/ql/STREAM.js +89 -0
  55. package/lib/ql/cds-ql.js +2 -1
  56. package/lib/req/request.js +6 -2
  57. package/lib/req/user.js +1 -1
  58. package/lib/srv/middlewares/index.js +9 -7
  59. package/lib/srv/middlewares/trace.js +6 -5
  60. package/lib/srv/srv-api.js +1 -0
  61. package/lib/utils/cds-utils.js +1 -1
  62. package/lib/utils/tar.js +30 -31
  63. package/libx/_runtime/audit/Service.js +96 -37
  64. package/libx/_runtime/audit/generic/personal/utils.js +26 -13
  65. package/libx/_runtime/audit/utils/v2.js +21 -22
  66. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
  67. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
  68. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +2 -0
  69. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +2 -3
  70. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -1
  71. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/batch/BatchProcessor.js +2 -0
  72. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +2 -1
  73. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +10 -3
  74. package/libx/_runtime/cds-services/services/Service.js +2 -7
  75. package/libx/_runtime/cds-services/services/utils/differ.js +1 -1
  76. package/libx/_runtime/cds-services/util/assert.js +28 -5
  77. package/libx/_runtime/common/aspects/any.js +4 -1
  78. package/libx/_runtime/common/generic/auth/utils.js +30 -41
  79. package/libx/_runtime/common/generic/crud.js +1 -1
  80. package/libx/_runtime/common/i18n/messages.properties +1 -1
  81. package/libx/_runtime/common/utils/generateOnCond.js +18 -22
  82. package/libx/_runtime/db/expand/expandCQNToJoin.js +49 -41
  83. package/libx/_runtime/db/expand/rawToExpanded.js +3 -5
  84. package/libx/_runtime/db/generic/rewrite.js +3 -0
  85. package/libx/_runtime/db/utils/generateAliases.js +1 -1
  86. package/libx/_runtime/fiori/generic/activate.js +1 -1
  87. package/libx/_runtime/fiori/generic/before.js +18 -19
  88. package/libx/_runtime/fiori/generic/prepare.js +1 -1
  89. package/libx/_runtime/fiori/generic/read.js +1 -1
  90. package/libx/_runtime/fiori/lean-draft.js +87 -53
  91. package/libx/_runtime/fiori/utils/handler.js +0 -6
  92. package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +1 -1
  93. package/libx/_runtime/hana/customBuilder/CustomReferenceBuilder.js +2 -1
  94. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +0 -5
  95. package/libx/_runtime/hana/execute.js +18 -11
  96. package/libx/_runtime/hana/pool.js +26 -18
  97. package/libx/_runtime/hana/search2Contains.js +1 -1
  98. package/libx/_runtime/hana/search2cqn4sql.js +26 -18
  99. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +23 -16
  100. package/libx/_runtime/messaging/outbox/utils.js +6 -1
  101. package/libx/_runtime/remote/Service.js +83 -48
  102. package/libx/_runtime/remote/utils/client.js +17 -19
  103. package/libx/_runtime/sqlite/execute.js +2 -0
  104. package/libx/rest/middleware/read.js +2 -1
  105. package/libx/rest/middleware/update.js +1 -1
  106. package/package.json +1 -1
@@ -54,7 +54,11 @@ const readAfterWrite = async (req, srv, { operation, isBefore } = { isBefore: fa
54
54
  if (_isDraftAction(req)) query.where({ IsActiveEntity: req.event === 'draftActivate' })
55
55
  } else if (req.event === 'NEW' || req.event === 'PATCH') {
56
56
  const { result } = operation
57
- query = getSimpleSelectCQN(req.target, result)
57
+ if (req.query.UPDATE?.entity?.ref[0]?.where) {
58
+ query = SELECT.one(req.query.UPDATE.entity)
59
+ } else {
60
+ query = getSimpleSelectCQN(req.target, result)
61
+ }
58
62
  } else if (req.event === 'UPDATE' && !hasDeepUpdate(srv.model, req.query)) {
59
63
  query = Array.isArray(req.data) ? SELECT.from(req.query.UPDATE.entity) : SELECT.one(req.query.UPDATE.entity)
60
64
  } else {
@@ -62,13 +66,14 @@ const readAfterWrite = async (req, srv, { operation, isBefore } = { isBefore: fa
62
66
  }
63
67
  Object.defineProperty(query.SELECT, '_4odata', { value: true })
64
68
  _ensureKeysAreSelected(query)
69
+
65
70
  // gracefully set location and no body if no read auth or not readable capability
66
71
  let result
67
72
  try {
68
73
  const _req = new Request({ query, event: 'READ', _: req._, params: req.params })
69
74
  result = await srv.dispatch(_req)
70
75
  if (result && req.target._isDraftEnabled) removeDraftUUIDIfNecessary(req)(result)
71
- if (result === null && !isBefore && (_isWriteWithResponse(req) || _isDraftAction(req))) {
76
+ if (result == null && !isBefore && (_isWriteWithResponse(req) || _isDraftAction(req))) {
72
77
  // > something must be written and no READ error <=> @restrict or static where
73
78
  _req.reject({
74
79
  code: 404,
@@ -82,10 +87,12 @@ const readAfterWrite = async (req, srv, { operation, isBefore } = { isBefore: fa
82
87
  _handleReadError(e, req)
83
88
  result = null
84
89
  }
90
+
85
91
  // draft actions have own logic to set location header
86
- if (result === null && _isWriteWithResponse(req) && !_isDraftAction(req)) {
92
+ if (result == null && _isWriteWithResponse(req) && !_isDraftAction(req)) {
87
93
  setLocationHeader(req, srv)
88
94
  }
95
+
89
96
  return result
90
97
  }
91
98
 
@@ -78,14 +78,9 @@ class ApplicationService extends cds.Service {
78
78
  if (Array.isArray(data)) return data.map(d => _addIsActiveEntity(d, IsActiveEntity))
79
79
  if (_key in data) data.IsActiveEntity = IsActiveEntity
80
80
  }
81
- this.on('READ', each, async (_, next) => {
81
+ this.on('READ', each, async (req, next) => {
82
82
  const data = await next()
83
- _addIsActiveEntity(data, true)
84
- return data
85
- })
86
- this.on('READ', each, async (_, next) => {
87
- const data = await next()
88
- _addIsActiveEntity(data, false)
83
+ _addIsActiveEntity(data, !req.target?.isDraft)
89
84
  return data
90
85
  })
91
86
  }
@@ -39,7 +39,7 @@ module.exports = class Differ {
39
39
  _diffDelete(req) {
40
40
  const { DELETE } = (req._ && req._.query) || req.query
41
41
  const query = SELECT.from(DELETE.from).columns(this._createSelectColumnsForDelete(req.target))
42
- if (DELETE.where) query.where(...DELETE.where)
42
+ if (DELETE.where) query.where(DELETE.where)
43
43
 
44
44
  return cds
45
45
  .tx(req)
@@ -112,10 +112,33 @@ const _checkISODateTime = value => (_checkString(value) && ISO_DATE_TIME_REGEX.t
112
112
 
113
113
  const _checkISOTimestamp = value => (_checkString(value) && ISO_TIMESTAMP_REGEX.test(value)) || value instanceof Date
114
114
 
115
- const _checkInRange = (val, range) => {
116
- return _checkISODate(val)
117
- ? (new Date(val) - new Date(range[0])) * (new Date(val) - new Date(range[1])) <= 0
118
- : (val - range[0]) * (val - range[1]) <= 0
115
+ const _checkDateValue = (val, r1, r2) => {
116
+ const dateVal = new Date(val)
117
+ return (dateVal - new Date(r1)) * (dateVal - new Date(r2)) <= 0
118
+ }
119
+
120
+ const _toDate = val => `2000-01-01T${val}Z`
121
+
122
+ const _checkInRange = (val, range, type) => {
123
+ switch (type) {
124
+ case 'cds.Date':
125
+ return _checkISODate(val) && _checkDateValue(val, range[0], range[1])
126
+ case 'cds.DateTime':
127
+ return _checkISODateTime(val) && _checkDateValue(val, range[0], range[1])
128
+ case 'cds.Timestamp':
129
+ return _checkISOTimestamp(val) && _checkDateValue(val, range[0], range[1])
130
+ case 'cds.Time':
131
+ return _checkISOTime(val) && _checkDateValue(_toDate(val), _toDate(range[0]), _toDate(range[1]))
132
+ default:
133
+ return (val - range[0]) * (val - range[1]) <= 0
134
+ }
135
+ }
136
+
137
+ const _resolveCDSType = element => {
138
+ if (element.type.startsWith('cds.')) return element.type
139
+ if (!element.type) return
140
+
141
+ return _resolveCDSType(element.__proto__)
119
142
  }
120
143
 
121
144
  // process.env.CDS_ASSERT_FORMAT_FLAGS not official!
@@ -227,7 +250,7 @@ const _checkEnumElement = (element, value, errors, key, pathSegmentsInfo) => {
227
250
 
228
251
  const _checkRangeElement = (element, value, errors, key, pathSegmentsInfo) => {
229
252
  const rangeElements = element['@assert.range'] && !_getEnumElement(element) ? element['@assert.range'] : undefined
230
- if (rangeElements && !_checkInRange(value, rangeElements)) {
253
+ if (rangeElements && !_checkInRange(value, rangeElements, _resolveCDSType(element))) {
231
254
  const args = [value, ...element['@assert.range']]
232
255
  errors.push(assertError({ code: ASSERT_RANGE, args }, element, value, key, pathSegmentsInfo))
233
256
  }
@@ -40,11 +40,14 @@ const _relationHandler = relation => ({
40
40
  if (newRelation) {
41
41
  target[prop] = new Proxy(_exposeRelation(newRelation), _relationHandler(newRelation))
42
42
  }
43
+
43
44
  return target[prop]
44
45
  }
45
- target[prop] = path.reduce((r, p) => r[p] || r.csn._relations[p], relation)
46
+
47
+ target[prop] = path.reduce((relation, value) => relation[value] || relation.csn._relations[value], relation)
46
48
  target[prop].path = path
47
49
  }
50
+
48
51
  return target[prop]
49
52
  }
50
53
  })
@@ -40,54 +40,51 @@ const _getCurrentSubClause = (next, restrict) => {
40
40
  const escaped = next[0].replace(/\$/g, '\\$').replace(/\./g, '\\.')
41
41
  const re1 = new RegExp(`([\\w\\.']*)\\s*=\\s*(${escaped})|(${escaped})\\s*=\\s*([\\w\\.']*)`)
42
42
  const re2 = new RegExp(`([\\w\\.']*)\\s*in\\s*(${escaped})|(${escaped})\\s*in\\s*([\\w\\.']*)`)
43
- const clause = restrict.where.match(re1) || restrict.where.match(re2)
43
+ const re3 = new RegExp(`(${escaped})\\s*is\\s*null`)
44
+ const re4 = new RegExp(`(${escaped})\\s*is\\s*not\\s*null`)
45
+ const clause =
46
+ restrict.where.match(re3) || restrict.where.match(re4) || restrict.where.match(re1) || restrict.where.match(re2)
44
47
 
45
48
  if (clause) return clause
46
49
 
47
50
  // NOTE: arrayed attr with "=" as operator is some kind of legacy case
48
- throw new Error('user attribute array must be used with operator "=" or "in"')
51
+ throw new Error('user attribute array must be used with operator "=", "in", "is null", or "is not null"')
49
52
  }
50
53
 
51
- const _processUserAttr = (next, restrict, user, attr) => {
54
+ const _isNull = (userAttrs, attr) =>
55
+ userAttrs[attr] == null || (Array.isArray(userAttrs[attr]) && userAttrs[attr].length === 0)
56
+ const _isNotNull = (userAttrs, attr) =>
57
+ userAttrs[attr] != null && Array.isArray(userAttrs[attr]) && userAttrs[attr].length > 0
58
+
59
+ const _processUserAttr = (next, restrict, userAttrs, attr) => {
52
60
  const clause = _getCurrentSubClause(next, restrict)
53
61
  const valOrRef = clause[1] || clause[4]
54
62
 
55
- if (clause[0].match(/ in /)) {
56
- if (!user[attr] || user[attr].length === 0) {
63
+ if (clause[0].match(/ is\s*null/)) {
64
+ restrict.where = restrict.where.replace(clause[0], _isNull(userAttrs, attr) ? '1 = 1' : '1 = 2')
65
+ } else if (clause[0].match(/ is\s*not\s*null/)) {
66
+ restrict.where = restrict.where.replace(clause[0], _isNotNull(userAttrs, attr) ? '1 = 1' : '1 = 2')
67
+ } else {
68
+ if (_isNull(userAttrs, attr)) {
57
69
  restrict.where = restrict.where.replace(clause[0], '1 = 2')
58
- } else if (user[attr].length === 1) {
59
- restrict.where = restrict.where.replace(clause[0], `${valOrRef} = '${user[attr][0]}'`)
70
+ } else if (clause[0].match(/ in /)) {
71
+ if (userAttrs[attr].length === 1) {
72
+ restrict.where = restrict.where.replace(clause[0], `${valOrRef} = '${userAttrs[attr][0]}'`)
73
+ } else {
74
+ restrict.where = restrict.where.replace(
75
+ clause[0],
76
+ `${valOrRef} in (${userAttrs[attr].map(ele => `'${ele}'`).join(', ')})`
77
+ )
78
+ }
79
+ } else if (valOrRef.startsWith("'") && userAttrs[attr].includes(valOrRef.split("'")[1])) {
80
+ restrict.where = restrict.where.replace(clause[0], `${valOrRef} = ${valOrRef}`)
60
81
  } else {
61
82
  restrict.where = restrict.where.replace(
62
83
  clause[0],
63
- `${valOrRef} in (${user[attr].map(ele => `'${ele}'`).join(', ')})`
84
+ `(${userAttrs[attr].map(ele => `${valOrRef} = '${ele}'`).join(' or ')})`
64
85
  )
65
86
  }
66
- } else if (valOrRef.startsWith("'") && user[attr].includes(valOrRef.split("'")[1])) {
67
- restrict.where = restrict.where.replace(clause[0], `${valOrRef} = ${valOrRef}`)
68
- } else {
69
- restrict.where = restrict.where.replace(
70
- clause[0],
71
- `(${user[attr].map(ele => `${valOrRef} = '${ele}'`).join(' or ')})`
72
- )
73
- }
74
- }
75
-
76
- const _getShortcut = (attrs, attr) => {
77
- // undefined
78
- if (attrs[attr] === undefined) {
79
- return '1 = 2'
80
87
  }
81
-
82
- // $UNRESTRICTED
83
- if (
84
- (typeof attrs[attr] === 'string' && attrs[attr].match(/\$UNRESTRICTED/i)) ||
85
- (Array.isArray(attrs[attr]) && attrs[attr].some(a => a.match(/\$UNRESTRICTED/i)))
86
- ) {
87
- return '1 = 1'
88
- }
89
-
90
- return null
91
88
  }
92
89
 
93
90
  /*
@@ -120,15 +117,7 @@ const resolveUserAttrs = (restrict, req) => {
120
117
  let attr = parts.shift()
121
118
 
122
119
  while (attr) {
123
- const shortcut = _getShortcut(attrs, attr)
124
- if (shortcut) {
125
- const clause = _getCurrentSubClause(next, restrict)
126
- restrict.where = restrict.where.replace(clause[0], shortcut)
127
- skip = true
128
- break
129
- }
130
-
131
- if (Array.isArray(attrs[attr])) {
120
+ if (attrs[attr] === undefined || Array.isArray(attrs[attr])) {
132
121
  _processUserAttr(next, restrict, attrs, attr)
133
122
  skip = true
134
123
  break
@@ -43,6 +43,7 @@ exports.impl = cds.service.impl(function () {
43
43
  // - INSERT has no where clause to do this in one roundtrip
44
44
  // - SELECT returns [] -> really empty collection or invalid path?
45
45
  let pathExistsQuery
46
+
46
47
  const { ref } = (req.query.INSERT && req.query.INSERT.into) || (req.query.SELECT && req.query.SELECT.from) || {}
47
48
  // REVISIT: why is copy necessary?
48
49
  if (ref && ref.length > 1) pathExistsQuery = SELECT(1).from({ ref: deepCopyArray(ref.slice(0, -1)) })
@@ -59,7 +60,6 @@ exports.impl = cds.service.impl(function () {
59
60
 
60
61
  // if no keys available, select all columns so we can delete the singleton with same content
61
62
  if (keyColumns.length) selectSingleton.columns(keyColumns)
62
-
63
63
  const singleton = await cds.tx(req).run(selectSingleton)
64
64
  if (!singleton) req.reject(404)
65
65
 
@@ -85,7 +85,7 @@ CRUD_VIA_NAVIGATION_NOT_SUPPORTED=CRUD via navigations is not yet supported
85
85
 
86
86
  # draft
87
87
  DRAFT_ALREADY_EXISTS=A draft for this entity already exists
88
- DRAFT_LOCKED_BY_ANOTHER_USER=The entity is locked by another user
88
+ DRAFT_LOCKED_BY_ANOTHER_USER=The entity is locked by user "{0}"
89
89
  DRAFT_MODIFICATION_ONLY_VIA_ROOT=A draft can only be modified via its root entity
90
90
 
91
91
  # singleton
@@ -8,6 +8,7 @@ const _toRef = (alias, column) => {
8
8
  const _adaptRefs = (onCond, path, { select, join }) => {
9
9
  const _adaptEl = el => {
10
10
  const ref = el.ref
11
+
11
12
  if (ref) {
12
13
  if (ref[0] === path.join('_') && ref[1]) {
13
14
  return _toRef(select, ref.slice(1))
@@ -19,41 +20,34 @@ const _adaptRefs = (onCond, path, { select, join }) => {
19
20
  }
20
21
 
21
22
  return _toRef(join, ref.slice(0))
22
- } else if (el.xpr) {
23
- return { xpr: el.xpr.map(_adaptEl) }
24
23
  }
25
24
 
25
+ if (el.xpr) return { xpr: el.xpr.map(_adaptEl) }
26
26
  return el
27
27
  }
28
+
28
29
  return onCond.map(_adaptEl)
29
30
  }
30
31
 
31
32
  const _args = (csnElement, path, aliases) => {
32
33
  const onCond = csnElement.on
33
-
34
- if (!onCond || !onCond.length) {
35
- return []
36
- }
37
-
38
- if (onCond.length < 3) {
39
- return onCond
40
- }
41
-
34
+ if (!onCond || onCond.length === 0) return []
35
+ if (onCond.length < 3 && !onCond[0]?.xpr) return onCond
42
36
  if (!csnElement._isSelfManaged) return _adaptRefs(onCond, path, aliases)
43
37
 
44
38
  // revert join and select aliases because of backlink
45
- const oc = _newOnConditions(csnElement._backlink, [csnElement._backlink.name], {
39
+ const mutOnCond = _newOnConditions(csnElement._backlink, [csnElement._backlink.name], {
46
40
  select: aliases.join,
47
41
  join: aliases.select
48
42
  })
49
43
 
50
44
  if (onCond.some(e => e === 'and')) {
51
- // managed with ON-conditions must contain `$self`, which we replace with `oc`
52
- const onCondWithouSelf = _adaptRefs(_onCondWithout$self(onCond), path, aliases)
53
- oc.push('and', ...onCondWithouSelf)
45
+ // managed with ON-conditions must contain `$self`, which we replace with `mutOnCond`
46
+ const onCondWithoutSelf = _adaptRefs(_onCondWithout$self(onCond), path, aliases)
47
+ mutOnCond.push('and', ...onCondWithoutSelf)
54
48
  }
55
49
 
56
- return oc
50
+ return mutOnCond
57
51
  }
58
52
 
59
53
  const _isSelfRef = e => e && e.ref && e.ref[0] === '$self'
@@ -64,23 +58,27 @@ const _onCondWithout$self = onCond => {
64
58
  if (e === 'and') return _isSelfRef(on[i + 1]) || _isSelfRef(on[i + 3])
65
59
  return on[i + 1] === '=' && (_isSelfRef(e) || _isSelfRef(on[i + 2]))
66
60
  })
61
+
67
62
  onCondWithoutSelf.splice(selfIndex, 4)
68
63
  return onCondWithoutSelf
69
64
  }
70
65
 
66
+ // this is only for 2one managed w/o on-conditions, i.e. no static values are possible
71
67
  const _foreignToOn = (csnElement, path, { select, join }) => {
72
- // this is only for 2one managed w/o ON-conditions i.e. no static values are possible
73
68
  const on = []
69
+
74
70
  for (const key of csnElement._foreignKeys) {
75
71
  if (on.length !== 0) {
76
72
  on.push('and')
77
73
  }
74
+
78
75
  const prefixChild = prefixForStruct(key.childElement)
79
76
  const ref1 = _toRef(select, prefixChild + key.childElement.name)
80
77
  const structPrefix = path.length > 1 ? path.slice(0, -1) : []
81
78
  const ref2 = _toRef(join, [...structPrefix, key.parentElement.name])
82
79
  on.push(ref1, '=', ref2)
83
80
  }
81
+
84
82
  return on
85
83
  }
86
84
 
@@ -93,10 +91,8 @@ const _newOnConditions = (csnElement, path, aliases) => {
93
91
  }
94
92
 
95
93
  const getOnCond = (csnElement, path = [], aliases = { select: '', join: '' }) => {
96
- const oncond = _newOnConditions(csnElement, path, aliases)
97
- return [{ xpr: oncond }]
94
+ const onCond = _newOnConditions(csnElement, path, aliases)
95
+ return [{ xpr: onCond }]
98
96
  }
99
97
 
100
- module.exports = {
101
- getOnCond
102
- }
98
+ module.exports = { getOnCond }