@sap/cds 7.8.2 → 7.9.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 +37 -0
- package/_i18n/i18n_ar.properties +3 -0
- package/_i18n/i18n_cs.properties +3 -0
- package/_i18n/i18n_da.properties +3 -0
- package/_i18n/i18n_es_MX.properties +3 -0
- package/_i18n/i18n_fi.properties +3 -0
- package/_i18n/i18n_hu.properties +6 -0
- package/_i18n/i18n_ko.properties +3 -0
- package/_i18n/i18n_ms.properties +3 -0
- package/_i18n/i18n_nl.properties +3 -0
- package/_i18n/i18n_no.properties +3 -0
- package/_i18n/i18n_ro.properties +3 -0
- package/_i18n/i18n_sv.properties +3 -0
- package/_i18n/i18n_th.properties +3 -0
- package/_i18n/i18n_tr.properties +6 -0
- package/_i18n/i18n_zh_TW.properties +3 -0
- package/bin/serve.js +5 -5
- package/lib/auth/basic-auth.js +1 -1
- package/lib/compile/cdsc.js +33 -6
- package/lib/compile/etc/_localized.js +14 -7
- package/lib/compile/for/lean_drafts.js +9 -0
- package/lib/compile/to/edm-files.js +116 -0
- package/lib/compile/to/edm.js +8 -1
- package/lib/compile/to/hdbtabledata.js +3 -3
- package/lib/compile/to/sql.js +4 -2
- package/lib/compile/to/yaml.js +22 -21
- package/lib/dbs/cds-deploy.js +5 -6
- package/lib/env/cds-env.js +7 -0
- package/lib/env/cds-requires.js +20 -1
- package/lib/env/defaults.js +21 -5
- package/lib/env/schemas/cds-package.js +1 -1
- package/lib/env/schemas/cds-rc.js +85 -4
- package/lib/index.js +1 -1
- package/lib/linked/entities.js +10 -0
- package/lib/linked/models.js +1 -1
- package/lib/plugins.js +1 -1
- package/lib/ql/INSERT.js +17 -3
- package/lib/ql/Query.js +4 -0
- package/lib/ql/infer.js +1 -1
- package/lib/req/request.js +1 -1
- package/lib/srv/cds-serve.js +1 -0
- package/lib/srv/middlewares/cds-context.js +1 -1
- package/lib/srv/protocols/odata-v4.js +5 -6
- package/lib/srv/srv-models.js +9 -2
- package/lib/utils/cds-test.js +2 -0
- package/lib/utils/cds-utils.js +9 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +3 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +22 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +4 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +4 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +38 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +32 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +1 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +0 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +3 -1
- package/libx/_runtime/cds-services/services/utils/compareJson.js +2 -274
- package/libx/_runtime/{cds-services/services → common}/Service.js +39 -29
- package/libx/_runtime/common/generic/auth/autoexpose.js +41 -0
- package/libx/_runtime/common/generic/auth/index.js +2 -0
- package/libx/_runtime/common/generic/auth/readOnly.js +0 -11
- package/libx/_runtime/common/generic/auth/restrict.js +6 -5
- package/libx/_runtime/common/generic/auth/utils.js +1 -1
- package/libx/_runtime/common/generic/crud.js +5 -8
- package/libx/_runtime/common/generic/etag.js +8 -6
- package/libx/_runtime/common/generic/sorting.js +2 -2
- package/libx/_runtime/common/i18n/messages.properties +1 -0
- package/libx/_runtime/{cds-services/services → common}/utils/columns.js +4 -4
- package/libx/_runtime/common/utils/compareJson.js +274 -0
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +1 -1
- package/libx/_runtime/{cds-services/services → common}/utils/differ.js +8 -8
- package/libx/_runtime/common/utils/ensureIEEE754.js +29 -0
- package/libx/_runtime/common/utils/{postProcessing.js → postProcess.js} +1 -3
- package/libx/_runtime/common/utils/resolveView.js +0 -16
- package/libx/_runtime/common/utils/rewriteAsterisks.js +1 -1
- package/libx/_runtime/common/utils/search2cqn4sql.js +1 -1
- package/libx/_runtime/common/utils/streamProp.js +9 -2
- package/libx/_runtime/common/utils/ucsn.js +1 -1
- package/libx/_runtime/db/expand/expandCQNToJoin.js +5 -3
- package/libx/_runtime/db/generic/rewrite.js +7 -13
- package/libx/_runtime/fiori/generic/activate.js +1 -1
- package/libx/_runtime/fiori/generic/edit.js +1 -1
- package/libx/_runtime/fiori/generic/prepare.js +1 -1
- package/libx/_runtime/fiori/lean-draft.js +151 -46
- package/libx/_runtime/fiori/utils/handler.js +1 -1
- package/libx/_runtime/hana/execute.js +6 -2
- package/libx/_runtime/hana/search2cqn4sql.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -2
- package/libx/_runtime/messaging/event-broker.js +212 -0
- package/libx/_runtime/remote/Service.js +9 -32
- package/libx/_runtime/remote/utils/client.js +13 -21
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +7 -1
- package/libx/_runtime/sqlite/execute.js +8 -3
- package/libx/_runtime/ucl/Service.js +259 -0
- package/libx/common/assert/index.js +5 -11
- package/libx/common/assert/validation.js +6 -1
- package/libx/odata/index.js +47 -25
- package/libx/odata/middleware/batch.js +8 -7
- package/libx/odata/middleware/create.js +42 -16
- package/libx/odata/middleware/delete.js +18 -11
- package/libx/odata/middleware/metadata.js +15 -14
- package/libx/odata/middleware/operation.js +30 -40
- package/libx/odata/middleware/parse.js +2 -3
- package/libx/odata/middleware/read.js +59 -52
- package/libx/odata/middleware/service-document.js +7 -7
- package/libx/odata/middleware/stream.js +26 -24
- package/libx/odata/middleware/update.js +53 -92
- package/libx/odata/parse/afterburner.js +45 -47
- package/libx/odata/parse/grammar.peggy +3 -3
- package/libx/odata/parse/multipartToJson.js +10 -22
- package/libx/odata/parse/parser.js +1 -1
- package/libx/odata/utils/etag.js +13 -0
- package/libx/odata/utils/handler.js +120 -0
- package/libx/odata/utils/index.js +15 -2
- package/libx/odata/utils/metaInfo.js +410 -0
- package/libx/odata/utils/path.js +5 -2
- package/libx/odata/utils/readAfterWrite.js +23 -0
- package/libx/odata/utils/result.js +4 -5
- package/libx/rest/RestAdapter.js +4 -13
- package/libx/rest/middleware/parse.js +40 -7
- package/package.json +1 -1
- package/server.js +1 -0
- package/libx/_runtime/cds-services/util/dataProcessUtils.js +0 -93
- package/libx/_runtime/common/utils/thenable.js +0 -51
- package/libx/_runtime/rest/service.js +0 -2
- package/libx/odata/parse/parseToCqn.js +0 -39
- package/libx/rest/middleware/input.js +0 -54
- package/libx/rest/middleware/payload.js +0 -13
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// REVISIT: why do we have processDeep and processDeepAsync?!
|
|
2
|
-
// REVISIT: replace all remaining usages of processDeep/processDeepAsync with new template mechanism
|
|
3
|
-
|
|
4
|
-
const { all } = require('../../common/utils/thenable')
|
|
5
|
-
|
|
6
|
-
const processDeep = (callbackFn, data, entity, skipRoot, isRoot) => {
|
|
7
|
-
if (!Array.isArray(data)) {
|
|
8
|
-
processDeep(callbackFn, [data], entity, skipRoot, isRoot)
|
|
9
|
-
return
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
data.forEach(entry => {
|
|
13
|
-
if (!(skipRoot && isRoot)) {
|
|
14
|
-
callbackFn(entry, entity, isRoot, skipRoot)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
for (const key in entity.elements) {
|
|
18
|
-
const element = entity.elements[key]
|
|
19
|
-
|
|
20
|
-
if (element.isComposition && entry[element.name]) {
|
|
21
|
-
const subData = Array.isArray(entry[element.name]) ? entry[element.name] : [entry[element.name]]
|
|
22
|
-
const subEntity = element._target
|
|
23
|
-
processDeep(callbackFn, subData, subEntity, false, false)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const _deepProcessWithDiffComposition = ({ entry, element, compositionTree, callbackFn }) => {
|
|
30
|
-
const subData = Array.isArray(entry[element.name]) ? entry[element.name] : [entry[element.name]]
|
|
31
|
-
const subEntity = element._target
|
|
32
|
-
const compositionElement = compositionTree.compositionElements.find(({ name }) => name === element.name)
|
|
33
|
-
|
|
34
|
-
processsDeepEnhanced({
|
|
35
|
-
callbackFn,
|
|
36
|
-
data: subData,
|
|
37
|
-
parentEntry: entry,
|
|
38
|
-
entity: subEntity,
|
|
39
|
-
compositionTree: compositionElement
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const processsDeepEnhanced = ({ callbackFn, data, parentEntry, entity, compositionTree }) => {
|
|
44
|
-
if (!Array.isArray(data)) {
|
|
45
|
-
processsDeepEnhanced({ callbackFn, data: [data], parentEntry, entity, compositionTree })
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
data.forEach(entry => {
|
|
50
|
-
callbackFn({ entry, parentEntry, entity, compositionTree })
|
|
51
|
-
|
|
52
|
-
for (const key in entity.elements) {
|
|
53
|
-
const element = entity.elements[key]
|
|
54
|
-
|
|
55
|
-
if (element.isComposition && entry[element.name]) {
|
|
56
|
-
_deepProcessWithDiffComposition({ entry, element, compositionTree, callbackFn })
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const _deeperElements = (callbackFn, entry, elements = {}) => {
|
|
63
|
-
return Object.keys(elements).map(key => {
|
|
64
|
-
const element = elements[key]
|
|
65
|
-
|
|
66
|
-
if (element.isComposition && entry[element.name]) {
|
|
67
|
-
const subData = Array.isArray(entry[element.name]) ? entry[element.name] : [entry[element.name]]
|
|
68
|
-
|
|
69
|
-
return processDeepAsync(callbackFn, subData, element._target, false, false)
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const processDeepAsync = (callbackFn, data, entity, skipRoot, isRoot) => {
|
|
75
|
-
if (!Array.isArray(data)) {
|
|
76
|
-
return processDeepAsync(callbackFn, [data], entity, skipRoot, isRoot)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const deep = data.map(async entry => {
|
|
80
|
-
if (!(skipRoot && isRoot)) {
|
|
81
|
-
await callbackFn(entry, entity, isRoot)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return all(_deeperElements(callbackFn, entry, entity.elements))
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
return all(deep)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
module.exports = {
|
|
91
|
-
processDeep,
|
|
92
|
-
processDeepAsync
|
|
93
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
const _asyncReturn = returned => {
|
|
2
|
-
if (returned && returned.then) {
|
|
3
|
-
return returned
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
return resolvedThenable(returned)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const rejectedThenable = err => {
|
|
10
|
-
return {
|
|
11
|
-
then(resolve, reject) {
|
|
12
|
-
try {
|
|
13
|
-
return reject ? _asyncReturn(reject(err)) : this
|
|
14
|
-
} catch (e) {
|
|
15
|
-
return rejectedThenable(e)
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
catch(reject) {
|
|
19
|
-
try {
|
|
20
|
-
return reject ? _asyncReturn(reject(err)) : this
|
|
21
|
-
} catch (e) {
|
|
22
|
-
return rejectedThenable(e)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const resolvedThenable = value => {
|
|
29
|
-
return {
|
|
30
|
-
then(resolve) {
|
|
31
|
-
try {
|
|
32
|
-
return _asyncReturn(resolve(value))
|
|
33
|
-
} catch (err) {
|
|
34
|
-
return rejectedThenable(err)
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
catch() {
|
|
38
|
-
return this
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const all = arr => {
|
|
44
|
-
return arr.length ? Promise.all(arr) : resolvedThenable([])
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
module.exports = {
|
|
48
|
-
reject: rejectedThenable,
|
|
49
|
-
resolve: resolvedThenable,
|
|
50
|
-
all: all
|
|
51
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
const cds = require('../../../')
|
|
2
|
-
|
|
3
|
-
module.exports = (component, service, target, data, odataReq, upsert) => {
|
|
4
|
-
let query = cds.odata.parse(odataReq, { service })
|
|
5
|
-
|
|
6
|
-
// for concat
|
|
7
|
-
if (component === 'READ' && Array.isArray(query)) return query
|
|
8
|
-
|
|
9
|
-
const _target = query.SELECT && query.SELECT.from
|
|
10
|
-
|
|
11
|
-
const {
|
|
12
|
-
SELECT: { one }
|
|
13
|
-
} = query
|
|
14
|
-
|
|
15
|
-
switch (component) {
|
|
16
|
-
case 'CREATE':
|
|
17
|
-
// create
|
|
18
|
-
// error in cases like `POST Books(1)` i.e. `POST` with navigation to single entity
|
|
19
|
-
if (one && !upsert) cds.error('POST not allowed on entity', { code: 400 })
|
|
20
|
-
return INSERT.into(_target).entries(data)
|
|
21
|
-
case 'DELETE':
|
|
22
|
-
if (!one) cds.error('DELETE not allowed on collection', { code: 400 })
|
|
23
|
-
// eslint-disable-next-line no-case-declarations
|
|
24
|
-
const last = query._propertyAccess || (_target.ref && _target.ref[_target.ref.length - 1])
|
|
25
|
-
if (target.elements[last] || target.elements[query._propertyAccess]) {
|
|
26
|
-
// delete simple property
|
|
27
|
-
const ref = { ref: query._propertyAccess ? _target.ref : _target.ref.slice(0, -1) }
|
|
28
|
-
return UPDATE(ref).data({ [last]: null })
|
|
29
|
-
} else {
|
|
30
|
-
return DELETE.from(_target)
|
|
31
|
-
}
|
|
32
|
-
case 'UPDATE':
|
|
33
|
-
// eslint-disable-next-line no-throw-literal
|
|
34
|
-
if (!one) throw { statusCode: 400, code: '400', message: `INVALID_${odataReq.getMethod()}` }
|
|
35
|
-
return UPDATE(_target).data(data)
|
|
36
|
-
default:
|
|
37
|
-
return query
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// const cds = require('../../_runtime/cds')
|
|
2
|
-
const getTemplate = require('../../_runtime/common/utils/template')
|
|
3
|
-
const templateProcessor = require('../../_runtime/common/utils/templateProcessor')
|
|
4
|
-
const { checkStaticElementByKey } = require('../../_runtime/cds-services/util/assert')
|
|
5
|
-
const { MULTIPLE_ERRORS } = require('../../_runtime/common/error/constants')
|
|
6
|
-
|
|
7
|
-
//
|
|
8
|
-
// REVISIT: We need to decipher what we are doing here...
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
const _picker = () => {
|
|
12
|
-
return element => {
|
|
13
|
-
const categories = {}
|
|
14
|
-
if (Array.isArray(element)) return
|
|
15
|
-
if (element._isStructured || element.isAssociation || element.items) return
|
|
16
|
-
categories['static_validation'] = true
|
|
17
|
-
return categories
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const _processorFn = errors => {
|
|
22
|
-
return ({ row, key, plain: categories, target }) => {
|
|
23
|
-
// REVISIT move validation to generic asserter => see PR 717
|
|
24
|
-
if (categories['static_validation'] && row[key] != null) {
|
|
25
|
-
const validations = checkStaticElementByKey(target, key, row[key])
|
|
26
|
-
errors.push(...validations)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const _cache = req => `rest-input;skip-key-validation:${req.method !== 'POST'}`
|
|
32
|
-
|
|
33
|
-
module.exports = srv => (req, res, next) => {
|
|
34
|
-
const { _query, _data, _operation } = req
|
|
35
|
-
let definition = _operation || _query.__target
|
|
36
|
-
if (typeof definition === 'string') definition = srv.model.definitions[definition] || srv.model.definitions[definition.split(':$:')[0]].actions[definition.split(':$:')[1]]
|
|
37
|
-
|
|
38
|
-
if (!(_data && srv && definition)) return next()
|
|
39
|
-
|
|
40
|
-
const errors = []
|
|
41
|
-
|
|
42
|
-
const template = getTemplate(_cache(req), srv, definition, { pick: _picker(req) })
|
|
43
|
-
if (template && template.elements.size) {
|
|
44
|
-
const rows = Array.isArray(_data) ? _data : [_data]
|
|
45
|
-
for (const row of rows) {
|
|
46
|
-
templateProcessor({ processFn: _processorFn(errors), row, template })
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (errors.length > 1) throw Object.assign(new Error(MULTIPLE_ERRORS), { details: errors })
|
|
51
|
-
if (errors.length === 1) throw errors[0]
|
|
52
|
-
|
|
53
|
-
next()
|
|
54
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const { base64ToBuffer } = require('../../_runtime/common/utils/binary')
|
|
2
|
-
|
|
3
|
-
module.exports = srv => (req, res, next) => {
|
|
4
|
-
const { _query, _data, _operation } = req
|
|
5
|
-
let definition = _operation || _query.__target
|
|
6
|
-
if (typeof definition === 'string') definition = srv.model.definitions[definition] || srv.model.definitions[definition.split(':$:')[0]].actions[definition.split(':$:')[1]]
|
|
7
|
-
|
|
8
|
-
if (!(_data && srv && definition)) return next()
|
|
9
|
-
|
|
10
|
-
base64ToBuffer(_data, srv, definition)
|
|
11
|
-
|
|
12
|
-
next()
|
|
13
|
-
}
|