@sap/cds 8.1.1 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/app/index.css +3 -0
- package/app/index.js +50 -4
- package/bin/serve.js +1 -1
- package/lib/compile/cdsc.js +2 -2
- package/lib/compile/etc/_localized.js +1 -1
- package/lib/compile/for/lean_drafts.js +1 -0
- package/lib/compile/to/sql.js +2 -2
- package/lib/env/cds-requires.js +6 -0
- package/lib/env/defaults.js +14 -3
- package/lib/env/plugins.js +6 -22
- package/lib/linked/classes.js +0 -14
- package/lib/linked/types.js +12 -0
- package/lib/log/cds-log.js +3 -3
- package/lib/log/format/aspects/als.js +23 -29
- package/lib/log/format/aspects/cls.js +9 -0
- package/lib/log/format/json.js +42 -6
- package/lib/ql/Whereable.js +5 -1
- package/lib/srv/cds-connect.js +33 -32
- package/lib/srv/cds-serve.js +2 -1
- package/lib/utils/cds-utils.js +4 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +1 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +2 -31
- package/libx/_runtime/common/generic/auth/utils.js +2 -0
- package/libx/_runtime/common/generic/input.js +2 -11
- package/libx/_runtime/common/generic/put.js +1 -10
- package/libx/_runtime/common/utils/binary.js +1 -7
- package/libx/_runtime/common/utils/resolveView.js +2 -2
- package/libx/_runtime/common/utils/search2cqn4sql.js +1 -1
- package/libx/_runtime/common/utils/streamProp.js +12 -1
- package/libx/_runtime/common/utils/template.js +26 -16
- package/libx/_runtime/common/utils/templateProcessor.js +8 -7
- package/libx/_runtime/common/utils/ucsn.js +2 -5
- package/libx/_runtime/db/expand/expandCQNToJoin.js +10 -0
- package/libx/_runtime/db/generic/input.js +1 -5
- package/libx/_runtime/fiori/lean-draft.js +272 -90
- package/libx/_runtime/messaging/event-broker.js +105 -40
- package/libx/_runtime/remote/utils/client.js +12 -4
- package/libx/_runtime/ucl/Service.js +16 -6
- package/libx/odata/middleware/batch.js +2 -2
- package/libx/odata/middleware/read.js +6 -10
- package/libx/odata/middleware/stream.js +4 -5
- package/libx/odata/parse/afterburner.js +3 -2
- package/libx/odata/utils/index.js +3 -3
- package/libx/odata/utils/postProcess.js +3 -25
- package/libx/rest/middleware/parse.js +1 -6
- package/package.json +2 -2
package/lib/utils/cds-utils.js
CHANGED
|
@@ -289,13 +289,15 @@ if (process.env.JEST_WORKER_ID === undefined) { // jest's ESM support is experi
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
const SECRETS = /(passw)|(cert)|(ca)|(secret)|(key)/i
|
|
292
293
|
/**
|
|
293
294
|
* Masks password-like strings, also reducing clutter in output
|
|
295
|
+
* @param {any} cred - object or array with credentials
|
|
296
|
+
* @returns {any}
|
|
294
297
|
*/
|
|
295
|
-
const SECRETS = /(password)|(certificate)|(ca)|(clientsecret)|(secret)|(key)|(clientcert)/i
|
|
296
298
|
exports._redacted = function _redacted(cred) {
|
|
297
299
|
if (!cred) return cred
|
|
298
|
-
if (Array.isArray(cred)) return cred.map(_redacted)
|
|
300
|
+
if (Array.isArray(cred)) return cred.map(c => typeof c === 'string' ? '...' : _redacted(c))
|
|
299
301
|
if (typeof cred === 'object') {
|
|
300
302
|
const newCred = Object.assign({}, cred)
|
|
301
303
|
Object.keys(newCred).forEach(k => (typeof newCred[k] === 'string' && SECRETS.test(k)) ? (newCred[k] = '...') : (newCred[k] = _redacted(newCred[k])))
|
|
@@ -5,7 +5,6 @@ const { resolveFromSelect, targetFromPath } = require('../../../../common/utils/
|
|
|
5
5
|
const { setEntityContained } = require('../../../../common/utils/csn')
|
|
6
6
|
const { getNavigationIfStruct } = require('../../../../common/utils/structured')
|
|
7
7
|
const getTemplate = require('../../../../common/utils/template')
|
|
8
|
-
const templateProcessor = require('../../../../common/utils/templateProcessor')
|
|
9
8
|
|
|
10
9
|
const _ignoreColumns = columns => {
|
|
11
10
|
if (!(Array.isArray(columns) && columns.some(c => c === '*' || c.as || c.ref))) return true
|
|
@@ -111,10 +110,7 @@ const _columnsFromData = (data, definition, service) => {
|
|
|
111
110
|
const columns = {}
|
|
112
111
|
const template = getTemplate('odata-context', service, definition, { pick: element => element.isAssociation })
|
|
113
112
|
if (!template || !template.elements.size) return ''
|
|
114
|
-
|
|
115
|
-
for (const row of arrayData) {
|
|
116
|
-
templateProcessor({ processFn: _processFn(columns), row, template, pathOptions: { pathSegmentsInfo: [] } })
|
|
117
|
-
}
|
|
113
|
+
template.process(data, _processFn(columns), { pathSegmentsInfo: [] })
|
|
118
114
|
return _stringifyColumnsFromData(columns)
|
|
119
115
|
}
|
|
120
116
|
|
|
@@ -4,7 +4,6 @@ const { Readable } = require('stream')
|
|
|
4
4
|
const { big } = require('@sap/cds-foss')
|
|
5
5
|
|
|
6
6
|
const getTemplate = require('../../../../common/utils/template')
|
|
7
|
-
const templateProcessor = require('../../../../common/utils/templateProcessor')
|
|
8
7
|
const { omitValue, applyOmitValuesPreference } = require('./omitValues')
|
|
9
8
|
const { setLocationHeader } = require('./readAfterWrite')
|
|
10
9
|
const normalizeTimestamp = require('../../../../common/utils/normalizeTimestamp')
|
|
@@ -251,19 +250,6 @@ const _processorFn = (req, previousResult, options) => elementInfo => {
|
|
|
251
250
|
}
|
|
252
251
|
}
|
|
253
252
|
|
|
254
|
-
const _getParent = (model, name) => {
|
|
255
|
-
const target = model.definitions[name]
|
|
256
|
-
|
|
257
|
-
if (target && target.elements) {
|
|
258
|
-
for (const elementName in target.elements) {
|
|
259
|
-
const element = target.elements[elementName]
|
|
260
|
-
if (element._anchor && element._anchor._isContained) return element._anchor
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return null
|
|
265
|
-
}
|
|
266
|
-
|
|
267
253
|
const _isUpAssoc = element => element && /^up_(_up_)*$/.test(element.name) && _isContainedOrBackLink(element)
|
|
268
254
|
|
|
269
255
|
const _isContainedOrBackLink = element =>
|
|
@@ -365,29 +351,14 @@ const postProcess = (req, res, service, result, previousResult) => {
|
|
|
365
351
|
|
|
366
352
|
const options = _getOptions(req)
|
|
367
353
|
const cacheKey = _generateCacheKey(headers, options)
|
|
368
|
-
const parent = _getParent(model, target.name)
|
|
369
354
|
// REVISIT: Why so many templates? -> Create only one (superset) template to reduce memory consumption
|
|
370
|
-
const template = getTemplate(cacheKey, service, target, { pick: _pick(options) }
|
|
355
|
+
const template = getTemplate(cacheKey, service, target, { pick: _pick(options) })
|
|
371
356
|
|
|
372
357
|
if (template.elements.size === 0) return
|
|
373
358
|
|
|
374
359
|
// normalize result to rows
|
|
375
360
|
result = result.value != null && Object.keys(result).filter(k => !k.match(/^\W/)).length === 1 ? result.value : result
|
|
376
|
-
|
|
377
|
-
if (typeof result === 'object' && result != null) {
|
|
378
|
-
const rows = Array.isArray(result) ? result : [result]
|
|
379
|
-
|
|
380
|
-
// process each row
|
|
381
|
-
const processFn = _processorFn(req, previousResult, options)
|
|
382
|
-
|
|
383
|
-
for (const row of rows) {
|
|
384
|
-
templateProcessor({
|
|
385
|
-
processFn,
|
|
386
|
-
row,
|
|
387
|
-
template
|
|
388
|
-
})
|
|
389
|
-
}
|
|
390
|
-
}
|
|
361
|
+
template.process(result, _processorFn(req, previousResult, options))
|
|
391
362
|
|
|
392
363
|
applyOmitValuesPreference(res, options.omitValuesPreference)
|
|
393
364
|
}
|
|
@@ -15,7 +15,6 @@ const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
|
15
15
|
const propagateForeignKeys = require('../utils/propagateForeignKeys')
|
|
16
16
|
const { checkInputConstraints, assertTargets } = require('../../cds-services/util/assert')
|
|
17
17
|
const getTemplate = require('../utils/template')
|
|
18
|
-
const templateProcessor = require('../utils/templateProcessor')
|
|
19
18
|
const { getDataFromCQN, setDataFromCQN } = require('../utils/data')
|
|
20
19
|
const getRowUUIDGeneratorFn = require('../utils/rowUUIDGenerator')
|
|
21
20
|
|
|
@@ -276,11 +275,8 @@ async function commonGenericInput(req) {
|
|
|
276
275
|
|
|
277
276
|
const data = getDataFromCQN(req.query) // REVISIT: req.data should point into req.query
|
|
278
277
|
enrichDataWithKeysFromWhere(data, req, this)
|
|
279
|
-
const arrayData = Array.isArray(data) ? data : [data]
|
|
280
278
|
|
|
281
|
-
|
|
282
|
-
templateProcessor({ processFn: _getProcessorFn(req, errors, assertMap), row, template, pathOptions })
|
|
283
|
-
}
|
|
279
|
+
template.process(data, _getProcessorFn(req, errors, assertMap), pathOptions)
|
|
284
280
|
|
|
285
281
|
if (assertMap.targets.size > 0) {
|
|
286
282
|
await assertTargets(assertMap, errors)
|
|
@@ -314,12 +310,7 @@ const _processActionFunctionRow = (row, param, key, errors, event, service) => {
|
|
|
314
310
|
ignore: element => element._isAssociationStrict
|
|
315
311
|
})
|
|
316
312
|
|
|
317
|
-
|
|
318
|
-
for (const value of values) {
|
|
319
|
-
const args = { processFn: _getProcessorFnForActionsFunctions(errors, key), row: value, template }
|
|
320
|
-
templateProcessor(args)
|
|
321
|
-
}
|
|
322
|
-
}
|
|
313
|
+
template.process(values, _getProcessorFnForActionsFunctions(errors, key))
|
|
323
314
|
}
|
|
324
315
|
|
|
325
316
|
const _processActionFunction = (row, eventParams, errors, event, service) => {
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
const cds = require('../../cds')
|
|
9
9
|
const getTemplate = require('../utils/template')
|
|
10
|
-
const templateProcessor = require('../utils/templateProcessor')
|
|
11
10
|
const { getDataFromCQN, setDataFromCQN } = require('../utils/data')
|
|
12
11
|
|
|
13
12
|
const _fillStructure = (row, parts, element, category, args) => {
|
|
@@ -73,15 +72,7 @@ function commonGenericPut(req) {
|
|
|
73
72
|
// REVISIT: req.data should point into req.query
|
|
74
73
|
const data = getDataFromCQN(req.query)
|
|
75
74
|
|
|
76
|
-
|
|
77
|
-
for (const row of arrayData) {
|
|
78
|
-
const args = {
|
|
79
|
-
processFn: _getProcessorFn(req),
|
|
80
|
-
row,
|
|
81
|
-
template
|
|
82
|
-
}
|
|
83
|
-
templateProcessor(args)
|
|
84
|
-
}
|
|
75
|
+
template.process(data, _getProcessorFn(req))
|
|
85
76
|
|
|
86
77
|
// REVISIT: req.data should point into req.query
|
|
87
78
|
setDataFromCQN(req)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const getTemplate = require('./template')
|
|
2
|
-
const templateProcessor = require('./templateProcessor')
|
|
3
2
|
|
|
4
3
|
// convert the standard base64 encoding to the URL-safe variant
|
|
5
4
|
const toBase64url = value => {
|
|
@@ -49,12 +48,7 @@ const _processorFn =
|
|
|
49
48
|
|
|
50
49
|
const _processBinaryData = (data, srv, definition, toBuffer) => {
|
|
51
50
|
const template = getTemplate('rest-payload', srv, definition, { pick: _picker })
|
|
52
|
-
|
|
53
|
-
const rows = Array.isArray(data) ? data : [data]
|
|
54
|
-
for (const row of rows) {
|
|
55
|
-
templateProcessor({ processFn: _processorFn(toBuffer), row, template })
|
|
56
|
-
}
|
|
57
|
-
}
|
|
51
|
+
template.process(data, _processorFn(toBuffer))
|
|
58
52
|
}
|
|
59
53
|
|
|
60
54
|
const base64ToBuffer = (data, srv, definition) => {
|
|
@@ -95,7 +95,7 @@ const _newNestedData = (queryTarget, newData, ref, value) => {
|
|
|
95
95
|
|
|
96
96
|
for (let i = 0; i < ref.length; i++) {
|
|
97
97
|
currentEntity = currentEntity.elements[ref[i]]
|
|
98
|
-
if (currentEntity.isAssociation) {
|
|
98
|
+
if (!currentEntity || currentEntity.isAssociation) {
|
|
99
99
|
// > don't follow associations
|
|
100
100
|
break
|
|
101
101
|
} else {
|
|
@@ -510,7 +510,7 @@ const _queryColumns = (target, columns = [], persistenceTable = false, force = f
|
|
|
510
510
|
|
|
511
511
|
// There could be some `where` clause inside `ref` which we don't support yet
|
|
512
512
|
if (!renamed.ref || renamed.ref.some(e => typeof e !== 'string') || renamed.xpr) return res
|
|
513
|
-
if (isTargetAliased) renamed.ref.shift()
|
|
513
|
+
if (isTargetAliased && renamed.ref[0] === from.as) renamed.ref.shift()
|
|
514
514
|
|
|
515
515
|
// If the entity is annotated with the annotation `@cds.persistence.table`
|
|
516
516
|
// and elements aliases exist, the aliases must be used as column references.
|
|
@@ -28,7 +28,7 @@ const search2cqn4sql = (query, model, options = {}) => {
|
|
|
28
28
|
const columnsToBeSearched = computeColumnsToBeSearched(query, entity, alias)
|
|
29
29
|
const expression = columnsToBeSearched?.length
|
|
30
30
|
? searchToLike(cqnSearchPhrase, columnsToBeSearched)
|
|
31
|
-
: [{ val: 0 }, '=', { val: 1 }]
|
|
31
|
+
: [{ val: '0' }, '=', { val: '1' }]
|
|
32
32
|
|
|
33
33
|
// REVISIT: find out here if where or having must be used
|
|
34
34
|
aggregated ? query.having(expression) : query.where(expression)
|
|
@@ -5,7 +5,18 @@ const { isDuplicate } = require('./rewriteAsterisks')
|
|
|
5
5
|
const _addColumn = (name, type, columns, url) => {
|
|
6
6
|
const mediaType = typeof type === 'object' ? { ref: [type['='].replaceAll(/\./g, '_')] } : { val: type }
|
|
7
7
|
const col = {
|
|
8
|
-
xpr: [
|
|
8
|
+
xpr: [
|
|
9
|
+
'case',
|
|
10
|
+
'when',
|
|
11
|
+
{ ref: [name] },
|
|
12
|
+
'=',
|
|
13
|
+
{ val: null },
|
|
14
|
+
'then',
|
|
15
|
+
{ val: null },
|
|
16
|
+
'else',
|
|
17
|
+
{ func: 'coalesce', args: [mediaType, { val: 'application/octet-stream' }] },
|
|
18
|
+
'end'
|
|
19
|
+
],
|
|
9
20
|
as: `${name}@odata.mediaContentType`
|
|
10
21
|
}
|
|
11
22
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const DELIMITER = require('./templateDelimiter')
|
|
2
2
|
|
|
3
|
+
const templateProcessor = require('./templateProcessor')
|
|
4
|
+
|
|
3
5
|
const _addSubTemplate = (templateElements, elementName, subTemplate) => {
|
|
4
6
|
if (subTemplate.elements.size > 0) {
|
|
5
7
|
const t = templateElements.get(elementName)
|
|
@@ -20,8 +22,8 @@ const _addCacheToTemplateElements = (templateElements, elementName, cached) => {
|
|
|
20
22
|
else templateElements.set(elementName, cached)
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
const _pick = (pick, element, target,
|
|
24
|
-
const _picked = pick(element, target
|
|
25
|
+
const _pick = (pick, element, target, templateElements, elementName) => {
|
|
26
|
+
const _picked = pick(element, target)
|
|
25
27
|
if (_picked) _addToTemplateElements(templateElements, elementName, { plain: _picked })
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -68,14 +70,25 @@ const _getNextTarget = (model, element, currentPath = []) => {
|
|
|
68
70
|
* @param {object} callbacks
|
|
69
71
|
* @param {function} callbacks.pick Callback function to pick elements. If it returns a truthy value, the element will be picked. The returned value is part of the template.
|
|
70
72
|
* @param {function} callbacks.ignore Callback function to ignore the target of an element. If it returns a truthy value, the element's target will be ignored.
|
|
71
|
-
* @param {object} [parent=null] The parent entity
|
|
72
73
|
* @param {Map} [_entityMap] This parameter is an implementation side-effect — don't use it
|
|
73
74
|
* @param {array} [targetPath=[]]
|
|
74
75
|
*/
|
|
75
|
-
function _getTemplate(model, cache, targetEntity, callbacks,
|
|
76
|
+
function _getTemplate(model, cache, targetEntity, callbacks, _entityMap = new Map(), targetPath = []) {
|
|
76
77
|
const { pick, ignore, flatAccess } = callbacks
|
|
77
78
|
const templateElements = new Map()
|
|
78
|
-
const template = {
|
|
79
|
+
const template = {
|
|
80
|
+
target: targetEntity,
|
|
81
|
+
elements: templateElements,
|
|
82
|
+
process(data, fn, pathOptions) {
|
|
83
|
+
templateProcessor({
|
|
84
|
+
processFn: fn,
|
|
85
|
+
data,
|
|
86
|
+
template,
|
|
87
|
+
pathOptions,
|
|
88
|
+
isRoot: true
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
79
92
|
const currentPath = [...targetPath, targetEntity.name]
|
|
80
93
|
_entityMap.set(currentPath.join(DELIMITER), { template })
|
|
81
94
|
const elements = targetEntity.elements || targetEntity.params
|
|
@@ -85,17 +98,17 @@ function _getTemplate(model, cache, targetEntity, callbacks, parent = null, _ent
|
|
|
85
98
|
if (targetEntity._flat2struct) {
|
|
86
99
|
for (const elementName in targetEntity._flat2struct) {
|
|
87
100
|
const element = targetEntity._flat2struct[elementName]
|
|
88
|
-
_pick(pick, element, targetEntity,
|
|
101
|
+
_pick(pick, element, targetEntity, templateElements, elementName)
|
|
89
102
|
}
|
|
90
103
|
}
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
for (const elementName in elements) {
|
|
94
107
|
const element = elements[elementName]
|
|
95
|
-
_pick(pick, element, targetEntity,
|
|
108
|
+
_pick(pick, element, targetEntity, templateElements, elementName)
|
|
96
109
|
|
|
97
110
|
if (element.items) {
|
|
98
|
-
_pick(pick, element.items, targetEntity,
|
|
111
|
+
_pick(pick, element.items, targetEntity, templateElements, ['_itemsOf', elementName].join(DELIMITER))
|
|
99
112
|
}
|
|
100
113
|
|
|
101
114
|
const { nextTargetName, nextTarget } = _getNextTarget(model, element, currentPath)
|
|
@@ -109,10 +122,10 @@ function _getTemplate(model, cache, targetEntity, callbacks, parent = null, _ent
|
|
|
109
122
|
// inline structures must be handled separately.
|
|
110
123
|
let subTemplate
|
|
111
124
|
if (_isInlineStructured(element))
|
|
112
|
-
subTemplate = _getTemplate(model, cache, nextTarget, callbacks,
|
|
125
|
+
subTemplate = _getTemplate(model, cache, nextTarget, callbacks, _entityMap, currentPath)
|
|
113
126
|
else if (cache.has(nextTarget)) subTemplate = cache.get(nextTarget)
|
|
114
127
|
else {
|
|
115
|
-
subTemplate = _getTemplate(model, cache, nextTarget, callbacks,
|
|
128
|
+
subTemplate = _getTemplate(model, cache, nextTarget, callbacks, _entityMap)
|
|
116
129
|
cache.set(nextTarget, subTemplate)
|
|
117
130
|
}
|
|
118
131
|
_addSubTemplate(templateElements, elementName, subTemplate)
|
|
@@ -129,16 +142,13 @@ module.exports = (usecase, tx, target, ...args) => {
|
|
|
129
142
|
const model = tx.model
|
|
130
143
|
if (!model) return
|
|
131
144
|
|
|
132
|
-
const root = model.definitions[target.name] || target
|
|
133
|
-
if (!root) return
|
|
134
|
-
|
|
135
145
|
if (!model._templateCache) Object.defineProperty(model, '_templateCache', { value: new Map() })
|
|
136
146
|
if (!model._templateCache.get(usecase)) model._templateCache.set(usecase, new WeakMap())
|
|
137
147
|
|
|
138
|
-
let tmplt = model._templateCache.get(usecase).get(
|
|
148
|
+
let tmplt = model._templateCache.get(usecase).get(target)
|
|
139
149
|
if (!tmplt) {
|
|
140
|
-
tmplt = _getTemplate(model, model._templateCache.get(usecase),
|
|
141
|
-
model._templateCache.get(usecase).set(
|
|
150
|
+
tmplt = _getTemplate(model, model._templateCache.get(usecase), target, ...args)
|
|
151
|
+
model._templateCache.get(usecase).set(target, tmplt)
|
|
142
152
|
}
|
|
143
153
|
return tmplt
|
|
144
154
|
}
|
|
@@ -48,7 +48,7 @@ const _processComplex = (processFn, row, template, key, pathOptions) => {
|
|
|
48
48
|
|
|
49
49
|
for (const row of rows) {
|
|
50
50
|
if (row == null) continue
|
|
51
|
-
const args = { processFn, row, template, isRoot: false, pathOptions }
|
|
51
|
+
const args = { processFn, data: row, template, isRoot: false, pathOptions }
|
|
52
52
|
|
|
53
53
|
let pathSegmentInfo
|
|
54
54
|
if (pathOptions.includeKeyValues) {
|
|
@@ -63,12 +63,13 @@ const _processComplex = (processFn, row, template, key, pathOptions) => {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
const templateProcessor = ({ processFn, data, template, isRoot = true, pathOptions = {} }) => {
|
|
67
|
+
if (!template || !template.elements.size || !data || typeof data !== 'object') return
|
|
68
|
+
const dataArr = Array.isArray(data) ? data : [data]
|
|
69
|
+
for (const row of dataArr) {
|
|
70
|
+
for (const [tKey, tValue] of template.elements) {
|
|
71
|
+
_processRow(processFn, row, template, tKey, tValue, isRoot, pathOptions)
|
|
72
|
+
}
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const getError = require('../error')
|
|
3
3
|
const getTemplate = require('./template')
|
|
4
|
-
const templateProcessor = require('./templateProcessor')
|
|
5
4
|
const IS_PROXY = Symbol('flat2structProxy')
|
|
6
5
|
|
|
7
6
|
const proxifyIfFlattened = (definition, payload) => {
|
|
@@ -106,10 +105,8 @@ function convertStructured(service, definition, data, { cleanupNull = false, cle
|
|
|
106
105
|
const template = getTemplate('universal-input', service, definition, { pick: _picker, flatAccess })
|
|
107
106
|
const arrayData = Array.isArray(data) ? data : [data]
|
|
108
107
|
if (template && template.elements.size) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
templateProcessor({ processFn: _processor, row, template })
|
|
112
|
-
}
|
|
108
|
+
const _data = arrayData.map(d => proxifyIfFlattened(definition, d))
|
|
109
|
+
template.process(_data, _processor)
|
|
113
110
|
}
|
|
114
111
|
for (const row of arrayData) {
|
|
115
112
|
_cleanup(row, definition, cleanupNull, cleanupStruct, errors)
|
|
@@ -999,6 +999,16 @@ class JoinCQNFromExpanded {
|
|
|
999
999
|
const res = this._buildNewAliasColumn(x, entity, tableAlias, mappings, true)
|
|
1000
1000
|
delete res.as
|
|
1001
1001
|
return res
|
|
1002
|
+
}
|
|
1003
|
+
if (x.func && x.args) {
|
|
1004
|
+
x.args = x.args.map(arg => {
|
|
1005
|
+
if (arg.ref) {
|
|
1006
|
+
const res = this._buildNewAliasColumn(arg, entity, tableAlias, mappings, true)
|
|
1007
|
+
delete res.as
|
|
1008
|
+
return res
|
|
1009
|
+
} else return arg
|
|
1010
|
+
})
|
|
1011
|
+
return x
|
|
1002
1012
|
} else return x
|
|
1003
1013
|
})
|
|
1004
1014
|
},
|
|
@@ -16,7 +16,6 @@ const normalizeTimeData = require('../utils/normalizeTimeData')
|
|
|
16
16
|
const { enrichDataWithKeysFromWhere } = require('../../common/utils/keys')
|
|
17
17
|
const propagateForeignKeys = require('../../common/utils/propagateForeignKeys')
|
|
18
18
|
const getTemplate = require('../../common/utils/template')
|
|
19
|
-
const templateProcessor = require('../../common/utils/templateProcessor')
|
|
20
19
|
|
|
21
20
|
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
22
21
|
|
|
@@ -220,10 +219,7 @@ function dbGenericInput(req) {
|
|
|
220
219
|
|
|
221
220
|
if (!draft) enrichDataWithKeysFromWhere(req.data, req, this)
|
|
222
221
|
|
|
223
|
-
|
|
224
|
-
for (const row of data) {
|
|
225
|
-
templateProcessor({ processFn: _processorFn(req), row, template })
|
|
226
|
-
}
|
|
222
|
+
template.process(req.data, _processorFn(req))
|
|
227
223
|
}
|
|
228
224
|
|
|
229
225
|
dbGenericInput._initial = true
|