@sap/cds-compiler 4.0.2 → 4.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHANGELOG.md +200 -5
  2. package/bin/cdsc.js +18 -15
  3. package/doc/CHANGELOG_BETA.md +16 -0
  4. package/doc/CHANGELOG_DEPRECATED.md +15 -0
  5. package/lib/api/main.js +33 -13
  6. package/lib/api/options.js +2 -2
  7. package/lib/api/validate.js +25 -25
  8. package/lib/base/location.js +6 -7
  9. package/lib/base/message-registry.js +123 -42
  10. package/lib/base/messages.js +18 -10
  11. package/lib/base/model.js +43 -10
  12. package/lib/checks/defaultValues.js +6 -6
  13. package/lib/checks/elements.js +11 -10
  14. package/lib/checks/foreignKeys.js +0 -5
  15. package/lib/checks/manyNavigations.js +33 -0
  16. package/lib/checks/onConditions.js +22 -14
  17. package/lib/checks/queryNoDbArtifacts.js +132 -73
  18. package/lib/checks/selectItems.js +4 -55
  19. package/lib/checks/sql-snippets.js +15 -4
  20. package/lib/checks/types.js +3 -3
  21. package/lib/checks/utils.js +4 -3
  22. package/lib/checks/validator.js +3 -1
  23. package/lib/compiler/.eslintrc.json +2 -1
  24. package/lib/compiler/assert-consistency.js +71 -40
  25. package/lib/compiler/base.js +7 -2
  26. package/lib/compiler/builtins.js +40 -41
  27. package/lib/compiler/checks.js +415 -367
  28. package/lib/compiler/classes.js +62 -0
  29. package/lib/compiler/cycle-detector.js +9 -9
  30. package/lib/compiler/define.js +124 -90
  31. package/lib/compiler/extend.js +115 -88
  32. package/lib/compiler/finalize-parse-cdl.js +26 -25
  33. package/lib/compiler/generate.js +57 -49
  34. package/lib/compiler/index.js +56 -56
  35. package/lib/compiler/kick-start.js +10 -7
  36. package/lib/compiler/moduleLayers.js +1 -1
  37. package/lib/compiler/populate.js +180 -144
  38. package/lib/compiler/propagator.js +10 -9
  39. package/lib/compiler/resolve.js +321 -246
  40. package/lib/compiler/shared.js +812 -433
  41. package/lib/compiler/tweak-assocs.js +114 -50
  42. package/lib/compiler/utils.js +241 -46
  43. package/lib/edm/.eslintrc.json +40 -1
  44. package/lib/edm/annotations/genericTranslation.js +721 -707
  45. package/lib/edm/annotations/preprocessAnnotations.js +88 -77
  46. package/lib/edm/csn2edm.js +389 -378
  47. package/lib/edm/edm.js +679 -770
  48. package/lib/edm/edmAnnoPreprocessor.js +132 -146
  49. package/lib/edm/edmInboundChecks.js +29 -27
  50. package/lib/edm/edmPreprocessor.js +689 -648
  51. package/lib/edm/edmUtils.js +279 -300
  52. package/lib/gen/Dictionary.json +34 -10
  53. package/lib/gen/language.checksum +1 -1
  54. package/lib/gen/language.interp +1 -1
  55. package/lib/gen/languageParser.js +2857 -2856
  56. package/lib/json/from-csn.js +77 -51
  57. package/lib/json/to-csn.js +15 -15
  58. package/lib/language/antlrParser.js +2 -1
  59. package/lib/language/genericAntlrParser.js +52 -43
  60. package/lib/language/language.g4 +61 -64
  61. package/lib/language/multiLineStringParser.js +2 -0
  62. package/lib/main.d.ts +65 -0
  63. package/lib/model/csnRefs.js +37 -19
  64. package/lib/model/csnUtils.js +51 -18
  65. package/lib/model/revealInternalProperties.js +30 -22
  66. package/lib/modelCompare/compare.js +149 -41
  67. package/lib/modelCompare/utils/filter.js +55 -25
  68. package/lib/optionProcessor.js +21 -9
  69. package/lib/render/manageConstraints.js +20 -17
  70. package/lib/render/toCdl.js +63 -23
  71. package/lib/render/toHdbcds.js +2 -2
  72. package/lib/render/toRename.js +4 -9
  73. package/lib/render/toSql.js +82 -35
  74. package/lib/render/utils/common.js +11 -9
  75. package/lib/render/utils/unique.js +52 -0
  76. package/lib/transform/db/applyTransformations.js +62 -21
  77. package/lib/transform/db/assertUnique.js +7 -8
  78. package/lib/transform/db/associations.js +2 -2
  79. package/lib/transform/db/cdsPersistence.js +9 -9
  80. package/lib/transform/db/constraints.js +47 -17
  81. package/lib/transform/db/expansion.js +138 -68
  82. package/lib/transform/db/flattening.js +98 -30
  83. package/lib/transform/db/rewriteCalculatedElements.js +20 -14
  84. package/lib/transform/db/temporal.js +1 -1
  85. package/lib/transform/db/transformExists.js +8 -7
  86. package/lib/transform/db/views.js +73 -33
  87. package/lib/transform/draft/db.js +11 -9
  88. package/lib/transform/draft/odata.js +1 -1
  89. package/lib/transform/{forOdataNew.js → forOdata.js} +10 -7
  90. package/lib/transform/forRelationalDB.js +148 -136
  91. package/lib/transform/localized.js +92 -54
  92. package/lib/transform/odata/toFinalBaseType.js +3 -3
  93. package/lib/transform/{transformUtilsNew.js → transformUtils.js} +13 -111
  94. package/lib/transform/translateAssocsToJoins.js +14 -28
  95. package/lib/utils/file.js +7 -7
  96. package/lib/utils/moduleResolve.js +210 -121
  97. package/lib/utils/objectUtils.js +1 -1
  98. package/package.json +5 -5
  99. package/share/messages/check-proper-type-of.md +1 -1
  100. package/share/messages/{check-proper-type.md → def-missing-type.md} +3 -5
  101. package/share/messages/message-explanations.json +1 -1
