@sap/cds 5.5.5 → 5.6.3
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 +139 -1
- package/apis/services.d.ts +31 -1
- package/app/index.js +22 -11
- package/bin/build/buildTaskFactory.js +1 -1
- package/bin/build/provider/buildTaskProviderInternal.js +1 -1
- package/bin/build/provider/fiori/index.js +1 -1
- package/bin/build/provider/hana/2migration.js +8 -7
- package/bin/build/provider/java-cf/index.js +1 -1
- package/bin/deploy/to-hana/hana.js +1 -17
- package/common.cds +8 -0
- package/lib/compile/to/sql.js +22 -2
- package/lib/connect/bindings.js +2 -1
- package/lib/core/reflect.js +4 -1
- package/lib/env/index.js +180 -42
- package/lib/env/requires.js +16 -1
- package/lib/i18n/localize.js +33 -5
- package/lib/index.js +3 -3
- package/lib/log/format/kibana.js +6 -2
- package/lib/ql/Query.js +1 -0
- package/lib/ql/SELECT.js +15 -8
- package/lib/ql/Whereable.js +5 -0
- package/lib/req/context.js +13 -5
- package/lib/serve/Service-dispatch.js +8 -1
- package/lib/utils/axios.js +7 -0
- package/lib/utils/data.js +1 -1
- package/lib/utils/tests.js +1 -1
- package/libx/_runtime/audit/Service.js +18 -18
- package/libx/_runtime/audit/generic/personal/access.js +1 -1
- package/libx/_runtime/audit/generic/personal/modification.js +3 -2
- package/libx/_runtime/audit/generic/personal/utils.js +23 -63
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +4 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +37 -35
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +3 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +5 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +13 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +84 -34
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +12 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +9 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +8 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectHelper.js +11 -95
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ResourcePathParser.js +17 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +2 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SetResponseHeadersCommand.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +6 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +3 -34
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +3 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +64 -31
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +10 -5
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +1 -3
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +20 -21
- package/libx/_runtime/cds-services/services/utils/columns.js +6 -1
- package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -8
- package/libx/_runtime/cds-services/services/utils/differ.js +7 -26
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -4
- package/libx/_runtime/cds-services/util/assert.js +29 -13
- package/libx/_runtime/cds.js +2 -1
- package/libx/_runtime/common/aspects/Association.js +72 -0
- package/libx/_runtime/common/aspects/any.js +8 -45
- package/libx/_runtime/common/aspects/entity.js +0 -1
- package/libx/_runtime/common/aspects/relation.js +40 -0
- package/libx/_runtime/common/aspects/utils.js +73 -1
- package/libx/_runtime/common/auth/strategies/utils/uaa.js +10 -14
- package/libx/_runtime/common/composition/data.js +3 -2
- package/libx/_runtime/common/composition/delete.js +3 -1
- package/libx/_runtime/common/composition/tree.js +23 -18
- package/libx/_runtime/common/composition/update.js +9 -1
- package/libx/_runtime/common/composition/utils.js +34 -8
- package/libx/_runtime/common/error/frontend.js +6 -1
- package/libx/_runtime/common/generic/auth.js +5 -9
- package/libx/_runtime/common/generic/crud.js +2 -2
- package/libx/_runtime/common/generic/etag.js +11 -8
- package/libx/_runtime/common/generic/input.js +3 -3
- package/libx/_runtime/common/generic/paging.js +9 -5
- package/libx/_runtime/common/generic/put.js +3 -2
- package/libx/_runtime/common/generic/sorting.js +3 -3
- package/libx/_runtime/common/generic/temporal.js +3 -3
- package/libx/_runtime/common/utils/cqn.js +20 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +125 -139
- package/libx/_runtime/common/utils/csn.js +50 -52
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +41 -176
- package/libx/_runtime/common/utils/generateOnCond.js +40 -70
- package/libx/_runtime/common/utils/{enrichWithKeysFromWhere.js → keys.js} +29 -28
- package/libx/_runtime/common/utils/postProcessing.js +3 -0
- package/libx/_runtime/common/utils/propagateForeignKeys.js +84 -0
- package/libx/_runtime/common/utils/resolveStructured.js +1 -1
- package/libx/_runtime/common/utils/resolveView.js +7 -5
- package/libx/_runtime/common/utils/rewriteAsterisks.js +94 -0
- package/libx/_runtime/common/utils/search2cqn4sql.js +9 -8
- package/libx/_runtime/common/utils/template.js +54 -46
- package/libx/_runtime/db/Service.js +9 -2
- package/libx/_runtime/db/expand/expandCQNToJoin.js +54 -33
- package/libx/_runtime/db/expand/rawToExpanded.js +2 -1
- package/libx/_runtime/db/generic/arrayed.js +13 -28
- package/libx/_runtime/db/generic/create.js +1 -0
- package/libx/_runtime/db/generic/input.js +7 -11
- package/libx/_runtime/db/generic/integrity.js +2 -2
- package/libx/_runtime/db/generic/rewrite.js +2 -5
- package/libx/_runtime/db/generic/update.js +1 -0
- package/libx/_runtime/db/query/read.js +9 -4
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +7 -2
- package/libx/_runtime/db/sql-builder/annotations.js +1 -0
- package/libx/_runtime/db/utils/columns.js +14 -43
- package/libx/_runtime/fiori/generic/activate.js +3 -2
- package/libx/_runtime/fiori/generic/before.js +2 -2
- package/libx/_runtime/fiori/generic/cancel.js +3 -2
- package/libx/_runtime/fiori/generic/delete.js +3 -2
- package/libx/_runtime/fiori/generic/edit.js +3 -3
- package/libx/_runtime/fiori/generic/new.js +2 -2
- package/libx/_runtime/fiori/generic/patch.js +2 -2
- package/libx/_runtime/fiori/generic/prepare.js +2 -2
- package/libx/_runtime/fiori/generic/read.js +45 -63
- package/libx/_runtime/fiori/generic/readOverDraft.js +4 -4
- package/libx/_runtime/fiori/uiflex/extensibility/index.cds +15 -0
- package/libx/_runtime/fiori/uiflex/extensibility/index.js +148 -0
- package/libx/_runtime/fiori/uiflex/handler/transformREAD.js +119 -0
- package/libx/_runtime/fiori/uiflex/handler/transformRESULT.js +43 -0
- package/libx/_runtime/fiori/uiflex/handler/transformWRITE.js +62 -0
- package/libx/_runtime/fiori/uiflex/index.js +35 -0
- package/libx/_runtime/fiori/uiflex/utils.js +78 -0
- package/libx/_runtime/fiori/utils/handler.js +3 -13
- package/libx/_runtime/fiori/utils/where.js +6 -1
- package/libx/_runtime/hana/pool.js +12 -11
- package/libx/_runtime/hana/search2cqn4sql.js +34 -43
- package/libx/_runtime/hana/searchToContains.js +3 -3
- package/libx/_runtime/index.js +5 -2
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +1 -1
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +16 -3
- package/libx/_runtime/messaging/common-utils/connections.js +11 -14
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -1
- package/libx/_runtime/messaging/message-queuing.js +18 -0
- package/libx/_runtime/remote/Service.js +20 -4
- package/libx/_runtime/remote/utils/client-types.d.ts +7 -0
- package/libx/_runtime/remote/utils/client.js +117 -23
- package/libx/_runtime/sqlite/Service.js +2 -2
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +1 -3
- package/libx/gql/GraphQLAdapter.js +33 -0
- package/libx/gql/constants/adapter.js +69 -0
- package/libx/gql/constants/cds.js +18 -0
- package/libx/gql/constants/graphql.js +33 -0
- package/libx/gql/resolvers/crud/create.js +15 -0
- package/libx/gql/resolvers/crud/delete.js +24 -0
- package/libx/gql/resolvers/crud/index.js +6 -0
- package/libx/gql/resolvers/crud/read.js +25 -0
- package/libx/gql/resolvers/crud/update.js +31 -0
- package/libx/gql/resolvers/crud/utils/index.js +36 -0
- package/libx/gql/resolvers/field.js +5 -0
- package/libx/gql/resolvers/index.js +7 -0
- package/libx/gql/resolvers/mutation.js +23 -0
- package/libx/gql/resolvers/parse/ast/enrich.js +51 -0
- package/libx/gql/resolvers/parse/ast/fragment.js +11 -0
- package/libx/gql/resolvers/parse/ast/fromObject.js +39 -0
- package/libx/gql/resolvers/parse/ast/index.js +3 -0
- package/libx/gql/resolvers/parse/ast/meta.js +4 -0
- package/libx/gql/resolvers/parse/ast/variable.js +7 -0
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +42 -0
- package/libx/gql/resolvers/parse/ast2cqn/entries.js +31 -0
- package/libx/gql/resolvers/parse/ast2cqn/index.js +8 -0
- package/libx/gql/resolvers/parse/ast2cqn/limit.js +6 -0
- package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +24 -0
- package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +3 -0
- package/libx/gql/resolvers/parse/ast2cqn/where.js +70 -0
- package/libx/gql/resolvers/parse/utils/index.js +8 -0
- package/libx/gql/resolvers/query.js +13 -0
- package/libx/gql/resolvers/root.js +34 -0
- package/libx/gql/schema/generate.js +18 -0
- package/libx/gql/schema/index.js +5 -0
- package/libx/gql/schema/mutation.js +76 -0
- package/libx/gql/schema/query.js +108 -0
- package/libx/gql/schema/typeDefMap.js +45 -0
- package/libx/gql/schema/utils/index.js +54 -0
- package/libx/gql/utils/index.js +12 -0
- package/libx/{_runtime/odata/cqn2odata.js → odata/cqn2odata/index.js} +39 -100
- package/libx/odata/index.js +80 -0
- package/libx/odata/odata2cqn/afterburner.js +170 -0
- package/libx/{_runtime/odata/odata2cqn.pegjs → odata/odata2cqn/grammar.pegjs} +102 -123
- package/libx/odata/odata2cqn/index.js +3 -0
- package/libx/odata/odata2cqn/parser.js +1 -0
- package/libx/odata/utils/index.js +64 -0
- package/libx/rest/RestAdapter.js +101 -0
- package/libx/rest/RestRequest.js +30 -0
- package/libx/rest/index.js +3 -0
- package/libx/rest/middleware/auth.js +22 -0
- package/libx/rest/middleware/content.js +15 -0
- package/libx/rest/middleware/create.js +40 -0
- package/libx/rest/middleware/delete.js +20 -0
- package/libx/rest/middleware/error.js +56 -0
- package/libx/rest/middleware/operation.js +39 -0
- package/libx/rest/middleware/parse.js +90 -0
- package/libx/rest/middleware/read.js +29 -0
- package/libx/rest/middleware/update.js +42 -0
- package/libx/rest/utils/data.js +65 -0
- package/package.json +4 -1
- package/server.js +29 -7
- package/libx/_runtime/cds-services/services/utils/diff.js +0 -53
- package/libx/_runtime/cds-services/util/auditlog.js +0 -247
- package/libx/_runtime/cds-services/util/xsenv.js +0 -51
- package/libx/_runtime/common/utils/backlinks.js +0 -83
- package/libx/_runtime/common/utils/rewriteAsterisk.js +0 -72
- package/libx/_runtime/odata/index.js +0 -55
- package/libx/_runtime/odata/odata2cqn.js +0 -1
- package/libx/_runtime/odata/readToCqn.js +0 -129
- package/libx/_runtime/remote/cqn2odata/index.js +0 -2
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// global.cds is used on purpose here!
|
|
2
|
+
const cds = global.cds
|
|
3
|
+
|
|
4
|
+
const ODATA_CONTAINED = '@odata.contained'
|
|
5
|
+
|
|
6
|
+
const { isSelfManaged, isBacklink, getAnchor, getBacklink } = require('./utils')
|
|
7
|
+
const { foreignKeyPropagations } = require('../utils/foreignKeyPropagations')
|
|
8
|
+
|
|
9
|
+
module.exports = class {
|
|
10
|
+
get _isAssociationStrict() {
|
|
11
|
+
return (
|
|
12
|
+
this.own('__isAssociationStrict') ||
|
|
13
|
+
this.set('__isAssociationStrict', !!(this.isAssociation && !this.isComposition))
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get _isAssociationEffective() {
|
|
18
|
+
return (
|
|
19
|
+
this.own('__isAssociationEffective') ||
|
|
20
|
+
this.set(
|
|
21
|
+
'__isAssociationEffective',
|
|
22
|
+
this._isAssociationStrict && (!this[ODATA_CONTAINED] || this.name === 'DraftAdministrativeData')
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get _isCompositionEffective() {
|
|
28
|
+
return (
|
|
29
|
+
this.own('__isCompositionEffective') ||
|
|
30
|
+
this.set(
|
|
31
|
+
'__isCompositionEffective',
|
|
32
|
+
this.isComposition ||
|
|
33
|
+
(this._isAssociationStrict && this[ODATA_CONTAINED] && this.name !== 'DraftAdministrativeData')
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get _isContained() {
|
|
39
|
+
return (
|
|
40
|
+
this.own('__isContained') ||
|
|
41
|
+
this.set(
|
|
42
|
+
'__isContained',
|
|
43
|
+
this.name !== 'DraftAdministrativeData_DraftUUID' &&
|
|
44
|
+
((this.isAssociation && this[ODATA_CONTAINED]) || (this.isComposition && cds.env.effective.odata.containment))
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get _isSelfManaged() {
|
|
50
|
+
return this.own('__isSelfManaged') || this.set('__isSelfManaged', isSelfManaged(this))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get _isBacklink() {
|
|
54
|
+
return this.own('__isBacklink') || this.set('__isBacklink', isBacklink(this))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get _isCompositionBacklink() {
|
|
58
|
+
return this.own('__isCompositionBacklink') || this.set('__isCompositionBacklink', isBacklink(this, true))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get _anchor() {
|
|
62
|
+
return this.own('__anchor') || this.set('__anchor', getAnchor(this))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get _backlink() {
|
|
66
|
+
return this.own('__backlink') || this.set('__backlink', getBacklink(this))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get _foreignKeys() {
|
|
70
|
+
return this.own('__foreignKeys') || this.set('__foreignKeys', foreignKeyPropagations(this))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,54 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
const cds = global.cds
|
|
3
|
-
|
|
4
|
-
const ODATA_CONTAINED = '@odata.contained'
|
|
5
|
-
|
|
6
|
-
const { isMandatory, isReadOnly } = require('./utils')
|
|
1
|
+
const { getRelations, isMandatory, isReadOnly } = require('./utils')
|
|
7
2
|
|
|
3
|
+
// NOTE: Please only add things which are relevant to _any_ type,
|
|
4
|
+
// use specialized types otherwise (entity, Association, ...).
|
|
8
5
|
module.exports = class {
|
|
9
|
-
get _isAssociationStrict() {
|
|
10
|
-
return (
|
|
11
|
-
this.own('__isAssociationStrict') ||
|
|
12
|
-
this.set('__isAssociationStrict', !!(this.isAssociation && !this.isComposition))
|
|
13
|
-
)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
get _isAssociationEffective() {
|
|
17
|
-
return (
|
|
18
|
-
this.own('__isAssociationEffective') ||
|
|
19
|
-
this.set(
|
|
20
|
-
'__isAssociationEffective',
|
|
21
|
-
this._isAssociationStrict && (!this[ODATA_CONTAINED] || this.name === 'DraftAdministrativeData')
|
|
22
|
-
)
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get _isCompositionEffective() {
|
|
27
|
-
return (
|
|
28
|
-
this.own('__isCompositionEffective') ||
|
|
29
|
-
this.set(
|
|
30
|
-
'__isCompositionEffective',
|
|
31
|
-
this.isComposition ||
|
|
32
|
-
(this._isAssociationStrict && this[ODATA_CONTAINED] && this.name !== 'DraftAdministrativeData')
|
|
33
|
-
)
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
6
|
get _isStructured() {
|
|
38
7
|
return this.own('__isStructured') || this.set('__isStructured', !!this.elements && this.kind !== 'entity')
|
|
39
8
|
}
|
|
40
9
|
|
|
41
|
-
get _isContained() {
|
|
42
|
-
return (
|
|
43
|
-
this.own('__isContained') ||
|
|
44
|
-
this.set(
|
|
45
|
-
'__isContained',
|
|
46
|
-
this.name !== 'DraftAdministrativeData_DraftUUID' &&
|
|
47
|
-
((this.isAssociation && this[ODATA_CONTAINED]) || (this.isComposition && cds.env.effective.odata.containment))
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
10
|
get _isMandatory() {
|
|
53
11
|
return this.own('__isMandatory') || this.set('__isMandatory', !this.isAssociation && isMandatory(this))
|
|
54
12
|
}
|
|
@@ -56,4 +14,9 @@ module.exports = class {
|
|
|
56
14
|
get _isReadOnly() {
|
|
57
15
|
return this.own('__isReadOnly') || this.set('__isReadOnly', !this.key && isReadOnly(this))
|
|
58
16
|
}
|
|
17
|
+
|
|
18
|
+
// REVISIT: Where to put?
|
|
19
|
+
get _relations() {
|
|
20
|
+
return this.own('__relations') || this.set('__relations', getRelations(this))
|
|
21
|
+
}
|
|
59
22
|
}
|
|
@@ -44,7 +44,6 @@ module.exports = class {
|
|
|
44
44
|
// lazily require on first use
|
|
45
45
|
getSearchableColumns =
|
|
46
46
|
getSearchableColumns || require('../../cds-services/services/utils/columns').getSearchableColumns
|
|
47
|
-
|
|
48
47
|
return this.own('__searchableColumns') || this.set('__searchableColumns', getSearchableColumns(this))
|
|
49
48
|
}
|
|
50
49
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const { getOnCond } = require('../utils/generateOnCond')
|
|
2
|
+
|
|
3
|
+
let initializing = false
|
|
4
|
+
|
|
5
|
+
module.exports = class Relation {
|
|
6
|
+
constructor(csn, path = []) {
|
|
7
|
+
if (!initializing) throw new Error(`Do not new a relation, use 'Relation.to()' instead`)
|
|
8
|
+
Object.defineProperty(this, 'csn', { get: () => csn })
|
|
9
|
+
Object.defineProperty(this, 'path', {
|
|
10
|
+
get: () => path,
|
|
11
|
+
set: _ => {
|
|
12
|
+
path = _
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
if (csn.target) Object.defineProperty(this, 'target', { get: () => csn.target })
|
|
16
|
+
initializing = false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static to(from, name) {
|
|
20
|
+
initializing = true
|
|
21
|
+
if (!name) return new Relation(from)
|
|
22
|
+
return from._elements[name] && new Relation(from._elements[name], [...from.path, name])
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_has(prop) {
|
|
26
|
+
return Reflect.has(this, prop) && !this._elements[prop]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get _elements() {
|
|
30
|
+
if (this.csn.elements) return this.csn.elements
|
|
31
|
+
if (this.csn._target && this.csn._target.elements) return this.csn._target.elements
|
|
32
|
+
// if (csn.targetAspect) relation.elements = model.definitions[csn.targetAspect].elements
|
|
33
|
+
// if (csn.kind = 'type') relation.elements = model.definitions[csn.type].element
|
|
34
|
+
return {}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
join(fromAlias = '', toAlias = '') {
|
|
38
|
+
return getOnCond(this.csn, this.path, { select: fromAlias, join: toAlias })
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const Relation = require('./relation')
|
|
2
|
+
|
|
1
3
|
const CommonFieldControl = e => {
|
|
2
4
|
const cfr = e['@Common.FieldControl']
|
|
3
5
|
return cfr && cfr['#']
|
|
@@ -65,10 +67,80 @@ const hasSensitiveData = entity => {
|
|
|
65
67
|
return val
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
const _exposeRelation = relation => Object.defineProperty({}, '_', { get: () => relation })
|
|
71
|
+
|
|
72
|
+
const _relationHandler = relation => ({
|
|
73
|
+
get: (target, name) => {
|
|
74
|
+
const path = name.split(',')
|
|
75
|
+
const prop = path.join('_')
|
|
76
|
+
if (!target[prop]) {
|
|
77
|
+
if (path.length === 1) {
|
|
78
|
+
// REVISIT: property 'join' must not be used in CSN to make this working
|
|
79
|
+
if (relation._has(prop)) return relation[prop]
|
|
80
|
+
const newRelation = Relation.to(relation, prop)
|
|
81
|
+
if (newRelation) {
|
|
82
|
+
target[prop] = new Proxy(_exposeRelation(newRelation), _relationHandler(newRelation))
|
|
83
|
+
}
|
|
84
|
+
return target[prop]
|
|
85
|
+
}
|
|
86
|
+
target[prop] = path.reduce((r, p) => r[p] || r.csn._relations[p], relation)
|
|
87
|
+
target[prop].path = path
|
|
88
|
+
}
|
|
89
|
+
return target[prop]
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const getRelations = e => {
|
|
94
|
+
const newRelation = Relation.to(e)
|
|
95
|
+
return new Proxy(_exposeRelation(newRelation), _relationHandler(newRelation))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const _hasJoinCondition = e => e.isAssociation && e.on && e.on.length > 2
|
|
99
|
+
|
|
100
|
+
const _isSelfRef = e => e.ref && e.ref[0] === '$self'
|
|
101
|
+
|
|
102
|
+
const _getBacklinkName = on => {
|
|
103
|
+
const i = on.findIndex(_isSelfRef)
|
|
104
|
+
if (i === -1) return
|
|
105
|
+
let ref
|
|
106
|
+
if (on[i + 1] && on[i + 1] === '=') ref = on[i + 2].ref
|
|
107
|
+
if (on[i - 1] && on[i - 1] === '=') ref = on[i - 2].ref
|
|
108
|
+
return ref && ref[ref.length - 1]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const isSelfManaged = e => {
|
|
112
|
+
if (!_hasJoinCondition(e)) return
|
|
113
|
+
return !!e.on.find(_isSelfRef)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const isBacklink = (e, checkComposition) => getAnchor(e, checkComposition) && true
|
|
117
|
+
|
|
118
|
+
const _isUnManagedAssociation = (e, checkComposition) =>
|
|
119
|
+
e.isAssociation && (!checkComposition || e._isCompositionEffective) && _hasJoinCondition(e)
|
|
120
|
+
|
|
121
|
+
const getAnchor = (e, checkComposition) => {
|
|
122
|
+
if (!(e._isAssociationStrict && (e.keys || e.on))) return
|
|
123
|
+
for (const anchor of Object.values(e._target.associations || {})) {
|
|
124
|
+
if (!_isUnManagedAssociation(anchor, checkComposition)) continue
|
|
125
|
+
if (_getBacklinkName(anchor.on) === e.name && anchor.target === e.parent.name) return anchor
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const getBacklink = (e, checkComposition) => {
|
|
130
|
+
if (!_isUnManagedAssociation(e, checkComposition)) return
|
|
131
|
+
const backlinkName = _getBacklinkName(e.on)
|
|
132
|
+
if (backlinkName) return e._target && e._target.elements && e._target.elements[backlinkName]
|
|
133
|
+
}
|
|
134
|
+
|
|
68
135
|
module.exports = {
|
|
69
136
|
isMandatory,
|
|
70
137
|
isReadOnly,
|
|
71
138
|
getETag,
|
|
72
139
|
hasPersonalData,
|
|
73
|
-
hasSensitiveData
|
|
140
|
+
hasSensitiveData,
|
|
141
|
+
getRelations,
|
|
142
|
+
isSelfManaged,
|
|
143
|
+
isBacklink,
|
|
144
|
+
getAnchor,
|
|
145
|
+
getBacklink
|
|
74
146
|
}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
const cds = require('../../../../cds')
|
|
2
2
|
|
|
3
|
-
const _require = require('../../../utils/require')
|
|
4
|
-
|
|
5
3
|
const getCredentials = uaa => {
|
|
6
|
-
uaa =
|
|
4
|
+
uaa =
|
|
5
|
+
uaa && uaa.credentials
|
|
6
|
+
? uaa
|
|
7
|
+
: cds.env.requires.uaa && cds.env.requires.uaa.credentials
|
|
8
|
+
? cds.env.requires.uaa
|
|
9
|
+
: cds.env.requires.xsuaa && cds.env.requires.xsuaa.credentials
|
|
10
|
+
? cds.env.requires.xsuaa
|
|
11
|
+
: {}
|
|
7
12
|
|
|
8
|
-
if (!uaa.credentials)
|
|
9
|
-
|
|
10
|
-
const vcap = cds.env.requires.uaa && cds.env.requires.uaa.vcap
|
|
11
|
-
uaa.credentials = _require('@sap/xsenv').serviceCredentials(vcap || { label: 'xsuaa' })
|
|
12
|
-
} catch (e) {
|
|
13
|
-
const msg =
|
|
14
|
-
'Unable to get xsuaa credentials. Please make sure your app is bound to a single xsuaa service instance or that you provide vcap information in the requires.uaa section.'
|
|
15
|
-
// REVISIT: switch to verror
|
|
16
|
-
throw Object.assign(new Error(msg), { original: e })
|
|
17
|
-
}
|
|
18
|
-
}
|
|
13
|
+
if (!uaa.credentials)
|
|
14
|
+
throw Object.assign(new Error('No or malformed uaa credentials'), { credentials: uaa.credentials })
|
|
19
15
|
|
|
20
16
|
return uaa.credentials
|
|
21
17
|
}
|
|
@@ -4,8 +4,9 @@ const { getEntityNameFromUpdateCQN } = require('../utils/cqn')
|
|
|
4
4
|
|
|
5
5
|
const { ensureNoDraftsSuffix } = require('../utils/draft')
|
|
6
6
|
const { getDBTable } = require('../utils/resolveView')
|
|
7
|
-
const cqn2cqn4sql = require('../utils/cqn2cqn4sql')
|
|
7
|
+
const { cqn2cqn4sql } = require('../utils/cqn2cqn4sql')
|
|
8
8
|
const cds = require('../../cds')
|
|
9
|
+
const { SELECT } = cds.ql
|
|
9
10
|
|
|
10
11
|
/*
|
|
11
12
|
* own utils
|
|
@@ -192,7 +193,7 @@ const _select = ({
|
|
|
192
193
|
}) => {
|
|
193
194
|
const entity = definitions && definitions[entityName]
|
|
194
195
|
const from = ctUtils.addDraftSuffix(draft, entity.name)
|
|
195
|
-
const selectCQN =
|
|
196
|
+
const selectCQN = SELECT.from(from)
|
|
196
197
|
if (alias) selectCQN.SELECT.from.as = alias
|
|
197
198
|
const selectAll = includeAllColumns || (includeAllRootColumns && root)
|
|
198
199
|
selectCQN.SELECT.columns = _columns(entity, data, compositionTree, selectAll)
|
|
@@ -20,8 +20,10 @@ const _recursivelyAliasRefs = (something, newAlias, oldAlias, subselect = false)
|
|
|
20
20
|
if (oldAlias && something.ref[0] === oldAlias) something.ref[0] = newAlias
|
|
21
21
|
else if (!subselect) something.ref.unshift(newAlias)
|
|
22
22
|
} else {
|
|
23
|
-
for (const key in something)
|
|
23
|
+
for (const key in something) {
|
|
24
|
+
if (key === 'from') continue // Workaround: Deep delete to be rewritten
|
|
24
25
|
_recursivelyAliasRefs(something[key], newAlias, oldAlias, subselect || key === 'SELECT')
|
|
26
|
+
}
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
|
|
3
|
-
const { isSelfManaged, isBacklink } = require('../utils/backlinks')
|
|
4
|
-
|
|
5
3
|
const { ensureNoDraftsSuffix } = require('../utils/draft')
|
|
6
4
|
const { isRootEntity } = require('../utils/csn')
|
|
7
5
|
const { getTransition, getDBTable } = require('../utils/resolveView')
|
|
8
6
|
|
|
9
|
-
const { foreignKeyPropagations } = require('../utils/foreignKeyPropagations')
|
|
10
|
-
|
|
11
7
|
const getError = require('../../common/error')
|
|
12
8
|
|
|
13
9
|
/*
|
|
@@ -15,21 +11,25 @@ const getError = require('../../common/error')
|
|
|
15
11
|
*/
|
|
16
12
|
|
|
17
13
|
const _foreignKeysToLinks = (element, inverse) =>
|
|
18
|
-
|
|
14
|
+
element._foreignKeys.map(e => {
|
|
19
15
|
e = inverse
|
|
20
16
|
? {
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
childElement: e.parentElement,
|
|
18
|
+
parentElement: e.childElement,
|
|
23
19
|
childFieldValue: e.parentFieldValue,
|
|
24
20
|
parentFieldValue: e.childFieldValue,
|
|
25
21
|
prefix: e.prefix
|
|
26
22
|
}
|
|
27
23
|
: e
|
|
28
|
-
const link = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
const link = {}
|
|
25
|
+
if (e.parentElement)
|
|
26
|
+
link.entityKey =
|
|
27
|
+
e.prefix && !e.parentElement.name.includes(e.prefix)
|
|
28
|
+
? `${e.prefix}_${e.parentElement.name}`
|
|
29
|
+
: e.parentElement.name
|
|
30
|
+
if (e.childElement)
|
|
31
|
+
link.targetKey =
|
|
32
|
+
e.prefix && !e.childElement.name.includes(e.prefix) ? `${e.prefix}_${e.childElement.name}` : e.childElement.name
|
|
33
33
|
if (e.parentFieldValue !== undefined) link.entityVal = e.parentFieldValue
|
|
34
34
|
if (e.childFieldValue !== undefined) link.targetVal = e.childFieldValue
|
|
35
35
|
return link
|
|
@@ -57,7 +57,7 @@ const _resolvedElement = (element, service) => {
|
|
|
57
57
|
const _navigationExistsInCompositionMap = (element, compositionMap) =>
|
|
58
58
|
compositionMap.has(element.target) && element._isCompositionEffective
|
|
59
59
|
|
|
60
|
-
const _isUnManaged = element => element.on && !
|
|
60
|
+
const _isUnManaged = element => element.on && !element._isSelfManaged
|
|
61
61
|
|
|
62
62
|
const _isNonRecursiveNavigation = (element, rootEntityName) =>
|
|
63
63
|
rootEntityName !== element.target && element._isCompositionEffective
|
|
@@ -106,7 +106,7 @@ const _getCompositionTreeRec = ({
|
|
|
106
106
|
backLinks: [],
|
|
107
107
|
customBackLinks: []
|
|
108
108
|
})
|
|
109
|
-
if (!
|
|
109
|
+
if (!element._isSelfManaged) {
|
|
110
110
|
const backLinks = _foreignKeysToLinks(element, true) || []
|
|
111
111
|
if (element.is2many) {
|
|
112
112
|
compositionElement.customBackLinks.push(...backLinks)
|
|
@@ -118,7 +118,11 @@ const _getCompositionTreeRec = ({
|
|
|
118
118
|
for (const backLinkName in targetEntity.elements) {
|
|
119
119
|
const _backLink = targetEntity.elements[backLinkName]
|
|
120
120
|
if (!_backLink._isAssociationEffective) continue
|
|
121
|
-
if (
|
|
121
|
+
if (
|
|
122
|
+
_backLink._isCompositionBacklink &&
|
|
123
|
+
_backLink.target === compositionElement.target &&
|
|
124
|
+
_backLink._anchor.name === element.name
|
|
125
|
+
) {
|
|
122
126
|
const backLinks = _foreignKeysToLinks(_backLink) || []
|
|
123
127
|
if (_isUnManaged(element)) {
|
|
124
128
|
compositionElement.customBackLinks.push(...backLinks)
|
|
@@ -131,7 +135,7 @@ const _getCompositionTreeRec = ({
|
|
|
131
135
|
compositionTree.compositionElements.push(compositionElement)
|
|
132
136
|
} else if (_isNonRecursiveNavigation(element, rootEntityName)) {
|
|
133
137
|
const subObject = _createSubElement(element, definitions)
|
|
134
|
-
if (!
|
|
138
|
+
if (!element._isSelfManaged) {
|
|
135
139
|
const backLinks = _foreignKeysToLinks(element, true) || []
|
|
136
140
|
if (element.is2many) {
|
|
137
141
|
subObject.customBackLinks.push(...backLinks)
|
|
@@ -151,7 +155,8 @@ const _getCompositionTreeRec = ({
|
|
|
151
155
|
})
|
|
152
156
|
} else if (
|
|
153
157
|
element._isAssociationEffective &&
|
|
154
|
-
|
|
158
|
+
element._isCompositionBacklink &&
|
|
159
|
+
element.target === compositionTree.target &&
|
|
155
160
|
compositionMap.has(element.target)
|
|
156
161
|
) {
|
|
157
162
|
const backLinks = _foreignKeysToLinks(element) || []
|
|
@@ -218,7 +223,7 @@ const _cacheCompositionParentsOfOne = ({ definitions }) => {
|
|
|
218
223
|
if (!parent.kind === 'entity' || !parent.elements) continue
|
|
219
224
|
for (const elementName in parent.elements) {
|
|
220
225
|
const element = parent.elements[elementName]
|
|
221
|
-
if (element._isCompositionEffective && element.is2one && !
|
|
226
|
+
if (element._isCompositionEffective && element.is2one && !element._isSelfManaged) {
|
|
222
227
|
const targetName = element.target
|
|
223
228
|
const target = definitions[targetName]
|
|
224
229
|
if (!target) continue
|
|
@@ -205,11 +205,19 @@ function _addSubDeepUpdateCQNRecursion({ definitions, compositionTree, entity, d
|
|
|
205
205
|
const selectSubData = []
|
|
206
206
|
for (const entry of data) {
|
|
207
207
|
if (element.name in entry) {
|
|
208
|
-
_addToData(subData, entity, element, entry)
|
|
209
208
|
const selectEntry = selectDataByKey.get(_serializedKey(entity, entry))
|
|
209
|
+
|
|
210
210
|
if (selectEntry && element.name in selectEntry) {
|
|
211
|
+
if (
|
|
212
|
+
selectEntry[element.name] === null &&
|
|
213
|
+
(entry[element.name] === null || Object.keys(entry[element.name]).length === 0)
|
|
214
|
+
) {
|
|
215
|
+
continue
|
|
216
|
+
}
|
|
211
217
|
_addToData(selectSubData, entity, element, selectEntry)
|
|
212
218
|
}
|
|
219
|
+
|
|
220
|
+
_addToData(subData, entity, element, entry)
|
|
213
221
|
}
|
|
214
222
|
}
|
|
215
223
|
_addSubDeepUpdateCQN({
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const { isSelfManaged } = require('../utils/backlinks')
|
|
2
|
-
|
|
3
1
|
const { ensureNoDraftsSuffix, ensureDraftsSuffix } = require('../utils/draft')
|
|
4
2
|
|
|
5
3
|
const addDraftSuffix = (draft, name) => {
|
|
@@ -24,6 +22,7 @@ const keyElements = entity => {
|
|
|
24
22
|
|
|
25
23
|
const key = (entity, data) => {
|
|
26
24
|
return keyElements(entity).reduce((result, element) => {
|
|
25
|
+
if (element.name === 'IsActiveEntity' && !Object.prototype.hasOwnProperty.call(data, element.name)) return result
|
|
27
26
|
result[element.name] = data[element.name]
|
|
28
27
|
return result
|
|
29
28
|
}, {})
|
|
@@ -33,10 +32,6 @@ const val = element => (element && element.val) || element
|
|
|
33
32
|
|
|
34
33
|
const array = x => (Array.isArray(x) ? x : [x])
|
|
35
34
|
|
|
36
|
-
const isManaged = element => {
|
|
37
|
-
return isSelfManaged(element) || !element.on
|
|
38
|
-
}
|
|
39
|
-
|
|
40
35
|
const isCompOrAssoc = (entity, k, onlyToOne) => {
|
|
41
36
|
return (
|
|
42
37
|
entity.elements &&
|
|
@@ -60,6 +55,37 @@ const cleanDeepData = (entity, data, onlyToOne = false) => {
|
|
|
60
55
|
})
|
|
61
56
|
}
|
|
62
57
|
|
|
58
|
+
const _getBacklinkNameFromOnCond = element => {
|
|
59
|
+
if (element.on && element.on.length === 3 && element.on[0].ref && element.on[2].ref) {
|
|
60
|
+
if (element.on[0].ref[0] === '$self') {
|
|
61
|
+
return element.on[2].ref[element.on[2].ref.length - 1]
|
|
62
|
+
} else if (element.on[2].ref[0] === '$self') {
|
|
63
|
+
return element.on[0].ref[element.on[0].ref.length - 1]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const isBacklink = (element, parent, checkContained, backLinkName) => {
|
|
69
|
+
if (!element._isAssociationStrict) return false
|
|
70
|
+
if (!parent || !(element.keys || element.on)) return false
|
|
71
|
+
if (element.target !== parent.name) return false
|
|
72
|
+
|
|
73
|
+
const _isBackLink = parentElement =>
|
|
74
|
+
(!checkContained || parentElement._isContained) && _getBacklinkNameFromOnCond(parentElement) === element.name
|
|
75
|
+
|
|
76
|
+
if (backLinkName) {
|
|
77
|
+
const parentElement = parent.elements[backLinkName]
|
|
78
|
+
return parentElement.isAssociation && _isBackLink(parentElement)
|
|
79
|
+
}
|
|
80
|
+
for (const parentElementName in parent.elements) {
|
|
81
|
+
const parentElement = parent.elements[parentElementName]
|
|
82
|
+
if (!parentElement.isAssociation) continue
|
|
83
|
+
if (_isBackLink(parentElement)) return true
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return false
|
|
87
|
+
}
|
|
88
|
+
|
|
63
89
|
module.exports = {
|
|
64
90
|
addDraftSuffix,
|
|
65
91
|
whereKey,
|
|
@@ -67,7 +93,7 @@ module.exports = {
|
|
|
67
93
|
key,
|
|
68
94
|
val,
|
|
69
95
|
array,
|
|
70
|
-
isManaged,
|
|
71
96
|
isCompOrAssoc,
|
|
72
|
-
cleanDeepData
|
|
97
|
+
cleanDeepData,
|
|
98
|
+
isBacklink
|
|
73
99
|
}
|
|
@@ -22,6 +22,8 @@ const {
|
|
|
22
22
|
MAX_SEVERITY
|
|
23
23
|
} = require('./constants')
|
|
24
24
|
|
|
25
|
+
const SKIP_SANITIZATION = '@cds.skip_sanitization'
|
|
26
|
+
|
|
25
27
|
const _getFiltered = err => {
|
|
26
28
|
const error = {}
|
|
27
29
|
|
|
@@ -103,10 +105,13 @@ const normalizeError = (err, req) => {
|
|
|
103
105
|
// make sure it's a number
|
|
104
106
|
statusCode = statusCode ? Number(statusCode) : 500
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
// REVISIT: make === 500 in cds^6
|
|
109
|
+
// error[SKIP_SANITIZATION] is not an official API!!!
|
|
110
|
+
if (statusCode >= 500 && process.env.NODE_ENV === 'production' && !error[SKIP_SANITIZATION]) {
|
|
107
111
|
// > return sanitized error to client
|
|
108
112
|
return { error: { code: `${statusCode}`, message: i18n(statusCode, locale) }, statusCode }
|
|
109
113
|
}
|
|
114
|
+
delete error[SKIP_SANITIZATION]
|
|
110
115
|
|
|
111
116
|
// no top level null codes
|
|
112
117
|
if (error.code === 'null') {
|
|
@@ -6,7 +6,7 @@ const cds = require('../../cds')
|
|
|
6
6
|
const { SELECT } = cds.ql
|
|
7
7
|
|
|
8
8
|
const { getRequiresAsArray } = require('../utils/auth')
|
|
9
|
-
const cqn2cqn4sql = require('../utils/cqn2cqn4sql')
|
|
9
|
+
const { cqn2cqn4sql } = require('../utils/cqn2cqn4sql')
|
|
10
10
|
const { isActiveEntityRequested, removeIsActiveEntityRecursively } = require('../../fiori/utils/where')
|
|
11
11
|
const { ensureDraftsSuffix } = require('../../fiori/utils/handler')
|
|
12
12
|
|
|
@@ -888,19 +888,15 @@ const _secureDependentEntities = srv => {
|
|
|
888
888
|
}
|
|
889
889
|
}
|
|
890
890
|
|
|
891
|
-
module.exports = function () {
|
|
892
|
-
|
|
893
|
-
* @restrict, @requires, @readonly, @insertonly, and @Capabilities for entities
|
|
894
|
-
*/
|
|
891
|
+
module.exports = cds.service.impl(function () {
|
|
892
|
+
// @restrict, @requires, @readonly, @insertonly, and @Capabilities for entities
|
|
895
893
|
_secureDependentEntities(this)
|
|
896
894
|
for (const k in this.entities) {
|
|
897
895
|
const entity = this.entities[k]
|
|
898
896
|
if (!_authDependsOnParents(entity)) _registerAuthHandlers(entity, this)
|
|
899
897
|
}
|
|
900
898
|
|
|
901
|
-
|
|
902
|
-
* @restrict and @requires for operations
|
|
903
|
-
*/
|
|
899
|
+
// @restrict and @requires for operations
|
|
904
900
|
for (const k in this.operations) {
|
|
905
901
|
const operation = this.operations[k]
|
|
906
902
|
|
|
@@ -910,4 +906,4 @@ module.exports = function () {
|
|
|
910
906
|
// @restrict
|
|
911
907
|
_registerOperationRestrictHandlers(operation, this)
|
|
912
908
|
}
|
|
913
|
-
}
|
|
909
|
+
})
|
|
@@ -67,7 +67,7 @@ const _updateReqData = (req, that) => {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
module.exports = function () {
|
|
70
|
+
module.exports = cds.service.impl(function () {
|
|
71
71
|
this.on(['CREATE', 'READ', 'UPDATE', 'DELETE'], '*', async function (req) {
|
|
72
72
|
if (typeof req.query !== 'string' && req.target && req.target._hasPersistenceSkip) {
|
|
73
73
|
req.reject(501, 'PERSISTENCE_SKIP_NO_GENERIC_CRUD', [req.target.name])
|
|
@@ -128,4 +128,4 @@ module.exports = function () {
|
|
|
128
128
|
|
|
129
129
|
return req.data
|
|
130
130
|
})
|
|
131
|
-
}
|
|
131
|
+
})
|
|
@@ -2,9 +2,9 @@ const cds = require('../../cds')
|
|
|
2
2
|
const { SELECT } = cds.ql
|
|
3
3
|
|
|
4
4
|
// REVISIT: draft should not be handled here, e.g., target.name should be adjusted before
|
|
5
|
-
const { isActiveEntityRequested
|
|
5
|
+
const { isActiveEntityRequested } = require('../../fiori/utils/where')
|
|
6
6
|
const { ensureDraftsSuffix } = require('../../fiori/utils/handler')
|
|
7
|
-
const cqn2cqn4sql = require('../../common/utils/cqn2cqn4sql')
|
|
7
|
+
const { cqn2cqn4sql } = require('../../common/utils/cqn2cqn4sql')
|
|
8
8
|
const ODataRequest = require('../../cds-services/adapter/odata-v4/ODataRequest')
|
|
9
9
|
|
|
10
10
|
const C_U_ = {
|
|
@@ -22,10 +22,11 @@ const getSelectCQN = (query, target, model) => {
|
|
|
22
22
|
} else {
|
|
23
23
|
requestTarget = query.DELETE.from
|
|
24
24
|
}
|
|
25
|
+
|
|
26
|
+
const targetName = isActiveEntityRequested(requestTarget.ref[0].where) ? target.name : ensureDraftsSuffix(target.name)
|
|
25
27
|
const cqn = cqn2cqn4sql(SELECT.from(requestTarget), model)
|
|
26
|
-
cqn.SELECT.from.ref[0] = isActiveEntityRequested(cqn.SELECT.where) ? target.name : ensureDraftsSuffix(target.name)
|
|
27
28
|
cqn.columns([target._etag])
|
|
28
|
-
cqn.SELECT.
|
|
29
|
+
cqn.SELECT.from.ref[0] = targetName
|
|
29
30
|
|
|
30
31
|
return cqn
|
|
31
32
|
}
|
|
@@ -60,11 +61,12 @@ const _handler = async function (req) {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
/**
|
|
64
65
|
* handler registration
|
|
66
|
+
*
|
|
65
67
|
*/
|
|
66
68
|
/* istanbul ignore next */
|
|
67
|
-
module.exports = function () {
|
|
69
|
+
module.exports = cds.service.impl(function () {
|
|
68
70
|
_handler._initial = true
|
|
69
71
|
|
|
70
72
|
for (const k in this.entities) {
|
|
@@ -75,8 +77,9 @@ module.exports = function () {
|
|
|
75
77
|
continue
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
//
|
|
80
|
+
// handler for CREATE is registered for backwards compatibility w.r.t. ETag generation
|
|
79
81
|
let events = ['CREATE', 'READ', 'UPDATE', 'DELETE']
|
|
82
|
+
|
|
80
83
|
// if odata and fiori is separated, this will not be needed in the odata version
|
|
81
84
|
if (entity._isDraftEnabled) {
|
|
82
85
|
events = ['READ', 'NEW', 'DELETE', 'PATCH', 'EDIT', 'CANCEL']
|
|
@@ -88,4 +91,4 @@ module.exports = function () {
|
|
|
88
91
|
this.before(action, entity, _handler)
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
|
-
}
|
|
94
|
+
})
|