@cap-js/ord 1.3.5 → 1.3.6
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/lib/build.js +49 -18
- package/lib/constants.js +11 -0
- package/lib/templates.js +54 -5
- package/package.json +5 -1
package/lib/build.js
CHANGED
|
@@ -3,6 +3,7 @@ const cds_dk = require("@sap/cds-dk");
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const { ord, getMetadata } = require("./index");
|
|
6
|
+
const cliProgress = require("cli-progress");
|
|
6
7
|
const { BUILD_DEFAULT_PATH, ORD_SERVICE_NAME, ORD_DOCUMENT_FILE_NAME } = require("./constants");
|
|
7
8
|
|
|
8
9
|
module.exports = class OrdBuildPlugin extends cds_dk.build.Plugin {
|
|
@@ -13,27 +14,58 @@ module.exports = class OrdBuildPlugin extends cds_dk.build.Plugin {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
async _writeResourcesFiles(resObj, model, promises) {
|
|
16
|
-
|
|
17
|
-
if (resource.ordId.includes(ORD_SERVICE_NAME)
|
|
18
|
-
|
|
17
|
+
let totalFiles = resObj.reduce((total, resource) => {
|
|
18
|
+
if (!resource.ordId.includes(ORD_SERVICE_NAME) && resource.resourceDefinitions) {
|
|
19
|
+
return total + resource.resourceDefinitions.length;
|
|
19
20
|
}
|
|
21
|
+
return total;
|
|
22
|
+
}, 0);
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
const progressBar = new cliProgress.SingleBar({
|
|
25
|
+
format: "Processing resourcesFiles [{bar}] {percentage}% | {value}/{total} | ETA: {eta}s",
|
|
26
|
+
barCompleteChar: "█",
|
|
27
|
+
barIncompleteChar: "░",
|
|
28
|
+
stopOnComplete: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
let warnings = [];
|
|
32
|
+
let completed = 0;
|
|
33
|
+
progressBar.start(totalFiles, 0);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
for (const resource of resObj) {
|
|
37
|
+
if (resource.ordId.includes(ORD_SERVICE_NAME) || !resource.resourceDefinitions) continue;
|
|
38
|
+
for (const resourceDefinition of resource.resourceDefinitions) {
|
|
39
|
+
try {
|
|
40
|
+
const { _, response } = await getMetadata(resourceDefinition.url, model); // eslint-disable-line no-unused-vars
|
|
41
|
+
const fileName = path
|
|
42
|
+
.join(resource.ordId, resourceDefinition.url.split("/").pop())
|
|
43
|
+
.replace(/:/g, "_");
|
|
44
|
+
promises.push(
|
|
45
|
+
this.write(response)
|
|
46
|
+
.to(fileName)
|
|
47
|
+
.catch((err) => {
|
|
48
|
+
warnings.push(`Error writing file ${fileName}: ${err.message}`);
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
completed++;
|
|
52
|
+
progressBar.update(completed);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
completed++;
|
|
55
|
+
progressBar.update(completed);
|
|
56
|
+
warnings.push(`Error getting metadata for ${resourceDefinition.url}: ${error.message}`);
|
|
57
|
+
} finally {
|
|
58
|
+
completed++;
|
|
59
|
+
progressBar.update(completed);
|
|
60
|
+
}
|
|
35
61
|
}
|
|
36
62
|
}
|
|
63
|
+
await Promise.all(promises);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
warnings.push("Failed to process resources: " + error.message);
|
|
66
|
+
throw error;
|
|
67
|
+
} finally {
|
|
68
|
+
progressBar.stop();
|
|
37
69
|
}
|
|
38
70
|
}
|
|
39
71
|
|
|
@@ -79,7 +111,6 @@ module.exports = class OrdBuildPlugin extends cds_dk.build.Plugin {
|
|
|
79
111
|
if (ordDocument.eventResources && ordDocument.eventResources.length > 0) {
|
|
80
112
|
await this._writeResourcesFiles(ordDocument.eventResources, model, promises);
|
|
81
113
|
}
|
|
82
|
-
|
|
83
114
|
return Promise.all(promises);
|
|
84
115
|
}
|
|
85
116
|
};
|
package/lib/constants.js
CHANGED
|
@@ -83,6 +83,14 @@ const RESOURCE_VISIBILITY = Object.freeze({
|
|
|
83
83
|
private: "private",
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
const ALLOWED_VISIBILITY = Object.values(RESOURCE_VISIBILITY);
|
|
87
|
+
|
|
88
|
+
const IMPLEMENTATIONSTANDARD_VERSIONS = Object.freeze({
|
|
89
|
+
v1: "sap:ord-document-api:v1",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const SUPPORTED_IMPLEMENTATIONSTANDARD_VERSIONS = Object.values(IMPLEMENTATIONSTANDARD_VERSIONS);
|
|
93
|
+
|
|
86
94
|
const SHORT_DESCRIPTION_PREFIX = "Short description of ";
|
|
87
95
|
|
|
88
96
|
const SEM_VERSION_REGEX =
|
|
@@ -111,6 +119,9 @@ module.exports = {
|
|
|
111
119
|
ORD_RESOURCE_TYPE,
|
|
112
120
|
ORD_SERVICE_NAME,
|
|
113
121
|
RESOURCE_VISIBILITY,
|
|
122
|
+
ALLOWED_VISIBILITY,
|
|
123
|
+
IMPLEMENTATIONSTANDARD_VERSIONS,
|
|
124
|
+
SUPPORTED_IMPLEMENTATIONSTANDARD_VERSIONS,
|
|
114
125
|
SHORT_DESCRIPTION_PREFIX,
|
|
115
126
|
SEM_VERSION_REGEX,
|
|
116
127
|
};
|
package/lib/templates.js
CHANGED
|
@@ -13,6 +13,8 @@ const {
|
|
|
13
13
|
ORD_ODM_ENTITY_NAME_ANNOTATION,
|
|
14
14
|
ORD_RESOURCE_TYPE,
|
|
15
15
|
RESOURCE_VISIBILITY,
|
|
16
|
+
ALLOWED_VISIBILITY,
|
|
17
|
+
SUPPORTED_IMPLEMENTATIONSTANDARD_VERSIONS,
|
|
16
18
|
SEM_VERSION_REGEX,
|
|
17
19
|
SHORT_DESCRIPTION_PREFIX,
|
|
18
20
|
CONTENT_MERGE_KEY,
|
|
@@ -139,7 +141,7 @@ function _getEntityVersion(entity) {
|
|
|
139
141
|
const entityVersion = entity.ordId.split(":").pop();
|
|
140
142
|
const version = entityVersion.replace("v", "") + ".0.0"; // TODO: version can be stated/overwritten by annotation
|
|
141
143
|
if (!SEM_VERSION_REGEX.test(version)) {
|
|
142
|
-
Logger.warn(
|
|
144
|
+
Logger.warn("Entity version", version, "is not a valid semantic version.");
|
|
143
145
|
}
|
|
144
146
|
return version;
|
|
145
147
|
}
|
|
@@ -240,16 +242,37 @@ const createEntityTypeTemplate = (appConfig, packageIds, entity) => {
|
|
|
240
242
|
};
|
|
241
243
|
};
|
|
242
244
|
|
|
243
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Determines the visibility of a resource based on provided extensions, definition, and default visibility.
|
|
247
|
+
*
|
|
248
|
+
* The function checks for custom visibility values, validates the default visibility,
|
|
249
|
+
* and applies specific rules based on the resource's definition and extensions.
|
|
250
|
+
*
|
|
251
|
+
* @param {Object} ordExtensions - Extensions object containing resource metadata.
|
|
252
|
+
* @param {Object} definition - The resource definition object.
|
|
253
|
+
* @param {string} [defaultVisibility=RESOURCE_VISIBILITY.public] - The default visibility value.
|
|
254
|
+
* @returns {string} The resolved visibility value for the resource.
|
|
255
|
+
*/
|
|
256
|
+
function _handleVisibility(ordExtensions, definition, defaultVisibility = RESOURCE_VISIBILITY.public) {
|
|
244
257
|
let visibility;
|
|
258
|
+
//check for supported custom visibility value in defaultVisibility variable
|
|
259
|
+
if (!ALLOWED_VISIBILITY.includes(defaultVisibility)) {
|
|
260
|
+
Logger.warn("Default visibility", defaultVisibility, "is not supported. Using", RESOURCE_VISIBILITY.public, "as fallback.");
|
|
261
|
+
defaultVisibility = RESOURCE_VISIBILITY.public;
|
|
262
|
+
}
|
|
263
|
+
// Determine visibility
|
|
245
264
|
if (isPrimaryDataProductService(definition)) {
|
|
246
265
|
visibility = RESOURCE_VISIBILITY.internal;
|
|
247
266
|
} else if (ordExtensions.visibility) {
|
|
248
267
|
visibility = ordExtensions.visibility;
|
|
249
268
|
} else if (definition[ORD_EXTENSIONS_PREFIX + "visibility"]) {
|
|
250
269
|
visibility = definition[ORD_EXTENSIONS_PREFIX + "visibility"];
|
|
251
|
-
} else {
|
|
270
|
+
} else if (SUPPORTED_IMPLEMENTATIONSTANDARD_VERSIONS.includes(ordExtensions.implementationStandard)) {
|
|
271
|
+
// if the implementationStandard is for example sap:ord-document-api:v1, it should be public by default
|
|
252
272
|
visibility = RESOURCE_VISIBILITY.public;
|
|
273
|
+
} else if (ALLOWED_VISIBILITY.includes(defaultVisibility)) {
|
|
274
|
+
// Default visibility from config file
|
|
275
|
+
visibility = defaultVisibility;
|
|
253
276
|
}
|
|
254
277
|
return visibility;
|
|
255
278
|
}
|
|
@@ -267,7 +290,7 @@ function _handleVisibility(ordExtensions, definition) {
|
|
|
267
290
|
*/
|
|
268
291
|
const createAPIResourceTemplate = (serviceName, serviceDefinition, appConfig, packageIds, accessStrategies) => {
|
|
269
292
|
const ordExtensions = readORDExtensions(serviceDefinition);
|
|
270
|
-
const visibility = _handleVisibility(ordExtensions, serviceDefinition);
|
|
293
|
+
const visibility = _handleVisibility(ordExtensions, serviceDefinition, appConfig.env?.defaultVisibility);
|
|
271
294
|
const packageId = _getPackageID(appConfig.ordNamespace, packageIds, ORD_RESOURCE_TYPE.api, visibility);
|
|
272
295
|
|
|
273
296
|
const paths = _generatePaths(serviceName, serviceDefinition);
|
|
@@ -287,6 +310,7 @@ const createAPIResourceTemplate = (serviceName, serviceDefinition, appConfig, pa
|
|
|
287
310
|
}
|
|
288
311
|
|
|
289
312
|
const entityTypeMappings = _getEntityTypeMappings(serviceDefinition);
|
|
313
|
+
const exposedEntityTypes = _getExposedEntityTypes(serviceDefinition);
|
|
290
314
|
|
|
291
315
|
let obj = {
|
|
292
316
|
ordId,
|
|
@@ -306,6 +330,7 @@ const createAPIResourceTemplate = (serviceName, serviceDefinition, appConfig, pa
|
|
|
306
330
|
supported: "no",
|
|
307
331
|
},
|
|
308
332
|
...(entityTypeMappings ? { entityTypeMappings } : {}),
|
|
333
|
+
...(exposedEntityTypes ? { exposedEntityTypes } : []),
|
|
309
334
|
...ordExtensions,
|
|
310
335
|
};
|
|
311
336
|
|
|
@@ -349,10 +374,11 @@ const createAPIResourceTemplate = (serviceName, serviceDefinition, appConfig, pa
|
|
|
349
374
|
*/
|
|
350
375
|
const createEventResourceTemplate = (serviceName, serviceDefinition, appConfig, packageIds, accessStrategies) => {
|
|
351
376
|
const ordExtensions = readORDExtensions(serviceDefinition);
|
|
352
|
-
const visibility = _handleVisibility(ordExtensions, serviceDefinition);
|
|
377
|
+
const visibility = _handleVisibility(ordExtensions, serviceDefinition, appConfig.env?.defaultVisibility);
|
|
353
378
|
const packageId = _getPackageID(appConfig.ordNamespace, packageIds, ORD_RESOURCE_TYPE.event, visibility);
|
|
354
379
|
const ordId = `${appConfig.ordNamespace}:eventResource:${_getGroupNameWithNestedNamespace(serviceDefinition, appConfig)}:v1`;
|
|
355
380
|
const entityTypeMappings = _getEntityTypeMappings(serviceDefinition);
|
|
381
|
+
const exposedEntityTypes = _getExposedEntityTypes(serviceDefinition);
|
|
356
382
|
|
|
357
383
|
let obj = {
|
|
358
384
|
ordId,
|
|
@@ -376,6 +402,7 @@ const createEventResourceTemplate = (serviceName, serviceDefinition, appConfig,
|
|
|
376
402
|
],
|
|
377
403
|
extensible: { supported: "no" },
|
|
378
404
|
...(entityTypeMappings ? { entityTypeMappings } : {}),
|
|
405
|
+
...(exposedEntityTypes ? { exposedEntityTypes } : []),
|
|
379
406
|
...ordExtensions,
|
|
380
407
|
};
|
|
381
408
|
|
|
@@ -408,6 +435,26 @@ function _getEntityTypeMappings(definitionObj) {
|
|
|
408
435
|
}
|
|
409
436
|
}
|
|
410
437
|
|
|
438
|
+
function _getExposedEntityTypes(definitionObj) {
|
|
439
|
+
if (!definitionObj.entities) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const entities = Object.values(definitionObj.entities).flatMap((entity) => {
|
|
443
|
+
const entityData = _flattenEntityGraph(entity).map(createEntityTypeMappingsItemTemplate);
|
|
444
|
+
return _.uniqBy(entityData, CONTENT_MERGE_KEY);
|
|
445
|
+
});
|
|
446
|
+
const exposedEntityTypes = _.uniqBy(entities, CONTENT_MERGE_KEY)
|
|
447
|
+
.filter((entity) => entity !== undefined)
|
|
448
|
+
.map(({ ordId }) => ({
|
|
449
|
+
ordId,
|
|
450
|
+
}));
|
|
451
|
+
if (exposedEntityTypes.length > 0) {
|
|
452
|
+
return exposedEntityTypes;
|
|
453
|
+
} else {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
411
458
|
function _flattenEntityGraph(currentEntity, processedEntities = []) {
|
|
412
459
|
if (!currentEntity.associations) {
|
|
413
460
|
return [currentEntity];
|
|
@@ -481,5 +528,7 @@ module.exports = {
|
|
|
481
528
|
createEventResourceTemplate,
|
|
482
529
|
_getPackageID,
|
|
483
530
|
_getEntityTypeMappings,
|
|
531
|
+
_getExposedEntityTypes,
|
|
484
532
|
_propagateORDVisibility,
|
|
533
|
+
_handleVisibility,
|
|
485
534
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js/ord",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"description": "CAP Plugin for generating ORD document.",
|
|
5
5
|
"repository": "cap-js/ord",
|
|
6
6
|
"author": "SAP SE (https://www.sap.com)",
|
|
@@ -35,12 +35,16 @@
|
|
|
35
35
|
"@cap-js/asyncapi": "^1.0.3",
|
|
36
36
|
"@cap-js/openapi": "^1.2.1",
|
|
37
37
|
"bcrypt": "^5.1.1",
|
|
38
|
+
"cli-progress": "^3.12.0",
|
|
38
39
|
"lodash": "^4.17.21"
|
|
39
40
|
},
|
|
40
41
|
"cds": {
|
|
41
42
|
"requires": {
|
|
42
43
|
"SAP ORD Service": {
|
|
43
44
|
"model": "@cap-js/ord/lib/ord-service"
|
|
45
|
+
},
|
|
46
|
+
"[java]": {
|
|
47
|
+
"SAP ORD Service": false
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
}
|