@sap/cds-compiler 6.2.2 → 6.3.4
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 +49 -0
- package/bin/cdsc.js +11 -4
- package/lib/api/options.js +1 -1
- package/lib/base/message-registry.js +36 -7
- package/lib/base/messages.js +11 -4
- package/lib/base/model.js +0 -1
- package/lib/checks/assocOutsideService.js +17 -30
- package/lib/checks/checkForTypes.js +0 -18
- package/lib/checks/checkPathsInStoredCalcElement.js +2 -1
- package/lib/checks/enricher.js +15 -3
- package/lib/checks/onConditions.js +2 -2
- package/lib/checks/queryNoDbArtifacts.js +16 -15
- package/lib/checks/types.js +1 -1
- package/lib/checks/utils.js +30 -6
- package/lib/checks/validator.js +36 -37
- package/lib/compiler/assert-consistency.js +1 -1
- package/lib/compiler/checks.js +47 -18
- package/lib/compiler/extend.js +1 -1
- package/lib/compiler/index.js +88 -6
- package/lib/compiler/populate.js +1 -1
- package/lib/compiler/resolve.js +7 -7
- package/lib/compiler/tweak-assocs.js +48 -25
- package/lib/edm/annotations/edmJson.js +19 -19
- package/lib/gen/BaseParser.js +1 -1
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +384 -383
- package/lib/gen/Dictionary.json +0 -2
- package/lib/json/to-csn.js +3 -2
- package/lib/model/csnRefs.js +9 -4
- package/lib/model/csnUtils.js +67 -2
- package/lib/optionProcessor.js +2 -3
- package/lib/parsers/AstBuildingParser.js +12 -11
- package/lib/render/toCdl.js +10 -4
- package/lib/render/utils/common.js +4 -2
- package/lib/transform/db/assertUnique.js +2 -1
- package/lib/transform/db/associations.js +37 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +21 -32
- package/lib/transform/db/assocsToQueries/utils.js +1 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/expansion.js +37 -36
- package/lib/transform/draft/db.js +20 -20
- package/lib/transform/draft/odata.js +38 -40
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +40 -47
- package/lib/transform/effective/main.js +6 -4
- package/lib/transform/forOdata.js +135 -115
- package/lib/transform/forRelationalDB.js +151 -142
- package/lib/transform/localized.js +116 -109
- package/lib/transform/odata/adaptAnnotationRefs.js +21 -16
- package/lib/transform/odata/createForeignKeys.js +73 -70
- package/lib/transform/odata/flattening.js +216 -200
- package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +47 -45
- package/lib/transform/odata/toFinalBaseType.js +40 -39
- package/lib/transform/odata/typesExposure.js +151 -133
- package/lib/transform/odata/utils.js +7 -6
- package/lib/transform/parseExpr.js +165 -162
- package/lib/transform/transformUtils.js +184 -551
- package/lib/transform/translateAssocsToJoins.js +510 -571
- package/lib/transform/tupleExpansion.js +495 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
- package/package.json +1 -1
- package/lib/base/cleanSymbols.js +0 -17
- package/lib/checks/nonexpandableStructured.js +0 -39
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
const { setProp, isBetaEnabled } = require('../../base/model');
|
|
10
10
|
const { defNameWithoutServiceOrContextName, isArtifactInService } = require('./utils');
|
|
11
|
-
const {
|
|
12
|
-
|
|
11
|
+
const {
|
|
12
|
+
getNamespace, copyAnnotations,
|
|
13
|
+
forEachDefinition, forEachMember, forEachGeneric, isEdmPropertyRendered,
|
|
14
|
+
} = require('../../model/csnUtils');
|
|
13
15
|
const { isBuiltinType } = require('../../base/builtins');
|
|
14
16
|
const { CompilerAssertion } = require('../../base/error');
|
|
15
17
|
const { cloneCsnNonDict } = require('../../model/cloneCsn');
|
|
@@ -81,23 +83,24 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
81
83
|
if (propertyName === 'elements') {
|
|
82
84
|
const newTypeName = getNewTypeName(element, elementName, defName, serviceName);
|
|
83
85
|
exposeTypeOf(element, element.key, elementName, defName, serviceName, newTypeName, defName, path);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
+
}
|
|
87
|
+
else if (propertyName === 'params') {
|
|
88
|
+
const newTypeName = getNewTypeName(element, elementName, `ep_${ defName.replace(/\./g, '_') }`, serviceName);
|
|
86
89
|
exposeTypeOf(element, true, elementName, defName, serviceName, newTypeName, defName, path);
|
|
87
90
|
}
|
|
88
91
|
}, path);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
if (def.kind === 'action' || def.kind === 'function')
|
|
94
|
+
if (def.kind === 'action' || def.kind === 'function')
|
|
92
95
|
exposeTypesOfAction(def, defName, defName, serviceName, path, false);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
exposeTypesOfAction(action, `${defName}_${actionName}`, defName, serviceName, path.concat(['actions', actionName]), true);
|
|
96
|
+
|
|
97
|
+
Object.entries(def.actions || {}).forEach(([ actionName, action ]) => {
|
|
98
|
+
exposeTypesOfAction(action, `${ defName }_${ actionName }`, defName, serviceName, path.concat([ 'actions', actionName ]), true);
|
|
96
99
|
});
|
|
97
100
|
}
|
|
98
101
|
});
|
|
99
102
|
|
|
100
|
-
if(isBetaEnabled(options, 'odataTerms')) {
|
|
103
|
+
if (isBetaEnabled(options, 'odataTerms')) {
|
|
101
104
|
forEachGeneric(csn, 'vocabularies', (def, defName, _propertyName, path) => {
|
|
102
105
|
const serviceName = whatsMyServiceName(defName, false);
|
|
103
106
|
if (serviceName && requestedServiceNames.includes(serviceName)) {
|
|
@@ -108,9 +111,9 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
108
111
|
// link def into definitions for later use
|
|
109
112
|
def.kind = 'annotation';
|
|
110
113
|
csn.definitions[defName] = def;
|
|
111
|
-
const artificialName = `term_${defName.replace(/\./g, '_')}`;//_${paramName}`;
|
|
114
|
+
const artificialName = `term_${ defName.replace(/\./g, '_') }`;// _${paramName}`;
|
|
112
115
|
const newTypeName = getNewTypeName(undefined, undefined, artificialName, serviceName);
|
|
113
|
-
exposeTypeOf(def, false, defName, defName, serviceName, newTypeName, defName, path.concat(['vocabularies', defName]), undefined, true);
|
|
116
|
+
exposeTypeOf(def, false, defName, defName, serviceName, newTypeName, defName, path.concat([ 'vocabularies', defName ]), undefined, true);
|
|
114
117
|
}
|
|
115
118
|
}
|
|
116
119
|
});
|
|
@@ -118,7 +121,7 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
118
121
|
|
|
119
122
|
return schemas;
|
|
120
123
|
|
|
121
|
-
/**
|
|
124
|
+
/**
|
|
122
125
|
* If an 'action' uses structured types as parameters or return values that are not exposed in 'service'
|
|
123
126
|
* (because the types are anonymous or have a definition outside of 'service'),
|
|
124
127
|
* create equivalent types in 'service' and make 'action' use them instead,
|
|
@@ -128,15 +131,15 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
128
131
|
*/
|
|
129
132
|
function exposeTypesOfAction(action, actionName, defName, serviceName, path, isBound) {
|
|
130
133
|
if (action.returns) {
|
|
131
|
-
const artificialName = `return_${actionName.replace(/\./g, '_')}`;
|
|
134
|
+
const artificialName = `return_${ actionName.replace(/\./g, '_') }`;
|
|
132
135
|
const newTypeName = getNewTypeName(action.returns, undefined, artificialName, serviceName);
|
|
133
|
-
exposeTypeOf(action.returns, false, actionName, defName, serviceName, newTypeName, defName, path.concat(['returns']));
|
|
136
|
+
exposeTypeOf(action.returns, false, actionName, defName, serviceName, newTypeName, defName, path.concat([ 'returns' ]));
|
|
134
137
|
}
|
|
135
138
|
|
|
136
|
-
|
|
137
|
-
const artificialName = `${isBound ? 'bap' : 'ap'}_${actionName.replace(/\./g, '_')}`;//_${paramName}`;
|
|
139
|
+
Object.entries(action.params || {}).forEach(([ paramName, param ]) => {
|
|
140
|
+
const artificialName = `${ isBound ? 'bap' : 'ap' }_${ actionName.replace(/\./g, '_') }`;// _${paramName}`;
|
|
138
141
|
const newTypeName = getNewTypeName(param, paramName, artificialName, serviceName);
|
|
139
|
-
exposeTypeOf(param, false, actionName, defName, serviceName, newTypeName, defName, path.concat(['params', paramName]));
|
|
142
|
+
exposeTypeOf(param, false, actionName, defName, serviceName, newTypeName, defName, path.concat([ 'params', paramName ]));
|
|
140
143
|
});
|
|
141
144
|
}
|
|
142
145
|
|
|
@@ -149,25 +152,27 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
149
152
|
* @param {String} serviceName
|
|
150
153
|
* @param {String} newTypeName
|
|
151
154
|
*/
|
|
152
|
-
function exposeTypeOf(node, isKey, memberName, defName, serviceName, newTypeName, lastNonAnonymousFQDefName, path, parentName, isTermDef=false, ignoreInAPI=false) {
|
|
153
|
-
const {
|
|
155
|
+
function exposeTypeOf(node, isKey, memberName, defName, serviceName, newTypeName, lastNonAnonymousFQDefName, path, parentName, isTermDef = false, ignoreInAPI = false) {
|
|
156
|
+
const {
|
|
157
|
+
isExposable, typeDef, typeName, elements, isAnonymous,
|
|
158
|
+
} = isTypeExposable();
|
|
154
159
|
if (isExposable) {
|
|
155
160
|
// this is the name used to register the new type in csn.definitions
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
// eslint-disable-next-line no-nested-ternary
|
|
162
|
+
let fullQualifiedNewTypeName = isMultiSchema
|
|
163
|
+
? (node.type || (node.items?.type)
|
|
164
|
+
? getTypeNameInMultiSchema(node.type || (node.items?.type), serviceName)
|
|
165
|
+
: getAnonymousTypeNameInMultiSchema(newTypeName, parentName || defName))
|
|
166
|
+
: `${ serviceName }.${ newTypeName }`;
|
|
162
167
|
|
|
163
168
|
if (!isAnonymous) {
|
|
164
169
|
// as soon as we leave of the anonymous world,
|
|
165
170
|
// we're no longer in a key def => don't set notNull:true on named types
|
|
166
|
-
if(isKey)
|
|
171
|
+
if (isKey)
|
|
167
172
|
isKey = false;
|
|
168
173
|
// in case this was a named type and if the openness does not match the type definition
|
|
169
174
|
// expose the type as a new one not changing the original definition.
|
|
170
|
-
if(elements && node['@open'] != null && !!node['@open'] !== !!typeDef['@open'])
|
|
175
|
+
if (elements && node['@open'] != null && !!node['@open'] !== !!typeDef['@open'])
|
|
171
176
|
fullQualifiedNewTypeName += node['@open'] ? '_open' : '_closed';
|
|
172
177
|
lastNonAnonymousFQDefName = fullQualifiedNewTypeName;
|
|
173
178
|
}
|
|
@@ -178,84 +183,86 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
178
183
|
if (!exposedTypes[fullQualifiedNewTypeName]) {
|
|
179
184
|
setProp(node, '$NameClashReported', true);
|
|
180
185
|
error(null, path, { type: fullQualifiedNewTypeName, name: memberName },
|
|
181
|
-
|
|
182
|
-
return {
|
|
186
|
+
'Can\'t create artificial type $(TYPE) for $(NAME) because the name is already used');
|
|
187
|
+
return {
|
|
188
|
+
isExposable, typeDef, typeName, isAnonymous,
|
|
189
|
+
};
|
|
183
190
|
}
|
|
184
191
|
}
|
|
185
|
-
else {
|
|
192
|
+
else if (elements) {
|
|
186
193
|
/* Expose new structured type
|
|
187
194
|
* Treat items.elements as ordinary elements for now.
|
|
188
195
|
*/
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
setProp(newType, '$ignoreInAPI', ignoreInAPI);
|
|
196
|
+
newType = createNewStructType(elements);
|
|
197
|
+
// if using node enforces open/closed, set it on type
|
|
198
|
+
if (node['@open'] !== undefined)
|
|
199
|
+
newType['@open'] = node['@open'];
|
|
200
|
+
if (node.$location)
|
|
201
|
+
setProp(newType, '$location', node.$location);
|
|
202
|
+
ignoreInAPI ||= !isEdmPropertyRendered(node, options);
|
|
203
|
+
setProp(newType, '$ignoreInAPI', ignoreInAPI);
|
|
198
204
|
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
csn.definitions[fullQualifiedNewTypeName] = newType;
|
|
206
|
+
exposedTypes[fullQualifiedNewTypeName] = 1;
|
|
201
207
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
// Recurse into elements of 'type' (if any) and expose them as well (is needed)
|
|
209
|
+
Object.entries(newType.elements || {}).forEach(([ elemName, newElem ]) => {
|
|
210
|
+
if (node.elements && node.elements[elemName].$location)
|
|
211
|
+
setProp(newElem, '$location', node.elements[elemName].$location);
|
|
212
|
+
if (newElem.$path)
|
|
213
|
+
newElem.$path[1] = lastNonAnonymousFQDefName;
|
|
214
|
+
defName = typeDef.kind === 'type' ? typeName : defName;
|
|
215
|
+
{
|
|
216
|
+
const { isExposable, typeDef, typeName } = exposeTypeOf(
|
|
217
|
+
newElem, isKey, elemName, defName, serviceName,
|
|
218
|
+
getNewTypeName(newElem, elemName, newTypeName, serviceName), lastNonAnonymousFQDefName, path, fullQualifiedNewTypeName, isTermDef, ignoreInAPI
|
|
219
|
+
);
|
|
212
220
|
// if the type for the newElem was not exposed it may be a scalar type def from an external service that hasn't
|
|
213
221
|
// been caught by expandToFinalBaseType() (forODataNew must not modify external imported services)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
222
|
+
if (!isExposable && isBuiltinType(typeName) && !isBuiltinType((newElem.items?.type || newElem.type))) {
|
|
223
|
+
if (typeDef.items) {
|
|
224
|
+
newElem.items = typeDef.items;
|
|
225
|
+
delete newElem.type;
|
|
226
|
+
}
|
|
227
|
+
else if (newElem.items) {
|
|
228
|
+
newElem.items.type = typeName;
|
|
229
|
+
if (typeDef.enum)
|
|
230
|
+
newElem.items.enum = typeDef.enum;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
newElem.type = typeName;
|
|
234
|
+
if (typeDef.enum)
|
|
235
|
+
newElem.enum = typeDef.enum;
|
|
229
236
|
}
|
|
230
237
|
}
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// Annotations are propagated only from user defined structured
|
|
234
|
-
// types that need to be added to a service
|
|
235
|
-
if (!isAnonymous) {
|
|
236
|
-
copyAnnotations(typeDef, newType);
|
|
237
238
|
}
|
|
239
|
+
});
|
|
238
240
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
newType[n] = typeDef[n];
|
|
241
|
+
// Annotations are propagated only from user defined structured
|
|
242
|
+
// types that need to be added to a service
|
|
243
|
+
if (!isAnonymous)
|
|
244
|
+
copyAnnotations(typeDef, newType);
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
// if the origin type had items, add items to exposed type
|
|
248
|
+
if (typeDef.kind === 'type') {
|
|
249
|
+
if (typeDef.items) {
|
|
250
|
+
newType.items = { elements: newType.elements };
|
|
251
|
+
delete newType.elements;
|
|
251
252
|
}
|
|
252
|
-
newType.kind = 'type';
|
|
253
|
-
csn.definitions[fullQualifiedNewTypeName] = newType;
|
|
254
|
-
exposedTypes[fullQualifiedNewTypeName] = 1;
|
|
255
253
|
}
|
|
256
254
|
}
|
|
255
|
+
else if (isTermDef) {
|
|
256
|
+
newType = Object.create(null);
|
|
257
|
+
for (const n in typeDef)
|
|
258
|
+
newType[n] = typeDef[n];
|
|
259
|
+
|
|
260
|
+
newType.kind = 'type';
|
|
261
|
+
csn.definitions[fullQualifiedNewTypeName] = newType;
|
|
262
|
+
exposedTypes[fullQualifiedNewTypeName] = 1;
|
|
263
|
+
}
|
|
257
264
|
// adjust current node to new type
|
|
258
|
-
if(node.items) {
|
|
265
|
+
if (node.items) {
|
|
259
266
|
delete node.items.elements;
|
|
260
267
|
delete node.type;
|
|
261
268
|
node.items.type = fullQualifiedNewTypeName;
|
|
@@ -265,7 +272,9 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
265
272
|
node.type = fullQualifiedNewTypeName;
|
|
266
273
|
}
|
|
267
274
|
}
|
|
268
|
-
return {
|
|
275
|
+
return {
|
|
276
|
+
isExposable, typeDef, typeName, isAnonymous,
|
|
277
|
+
};
|
|
269
278
|
|
|
270
279
|
/**
|
|
271
280
|
* Check if the node's type can be exposed:
|
|
@@ -283,31 +292,37 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
283
292
|
* @returns {object} { isExposable, typeDef, typeName, elements, isAnonymous }
|
|
284
293
|
*/
|
|
285
294
|
function isTypeExposable() {
|
|
286
|
-
let typeName
|
|
295
|
+
let typeName;
|
|
287
296
|
let typeDef = node;
|
|
288
|
-
const elements = (node.items?.elements || node.elements)
|
|
297
|
+
const elements = (node.items?.elements || node.elements);
|
|
289
298
|
// anonymous structured type
|
|
290
|
-
if(elements)
|
|
291
|
-
return {
|
|
299
|
+
if (elements) {
|
|
300
|
+
return {
|
|
301
|
+
isExposable: true, typeDef, typeName, elements, isAnonymous: true,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
292
304
|
// named type, resolve the type to inspect it
|
|
293
305
|
let type = node.items?.type || node.type;
|
|
294
|
-
if(type) {
|
|
306
|
+
if (type) {
|
|
295
307
|
typeName = (type.ref && csnUtils.artifactRef(type)) || type;
|
|
296
|
-
const rc = {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
308
|
+
const rc = {
|
|
309
|
+
isExposable: true, typeDef, typeName, isAnonymous: false,
|
|
310
|
+
};
|
|
311
|
+
if ((!isBuiltinType(typeName) || typeName === 'cds.Map') && typeName !== special$self) {
|
|
312
|
+
typeDef = csnUtils.artifactRef(typeName, typeName);
|
|
313
|
+
rc.typeDef = typeDef;
|
|
314
|
+
if (!isArtifactInService(typeName, serviceName)) {
|
|
315
|
+
while (!isBuiltinType(typeName) || typeDef.$emtpyMapType) {
|
|
301
316
|
typeDef = csnUtils.artifactRef(typeName, typeName);
|
|
302
|
-
if(typeDef !== typeName) {
|
|
317
|
+
if (typeDef !== typeName) {
|
|
303
318
|
// Implementation note: For `type S: T:struct;`, elements from `T:struct` were already propagated to `S`.
|
|
304
|
-
if((isTermDef && typeDef.enum) || (rc.elements = (typeDef.items?.elements || typeDef.elements)) !== undefined)
|
|
319
|
+
if ((isTermDef && typeDef.enum) || (rc.elements = (typeDef.items?.elements || typeDef.elements)) !== undefined)
|
|
305
320
|
return rc;
|
|
306
321
|
type = typeDef.items?.type || typeDef.type;
|
|
307
322
|
typeName = (type.ref && csnUtils.artifactRef(type)) || type;
|
|
308
323
|
}
|
|
309
324
|
else {
|
|
310
|
-
throw new CompilerAssertion(`Debug me: ${typeName} not found`);
|
|
325
|
+
throw new CompilerAssertion(`Debug me: ${ typeName } not found`);
|
|
311
326
|
}
|
|
312
327
|
}
|
|
313
328
|
}
|
|
@@ -320,7 +335,9 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
320
335
|
// return rc;
|
|
321
336
|
// }
|
|
322
337
|
}
|
|
323
|
-
return {
|
|
338
|
+
return {
|
|
339
|
+
isExposable: false, typeDef, typeName, isAnonymous: false,
|
|
340
|
+
};
|
|
324
341
|
}
|
|
325
342
|
|
|
326
343
|
|
|
@@ -336,24 +353,24 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
336
353
|
if (typeService) {
|
|
337
354
|
// new type name without any prefixes
|
|
338
355
|
const typePlainName = defNameWithoutServiceOrContextName(typeName, typeService);
|
|
339
|
-
const newSchemaName = `${serviceName}.${typeService}`;
|
|
356
|
+
const newSchemaName = `${ serviceName }.${ typeService }`;
|
|
340
357
|
createSchema(newSchemaName);
|
|
341
358
|
// return the new type name
|
|
342
|
-
return `${newSchemaName}.${typePlainName.replace(/\./g, '_')}`;
|
|
343
|
-
} else {
|
|
344
|
-
const typeContext = csnUtils.getContextOfArtifact(typeName);
|
|
345
|
-
const typeNamespace = getNamespace(csn, typeName);
|
|
346
|
-
const newSchemaName = `${serviceName}.${typeContext || typeNamespace || fallBackSchemaName}`;
|
|
347
|
-
// new type name without any prefixes
|
|
348
|
-
const typePlainName = typeContext
|
|
349
|
-
? defNameWithoutServiceOrContextName(typeName, typeContext)
|
|
350
|
-
: (typeNamespace
|
|
351
|
-
? typeName.replace(typeNamespace + '.', '')
|
|
352
|
-
: typeName);
|
|
353
|
-
createSchema(newSchemaName);
|
|
354
|
-
// return the new type name
|
|
355
|
-
return `${newSchemaName}.${typePlainName.replace(/\./g, '_')}`;
|
|
359
|
+
return `${ newSchemaName }.${ typePlainName.replace(/\./g, '_') }`;
|
|
356
360
|
}
|
|
361
|
+
const typeContext = csnUtils.getContextOfArtifact(typeName);
|
|
362
|
+
const typeNamespace = getNamespace(csn, typeName);
|
|
363
|
+
const newSchemaName = `${ serviceName }.${ typeContext || typeNamespace || fallBackSchemaName }`;
|
|
364
|
+
// new type name without any prefixes
|
|
365
|
+
// eslint-disable-next-line no-nested-ternary
|
|
366
|
+
const typePlainName = typeContext
|
|
367
|
+
? defNameWithoutServiceOrContextName(typeName, typeContext)
|
|
368
|
+
: (typeNamespace
|
|
369
|
+
? typeName.replace(`${ typeNamespace }.`, '')
|
|
370
|
+
: typeName);
|
|
371
|
+
createSchema(newSchemaName);
|
|
372
|
+
// return the new type name
|
|
373
|
+
return `${ newSchemaName }.${ typePlainName.replace(/\./g, '_') }`;
|
|
357
374
|
}
|
|
358
375
|
|
|
359
376
|
/**
|
|
@@ -370,7 +387,7 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
370
387
|
const typePlainName = defNameWithoutServiceOrContextName(typeName, newSchemaName);
|
|
371
388
|
|
|
372
389
|
createSchema(newSchemaName);
|
|
373
|
-
return `${newSchemaName}.${typePlainName.replace(/\./g, '_')}`;
|
|
390
|
+
return `${ newSchemaName }.${ typePlainName.replace(/\./g, '_') }`;
|
|
374
391
|
}
|
|
375
392
|
|
|
376
393
|
/**
|
|
@@ -394,18 +411,18 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
394
411
|
setProp(type, '$exposedBy', 'typeExposure');
|
|
395
412
|
|
|
396
413
|
// Duplicate elements
|
|
397
|
-
Object.entries(elements).forEach(([elemName, element]) => {
|
|
414
|
+
Object.entries(elements).forEach(([ elemName, element ]) => {
|
|
398
415
|
const cloned = cloneCsnNonDict(element, options);
|
|
399
416
|
// if this was an anonymous sub element of a key, mark it as not nullable
|
|
400
|
-
if(isAnonymous && isKey && !cloned.key) {
|
|
401
|
-
if(cloned.target) {
|
|
402
|
-
if(cloned.cardinality === undefined)
|
|
417
|
+
if (isAnonymous && isKey && !cloned.key) {
|
|
418
|
+
if (cloned.target) {
|
|
419
|
+
if (cloned.cardinality === undefined)
|
|
403
420
|
cloned.cardinality = {};
|
|
404
421
|
cloned.cardinality.min = 1;
|
|
405
422
|
}
|
|
406
423
|
// if odata-unexpected-nullable-key is checking on min>1, this can
|
|
407
424
|
// be an else if
|
|
408
|
-
if(cloned.notNull === undefined)
|
|
425
|
+
if (cloned.notNull === undefined)
|
|
409
426
|
cloned.notNull = true;
|
|
410
427
|
}
|
|
411
428
|
type.elements[elemName] = cloned;
|
|
@@ -418,18 +435,19 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
418
435
|
* Calculate the name of the exposed type based on the information, the element can provide
|
|
419
436
|
* If the element is typed, use the type name
|
|
420
437
|
* else assume it's a de-anonymized type, concatenate the element name to the defName
|
|
421
|
-
|
|
438
|
+
*/
|
|
422
439
|
function getNewTypeName(element, elementName, typeNamePrefix, serviceName) {
|
|
423
440
|
// for the new type name node.type has precedence over node.items.type
|
|
424
441
|
const typeName = (!element?.elements && element?.type || !element?.items?.elements && element?.items?.type);
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
442
|
+
if (typeName) {
|
|
443
|
+
return `${ isMultiSchema
|
|
444
|
+
? typeName.split('.').pop() // use leaf element
|
|
445
|
+
: typeName.replace(/\./g, '_') }`; // concatenate path
|
|
446
|
+
}
|
|
447
|
+
return ( elementName // returns has no elementName, return the precalculated prefix
|
|
448
|
+
? `${ defNameWithoutServiceOrContextName(typeNamePrefix, serviceName).replace(/\./g, '_') }_${ elementName }`
|
|
449
|
+
: typeNamePrefix
|
|
450
|
+
);
|
|
433
451
|
}
|
|
434
452
|
}
|
|
435
453
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {string} srvOrCtx
|
|
7
7
|
*/
|
|
8
8
|
function defNameWithoutServiceOrContextName(name, srvOrCtx) {
|
|
9
|
-
return name.replace(`${srvOrCtx}.`, '');
|
|
9
|
+
return name.replace(`${ srvOrCtx }.`, '');
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -20,7 +20,7 @@ function defNameWithoutServiceOrContextName(name, srvOrCtx) {
|
|
|
20
20
|
* @param {string[]} services
|
|
21
21
|
*/
|
|
22
22
|
function getServiceOfArtifact(artName, services) {
|
|
23
|
-
return services.find(serviceName => artName.startsWith(`${serviceName}.`));
|
|
23
|
+
return services.find(serviceName => artName.startsWith(`${ serviceName }.`));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -29,7 +29,7 @@ function getServiceOfArtifact(artName, services) {
|
|
|
29
29
|
* @param {string} service Name of the service
|
|
30
30
|
*/
|
|
31
31
|
function isArtifactInService(artName, service) {
|
|
32
|
-
return typeof artName === 'string' ? artName.startsWith(`${service}.`) : false;
|
|
32
|
+
return typeof artName === 'string' ? artName.startsWith(`${ service }.`) : false;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -40,7 +40,7 @@ function isArtifactInService(artName, service) {
|
|
|
40
40
|
* @param {string[]} services
|
|
41
41
|
*/
|
|
42
42
|
function isArtifactInSomeService(artName, services) {
|
|
43
|
-
return services.some(serviceName => artName.startsWith(`${serviceName}.`));
|
|
43
|
+
return services.some(serviceName => artName.startsWith(`${ serviceName }.`));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -51,7 +51,8 @@ function isArtifactInSomeService(artName, services) {
|
|
|
51
51
|
* @param {string[]} services
|
|
52
52
|
*/
|
|
53
53
|
function isLocalizedArtifactInService(artName, services) {
|
|
54
|
-
if (!artName.startsWith('localized.'))
|
|
54
|
+
if (!artName.startsWith('localized.'))
|
|
55
|
+
return false;
|
|
55
56
|
return isArtifactInSomeService(artName.split('.').slice(1).join('.'), services);
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -61,4 +62,4 @@ module.exports = {
|
|
|
61
62
|
isArtifactInService,
|
|
62
63
|
isArtifactInSomeService,
|
|
63
64
|
isLocalizedArtifactInService,
|
|
64
|
-
}
|
|
65
|
+
};
|