@sap/cds-compiler 2.15.4 → 3.0.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 +33 -1590
- package/bin/cdsc.js +36 -33
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +3 -4
- package/doc/CHANGELOG_DEPRECATED.md +35 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +220 -103
- package/lib/api/options.js +15 -85
- package/lib/api/validate.js +6 -10
- package/lib/base/keywords.js +216 -109
- package/lib/base/message-registry.js +60 -20
- package/lib/base/messages.js +65 -24
- package/lib/base/model.js +44 -2
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +5 -1
- package/lib/checks/types.js +4 -2
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +2 -1
- package/lib/compiler/assert-consistency.js +15 -10
- package/lib/compiler/builtins.js +87 -9
- package/lib/compiler/define.js +2 -2
- package/lib/compiler/extend.js +59 -11
- package/lib/compiler/finalize-parse-cdl.js +20 -9
- package/lib/compiler/index.js +25 -11
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +13 -13
- package/lib/compiler/propagator.js +3 -3
- package/lib/compiler/resolve.js +193 -218
- package/lib/compiler/shared.js +47 -76
- package/lib/compiler/tweak-assocs.js +9 -10
- package/lib/compiler/utils.js +5 -0
- package/lib/edm/csn2edm.js +18 -21
- package/lib/edm/edmPreprocessor.js +25 -30
- package/lib/edm/edmUtils.js +10 -24
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +8 -30
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +889 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20632 -22313
- package/lib/json/from-csn.js +56 -49
- package/lib/json/to-csn.js +10 -8
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +61 -38
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +303 -229
- package/lib/language/language.g4 +573 -629
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +27 -42
- package/lib/main.js +104 -81
- package/lib/model/csnRefs.js +1 -1
- package/lib/model/csnUtils.js +170 -283
- package/lib/model/revealInternalProperties.js +28 -8
- package/lib/model/sortViews.js +32 -31
- package/lib/optionProcessor.js +12 -21
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +334 -339
- package/lib/render/toHdbcds.js +19 -15
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +53 -51
- package/lib/render/utils/common.js +15 -1
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +3 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +7 -6
- package/lib/transform/db/flattening.js +18 -19
- package/lib/transform/db/views.js +3 -3
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +19 -22
- package/lib/transform/forOdataNew.js +10 -12
- package/lib/transform/localized.js +22 -16
- package/lib/transform/odata/toFinalBaseType.js +10 -10
- package/lib/transform/odata/typesExposure.js +3 -3
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +63 -77
- package/lib/transform/translateAssocsToJoins.js +2 -2
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +11 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
- package/lib/utils/file.js +3 -3
- package/lib/utils/timetrace.js +20 -21
- package/package.json +35 -4
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/fix_antlr4-8_warning.js +0 -56
|
@@ -39,7 +39,7 @@ function tweakAssocs( model ) {
|
|
|
39
39
|
const { environment } = model.$volatileFunctions;
|
|
40
40
|
|
|
41
41
|
// behavior depending on option `deprecated`:
|
|
42
|
-
const enableExpandElements = !isDeprecatedEnabled( options, '
|
|
42
|
+
const enableExpandElements = !isDeprecatedEnabled( options, '_noElementsExpansion' );
|
|
43
43
|
// TODO: we should get rid of noElementsExpansion soon; both
|
|
44
44
|
// beta.nestedProjections and beta.universalCsn do not work with it.
|
|
45
45
|
|
|
@@ -95,15 +95,14 @@ function tweakAssocs( model ) {
|
|
|
95
95
|
if (!target || target._service) // assoc to other service is OK
|
|
96
96
|
return;
|
|
97
97
|
if (!elem.$inferred) { // && !elem.target.$inferred
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
} );
|
|
98
|
+
info( 'assoc-target-not-in-service', [ elem.target.location, elem ],
|
|
99
|
+
{ target, '#': (elem._main.query ? 'select' : 'define') }, {
|
|
100
|
+
std: 'Target $(TARGET) of association is outside any service', // not used
|
|
101
|
+
// eslint-disable-next-line max-len
|
|
102
|
+
define: 'Target $(TARGET) of explicitly defined association is outside any service',
|
|
103
|
+
// eslint-disable-next-line max-len
|
|
104
|
+
select: 'Target $(TARGET) of explicitly selected association is outside any service',
|
|
105
|
+
} );
|
|
107
106
|
}
|
|
108
107
|
else {
|
|
109
108
|
info( 'assoc-outside-service', [ elem.target.location, elem ],
|
package/lib/compiler/utils.js
CHANGED
|
@@ -31,6 +31,10 @@ function annotationVal( anno ) {
|
|
|
31
31
|
function annotationIsFalse( anno ) { // falsy, but not null (unset)
|
|
32
32
|
return anno && (anno.val === false || anno.val === 0 || anno.val === '');
|
|
33
33
|
}
|
|
34
|
+
function annotationHasEllipsis( anno ) {
|
|
35
|
+
const { val } = anno || {};
|
|
36
|
+
return Array.isArray( val ) && val.some( v => v.literal === 'token' && v.val === '...' );
|
|
37
|
+
}
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* Set compiler-calculated annotation value.
|
|
@@ -381,6 +385,7 @@ module.exports = {
|
|
|
381
385
|
pushLink,
|
|
382
386
|
annotationVal,
|
|
383
387
|
annotationIsFalse,
|
|
388
|
+
annotationHasEllipsis,
|
|
384
389
|
annotateWith,
|
|
385
390
|
setLink,
|
|
386
391
|
setArtifactLink,
|
package/lib/edm/csn2edm.js
CHANGED
|
@@ -395,14 +395,14 @@ function csn2edmAll(_csn, _options, serviceNames=undefined) {
|
|
|
395
395
|
{
|
|
396
396
|
const EntityTypeName = entityCsn.name.replace(schemaNamePrefix, '');
|
|
397
397
|
const EntitySetName = edmUtils.getBaseName(entityCsn.$entitySetName || entityCsn.name);
|
|
398
|
-
|
|
398
|
+
const isSingleton = edmUtils.isSingleton(entityCsn) && options.isV4();
|
|
399
399
|
const [ properties, hasStream ] = createProperties(entityCsn);
|
|
400
400
|
|
|
401
401
|
const loc = ['definitions', entityCsn.name];
|
|
402
402
|
const type = `${schema.name}.${EntityTypeName}`;
|
|
403
403
|
if(properties.length === 0)
|
|
404
404
|
warning(null, loc, { type }, 'EDM EntityType $(TYPE) has no properties');
|
|
405
|
-
else if(entityCsn.$edmKeyPaths.length === 0)
|
|
405
|
+
else if(entityCsn.$edmKeyPaths.length === 0 && !isSingleton)
|
|
406
406
|
message('odata-spec-violation-no-key', loc);
|
|
407
407
|
|
|
408
408
|
if(!edmUtils.isODataSimpleIdentifier(EntityTypeName))
|
|
@@ -688,9 +688,7 @@ function csn2edmAll(_csn, _options, serviceNames=undefined) {
|
|
|
688
688
|
if(elementCsn._edmParentCsn == undefined)
|
|
689
689
|
setProp(elementCsn, '_edmParentCsn', edmParentCsn);
|
|
690
690
|
|
|
691
|
-
if(
|
|
692
|
-
if(edmUtils.isAssociationOrComposition(elementCsn))
|
|
693
|
-
{
|
|
691
|
+
if(edmUtils.isAssociationOrComposition(elementCsn)) {
|
|
694
692
|
// Foreign keys are part of the generic elementCsn.elements property creation
|
|
695
693
|
|
|
696
694
|
// This is the V4 edmx:NavigationProperty
|
|
@@ -698,36 +696,35 @@ function csn2edmAll(_csn, _options, serviceNames=undefined) {
|
|
|
698
696
|
|
|
699
697
|
// suppress navprop creation only if @odata.navigable:false is not annotated.
|
|
700
698
|
// (undefined !== false) still evaluates to true
|
|
701
|
-
|
|
699
|
+
if (!elementCsn._target.abstract && elementCsn['@odata.navigable'] !== false)
|
|
702
700
|
{
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
701
|
+
const navProp = new Edm.NavigationProperty(v, {
|
|
702
|
+
Name: elementName,
|
|
703
|
+
Type: elementCsn._target.name
|
|
704
|
+
}, elementCsn);
|
|
705
|
+
props.push(navProp);
|
|
708
706
|
// save the navProp in the global array for late constraint building
|
|
709
|
-
|
|
710
|
-
}
|
|
707
|
+
navigationProperties.push(navProp);
|
|
711
708
|
}
|
|
709
|
+
}
|
|
712
710
|
// render ordinary property if element is NOT ...
|
|
713
711
|
// 1) ... annotated @cds.api.ignore
|
|
714
712
|
// 2) ... annotated @odata.foreignKey4 and odataFormat: structured
|
|
715
713
|
|
|
716
|
-
|
|
714
|
+
else if(isEdmPropertyRendered(elementCsn, options))
|
|
717
715
|
{
|
|
718
716
|
// CDXCORE-CDXCORE-173
|
|
719
717
|
// V2: filter @Core.MediaType
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
718
|
+
if ( options.isV2() && elementCsn['@Core.MediaType']) {
|
|
719
|
+
hasStream = elementCsn['@Core.MediaType'];
|
|
720
|
+
delete elementCsn['@Core.MediaType'];
|
|
723
721
|
// CDXCORE-CDXCORE-177:
|
|
724
722
|
// V2: don't render element but add attribute 'm:HasStream="true' to EntityType
|
|
725
723
|
// V4: render property type 'Edm.Stream'
|
|
726
|
-
|
|
724
|
+
streamProps.push(elementName);
|
|
727
725
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
}
|
|
726
|
+
} else {
|
|
727
|
+
props.push(new Edm.Property(v, { Name: elementName }, elementCsn));
|
|
731
728
|
}
|
|
732
729
|
}
|
|
733
730
|
|
|
@@ -54,6 +54,10 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
54
54
|
fallBackSchemaName,
|
|
55
55
|
whatsMyServiceRootName ] = getAnOverviewOnTheServices(csn);
|
|
56
56
|
|
|
57
|
+
if(serviceRootNames.length === 0) {
|
|
58
|
+
return [serviceRoots, Object.create(null), reqDefs, whatsMyServiceRootName, fallBackSchemaName, options];
|
|
59
|
+
}
|
|
60
|
+
|
|
57
61
|
if(requestedServiceNames === undefined)
|
|
58
62
|
requestedServiceNames = options.serviceNames;
|
|
59
63
|
if(requestedServiceNames === undefined) {
|
|
@@ -64,10 +68,6 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
64
68
|
return requestedServiceNames.includes(whatsMyServiceRootName(n));
|
|
65
69
|
}
|
|
66
70
|
|
|
67
|
-
if(serviceRootNames.length === 0) {
|
|
68
|
-
return [serviceRoots, Object.create(null), reqDefs, whatsMyServiceRootName, fallBackSchemaName, options];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
71
|
// Structural CSN inbound QA checks
|
|
72
72
|
inboundQualificationChecks();
|
|
73
73
|
// not needed at the moment
|
|
@@ -85,7 +85,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
85
85
|
|
|
86
86
|
/*
|
|
87
87
|
Final base type expansion is required here when:
|
|
88
|
-
1) The input CSN was already transformed for V4 but shall be rendered in V2 and the
|
|
88
|
+
1) The input CSN was already transformed for V4 but shall be rendered in V2 and the
|
|
89
89
|
edmx generator is called directly (bypassing OData transformation)
|
|
90
90
|
2) The input CSN was already transformed for V4 and persisted (all non-enumerables are
|
|
91
91
|
stripped of)
|
|
@@ -119,11 +119,6 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
if(schemaNames.length) {
|
|
122
|
-
// First attach names to all definitions (and actions/params) in the model
|
|
123
|
-
// elements are done in initializeStruct
|
|
124
|
-
// Set myServiceName for later reference and indication of a service member
|
|
125
|
-
// First attach names to all definitions in the model and fill reqDefs
|
|
126
|
-
// Link association targets and spray @odata.contained over untagged compositions
|
|
127
122
|
forEachDefinition(csn, [
|
|
128
123
|
attachNameProperty,
|
|
129
124
|
(def, defName) => {
|
|
@@ -307,7 +302,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
307
302
|
const myServiceRoot = whatsMyServiceRootName(defName);
|
|
308
303
|
const mySchemaPrefix = getSchemaPrefix(defName);
|
|
309
304
|
if(myServiceRoot && options.isV4() &&
|
|
310
|
-
/*(options.
|
|
305
|
+
/*(options.odataProxies || options.odataXServiceRefs) && options.isStructFormat && */
|
|
311
306
|
defName !== myServiceRoot && myServiceRoot !== mySchemaPrefix) {
|
|
312
307
|
const service = { kind: 'service', name: mySchemaPrefix };
|
|
313
308
|
serviceRoots[mySchemaPrefix] = service;
|
|
@@ -341,7 +336,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
341
336
|
// link association target to association and add @odata.contained to compositions in V4
|
|
342
337
|
function linkAssociationTarget(struct) {
|
|
343
338
|
forEachMemberRecursively(struct, (element, name, prop, subpath) => {
|
|
344
|
-
if(isAssociationOrComposition(element)
|
|
339
|
+
if(isAssociationOrComposition(element)) {
|
|
345
340
|
if(!element._target) {
|
|
346
341
|
let target = csn.definitions[element.target];
|
|
347
342
|
if(target) {
|
|
@@ -685,7 +680,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
685
680
|
applyAppSpecificLateCsnTransformationOnElement(options, element, def, error);
|
|
686
681
|
}, [], true, { elementsOnly: true });
|
|
687
682
|
|
|
688
|
-
if(!isDeprecatedEnabled(options, '
|
|
683
|
+
if(!isDeprecatedEnabled(options, '_v1KeysForTemporal')) {
|
|
689
684
|
// if artifact has a cds.valid.key mention it as @Core.AlternateKey
|
|
690
685
|
if(validKey.length) {
|
|
691
686
|
let altKeys = [{ Key: [] }];
|
|
@@ -738,7 +733,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
738
733
|
forEachMemberRecursively(def.items || def, initConstraintsOnAssoc, [], true, { elementsOnly: true });
|
|
739
734
|
}
|
|
740
735
|
function initConstraintsOnAssoc(element) {
|
|
741
|
-
if (isAssociationOrComposition(element) && !element.
|
|
736
|
+
if (isAssociationOrComposition(element) && !element._constraints) {
|
|
742
737
|
// setup the constraints object
|
|
743
738
|
setProp(element, '_constraints', { constraints: Object.create(null), selfs: [], _origins: [], termCount: 0 });
|
|
744
739
|
// and crack the ON condition
|
|
@@ -790,7 +785,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
790
785
|
delete struct.$keys[element.name];
|
|
791
786
|
}
|
|
792
787
|
}
|
|
793
|
-
// deprecated
|
|
788
|
+
// deprecated._unmanagedUpInComponent:
|
|
794
789
|
// Only in containment:
|
|
795
790
|
// Ignore this (foreign key) elment if renderForeignKeys is false
|
|
796
791
|
if(options.odataContainment && element['@odata.containment.ignore']) {
|
|
@@ -855,7 +850,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
855
850
|
sub artifacts exposed by the initial type exposure
|
|
856
851
|
*/
|
|
857
852
|
function convertExposedTypesOfOtherServicesIntoCrossReferences() {
|
|
858
|
-
if(options.
|
|
853
|
+
if(options.odataXServiceRefs && options.isV4()) {
|
|
859
854
|
serviceRootNames.forEach(srn => {
|
|
860
855
|
schemaNames.forEach(fqSchemaName => {
|
|
861
856
|
if(fqSchemaName.startsWith(srn + '.')) {
|
|
@@ -912,7 +907,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
912
907
|
// if this artifact is a service member check its associations
|
|
913
908
|
if(globalSchemaPrefix) {
|
|
914
909
|
forEachGeneric(struct.items || struct, 'elements', element => {
|
|
915
|
-
if(!isAssociationOrComposition(element) || element
|
|
910
|
+
if(!isAssociationOrComposition(element) || element['@odata.navigable'] === false)
|
|
916
911
|
return;
|
|
917
912
|
/*
|
|
918
913
|
* Consider everything @cds.autoexpose: falsy to be a proxy candidate for now
|
|
@@ -949,18 +944,18 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
949
944
|
const targetSchemaName = element._target.$mySchemaName;
|
|
950
945
|
if(isProxyRequired(element)) {
|
|
951
946
|
if(options.isV4() &&
|
|
952
|
-
(options.
|
|
947
|
+
(options.odataProxies || options.odataXServiceRefs) &&
|
|
953
948
|
// must be a managed association with keys OR an unambiguous backlink
|
|
954
|
-
element.keys ||
|
|
949
|
+
element.keys ||
|
|
955
950
|
(element.on && element._constraints.selfs.length === 1 && element._constraints.termCount === 1)
|
|
956
951
|
) {
|
|
957
952
|
// reuse proxy if available
|
|
958
953
|
let proxy = getProxyForTargetOf(element);
|
|
959
954
|
if(!proxy) {
|
|
960
|
-
if(targetSchemaName && options.
|
|
955
|
+
if(targetSchemaName && options.odataXServiceRefs) {
|
|
961
956
|
proxy = createSchemaRefFor(targetSchemaName);
|
|
962
957
|
}
|
|
963
|
-
else if(options.
|
|
958
|
+
else if(options.odataProxies) {
|
|
964
959
|
proxy = createProxyFor(element, targetSchemaName);
|
|
965
960
|
}
|
|
966
961
|
proxy = registerProxy(proxy, element);
|
|
@@ -1024,7 +1019,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1024
1019
|
// proxyDefinitionName: strip the serviceName and replace '.' with '_'
|
|
1025
1020
|
let defName =
|
|
1026
1021
|
`${assoc._target.name.replace(proxySchemaName + '.', '').replace(/\./g, '_')}`;
|
|
1027
|
-
|
|
1022
|
+
|
|
1028
1023
|
// fullName: Prepend serviceName and if in same service add '_proxy'
|
|
1029
1024
|
const proxy = isParamProxy
|
|
1030
1025
|
? createParameterEntity(assoc._target, proxySchemaName + '.' + defName, true)
|
|
@@ -1074,7 +1069,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1074
1069
|
if(!newElt) {
|
|
1075
1070
|
if(csnUtils.isAssocOrComposition(e.type)) {
|
|
1076
1071
|
if(!e.on && e.keys) {
|
|
1077
|
-
if(options.
|
|
1072
|
+
if(options.odataNoTransitiveProxies)
|
|
1078
1073
|
newElt = convertManagedAssocIntoStruct(e);
|
|
1079
1074
|
else
|
|
1080
1075
|
newElt = createProxyOrSchemaRefForManagedAssoc(e);
|
|
@@ -1275,10 +1270,10 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1275
1270
|
proxy = getProxyForTargetOf(e);
|
|
1276
1271
|
if(!proxy) {
|
|
1277
1272
|
// option odataXServiceRefs has precedence over odataProxies
|
|
1278
|
-
if(e._target.$mySchemaName && options.
|
|
1273
|
+
if(e._target.$mySchemaName && options.odataXServiceRefs) {
|
|
1279
1274
|
proxy = createSchemaRefFor(e._target.$mySchemaName);
|
|
1280
1275
|
}
|
|
1281
|
-
else if(options.
|
|
1276
|
+
else if(options.odataProxies) {
|
|
1282
1277
|
proxy = createProxyFor(e, e._target.$mySchemaName);
|
|
1283
1278
|
if(!e._target.$isParamEntity)
|
|
1284
1279
|
populateProxyElements(e, proxy, getForeignKeyDefinitions(e));
|
|
@@ -1451,7 +1446,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1451
1446
|
if(def.$keys) {
|
|
1452
1447
|
setProp(def, '$edmKeyPaths', []);
|
|
1453
1448
|
// for all key elements that shouldn't be ignored produce the paths
|
|
1454
|
-
foreach(def.$keys, k => !
|
|
1449
|
+
foreach(def.$keys, k => !(k._isToContainer && k._selfReferences.length), (k, kn) => {
|
|
1455
1450
|
if(isEdmPropertyRendered(k, options) &&
|
|
1456
1451
|
!(options.isV2() && k['@Core.MediaType'])) {
|
|
1457
1452
|
if(options.isV4() && options.isStructFormat) {
|
|
@@ -1922,7 +1917,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1922
1917
|
if(Object.keys(o).length) {
|
|
1923
1918
|
// ReadRestrictions may have sub type ReadByKeyRestrictions { Description, LongDescription }
|
|
1924
1919
|
// chop annotations into dictionaries
|
|
1925
|
-
if(prefix === '@Capabilities.ReadRestrictions' &&
|
|
1920
|
+
if(prefix === '@Capabilities.ReadRestrictions' &&
|
|
1926
1921
|
Object.keys(o).some(k => k.startsWith('ReadByKeyRestrictions.'))) {
|
|
1927
1922
|
const no = {};
|
|
1928
1923
|
Object.entries(o).forEach(([k,v]) => {
|
|
@@ -1964,15 +1959,15 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1964
1959
|
|
|
1965
1960
|
function mapCdsToEdmProp(obj) {
|
|
1966
1961
|
if (obj.type && isBuiltinType(obj.type) && !isAssociationOrComposition(obj) && !obj.targetAspect) {
|
|
1967
|
-
let edmType = edmUtils.mapCdsToEdmType(obj, messageFunctions, _options.
|
|
1962
|
+
let edmType = edmUtils.mapCdsToEdmType(obj, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType']);
|
|
1968
1963
|
assignProp(obj, '_edmType', edmType);
|
|
1969
1964
|
} else if (obj._isCollection && (obj.items && isBuiltinType(csnUtils.getFinalTypeDef(obj.items.type)))) {
|
|
1970
|
-
let edmType = edmUtils.mapCdsToEdmType(obj.items, messageFunctions, _options.
|
|
1965
|
+
let edmType = edmUtils.mapCdsToEdmType(obj.items, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType'], obj.$path);
|
|
1971
1966
|
assignProp(obj, '_edmType', edmType);
|
|
1972
1967
|
}
|
|
1973
1968
|
// This is the special case when we have array of array, but will not be supported in the future
|
|
1974
1969
|
else if (obj._isCollection && obj.items && obj.items.type && obj.items.items && isBuiltinType(csnUtils.getFinalTypeDef(obj.items.items.type))) {
|
|
1975
|
-
let edmType = edmUtils.mapCdsToEdmType(obj.items.items, messageFunctions, _options.
|
|
1970
|
+
let edmType = edmUtils.mapCdsToEdmType(obj.items.items, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType']);
|
|
1976
1971
|
assignProp(obj, '_edmType', edmType);
|
|
1977
1972
|
}
|
|
1978
1973
|
}
|
package/lib/edm/edmUtils.js
CHANGED
|
@@ -8,31 +8,17 @@ function validateOptions(_options)
|
|
|
8
8
|
{
|
|
9
9
|
if(!_options.isV2 && !_options.isV4)
|
|
10
10
|
{
|
|
11
|
-
// csn2edm expects "
|
|
11
|
+
// csn2edm expects "odataVersion" to be a top-level property of options
|
|
12
12
|
// set to 'v4' as default, override with value from incoming options
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if(options.toOdata.odataForeignKeys)
|
|
23
|
-
options.odataForeignKeys = options.toOdata.odataForeignKeys;
|
|
24
|
-
if(options.toOdata.odataV2PartialConstr)
|
|
25
|
-
options.odataV2PartialConstr = options.toOdata.odataV2PartialConstr;
|
|
26
|
-
// global flag that indicates whether or not FKs shall be rendered in general
|
|
27
|
-
// V2/V4 flat: yes
|
|
28
|
-
// V4/struct: depending on odataForeignKeys
|
|
29
|
-
options.renderForeignKeys =
|
|
30
|
-
options.version === 'v4' ? options.odataFormat === 'structured' && !!options.odataForeignKeys : true;
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const v2 = options.version.match(/v2/i) !== null;
|
|
35
|
-
const v4 = options.version.match(/v4/i) !== null;
|
|
13
|
+
const options = Object.assign({ odataVersion: 'v4'}, _options);
|
|
14
|
+
// global flag that indicates whether or not FKs shall be rendered in general
|
|
15
|
+
// V2/V4 flat: yes
|
|
16
|
+
// V4/struct: depending on odataForeignKeys
|
|
17
|
+
options.renderForeignKeys =
|
|
18
|
+
options.odataVersion === 'v4' ? options.odataFormat === 'structured' && !!options.odataForeignKeys : true;
|
|
19
|
+
|
|
20
|
+
const v2 = options.odataVersion.match(/v2/i) !== null;
|
|
21
|
+
const v4 = options.odataVersion.match(/v4/i) !== null;
|
|
36
22
|
|
|
37
23
|
options.v = [v2, v4];
|
|
38
24
|
options.isStructFormat = options.odataFormat && options.odataFormat === 'structured';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
dd18d05cabbe93eabf1bd17b83add5ee
|