@@ -23,43 +23,34 @@ const { forEachGeneric } = require('../model/csnUtils');
23
23
 
24
24
  /* eslint max-statements-per-line:off */
25
25
 
26
- function mapAnnotationAssignment(artifact, parent, mappingDictionary)
27
- {
28
- let props = edmUtils.intersect(Object.keys(mappingDictionary), Object.keys(artifact));
26
+ function mapAnnotationAssignment( artifact, parent, mappingDictionary ) {
27
+ const props = edmUtils.intersect(Object.keys(mappingDictionary), Object.keys(artifact));
29
28
  // now start the substitution
30
- props.forEach(prop => {
31
- let [ mapping, value, remove_original ] = mappingDictionary[prop];
32
- if(mapping instanceof Function)
33
- {
29
+ props.forEach((prop) => {
30
+ const [ mapping, value, removeOriginal ] = mappingDictionary[prop];
31
+ if (mapping instanceof Function)
34
32
  mapping(artifact, parent, prop);
35
- }
33
+
36
34
  else
37
- {
38
35
  edmUtils.assignAnnotation(artifact, mapping, value || artifact[prop]['='] || artifact[prop]);
39
- }
40
36
 
41
- if(remove_original)
37
+
38
+ if (removeOriginal)
42
39
  delete artifact[prop];
43
40
  });
44
41
  }
45
42
 
46
- function addToSetAttr(carrier, propName, propValue, removeFromType=true) {
43
+ function addToSetAttr( carrier, propName, propValue, removeFromType = true ) {
47
44
  edmUtils.assignProp(carrier, '_SetAttributes', Object.create(null));
48
45
  edmUtils.assignAnnotation(carrier._SetAttributes, propName, propValue);
49
- if(removeFromType) {
46
+ if (removeFromType)
50
47
  delete carrier[propName];
51
- }
52
48
  }
53
49
 
54
- function applyAppSpecificLateCsnTransformationOnElement(options, element, struct, error)
55
- {
56
- if(options.isV2())
57
- {
58
- if(struct['@Aggregation.ApplySupported.PropertyRestrictions'])
59
- {
60
- mapAnnotationAssignment(element, struct, AnalyticalAnnotations());
61
- }
62
- }
50
+ function applyAppSpecificLateCsnTransformationOnElement( options, element, struct, error ) {
51
+ if (options.isV2() && struct['@Aggregation.ApplySupported.PropertyRestrictions'])
52
+ mapAnnotationAssignment(element, struct, AnalyticalAnnotations());
53
+
63
54
 
64
55
  // etag requires Core.OptimisticConcurrency to be set in V4 (cap/issues#2641)
65
56
  // Oliver Heinrich mentions in the issue that the Okra runtime must be set to a
@@ -67,51 +58,45 @@ function applyAppSpecificLateCsnTransformationOnElement(options, element, struct
67
58
  // it doesn't appear in the forOData processed CSN, meaning that the
68
59
  // runtime cannot set that okra flag (alternatively the runtime has to search
69
60
  // for @[odata|cds].etag annotations...
70
- if(options.isV4())
71
- {
61
+ if (options.isV4() && (element['@odata.etag'] || element['@cds.etag'])) {
72
62
  // eslint-disable-next-line sonarjs/no-redundant-boolean
73
- if(element['@odata.etag'] == true || element['@cds.etag'] == true) {
74
- // don't put element name into collection as per advice from Ralf Handl, as
75
- // no runtime is interested in the property itself, it is sufficient to mark
76
- // the entity set.
77
- edmUtils.assignAnnotation(struct, '@Core.OptimisticConcurrency',
78
- (struct['@Core.OptimisticConcurrency'] || [])/*.push(element.name)*/);
79
- }
63
+ // don't put element name into collection as per advice from Ralf Handl, as
64
+ // no runtime is interested in the property itself, it is sufficient to mark
65
+ // the entity set.
66
+ edmUtils.assignAnnotation(struct, '@Core.OptimisticConcurrency',
67
+ (struct['@Core.OptimisticConcurrency'] || [])/* .push(element.name) */);
80
68
  }
81
69
 
82
- function AnalyticalAnnotations()
83
- {
84
- function mapCommonAttributes(element, struct, prop)
85
- {
86
- let CommonAttributes = element[prop];
87
- if(!Array.isArray(CommonAttributes)) {
88
- error(null, ['definitions', struct.name, 'elements', element.name],
89
- { anno: '@Common.Attributes', code: JSON.stringify(CommonAttributes) },
90
- 'Expecting array value for $(ANNO): $(CODE)');
70
+ function AnalyticalAnnotations() {
71
+ function mapCommonAttributes( elt, structure, prop ) {
72
+ const CommonAttributes = elt[prop];
73
+ if (!Array.isArray(CommonAttributes)) {
74
+ error(null, [ 'definitions', structure.name, 'elements', elt.name ],
75
+ { anno: '@Common.Attributes', code: JSON.stringify(CommonAttributes) },
76
+ 'Expecting array value for $(ANNO): $(CODE)');
91
77
  return;
92
78
  }
93
79
 
94
- let targets = edmUtils.intersect(CommonAttributes, Object.keys(struct.elements));
95
- targets.forEach(tgt => {
96
- edmUtils.assignAnnotation(struct.elements[tgt], '@sap.attribute-for', element.name);
80
+ const targets = edmUtils.intersect(CommonAttributes, Object.keys(structure.elements));
81
+ targets.forEach((tgt) => {
82
+ edmUtils.assignAnnotation(structure.elements[tgt], '@sap.attribute-for', elt.name);
97
83
  });
98
84
  }
99
85
 
100
- function mapContextDefiningProperties(element, struct, prop)
101
- {
102
- let ContextDefiningProperties = element[prop];
103
- if(!Array.isArray(ContextDefiningProperties)) {
104
- error(null, ['definitions', struct.name, 'elements', element.name],
105
- { anno: '@Aggregation.ContextDefiningProperties', code: JSON.stringify(ContextDefiningProperties) },
106
- 'Expecting array value for $(ANNO): $(CODE)');
86
+ function mapContextDefiningProperties( elt, structure, prop ) {
87
+ const ContextDefiningProperties = elt[prop];
88
+ if (!Array.isArray(ContextDefiningProperties)) {
89
+ error(null, [ 'definitions', structure.name, 'elements', elt.name ],
90
+ { anno: '@Aggregation.ContextDefiningProperties', code: JSON.stringify(ContextDefiningProperties) },
91
+ 'Expecting array value for $(ANNO): $(CODE)');
107
92
  return;
108
93
  }
109
- if(ContextDefiningProperties.length > 0)
110
- edmUtils.assignAnnotation(element, '@sap.super-ordinate', ContextDefiningProperties[ContextDefiningProperties.length-1]);
94
+ if (ContextDefiningProperties.length > 0)
95
+ edmUtils.assignAnnotation(elt, '@sap.super-ordinate', ContextDefiningProperties[ContextDefiningProperties.length - 1]);
111
96
  }
112
97
 
113
- let dict = Object.create(null);
114
- //analytics term definition unknown, lower case
98
+ const dict = Object.create(null);
99
+ // analytics term definition unknown, lower case
115
100
  dict['@Analytics.Measure'] = [ '@sap.aggregation-role', 'measure' ];
116
101
  dict['@Analytics.Dimension'] = [ '@sap.aggregation-role', 'dimension' ];
117
102
  dict['@Semantics.currencyCode'] = [ '@sap.semantics', 'currency-code', true ];
@@ -126,92 +111,90 @@ function applyAppSpecificLateCsnTransformationOnElement(options, element, struct
126
111
  dict['@Common.Attributes'] = [ mapCommonAttributes ];
127
112
 
128
113
  // respect flattened annotation $value
129
- Object.entries(dict).forEach(([k, v]) => dict[k+'.$value'] = v);
114
+ Object.entries(dict).forEach(([ k, v ]) => {
115
+ dict[`${k}.$value`] = v;
116
+ });
130
117
  return dict;
131
118
  }
132
119
  }
133
120
 
134
- function applyAppSpecificLateCsnTransformationOnStructure(options, struct, error)
135
- {
136
- if(options.isV2())
137
- {
138
- if(struct['@Aggregation.ApplySupported.PropertyRestrictions'])
139
- {
140
- transformAnalyticalModel(struct);
141
- mapAnnotationAssignment(struct, undefined, AnalyticalAnnotations());
142
- }
121
+ function applyAppSpecificLateCsnTransformationOnStructure( options, struct, error ) {
122
+ if (options.isV2() && struct['@Aggregation.ApplySupported.PropertyRestrictions']) {
123
+ transformAnalyticalModel(struct);
124
+ mapAnnotationAssignment(struct, undefined, AnalyticalAnnotations());
143
125
  }
144
126
 
145
127
  // nested functions begin
146
- function transformAnalyticalModel(struct)
147
- {
148
- let keyName = 'ID__';
149
- if(struct == undefined || struct.elements == undefined || struct.elements[keyName] != undefined)
128
+ function transformAnalyticalModel( structure ) {
129
+ const keyName = 'ID__';
130
+ if (!structure?.elements || structure.elements[keyName])
150
131
  return;
151
132
 
152
133
  // remove key prop from elements, add new key to elements
153
- let elements = Object.create(null);
154
- let key = { name: keyName, key : true, type : 'cds.String', '@sap.sortable':false, '@sap.filterable':false, '@UI.Hidden': true };
134
+ const elements = Object.create(null);
135
+ const key = {
136
+ name: keyName, key: true, type: 'cds.String', '@sap.sortable': false, '@sap.filterable': false, '@UI.Hidden': true,
137
+ };
155
138
  elements[keyName] = key;
156
- setProp(struct, '$keys',{ [keyName] : key } );
157
- forEachGeneric(struct.items || struct, 'elements', (e,n) =>
158
- {
159
- if(e.key) delete e.key;
139
+ setProp(structure, '$keys', { [keyName]: key } );
140
+ forEachGeneric(structure.items || structure, 'elements', (e, n) => {
141
+ if (e.key)
142
+ delete e.key;
160
143
  elements[n] = e;
161
144
  });
162
- struct.elements = elements;
145
+ structure.elements = elements;
163
146
  }
164
147
 
165
- function AnalyticalAnnotations()
166
- {
167
- function mapFilterRestrictions(struct, parent, prop)
168
- {
169
- let stringDict = Object.create(null);
170
- stringDict['SingleValue'] = 'single-value';
171
- stringDict['MultiValue'] = 'multi-value';
172
- stringDict['SingleRange'] = 'interval';
173
-
174
- let filterRestrictions = struct[prop];
175
- if(!Array.isArray(filterRestrictions)) {
176
- error(null, ['definitions', struct.name ],
177
- { anno: '@Capabilities.FilterRestrictions.FilterExpressionRestrictions',
178
- code: JSON.stringify(filterRestrictions) },
179
- 'Expected array value for $(ANNO): $(CODE)');
148
+ function AnalyticalAnnotations() {
149
+ function mapFilterRestrictions( structure, parent, prop ) {
150
+ const stringDict = Object.create(null);
151
+ stringDict.SingleValue = 'single-value';
152
+ stringDict.MultiValue = 'multi-value';
153
+ stringDict.SingleRange = 'interval';
154
+
155
+ const filterRestrictions = structure[prop];
156
+ if (!Array.isArray(filterRestrictions)) {
157
+ error(null, [ 'definitions', structure.name ],
158
+ {
159
+ anno: '@Capabilities.FilterRestrictions.FilterExpressionRestrictions',
160
+ code: JSON.stringify(filterRestrictions),
161
+ },
162
+ 'Expected array value for $(ANNO): $(CODE)');
180
163
  return;
181
164
  }
182
- filterRestrictions.forEach(v => {
183
- let e = struct.elements[v.Property];
184
- if(e)
165
+ filterRestrictions.forEach((v) => {
166
+ const e = structure.elements[v.Property];
167
+ if (e)
185
168
  edmUtils.assignAnnotation(e, '@sap.filter-restriction', stringDict[v.AllowedExpressions]);
186
169
  });
187
170
  }
188
171
 
189
- function mapRequiredProperties(struct, parent, prop)
190
- {
191
- let requiredProperties = struct[prop];
192
- if(!Array.isArray(requiredProperties)) {
193
- error(null, ['definitions', struct.name],
194
- { anno: '@Capabilities.FilterRestrictions.RequiredProperties',
195
- code: JSON.stringify(requiredProperties) },
196
- 'Expecting array value for $(ANNO): $(CODE)');
172
+ function mapRequiredProperties( structure, parent, prop ) {
173
+ const requiredProperties = structure[prop];
174
+ if (!Array.isArray(requiredProperties)) {
175
+ error(null, [ 'definitions', structure.name ],
176
+ {
177
+ anno: '@Capabilities.FilterRestrictions.RequiredProperties',
178
+ code: JSON.stringify(requiredProperties),
179
+ },
180
+ 'Expecting array value for $(ANNO): $(CODE)');
197
181
  return;
198
182
  }
199
183
 
200
- let props = edmUtils.intersect(Object.keys(struct.elements), requiredProperties)
201
- props.forEach(p => {
202
- edmUtils.assignAnnotation(struct.elements[p], '@sap.required-in-filter', true);
184
+ const props = edmUtils.intersect(Object.keys(structure.elements), requiredProperties);
185
+ props.forEach((p) => {
186
+ edmUtils.assignAnnotation(structure.elements[p], '@sap.required-in-filter', true);
203
187
  });
204
188
  }
205
189
 
206
- function mapRequiresFilter(struct, parent, prop)
207
- {
208
- let requiresFilter = struct[prop];
209
- if(requiresFilter)
210
- edmUtils.assignAnnotation(struct._SetAttributes, '@sap.requires-filter', requiresFilter);
190
+ function mapRequiresFilter( structure, parent, prop ) {
191
+ const requiresFilter = structure[prop];
192
+ if (requiresFilter)
193
+ edmUtils.assignAnnotation(structure._SetAttributes, '@sap.requires-filter', requiresFilter);
211
194
  }
212
195
 
213
- // Entity Props
214
- let dict = Object.create(null);
196
+ // Entity Props
197
+ const dict = Object.create(null);
215
198
  dict['@Aggregation.ApplySupported.PropertyRestrictions'] = [ '@sap.semantics', 'aggregate' ];
216
199
  dict['@Common.Label'] = [ '@sap.label' ];
217
200
  dict['@Capabilities.FilterRestrictions.RequiresFilter'] = [ mapRequiresFilter ];
@@ -219,43 +202,47 @@ function applyAppSpecificLateCsnTransformationOnStructure(options, struct, error
219
202
  dict['@Capabilities.FilterRestrictions.FilterExpressionRestrictions'] = [ mapFilterRestrictions ];
220
203
 
221
204
  // respect flattened annotation $value
222
- Object.keys(dict).forEach(k => dict[k+'.$value'] = dict[k]);
205
+ Object.keys(dict).forEach((k) => {
206
+ dict[`${k}.$value`] = dict[k];
207
+ });
223
208
 
224
209
  return dict;
225
210
  }
226
211
  }
227
212
 
228
- function setSAPSpecificV2AnnotationsToEntityContainer(options, carrier) {
229
- if(!options.isV2())
213
+ function setSAPSpecificV2AnnotationsToEntityContainer( options, carrier ) {
214
+ if (!options.isV2())
230
215
  return;
231
216
  // documented in https://wiki.scn.sap.com/wiki/display/EmTech/SAP+Annotations+for+OData+Version+2.0#SAPAnnotationsforODataVersion2.0-Elementedm:EntityContainer
232
217
  const SetAttributes = {
233
218
  // EntityContainer only
234
- '@sap.supported.formats' : addToSetAttr,
219
+ '@sap.supported.formats': addToSetAttr,
235
220
  '@sap.use.batch': addToSetAttr,
236
221
  '@sap.message.scope.supported': addToSetAttr,
237
222
  };
238
223
 
239
- Object.entries(carrier).forEach(([p, v]) => {
240
- (SetAttributes[p] || function() { /* no-op */ })(carrier, p, v);
224
+ Object.entries(carrier).forEach(([ p, v ]) => {
225
+ (SetAttributes[p] || function () { /* no-op */ })(carrier, p, v); // eslint-disable-line func-names
241
226
  });
242
227
  }
243
228
 
244
- function setSAPSpecificV2AnnotationsToEntitySet(options, carrier) {
245
- if(!options.isV2())
229
+ function setSAPSpecificV2AnnotationsToEntitySet( options, carrier ) {
230
+ if (!options.isV2())
246
231
  return;
247
232
  // documented in https://wiki.scn.sap.com/wiki/display/EmTech/SAP+Annotations+for+OData+Version+2.0#SAPAnnotationsforODataVersion2.0-Elementedm:EntitySet
248
233
  const SetAttributes = {
249
234
  // EntitySet, EntityType
250
- '@sap.label' : (s,pn, pv) => { addToSetAttr(s, pn, pv, false); },
235
+ '@sap.label': (s, pn, pv) => {
236
+ addToSetAttr(s, pn, pv, false);
237
+ },
251
238
  '@sap.semantics': checkSemantics,
252
239
  // EntitySet only
253
- '@sap.creatable' : addToSetAttr,
254
- '@sap.updatable' : addToSetAttr,
240
+ '@sap.creatable': addToSetAttr,
241
+ '@sap.updatable': addToSetAttr,
255
242
  '@sap.deletable': addToSetAttr,
256
243
  '@sap.updatable.path': addToSetAttr,
257
244
  '@sap.deletable.path': addToSetAttr,
258
- '@sap.searchable' : addToSetAttr,
245
+ '@sap.searchable': addToSetAttr,
259
246
  '@sap.pagable': addToSetAttr,
260
247
  '@sap.topable': addToSetAttr,
261
248
  '@sap.countable': addToSetAttr,
@@ -266,25 +253,27 @@ function setSAPSpecificV2AnnotationsToEntitySet(options, carrier) {
266
253
  '@sap.delta.link.validity': addToSetAttr,
267
254
  };
268
255
 
269
- Object.entries(carrier).forEach(([p, v]) => {
270
- (SetAttributes[p] || function() { /* no-op */ })(carrier, p, v);
256
+ Object.entries(carrier).forEach(([ p, v ]) => {
257
+ (SetAttributes[p] || function () { /* no-op */ })(carrier, p, v); // eslint-disable-line func-names
271
258
  });
272
259
 
273
- function checkSemantics(struct, propName, propValue) {
274
- if(propValue === 'timeseries' || propValue === 'aggregate') {
260
+ function checkSemantics( struct, propName, propValue ) {
261
+ if (propValue === 'timeseries' || propValue === 'aggregate') {
275
262
  // aggregate is forwarded to Set and must remain on Type
276
263
  addToSetAttr(struct, propName, propValue, propValue !== 'aggregate');
277
264
  }
278
265
  }
279
266
  }
280
267
 
281
- function setSAPSpecificV2AnnotationsToAssociation(carrier) {
268
+ function setSAPSpecificV2AnnotationsToAssociation( carrier ) {
282
269
  // documented in https://wiki.scn.sap.com/wiki/display/EmTech/SAP+Annotations+for+OData+Version+2.0
283
270
  const SetAttributes = {
284
271
  // Applicable to NavProp and foreign keys, add to AssociationSet
285
- '@sap.creatable' : (c, pn, pv) => { addToAssociationSet(c, pn, pv, false); },
272
+ '@sap.creatable': (c, pn, pv) => {
273
+ addToAssociationSet(c, pn, pv, false);
274
+ },
286
275
  // Not applicable to NavProp, applicable to foreign keys, add to AssociationSet
287
- '@sap.updatable' : addToAssociationSet,
276
+ '@sap.updatable': addToAssociationSet,
288
277
  // Not applicable to NavProp, not applicable to foreign key, add to AssociationSet
289
278
  '@sap.deletable': (c, pn, pv) => {
290
279
  addToAssociationSet(c, pn, pv);
@@ -295,33 +284,30 @@ function setSAPSpecificV2AnnotationsToAssociation(carrier) {
295
284
  '@sap.filterable': removeFromForeignKey,
296
285
  };
297
286
 
298
- Object.entries(carrier).forEach(([p, v]) => {
299
- (SetAttributes[p] || function() {/* no-op */})(carrier, p, v);
287
+ Object.entries(carrier).forEach(([ p, v ]) => {
288
+ (SetAttributes[p] || function () { /* no-op */ })(carrier, p, v); // eslint-disable-line func-names
300
289
  });
301
290
 
302
- function addToAssociationSet(carrier, propName, propValue, removeFromType=true) {
303
- if(carrier.target) {
304
- edmUtils.assignProp(carrier, '_SetAttributes', Object.create(null));
305
- edmUtils.assignAnnotation(carrier._SetAttributes, propName, propValue);
306
- if(removeFromType) {
307
- delete carrier[propName];
308
- }
291
+ function addToAssociationSet( target, propName, propValue, removeFromType = true ) {
292
+ if (target.target) {
293
+ edmUtils.assignProp(target, '_SetAttributes', Object.create(null));
294
+ edmUtils.assignAnnotation(target._SetAttributes, propName, propValue);
295
+ if (removeFromType)
296
+ delete target[propName];
309
297
  }
310
298
  }
311
299
 
312
- function removeFromForeignKey(carrier, propName) {
313
- if(carrier['@odata.foreignKey4'] && carrier[propName] !== undefined) {
314
- delete carrier[propName];
315
- }
300
+ function removeFromForeignKey( target, propName ) {
301
+ if (target['@odata.foreignKey4'] && target[propName] !== undefined)
302
+ delete target[propName];
316
303
  }
317
304
  }
318
305
 
319
306
 
320
-
321
307
  module.exports = {
322
308
  applyAppSpecificLateCsnTransformationOnElement,
323
309
  applyAppSpecificLateCsnTransformationOnStructure,
324
310
  setSAPSpecificV2AnnotationsToEntityContainer,
325
311
  setSAPSpecificV2AnnotationsToEntitySet,
326
- setSAPSpecificV2AnnotationsToAssociation
312
+ setSAPSpecificV2AnnotationsToAssociation,
327
313
  };
@@ -6,13 +6,13 @@ const {
6
6
  } = require('../model/csnUtils');
7
7
 
8
8
  // eslint-disable-next-line no-unused-vars
9
- function resolveForeignKeyRefs(csn, csnUtils) {
9
+ function resolveForeignKeyRefs( csn, csnUtils ) {
10
10
  forEachDefinition(csn, (def, defName) => {
11
- let currPath = ['definitions', defName ];
11
+ const currPath = [ 'definitions', defName ];
12
12
  forEachMemberRecursively(def, (construct, _constructName, _prop, path) => {
13
- if(construct.target && construct.keys) {
13
+ if (construct.target && construct.keys) {
14
14
  construct.keys.forEach((fk, i) => {
15
- setProp(fk, '_artifact', csnUtils.inspectRef([...path, 'keys', i]).art);
15
+ setProp(fk, '_artifact', csnUtils.inspectRef([ ...path, 'keys', i ]).art);
16
16
  });
17
17
  }
18
18
  }, currPath, true, { elementsOnly: true });
@@ -20,34 +20,34 @@ function resolveForeignKeyRefs(csn, csnUtils) {
20
20
  }
21
21
 
22
22
 
23
- function inboundQualificationChecks(csn, options, messageFunctions,
24
- serviceRootNames, requestedServiceNames, isMyServiceRequested, whatsMyServiceRootName, csnUtils) {
23
+ function inboundQualificationChecks( csn, options, messageFunctions,
24
+ serviceRootNames, requestedServiceNames, isMyServiceRequested, whatsMyServiceRootName, csnUtils ) {
25
25
  const { message, throwWithError } = messageFunctions;
26
26
 
27
27
  forEachDefinition(csn, [ attach$path, checkProperArrayUsage ]);
28
28
  checkNestedContextsAndServices();
29
29
  throwWithError();
30
30
 
31
- // attach $path to all
32
- function attach$path(def, defName) {
31
+ // attach $path to all
32
+ function attach$path( def, defName ) {
33
33
  setProp(def, '$path', [ 'definitions', defName ]);
34
34
  forEachMemberRecursively(def,
35
- (member, _memberName, _prop, path) => {
36
- setProp(member, '$path', path);
37
- }, [ 'definitions', defName ]);
35
+ (member, _memberName, _prop, path) => {
36
+ setProp(member, '$path', path);
37
+ }, [ 'definitions', defName ]);
38
38
  }
39
39
 
40
- function checkProperArrayUsage(def, defName) {
40
+ function checkProperArrayUsage( def, defName ) {
41
41
  if (!isMyServiceRequested(defName))
42
42
  return;
43
- let currPath = ['definitions', defName];
43
+ const currPath = [ 'definitions', defName ];
44
44
  checkIfItemsOfItems(def, undefined, undefined, currPath);
45
45
  forEachMemberRecursively(def, checkIfItemsOfItems, currPath);
46
46
 
47
- function checkIfItemsOfItems(construct, _constructName, _prop, path) {
47
+ function checkIfItemsOfItems( construct, _constructName, _prop, path ) {
48
48
  const constructType = csnUtils.effectiveType(construct);
49
49
  if (constructType.items) {
50
- if(constructType.items.target) {
50
+ if (constructType.items.target) {
51
51
  const isComp = constructType.items.type === 'cds.Composition';
52
52
  message('type-invalid-items', path, { '#': isComp ? 'comp' : 'assoc', prop: 'items' });
53
53
  return;
@@ -65,24 +65,26 @@ function inboundQualificationChecks(csn, options, messageFunctions,
65
65
  }
66
66
 
67
67
  function checkNestedContextsAndServices() {
68
- !isBetaEnabled(options, 'nestedServices') && serviceRootNames.forEach(sn => {
69
- const parent = whatsMyServiceRootName(sn, false);
70
- if(parent && requestedServiceNames.includes(parent) && parent !== sn) {
71
- message( 'service-nested-service', [ 'definitions', sn ], { art: parent },
72
- 'A service can\'t be nested within a service $(ART)' );
73
- }
74
- });
68
+ if (!isBetaEnabled(options, 'nestedServices')) {
69
+ serviceRootNames.forEach((sn) => {
70
+ const parent = whatsMyServiceRootName(sn, false);
71
+ if (parent && requestedServiceNames.includes(parent) && parent !== sn) {
72
+ message( 'service-nested-service', [ 'definitions', sn ], { art: parent },
73
+ 'A service can\'t be nested within a service $(ART)' );
74
+ }
75
+ });
76
+ }
75
77
 
76
- Object.entries(csn.definitions).forEach(([fqName, art]) => {
77
- if(art.kind === 'context') {
78
+ Object.entries(csn.definitions).forEach(([ fqName, art ]) => {
79
+ if (art.kind === 'context') {
78
80
  const parent = whatsMyServiceRootName(fqName);
79
- if(requestedServiceNames.includes(parent)) {
81
+ if (requestedServiceNames.includes(parent)) {
80
82
  message( 'service-nested-context', [ 'definitions', fqName ], { art: parent },
81
- 'A context can\'t be nested within a service $(ART)' );
83
+ 'A context can\'t be nested within a service $(ART)' );
82
84
  }
83
85
  }
84
86
  });
85
87
  }
86
88
  }
87
89
 
88
- module.exports = { inboundQualificationChecks }
90
+ module.exports = { inboundQualificationChecks };