@sap/cds-dk 8.1.1 → 8.2.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 +58 -0
- package/bin/bind.js +44 -11
- package/bin/cds-tsx.js +2 -0
- package/bin/cds.js +5 -3
- package/bin/compile/index.js +2 -1
- package/bin/deploy/index.js +19 -1
- package/bin/import.js +13 -4
- package/bin/init.js +1 -1
- package/bin/version.js +1 -0
- package/bin/watch.js +2 -2
- package/lib/bind/bindingManager.js +1 -1
- package/lib/bind/cfKeyProvider.js +1 -1
- package/lib/build/buildTaskProviderFactory.js +9 -3
- package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/service-instance/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/service-instance/values.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +2 -2
- package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +1 -1
- package/lib/build/provider/hana/2migration.js +6 -6
- package/lib/build/provider/nodejs/index.js +5 -4
- package/lib/build/util.js +2 -1
- package/lib/compile/to-mermaid.js +4 -6
- package/lib/import/common.js +16 -18
- package/lib/import/message.js +6 -5
- package/lib/import/odata/index.js +1 -1
- package/lib/import/odata/v2parser.js +18 -17
- package/lib/import/odata/v4parser.js +62 -62
- package/lib/init/constants.js +3 -2
- package/lib/init/mvn.js +43 -6
- package/lib/init/plugin.js +1 -1
- package/lib/init/projectReader.js +1 -1
- package/lib/init/template/approuter/files/containerize.yaml.hbs +5 -0
- package/lib/init/template/cloud-logging/files/mta.yaml.hbs +25 -0
- package/lib/init/template/cloud-logging/files/package.json +14 -0
- package/lib/init/template/cloud-logging/index.js +80 -0
- package/lib/init/template/containerize/files/containerize.yaml.hbs +5 -0
- package/lib/init/template/dynatrace/files/mta.yaml.hbs +24 -0
- package/lib/init/template/dynatrace/files/package.json.hbs +14 -0
- package/lib/init/template/dynatrace/files/sidecar.package.json +0 -0
- package/lib/init/template/dynatrace/index.js +55 -0
- package/lib/init/template/hana/files/containerize.yaml.hbs +5 -0
- package/lib/init/template/hana/files/package.json.hbs +5 -3
- package/lib/init/template/handler/index.js +22 -0
- package/lib/init/template/helm/index.js +5 -1
- package/lib/init/template/html5-repo/index.js +5 -0
- package/lib/init/template/http/index.js +1 -1
- package/lib/init/template/java/index.js +2 -2
- package/lib/init/template/multitenancy/files/containerize.yaml.hbs +5 -0
- package/lib/init/template/portal/files/portal-site/CommonDataModel.json.hbs +2 -2
- package/lib/init/template/portal/files/values.yaml.hbs +43 -0
- package/lib/init/template/portal/index.js +4 -2
- package/lib/init/template/telemetry/index.js +19 -0
- package/lib/init/template/typescript/files/package.json +1 -3
- package/lib/mtx/auth_manager.js +12 -15
- package/lib/mtx/settings_manager.js +5 -2
- package/lib/mtx/util/logging.js +4 -4
- package/lib/util/cf.js +15 -5
- package/lib/util/command.js +3 -3
- package/lib/watch/livereload-server.js +3 -3
- package/lib/watch/node-watch.js +3 -3
- package/npm-shrinkwrap.json +32 -23
- package/package.json +3 -2
- package/readme.md +2 -2
|
@@ -61,7 +61,7 @@ async function edmx2csn(edmx, filename, context) {
|
|
|
61
61
|
namespace = (index > 0) ? result[1].substring(0, index) : result[1];
|
|
62
62
|
}
|
|
63
63
|
else {
|
|
64
|
-
// to support edmx without entities -
|
|
64
|
+
// to support edmx without entities - unbound actions and functions only
|
|
65
65
|
console.warn('There are no entities in the OData model');
|
|
66
66
|
let schema = edmx.match(/(<Schema [^>]*>)/);
|
|
67
67
|
if (!schema) throw new Error(messages.INVALID_EDMX_METADATA);
|
|
@@ -303,21 +303,21 @@ function _getFunctionAttributes(functionImport, serviceNamespaceParam) {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
function _extractFunctionImport(functionImport, parserContext) {
|
|
306
|
-
//extracting the
|
|
307
|
-
let
|
|
306
|
+
//extracting the bound and unbound function import
|
|
307
|
+
let boundFunctionImports = [];
|
|
308
308
|
let entityName;
|
|
309
309
|
Object.keys(functionImport).forEach((key) => {
|
|
310
310
|
if (key === "_attributes") {
|
|
311
311
|
if (functionImport[key]["sap:action-for"]) {
|
|
312
|
-
//storing
|
|
312
|
+
//storing bound function imports
|
|
313
313
|
entityName = _extractEntityFromNamespace(functionImport[key]["sap:action-for"]);
|
|
314
|
-
|
|
314
|
+
boundFunctionImports = (parserContext.allFunctionImportsMap[entityName])
|
|
315
315
|
? parserContext.allFunctionImportsMap[entityName] : [];
|
|
316
|
-
|
|
317
|
-
parserContext.allFunctionImportsMap[entityName] =
|
|
316
|
+
boundFunctionImports.push(_getFunctionAttributes(functionImport, ""));
|
|
317
|
+
parserContext.allFunctionImportsMap[entityName] = boundFunctionImports;
|
|
318
318
|
}
|
|
319
319
|
else {
|
|
320
|
-
//storing
|
|
320
|
+
//storing unbound function imports
|
|
321
321
|
parserContext.allFunctionImports.push(
|
|
322
322
|
_getFunctionAttributes(functionImport, parserContext.serviceNamespace + ".")
|
|
323
323
|
);
|
|
@@ -786,7 +786,7 @@ function _parseParametersFunctionImport(parameters, entityKeysList, parserContex
|
|
|
786
786
|
return csn;
|
|
787
787
|
}
|
|
788
788
|
|
|
789
|
-
function _getFunctionImport(functionImport,
|
|
789
|
+
function _getFunctionImport(functionImport, isBound, entityKeysList, parserContext) {
|
|
790
790
|
let noValue;
|
|
791
791
|
let csn = "";
|
|
792
792
|
csn = csn + '"' + functionImport[0] + '": { \n';
|
|
@@ -803,10 +803,10 @@ function _getFunctionImport(functionImport, isBounded, entityKeysList, parserCon
|
|
|
803
803
|
return "";
|
|
804
804
|
}
|
|
805
805
|
csn = csn + '"';
|
|
806
|
-
if (!
|
|
806
|
+
if (!isBound) csn = csn + ',\n"@cds.external": true';
|
|
807
807
|
|
|
808
808
|
if (functionImport[3] !== -1) {
|
|
809
|
-
if (
|
|
809
|
+
if (isBound === 0 || (isBound === 1 && functionImport[3] instanceof Array)) {
|
|
810
810
|
let parametersCsn = _parseParametersFunctionImport(functionImport[3], entityKeysList, parserContext);
|
|
811
811
|
if (parametersCsn != "") {
|
|
812
812
|
csn = csn + ", \n";
|
|
@@ -846,12 +846,12 @@ function _getFunctionImport(functionImport, isBounded, entityKeysList, parserCon
|
|
|
846
846
|
return csn;
|
|
847
847
|
}
|
|
848
848
|
|
|
849
|
-
function _getAllFunctionImports(functionImports,
|
|
849
|
+
function _getAllFunctionImports(functionImports, isBound, entityKeysList, parserContext) {
|
|
850
850
|
let functionImportsCSN = "";
|
|
851
851
|
let i;
|
|
852
852
|
let functionImportCSN = "";
|
|
853
853
|
for (i = 0; i < functionImports.length; i++) {
|
|
854
|
-
functionImportCSN = _getFunctionImport(functionImports[i],
|
|
854
|
+
functionImportCSN = _getFunctionImport(functionImports[i], isBound, entityKeysList, parserContext);
|
|
855
855
|
functionImportsCSN = functionImportsCSN + functionImportCSN;
|
|
856
856
|
if (i !== functionImports.length - 1 && functionImportCSN !== "") {
|
|
857
857
|
functionImportsCSN = functionImportsCSN + ",\n";
|
|
@@ -1439,7 +1439,7 @@ function _constructServiceEntity(
|
|
|
1439
1439
|
}
|
|
1440
1440
|
}
|
|
1441
1441
|
|
|
1442
|
-
// if the function import is
|
|
1442
|
+
// if the function import is bound to entitySet
|
|
1443
1443
|
if (parserContext.allFunctionImportsMap[entityName]) {
|
|
1444
1444
|
csnEntity = csnEntity + ', \n "actions": {\n';
|
|
1445
1445
|
csnEntity = csnEntity +
|
|
@@ -1448,7 +1448,7 @@ function _constructServiceEntity(
|
|
|
1448
1448
|
);
|
|
1449
1449
|
csnEntity = csnEntity + "}";
|
|
1450
1450
|
}
|
|
1451
|
-
// if the function import is
|
|
1451
|
+
// if the function import is bound to entityType
|
|
1452
1452
|
else if (parserContext.allFunctionImportsMap[_extractEntityFromNamespace(parserContext.allEntitySetMap[entityName])]) {
|
|
1453
1453
|
csnEntity = csnEntity + ', \n "actions": {\n';
|
|
1454
1454
|
csnEntity = csnEntity +
|
|
@@ -1650,7 +1650,8 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, parserContext) {
|
|
|
1650
1650
|
}
|
|
1651
1651
|
|
|
1652
1652
|
// Construct CSN entity based on EDMX entity
|
|
1653
|
-
|
|
1653
|
+
let entityJson = jsonObj["edmx:Edmx"]["edmx:DataServices"].Schema.EntityType;
|
|
1654
|
+
if (!Array.isArray(entityJson)) entityJson = [entityJson];
|
|
1654
1655
|
const definitions = [];
|
|
1655
1656
|
|
|
1656
1657
|
if (parserContext.mockServerUc) {
|
|
@@ -1695,9 +1696,9 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, parserContext) {
|
|
|
1695
1696
|
definitions.push(_getServiceComplexTypes(parserContext));
|
|
1696
1697
|
}
|
|
1697
1698
|
|
|
1698
|
-
// if there are
|
|
1699
|
+
// if there are unbound function imports
|
|
1699
1700
|
if (Object.keys(parserContext.allFunctionImports).length > 0) {
|
|
1700
|
-
// passing 0 for
|
|
1701
|
+
// passing 0 for unbound actions/functions and 0 for entityKeysList
|
|
1701
1702
|
definitions.push(
|
|
1702
1703
|
_getAllFunctionImports(parserContext.allFunctionImports, 0, 0, parserContext)
|
|
1703
1704
|
);
|
|
@@ -83,8 +83,8 @@ const known_vocabularies = {
|
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
function _initialize(parserContext) {
|
|
86
|
-
parserContext.
|
|
87
|
-
parserContext.
|
|
86
|
+
parserContext.unboundActions = {};
|
|
87
|
+
parserContext.unboundFunctions = {};
|
|
88
88
|
parserContext.entityTypes = [];
|
|
89
89
|
parserContext.entityTypeOpenEntries = [];
|
|
90
90
|
parserContext.complexTypeOpenEntries = [];
|
|
@@ -100,8 +100,8 @@ function _initialize(parserContext) {
|
|
|
100
100
|
parserContext.schemaAliasToNamespace = {};
|
|
101
101
|
parserContext.schemaToSchemaDataIndex = {};
|
|
102
102
|
parserContext.vocabNamespaceToAlias = {};
|
|
103
|
-
parserContext.
|
|
104
|
-
parserContext.
|
|
103
|
+
parserContext.entityToBoundActions = {};
|
|
104
|
+
parserContext.entityToBoundFunctions = {};
|
|
105
105
|
parserContext.entityContainerAnnotations = {};
|
|
106
106
|
parserContext.mockServerUc = true;
|
|
107
107
|
parserContext.beta = false;
|
|
@@ -911,9 +911,9 @@ function _parseParameterAndReturnTypeContent(elementObject, parserContext) {
|
|
|
911
911
|
}
|
|
912
912
|
}
|
|
913
913
|
|
|
914
|
-
function
|
|
914
|
+
function _generateCSNForBoundActionFunction(actionFunctionObject, kind, parserContext) {
|
|
915
915
|
const csnObj = {};
|
|
916
|
-
const
|
|
916
|
+
const isBound = actionFunctionObject.$IsBound;
|
|
917
917
|
const parameters = actionFunctionObject.$Parameter;
|
|
918
918
|
const returnType = actionFunctionObject.$ReturnType;
|
|
919
919
|
|
|
@@ -932,7 +932,7 @@ function _generateCSNForBoundedActionFunction(actionFunctionObject, kind, parser
|
|
|
932
932
|
* NOTE: Edm.Stream can act as the binding parameter for action/function
|
|
933
933
|
* We don't have any example for it, so not handled as of now
|
|
934
934
|
*/
|
|
935
|
-
if (
|
|
935
|
+
if (isBound && index === 0) {
|
|
936
936
|
if (isCollection) {
|
|
937
937
|
csnObj.params[parameters[index].$Name].items.type = '$self';
|
|
938
938
|
}
|
|
@@ -949,20 +949,20 @@ function _generateCSNForBoundedActionFunction(actionFunctionObject, kind, parser
|
|
|
949
949
|
return csnObj;
|
|
950
950
|
}
|
|
951
951
|
|
|
952
|
-
function
|
|
953
|
-
const
|
|
952
|
+
function _parseBoundActionFunction(schemaData, csnObj, kind, parserContext) {
|
|
953
|
+
const boundObject = (kind === 'action') ? parserContext.entityToBoundActions : parserContext.entityToBoundFunctions;
|
|
954
954
|
|
|
955
|
-
Object.keys(
|
|
955
|
+
Object.keys(boundObject).forEach(fqEntityName => {
|
|
956
956
|
const [schemaName, ] = _extractSchemaNameAndElementName(fqEntityName);
|
|
957
957
|
|
|
958
958
|
if (schemaName === schemaData.$SchemaNamespace) {
|
|
959
|
-
const actionFunctionObjectList =
|
|
959
|
+
const actionFunctionObjectList = boundObject[fqEntityName];
|
|
960
960
|
|
|
961
961
|
if (!csnObj[fqEntityName].actions) {
|
|
962
962
|
csnObj[fqEntityName].actions = {};
|
|
963
963
|
}
|
|
964
964
|
Object.keys(actionFunctionObjectList).forEach(actionFunctionName => {
|
|
965
|
-
csnObj[fqEntityName].actions[actionFunctionName] =
|
|
965
|
+
csnObj[fqEntityName].actions[actionFunctionName] = _generateCSNForBoundActionFunction(
|
|
966
966
|
actionFunctionObjectList[actionFunctionName], kind, parserContext
|
|
967
967
|
);
|
|
968
968
|
});
|
|
@@ -970,15 +970,15 @@ function _parseBoundedActionFunction(schemaData, csnObj, kind, parserContext) {
|
|
|
970
970
|
});
|
|
971
971
|
}
|
|
972
972
|
|
|
973
|
-
function
|
|
974
|
-
const
|
|
973
|
+
function _parseUnboundActionFunction(schemaData, kind, parserContext) {
|
|
974
|
+
const unboundObject = (kind === 'action') ? parserContext.unboundActions : parserContext.unboundFunctions;
|
|
975
975
|
const csnObj = {};
|
|
976
976
|
|
|
977
|
-
Object.keys(
|
|
977
|
+
Object.keys(unboundObject).forEach(fqName => {
|
|
978
978
|
const [schemaName, ] = _extractSchemaNameAndElementName(fqName);
|
|
979
979
|
|
|
980
980
|
if (schemaName === schemaData.$SchemaNamespace) {
|
|
981
|
-
const actionFunctionObject =
|
|
981
|
+
const actionFunctionObject = unboundObject[fqName];
|
|
982
982
|
const parameters = actionFunctionObject.$Parameter;
|
|
983
983
|
const returnType = actionFunctionObject.$ReturnType;
|
|
984
984
|
|
|
@@ -1129,7 +1129,7 @@ function _resolveActionFunctionAnnotationTarget(targetPath, csnDefs, hasParamete
|
|
|
1129
1129
|
const fqActFunName = _resolveAliasedElementName(elemNameList[0], parserContext);
|
|
1130
1130
|
const paramName = hasParameter ? targetPath.split('/')[1] : null;
|
|
1131
1131
|
|
|
1132
|
-
//
|
|
1132
|
+
// unbound action or function
|
|
1133
1133
|
if (csnDefs[fqActFunName]) {
|
|
1134
1134
|
// with parameter
|
|
1135
1135
|
if (hasParameter && csnDefs[fqActFunName].params[paramName]) {
|
|
@@ -1140,7 +1140,7 @@ function _resolveActionFunctionAnnotationTarget(targetPath, csnDefs, hasParamete
|
|
|
1140
1140
|
return csnDefs[fqActFunName];
|
|
1141
1141
|
}
|
|
1142
1142
|
}
|
|
1143
|
-
//
|
|
1143
|
+
// bound action or function
|
|
1144
1144
|
else {
|
|
1145
1145
|
const [, elementName] = _extractSchemaNameAndElementName(fqActFunName);
|
|
1146
1146
|
const isCollection = elemNameList[1] === 'Collection' ? true : false;
|
|
@@ -1388,10 +1388,10 @@ function _collectAllParameters(dataObjList) {
|
|
|
1388
1388
|
* @param {Object} parserContext
|
|
1389
1389
|
*
|
|
1390
1390
|
* Scenarios:
|
|
1391
|
-
* 1.
|
|
1392
|
-
* 2.
|
|
1391
|
+
* 1. Unbound Actions can't have collision. Action name must be unique.
|
|
1392
|
+
* 2. Unbound Functions can have collision; capture the max number of parameters.
|
|
1393
1393
|
*/
|
|
1394
|
-
function
|
|
1394
|
+
function _populateUnboundActionFunction(isAction, fqName, schemaDataList, parserContext) {
|
|
1395
1395
|
let [schemaName, actFunName] = _extractSchemaNameAndElementName(fqName);
|
|
1396
1396
|
let indexOfSchema;
|
|
1397
1397
|
[indexOfSchema, schemaName] = _getIndexAndNamespaceOfSchema(fqName, schemaName, parserContext);
|
|
@@ -1401,33 +1401,33 @@ function _populateUnboundedActionFunction(isAction, fqName, schemaDataList, pars
|
|
|
1401
1401
|
|
|
1402
1402
|
if (isAction) {
|
|
1403
1403
|
if (dataList.length === 1) {
|
|
1404
|
-
parserContext.
|
|
1404
|
+
parserContext.unboundActions[fqName] = actionFunctionObject;
|
|
1405
1405
|
}
|
|
1406
1406
|
else {
|
|
1407
|
-
throw new Error(messages.
|
|
1407
|
+
throw new Error(messages.UNBOUND_ACTION_COLLISION + `'${actFunName}' of Schema: ${schemaName} `);
|
|
1408
1408
|
}
|
|
1409
1409
|
}
|
|
1410
1410
|
else {
|
|
1411
1411
|
if (dataList.length > 1) {
|
|
1412
1412
|
actionFunctionObject['$Parameter'] = _collectAllParameters(dataList);
|
|
1413
|
-
parserContext.
|
|
1413
|
+
parserContext.unboundFunctions[fqName] = actionFunctionObject;
|
|
1414
1414
|
}
|
|
1415
1415
|
else {
|
|
1416
|
-
parserContext.
|
|
1416
|
+
parserContext.unboundFunctions[fqName] = actionFunctionObject;
|
|
1417
1417
|
}
|
|
1418
1418
|
// throw error if the return type is missing
|
|
1419
|
-
if (!parserContext.
|
|
1419
|
+
if (!parserContext.unboundFunctions[fqName].$ReturnType) {
|
|
1420
1420
|
throw new Error(messages.NO_RETURN_TYPE + actFunName);
|
|
1421
1421
|
}
|
|
1422
1422
|
}
|
|
1423
1423
|
}
|
|
1424
1424
|
|
|
1425
|
-
function
|
|
1425
|
+
function _collectUnboundActionFunction(schemaDataList, parserContext) {
|
|
1426
1426
|
for (let actionName of parserContext.actionToActionImportMap.keys()) {
|
|
1427
|
-
|
|
1427
|
+
_populateUnboundActionFunction(true, actionName, schemaDataList, parserContext);
|
|
1428
1428
|
}
|
|
1429
1429
|
for (let functionName of parserContext.functionToFunctionImportMap.keys()) {
|
|
1430
|
-
|
|
1430
|
+
_populateUnboundActionFunction(false, functionName, schemaDataList, parserContext);
|
|
1431
1431
|
}
|
|
1432
1432
|
}
|
|
1433
1433
|
|
|
@@ -1435,22 +1435,22 @@ function _collectUnboundedActionFunction(schemaDataList, parserContext) {
|
|
|
1435
1435
|
* @param {Boolean} isAction
|
|
1436
1436
|
* @param {String} currNamespace
|
|
1437
1437
|
* @param {String} elementName
|
|
1438
|
-
* @param {List<Object>} elementDataList,
|
|
1438
|
+
* @param {List<Object>} elementDataList, bound action/function details
|
|
1439
1439
|
* @param {Object} parserContext
|
|
1440
1440
|
*
|
|
1441
|
-
* Scenarios for
|
|
1441
|
+
* Scenarios for bound actions, functions:
|
|
1442
1442
|
* 1. Actions with same name and binding parameter type can't have collision.
|
|
1443
1443
|
* 2. Functions can have collision and we will capture the max number of parameters.
|
|
1444
|
-
* Special scenario is when same function name is
|
|
1444
|
+
* Special scenario is when same function name is bound to different entity as well.
|
|
1445
1445
|
*/
|
|
1446
|
-
function
|
|
1446
|
+
function _collectBoundActionFunction(isAction, currNamespace, elementName, elementDataList, parserContext) {
|
|
1447
1447
|
let functionObjList; // list to collect all the collision obj for function
|
|
1448
1448
|
|
|
1449
1449
|
for (let i = 0; i < elementDataList.length; i++) {
|
|
1450
1450
|
let dataObj = elementDataList[i];
|
|
1451
|
-
let
|
|
1451
|
+
let boundEntityName = dataObj.$Parameter[0].$Type;
|
|
1452
1452
|
let entityTypeNamespace = currNamespace;
|
|
1453
|
-
let [schemaName, entityName] = _extractSchemaNameAndElementName(
|
|
1453
|
+
let [schemaName, entityName] = _extractSchemaNameAndElementName(boundEntityName);
|
|
1454
1454
|
|
|
1455
1455
|
// binding parameter type should be within the available namespaces in the scope of a document.
|
|
1456
1456
|
if (entityTypeNamespace !== schemaName && entityTypeNamespace !== parserContext.schemaAliasToNamespace[schemaName]) {
|
|
@@ -1463,35 +1463,35 @@ function _collectBoundedActionFunction(isAction, currNamespace, elementName, ele
|
|
|
1463
1463
|
else if (parserContext.schemaAliasToNamespace[schemaName]) {
|
|
1464
1464
|
entityTypeNamespace = parserContext.schemaAliasToNamespace[schemaName];
|
|
1465
1465
|
} else {
|
|
1466
|
-
throw new Error(messages.
|
|
1466
|
+
throw new Error(messages.INVALID_BOUND_PARAM_TYPE + ` Check the Element: ${elementName} of Schema: ${currNamespace} `);
|
|
1467
1467
|
}
|
|
1468
1468
|
}
|
|
1469
1469
|
|
|
1470
1470
|
if (!parserContext.entityTypes.includes(entityTypeNamespace + '.' + entityName)) {
|
|
1471
|
-
throw new Error(messages.UNRESOLVED_TYPE +
|
|
1471
|
+
throw new Error(messages.UNRESOLVED_TYPE + boundEntityName);
|
|
1472
1472
|
}
|
|
1473
|
-
|
|
1473
|
+
boundEntityName = entityTypeNamespace + '.' + entityName;
|
|
1474
1474
|
|
|
1475
1475
|
if (isAction) {
|
|
1476
|
-
if (!parserContext.
|
|
1477
|
-
if (!parserContext.
|
|
1478
|
-
parserContext.
|
|
1476
|
+
if (!parserContext.entityToBoundActions[boundEntityName]?.[elementName]) {
|
|
1477
|
+
if (!parserContext.entityToBoundActions[boundEntityName]) {
|
|
1478
|
+
parserContext.entityToBoundActions[boundEntityName] = {};
|
|
1479
1479
|
}
|
|
1480
|
-
parserContext.
|
|
1480
|
+
parserContext.entityToBoundActions[boundEntityName][elementName] = dataObj;
|
|
1481
1481
|
}
|
|
1482
1482
|
else {
|
|
1483
|
-
throw new Error(messages.
|
|
1483
|
+
throw new Error(messages.BOUND_ACTION_COLLISION + `${elementName} in entity ${entityName} of schema ${currNamespace}.`);
|
|
1484
1484
|
}
|
|
1485
1485
|
}
|
|
1486
1486
|
else {
|
|
1487
|
-
if (!parserContext.
|
|
1488
|
-
if (!parserContext.
|
|
1489
|
-
parserContext.
|
|
1487
|
+
if (!parserContext.entityToBoundFunctions[boundEntityName]?.[elementName]) {
|
|
1488
|
+
if (!parserContext.entityToBoundFunctions[boundEntityName]) {
|
|
1489
|
+
parserContext.entityToBoundFunctions[boundEntityName] = {};
|
|
1490
1490
|
}
|
|
1491
|
-
if (!functionObjList || !parserContext.
|
|
1491
|
+
if (!functionObjList || !parserContext.entityToBoundFunctions[boundEntityName][elementName]) {
|
|
1492
1492
|
functionObjList = [];
|
|
1493
1493
|
}
|
|
1494
|
-
parserContext.
|
|
1494
|
+
parserContext.entityToBoundFunctions[boundEntityName][elementName] = dataObj;
|
|
1495
1495
|
functionObjList.push(dataObj);
|
|
1496
1496
|
}
|
|
1497
1497
|
else {
|
|
@@ -1499,10 +1499,10 @@ function _collectBoundedActionFunction(isAction, currNamespace, elementName, ele
|
|
|
1499
1499
|
let functionObject = functionObjList[0];
|
|
1500
1500
|
functionObject['$Parameter'] = _collectAllParameters(functionObjList);
|
|
1501
1501
|
functionObjList = [functionObject]; // reset the function object list with recently formed object
|
|
1502
|
-
parserContext.
|
|
1502
|
+
parserContext.entityToBoundFunctions[boundEntityName][elementName] = functionObject;
|
|
1503
1503
|
}
|
|
1504
1504
|
// throw error if the return type is missing
|
|
1505
|
-
if (!parserContext.
|
|
1505
|
+
if (!parserContext.entityToBoundFunctions[boundEntityName][elementName].$ReturnType) {
|
|
1506
1506
|
throw new Error(messages.NO_RETURN_TYPE + elementName);
|
|
1507
1507
|
}
|
|
1508
1508
|
}
|
|
@@ -1515,10 +1515,10 @@ function _collectBoundedActionFunction(isAction, currNamespace, elementName, ele
|
|
|
1515
1515
|
* @param {Object} parserContext, contains parser level context informations
|
|
1516
1516
|
*/
|
|
1517
1517
|
function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
1518
|
-
// This array is used to store the parameter values which will be used later to call
|
|
1518
|
+
// This array is used to store the parameter values which will be used later to call _collectBoundActionFunction.
|
|
1519
1519
|
let boundActionFunctionDetails = [];
|
|
1520
1520
|
|
|
1521
|
-
|
|
1521
|
+
_collectUnboundActionFunction(schemaDataList, parserContext);
|
|
1522
1522
|
|
|
1523
1523
|
// capture all the references
|
|
1524
1524
|
if (edmxAsJson.$Reference) {
|
|
@@ -1527,7 +1527,7 @@ function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
|
1527
1527
|
});
|
|
1528
1528
|
}
|
|
1529
1529
|
|
|
1530
|
-
// collect entityType, enumType, complexType, typeDefinition,
|
|
1530
|
+
// collect entityType, enumType, complexType, typeDefinition, bound action/function, annotations
|
|
1531
1531
|
for (let schemaData of schemaDataList) {
|
|
1532
1532
|
let currNamespace = schemaData.$SchemaNamespace;
|
|
1533
1533
|
|
|
@@ -1540,7 +1540,7 @@ function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
|
1540
1540
|
else if (elementData.$Kind === 'EnumType') parserContext.enumTypes.push(fqName);
|
|
1541
1541
|
else if (elementData.$Kind === 'ComplexType') parserContext.complexTypes.push(fqName);
|
|
1542
1542
|
else if (elementData.$Kind === 'TypeDefinition') parserContext.typeDefinitions.push(fqName);
|
|
1543
|
-
//
|
|
1543
|
+
// bound actions/functions
|
|
1544
1544
|
else if (elementData instanceof Array) {
|
|
1545
1545
|
let isAction = elementData[0].$Kind === 'Action' ? true : false;
|
|
1546
1546
|
if (elementData[0].$IsBound) {
|
|
@@ -1570,9 +1570,9 @@ function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
|
1570
1570
|
}
|
|
1571
1571
|
});
|
|
1572
1572
|
}
|
|
1573
|
-
// This will delay the execution of
|
|
1573
|
+
// This will delay the execution of _collectBoundActionFunction, as we need to collect all the entityTypes first.
|
|
1574
1574
|
boundActionFunctionDetails.forEach(paramValues => {
|
|
1575
|
-
|
|
1575
|
+
_collectBoundActionFunction(...paramValues, parserContext);
|
|
1576
1576
|
});
|
|
1577
1577
|
}
|
|
1578
1578
|
|
|
@@ -1651,12 +1651,12 @@ function _generateCSN(edmxAsJson, ignorePersistenceSkip, parserContext, importer
|
|
|
1651
1651
|
csn.definitions = Object.assign(_parserCSNForComplexType(schemaData, parserContext), csn.definitions);
|
|
1652
1652
|
// Step 4: parse all entity type
|
|
1653
1653
|
csn.definitions = Object.assign(_parseCSNForEntityType(schemaData, ignorePersistenceSkip, parserContext), csn.definitions);
|
|
1654
|
-
// Step 5: parse all
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
// Step 6: parse all
|
|
1658
|
-
csn.definitions = Object.assign(
|
|
1659
|
-
csn.definitions = Object.assign(
|
|
1654
|
+
// Step 5: parse all bound action & function
|
|
1655
|
+
_parseBoundActionFunction(schemaData, csn.definitions, 'action', parserContext);
|
|
1656
|
+
_parseBoundActionFunction(schemaData, csn.definitions, 'function', parserContext);
|
|
1657
|
+
// Step 6: parse all unbound action & function
|
|
1658
|
+
csn.definitions = Object.assign(_parseUnboundActionFunction(schemaData, 'action', parserContext), csn.definitions);
|
|
1659
|
+
csn.definitions = Object.assign(_parseUnboundActionFunction(schemaData, 'function', parserContext), csn.definitions);
|
|
1660
1660
|
// Step 7: parse all annotations
|
|
1661
1661
|
if (schemaData.$Annotations) {
|
|
1662
1662
|
_parseAnnotations(schemaData.$Annotations, csn.definitions, parserContext);
|
package/lib/init/constants.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = {
|
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
7
|
JAVA_LTS_VERSIONS: [17, 21],
|
|
8
|
-
MAVEN_ARCHETYPE_VERSION: '3.
|
|
8
|
+
MAVEN_ARCHETYPE_VERSION: '3.2.0',
|
|
9
9
|
|
|
10
10
|
OPTIONS: Object.freeze({
|
|
11
11
|
COMPLETION: 'completion',
|
|
@@ -72,7 +72,8 @@ module.exports = {
|
|
|
72
72
|
MAVEN_INSTALL_HELP: `https://maven.apache.org/install.html`,
|
|
73
73
|
CAP_JS_COMMUNITY_ODATA_V2: 'https://github.com/cap-js-community/odata-v2-adapter',
|
|
74
74
|
CAP_JS_COMMUNITY_EVENT_QUEUE: 'https://github.com/cap-js-community/event-queue',
|
|
75
|
-
CAP_JS_COMMUNITY_WEBSOCKET: 'https://github.com/cap-js-community/websocket'
|
|
75
|
+
CAP_JS_COMMUNITY_WEBSOCKET: 'https://github.com/cap-js-community/websocket',
|
|
76
|
+
CF_CLI: 'https://github.com/cloudfoundry/cli'
|
|
76
77
|
}),
|
|
77
78
|
|
|
78
79
|
PROJECT_FILES: ['package.json', 'pom.xml', '.cdsrc.json']
|
package/lib/init/mvn.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const util = require('util')
|
|
2
|
+
const path = require('path');
|
|
2
3
|
const { exec } = require('child_process')
|
|
3
4
|
const execAsync = util.promisify(exec)
|
|
4
5
|
|
|
@@ -6,7 +7,7 @@ const term = require('../util/term')
|
|
|
6
7
|
const cmd = require('../util/command')
|
|
7
8
|
|
|
8
9
|
const cds = require('../cds')
|
|
9
|
-
const DEBUG = cds.debug('cli|init|add|mvn')
|
|
10
|
+
const LOG = cds.log('cli|init|add|mvn'), DEBUG = cds.debug('cli|init|add|mvn')
|
|
10
11
|
|
|
11
12
|
const { URLS, MAVEN_ARCHETYPE_VERSION, OPTIONS: { JAVA_PACKAGE, HANA }, REGEX_JAVA_PACKAGE } = require('./constants')
|
|
12
13
|
|
|
@@ -16,9 +17,9 @@ module.exports.add = async function (feature) {
|
|
|
16
17
|
const { 'java:mvn': javaMvn, force } = cds.cli.options
|
|
17
18
|
if (javaMvn) _scan(javaMvn).forEach(([k,v]) => params.set(k,v))
|
|
18
19
|
const archetypeVersion = params.get('-DarchetypeVersion') ?? MAVEN_ARCHETYPE_VERSION
|
|
19
|
-
if (feature === HANA) { // REVISIT: compat for HANA
|
|
20
|
+
if (feature === HANA) { // REVISIT: compat for HANA until -Dfeature HANA is provided by Java
|
|
20
21
|
params.set(`com.sap.cds:cds-maven-plugin:${archetypeVersion}:addTargetPlatform`)
|
|
21
|
-
params.set(`-DtargetPlatform`, `cloudfoundry`) // REVISIT:
|
|
22
|
+
params.set(`-DtargetPlatform`, `cloudfoundry`) // REVISIT: Should get rid of CF dependency for Kyma scenarios
|
|
22
23
|
} else {
|
|
23
24
|
params.set(`com.sap.cds:cds-maven-plugin:${archetypeVersion}:add`)
|
|
24
25
|
params.set(`-Dfeature`, feature)
|
|
@@ -46,6 +47,7 @@ module.exports.init = async function (projectName, options = cds.cli.options) {
|
|
|
46
47
|
params.set(`-DarchetypeGroupId`, `com.sap.cds`);
|
|
47
48
|
params.set(`-DarchetypeVersion`, MAVEN_ARCHETYPE_VERSION);
|
|
48
49
|
params.set('-DinteractiveMode', false);
|
|
50
|
+
if (cds.cli.options['no-db']) params.set('-Dpersistence', false)
|
|
49
51
|
|
|
50
52
|
// set defaults, might be changed by java:mvn param
|
|
51
53
|
params.set(`-DartifactId`, projectName);
|
|
@@ -101,6 +103,41 @@ module.exports.init = async function (projectName, options = cds.cli.options) {
|
|
|
101
103
|
return { params: _finalize(params), archetypeVersion, artifactId }
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
module.exports.generate = async function (feature, options = cds.cli.options) {
|
|
107
|
+
const command = this.generateMvnParams(feature, options)
|
|
108
|
+
const cwd = options.cwd
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
console.log(`Executing command: `, term.highlight('mvn ' + command.join(' ')))
|
|
112
|
+
await cmd.spawnCommand('mvn', command, { cwd: cwd ?? path.join(cds.root, 'srv') })
|
|
113
|
+
return command
|
|
114
|
+
} catch (err) {
|
|
115
|
+
if (err.code === 'ENOENT' && err.path === 'mvn') {
|
|
116
|
+
throw `Maven executable 'mvn' not found. Follow ${term.info(URLS.MAVEN_INSTALL_HELP)} and install Maven on your machine.`
|
|
117
|
+
}
|
|
118
|
+
throw err
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports.generateMvnParams = function (feature, options = cds.cli.options) {
|
|
123
|
+
const params = new Map()
|
|
124
|
+
|
|
125
|
+
const { 'java:mvn': javaMvn, force, filter, out } = options
|
|
126
|
+
if (javaMvn) _scan(javaMvn).forEach(([k,v]) => params.set(k,v))
|
|
127
|
+
const archVersion = params.get(`-DarchetypeVersion`) ?? ''
|
|
128
|
+
params.set(`cds:${archVersion}:generate`)
|
|
129
|
+
|
|
130
|
+
switch (feature) {
|
|
131
|
+
case 'handler':
|
|
132
|
+
params.set(`-Dcds.generate.feature=EVENT_HANDLERS`)
|
|
133
|
+
break
|
|
134
|
+
}
|
|
135
|
+
if (filter) params.set(`-Dcds.generate.includes=**.${filter.replace(/\*+\.?/, '')}**`)
|
|
136
|
+
if (out) params.set(`-Dcds.generate.handlers.package=${out.replaceAll('/', '.')}`)
|
|
137
|
+
if (force) params.set(`-Dcds.generate.overwrite`, true)
|
|
138
|
+
return _finalize(params)
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
const sanitize = module.exports.sanitize = name => name
|
|
105
142
|
.toLowerCase()
|
|
106
143
|
.replace(/-/g, '_')
|
|
@@ -123,10 +160,10 @@ function _scan(mvnParams) {
|
|
|
123
160
|
|
|
124
161
|
function _finalize(params) {
|
|
125
162
|
params.set(`-Dstyle.color`, `always`)
|
|
126
|
-
if (
|
|
127
|
-
if (
|
|
163
|
+
if (LOG._debug) params.set('-X')
|
|
164
|
+
if (LOG._debug) params.set('-e')
|
|
128
165
|
if (process.env.CI) params.set('--batch-mode')
|
|
129
166
|
const final = Array.from(params, ([arg, val]) => val !== null && val !== undefined ? `${arg}=${val}` : arg)
|
|
130
|
-
DEBUG?.(term.highlight('mvn' + final.join(' ')))
|
|
167
|
+
DEBUG?.(term.highlight('mvn ' + final.join(' ')))
|
|
131
168
|
return final
|
|
132
169
|
}
|
package/lib/init/plugin.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
2
|
const cds = require('../cds')
|
|
3
3
|
const { readdir } = cds.utils
|
|
4
|
-
const DEBUG = cds.debug('cli|add')
|
|
5
4
|
|
|
6
5
|
module.exports = class Plugin {
|
|
7
6
|
|
|
@@ -68,6 +67,7 @@ module.exports = class Plugin {
|
|
|
68
67
|
–––––––––––– */
|
|
69
68
|
|
|
70
69
|
async combineSupported() {
|
|
70
|
+
const DEBUG = cds.log('cli|add')._debug
|
|
71
71
|
DEBUG && console.log()
|
|
72
72
|
DEBUG && console.log('Plugins active for production:')
|
|
73
73
|
const fromDk = await readdir(join(__dirname, './template'))
|
|
@@ -145,7 +145,7 @@ module.exports = new class ProjectReader {
|
|
|
145
145
|
const inbounds = manifest?.['sap.app']?.crossNavigation?.inbounds
|
|
146
146
|
const [firstInbound] = Object.values(inbounds ?? { intent: { semanticObject: 'Books', action: 'display' }})
|
|
147
147
|
const vizId = firstInbound.semanticObject + '-' + firstInbound.action
|
|
148
|
-
return { app, strippedApp: app.replace(/-/g, ''), vizId, isNotLast: i < apps.length - 1 }
|
|
148
|
+
return { app, strippedApp: app.replace(/-/g, ''), vizId, isNotLast: i < apps.length - 1, manifestAppId: manifest?.['sap.app']?.id ?? app}
|
|
149
149
|
})
|
|
150
150
|
},
|
|
151
151
|
appUIPaths: () => (fs.readdirSync(path.resolve(cds.root, cds.env.folders.app))).filter(e =>
|
|
@@ -3,8 +3,13 @@ modules:
|
|
|
3
3
|
- name: {{appName}}-approuter
|
|
4
4
|
build-parameters:
|
|
5
5
|
buildpack:
|
|
6
|
+
{{#hasHelmUnifiedRuntime}}
|
|
7
|
+
builder: proxy-unified-runtime-dmz.int.repositories.cloud.sap/builder/noble
|
|
8
|
+
{{/hasHelmUnifiedRuntime}}
|
|
9
|
+
{{^hasHelmUnifiedRuntime}}
|
|
6
10
|
type: nodejs
|
|
7
11
|
builder: builder-jammy-base
|
|
12
|
+
{{/hasHelmUnifiedRuntime}}
|
|
8
13
|
path: app/router
|
|
9
14
|
env:
|
|
10
15
|
BP_NODE_RUN_SCRIPTS: ""
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
modules:
|
|
3
|
+
- name: {{appName}}-srv
|
|
4
|
+
type: {{language}}
|
|
5
|
+
path: {{& srvPath}}
|
|
6
|
+
requires:
|
|
7
|
+
- name: {{appName}}-cloud-logging
|
|
8
|
+
- name: {{appName}}-mtx
|
|
9
|
+
type: nodejs
|
|
10
|
+
path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
|
|
11
|
+
requires:
|
|
12
|
+
- name: {{appName}}-cloud-logging
|
|
13
|
+
- name: {{appName}}
|
|
14
|
+
type: approuter.nodejs
|
|
15
|
+
requires:
|
|
16
|
+
- name: {{appName}}-cloud-logging
|
|
17
|
+
resources:
|
|
18
|
+
- name: {{appName}}-cloud-logging
|
|
19
|
+
type: org.cloudfoundry.managed-service
|
|
20
|
+
parameters:
|
|
21
|
+
service: cloud-logging
|
|
22
|
+
service-plan: {{cloudLoggingServicePlan}}
|
|
23
|
+
config:
|
|
24
|
+
ingest_otlp:
|
|
25
|
+
enabled: true
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@cap-js/telemetry": ">=0",
|
|
4
|
+
"@grpc/grpc-js": "^1",
|
|
5
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0",
|
|
6
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0",
|
|
7
|
+
"@opentelemetry/host-metrics": "^0"
|
|
8
|
+
},
|
|
9
|
+
"cds": {
|
|
10
|
+
"requires": {
|
|
11
|
+
"telemetry": "to-cloud-logging"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|