@sap/cds-dk 6.1.4 → 6.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.
Files changed (153) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/bin/build/all.js +5 -5
  3. package/bin/cds.js +7 -5
  4. package/bin/deploy/index.js +3 -2
  5. package/bin/deploy/to-sqlite.js +4 -3
  6. package/bin/help.js +4 -0
  7. package/bin/init.js +2 -1
  8. package/bin/login.js +23 -9
  9. package/bin/mock.js +1 -0
  10. package/bin/pull.js +24 -19
  11. package/bin/push.js +20 -9
  12. package/bin/subscribe.js +40 -10
  13. package/bin/watch.js +15 -10
  14. package/lib/bind/kubernetesCredentialsProvider.js +1 -0
  15. package/lib/client/activate.js +42 -51
  16. package/lib/client/auth_manager.js +7 -8
  17. package/lib/client/base_command.js +5 -2
  18. package/lib/client/extend.js +33 -38
  19. package/lib/client/helper/cf_helper.js +11 -11
  20. package/lib/client/helper/dependency_helper.js +2 -2
  21. package/lib/client/helper/errors.js +4 -3
  22. package/lib/client/helper/logging.js +17 -23
  23. package/lib/client/params.js +5 -5
  24. package/lib/client/pull.js +19 -21
  25. package/lib/client/push.js +16 -15
  26. package/lib/client/settings_manager.js +54 -55
  27. package/lib/compile/openapi/csdl2openapi.js +18 -12
  28. package/lib/import/message.js +1 -1
  29. package/lib/import/odata/metadataconverter/MetadataConverter.js +23 -17
  30. package/lib/import/odata/v2parser.js +43 -17
  31. package/lib/import/odata/v4parser.js +77 -22
  32. package/lib/init/constants.js +5 -2
  33. package/lib/init/index.js +16 -4
  34. package/lib/init/template/_merging/registry-mta.js +13 -0
  35. package/lib/init/template/approuter/index.js +9 -0
  36. package/lib/{k8s/connectivity/templates/connectivity.yaml → init/template/auditlog/files/auditlog.yaml} +0 -0
  37. package/lib/init/template/auditlog/index.js +46 -27
  38. package/lib/{k8s/connectivity/templates → init/template/connectivity/files}/connectivity-binding.yaml +0 -0
  39. package/lib/{k8s/connectivity/templates → init/template/connectivity/files}/connectivity-proxy-info.yaml +1 -1
  40. package/lib/init/template/connectivity/files/connectivity.yaml +1 -0
  41. package/lib/init/template/connectivity/files/values.yaml.hbs +26 -0
  42. package/lib/init/template/connectivity/index.js +41 -0
  43. package/lib/init/template/data/index.js +8 -8
  44. package/lib/init/template/destinations/files/destination.yaml +1 -0
  45. package/lib/init/template/destinations/index.js +44 -0
  46. package/lib/init/template/enterprise-messaging/files/cds.package.json +10 -0
  47. package/lib/init/template/enterprise-messaging/files/cds.profile.package.json.hbs +12 -0
  48. package/lib/init/template/enterprise-messaging/files/cdsrc.json +8 -0
  49. package/lib/init/template/enterprise-messaging/files/cdsrc.json.hbs +10 -0
  50. package/lib/init/template/enterprise-messaging/files/event-mesh.yaml +1 -0
  51. package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +13 -0
  52. package/lib/init/template/enterprise-messaging/files/values.yaml +8 -0
  53. package/lib/init/template/enterprise-messaging/index.js +56 -0
  54. package/lib/init/template/extensibility/files/cdsrc.json +5 -0
  55. package/lib/init/template/extensibility/files/cdsrc.json.hbs +7 -0
  56. package/lib/init/template/extensibility/index.js +18 -13
  57. package/lib/{k8s/hana-deployer/templates → init/template/hana/files}/hana-deployer-job.yaml +0 -0
  58. package/lib/init/template/hana/files/java/{cdsrc.json.hbs → cds.json.hbs} +0 -0
  59. package/lib/init/template/hana/files/java/{profile.cdsrc.json.hbs → cds.profile.json.hbs} +0 -0
  60. package/lib/init/template/hana/files/java/cds.shortcut.json.hbs +5 -0
  61. package/lib/init/template/hana/files/java/cds.shortcut.profile.json.hbs +8 -0
  62. package/lib/init/template/hana/files/java/db/package.json +2 -1
  63. package/lib/init/template/hana/files/mta.yaml.hbs +6 -0
  64. package/lib/init/template/hana/files/nodejs/{cds.package.json.hbs → cds.json.hbs} +0 -0
  65. package/lib/init/template/hana/files/nodejs/{cds.profile.package.json.hbs → cds.profile.json.hbs} +0 -0
  66. package/lib/init/template/hana/files/nodejs/cds.shortcut.json.hbs +7 -0
  67. package/lib/init/template/hana/files/nodejs/cds.shortcut.profile.json.hbs +10 -0
  68. package/lib/init/template/hana/files/values.yaml.hbs +19 -0
  69. package/lib/init/template/hana/index.js +29 -29
  70. package/lib/{k8s → init/template/helm}/Model.d.ts +0 -0
  71. package/lib/{k8s/resources → init/template}/helm/chart/templates/NOTES.txt +0 -0
  72. package/lib/{k8s/resources → init/template}/helm/chart/templates/_deployment_helpers.tpl +0 -0
  73. package/lib/{k8s/resources → init/template}/helm/chart/templates/_helpers.tpl +4 -5
  74. package/lib/{k8s/resources → init/template}/helm/chart/templates/_sapcp_helpers.tpl +0 -0
  75. package/lib/{k8s/resources/helm/chart/schemas → init/template/helm/chart}/values.root.schema.json +0 -0
  76. package/lib/{k8s/resources/helm/chart/schemas → init/template/helm/chart}/values.schema.json +0 -0
  77. package/lib/init/template/helm/files/Chart.yaml.hbs +13 -0
  78. package/lib/init/template/helm/files/values.yaml.hbs +26 -0
  79. package/lib/init/template/helm/index.js +74 -14
  80. package/lib/{k8s/deployment → init/template/helm}/subchart/Chart.yaml +0 -0
  81. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/_helpers.tpl +0 -0
  82. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/api-rule.yaml +0 -0
  83. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/deployment.yaml +0 -0
  84. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/network-policy.yaml +0 -0
  85. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/pod-disruption-budget.yaml +0 -0
  86. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/secret.yaml +0 -0
  87. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/service-binding.yaml +0 -0
  88. package/lib/{k8s/deployment → init/template/helm}/subchart/templates/service.yaml +0 -0
  89. package/lib/{k8s/deployment → init/template/helm}/subchart/values-lint.yaml +0 -0
  90. package/lib/{k8s/deployment → init/template/helm}/subchart/values.md +0 -0
  91. package/lib/{k8s/deployment → init/template/helm}/subchart/values.schema.json +0 -0
  92. package/lib/{k8s/deployment → init/template/helm}/subchart/values.yaml +0 -0
  93. package/lib/{k8s/html5-apps-deployer/templates → init/template/html5-repo/files}/_html5_deployment_helpers.tpl +0 -0
  94. package/lib/{k8s/html5-apps-deployer/templates → init/template/html5-repo/files}/html5-apps-deployer-job.yaml +1 -1
  95. package/lib/{k8s/html5-apps-repo-host/templates → init/template/html5-repo/files}/html5-apps-repo-host.yaml +0 -0
  96. package/lib/init/template/html5-repo/index.js +59 -0
  97. package/lib/init/template/kibana-logging/index.js +8 -0
  98. package/lib/init/template/lint/index.js +1 -4
  99. package/lib/init/template/mta/files/mta.yaml.hbs +3 -2
  100. package/lib/init/template/mta/index.js +6 -1
  101. package/lib/init/template/multitenancy/files/java/.cdsrc.json +3 -0
  102. package/lib/init/template/multitenancy/files/java/package.json +2 -6
  103. package/lib/{k8s/multitenancy/templates → init/template/multitenancy/files}/saas-registry.yaml +3 -3
  104. package/lib/init/template/multitenancy/files/xsuaa.yaml +1 -0
  105. package/lib/init/template/multitenancy/index.js +53 -26
  106. package/lib/init/template/nodejs/files/.gitignore.hbs +1 -0
  107. package/lib/init/template/templateBase.js +1 -1
  108. package/lib/init/template/xsuaa/files/values.yaml.hbs +10 -0
  109. package/lib/init/template/xsuaa/files/xsuaa.yaml +1 -0
  110. package/lib/init/template/xsuaa/index.js +34 -22
  111. package/lib/init/util/fsUtil.js +11 -5
  112. package/lib/init/util/projectReader.js +24 -32
  113. package/lib/init/util/templateUtil.js +17 -5
  114. package/lib/lint/Linter.js +9 -17
  115. package/lib/lint/checks.js +0 -1
  116. package/lib/lint/generators.js +2 -192
  117. package/lib/lint/io.js +1 -3
  118. package/lib/watch/node-watch.js +2 -2
  119. package/npm-shrinkwrap.json +1412 -791
  120. package/package.json +5 -4
  121. package/lib/init/template/helm/update/index.js +0 -28
  122. package/lib/k8s/ChartAdder.js +0 -75
  123. package/lib/k8s/ChartBuilder.js +0 -192
  124. package/lib/k8s/Context.js +0 -71
  125. package/lib/k8s/ImageUtil.js +0 -21
  126. package/lib/k8s/auditlog/index.js +0 -29
  127. package/lib/k8s/auditlog/templates/auditlog.yaml +0 -1
  128. package/lib/k8s/buildModel.js +0 -68
  129. package/lib/k8s/connectivity/index.js +0 -80
  130. package/lib/k8s/deployment/index.js +0 -79
  131. package/lib/k8s/deployment/subchart-override/templates/_web_application_helpers.tpl +0 -81
  132. package/lib/k8s/destinations/index.js +0 -40
  133. package/lib/k8s/destinations/lib.js +0 -16
  134. package/lib/k8s/destinations/templates/destinations.yaml +0 -1
  135. package/lib/k8s/docker/push.js +0 -8
  136. package/lib/k8s/event-mesh/index.js +0 -53
  137. package/lib/k8s/event-mesh/lib.js +0 -9
  138. package/lib/k8s/event-mesh/templates/event-mesh.yaml +0 -1
  139. package/lib/k8s/hana-deployer/index.js +0 -48
  140. package/lib/k8s/helm/Release.js +0 -80
  141. package/lib/k8s/html5-apps-deployer/index.js +0 -53
  142. package/lib/k8s/html5-apps-repo-host/index.js +0 -26
  143. package/lib/k8s/html5-apps-repo-host/lib.js +0 -16
  144. package/lib/k8s/index.js +0 -153
  145. package/lib/k8s/modules.js +0 -36
  146. package/lib/k8s/multitenancy/index.js +0 -24
  147. package/lib/k8s/multitenancy/lib.js +0 -25
  148. package/lib/k8s/readProject.js +0 -14
  149. package/lib/k8s/util.js +0 -186
  150. package/lib/k8s/wrapFeature.js +0 -55
  151. package/lib/k8s/xsuaa/index.js +0 -64
  152. package/lib/k8s/xsuaa/lib.js +0 -17
  153. package/lib/k8s/xsuaa/templates/xsuaa.yaml +0 -1
@@ -394,6 +394,9 @@ function _getServiceEntityProperty(
394
394
  let hasInvalidPrecision = false;
395
395
  let propertyJson = '';
396
396
  if (length && length > 0) {
397
+ if(dataType == "Edm.Binary" && length >= 5000){
398
+ console.log(warn("MaxLength for type Edm.Binary should not exceed 5000"));
399
+ }
397
400
  cdsDataType = edmxncdsdatatype[dataType + "_m"];
398
401
  } else if (precision && precision > 0) {
399
402
  cdsDataType = edmxncdsdatatype[dataType + "_p"];
@@ -429,6 +432,9 @@ function _getServiceEntityProperty(
429
432
  } else if (!cdsDataType && parserContext.allEntitySetMap[_extractEntityFromNamespace(dataType)]) {
430
433
  cdsDataType = dataType;
431
434
  }
435
+ else if (!cdsDataType && parserContext.allEntities.includes(_extractEntityFromNamespace(dataType))) {
436
+ cdsDataType = dataType;
437
+ }
432
438
 
433
439
  //if the cdsDataType is undefined/ not supported
434
440
  if (cdsDataType === undefined) {
@@ -458,8 +464,9 @@ function _getServiceEntityProperty(
458
464
 
459
465
  //adding precision in case of DateTime datatypes
460
466
  if ((dataType === "Edm.DateTimeOffset" || dataType === "Edm.DateTime") && cdsDataType != "cds.Date") {
461
- if (!precision || precision === -1) precision = 0;
462
- propertyJson = propertyJson + '"@odata.Precision": ' + precision + ',\n';
467
+ if (precision && precision > 0){
468
+ propertyJson = propertyJson + '"@odata.Precision": ' + precision + ',\n';
469
+ }
463
470
  }
464
471
 
465
472
  propertyJson = propertyJson + '"items": { \n'
@@ -500,8 +507,9 @@ function _getServiceEntityProperty(
500
507
 
501
508
  //adding precision in case of DateTime datatypes
502
509
  if ((dataType === "Edm.DateTimeOffset" || dataType === "Edm.DateTime") && cdsDataType != "cds.Date") {
503
- if (!precision || precision === -1) precision = 0;
504
- propertyJson = propertyJson + ',\n"@odata.Precision": ' + precision;
510
+ if (precision && precision > 0){
511
+ propertyJson = propertyJson + ',\n"@odata.Precision": ' + precision;
512
+ }
505
513
  }
506
514
  }
507
515
 
@@ -945,12 +953,18 @@ function _generateCSNEntityProperties(entityKeysList, entityPropertiesMap, parse
945
953
  return csnEntity;
946
954
  }
947
955
 
948
- function _getAssociatedEntity(associationEnds, toRole, mockServerUc, parserContext) {
956
+ function _getAssociatedEntity(associationEnds, toRole, isAssociationSetMissing, mockServerUc, parserContext) {
949
957
  let entityName;
950
958
  let entitySetName;
959
+ let entityTypeName;
951
960
  Object.keys(associationEnds).forEach((i) => {
952
961
  if (toRole === associationEnds[i]._attributes.Role) {
953
- entitySetName = associationEnds[i]._attributes.EntitySet;
962
+ if (isAssociationSetMissing) {
963
+ entityTypeName = associationEnds[i]._attributes.Type;
964
+ entitySetName = parserContext.allEntitySetMapMC[entityTypeName][0];
965
+ } else {
966
+ entitySetName = associationEnds[i]._attributes.EntitySet;
967
+ }
954
968
  if (mockServerUc) {
955
969
  entityName = parserContext.serviceNamespace + "." + entitySetName;
956
970
  } else {
@@ -1167,13 +1181,20 @@ function _getCSNAssociatedEntitySet(
1167
1181
  parserContext
1168
1182
  ) {
1169
1183
  let associationSet = parserContext.allAssociationSets[relationshipName];
1184
+ let associationName = relationshipName.replace(parserContext.serviceNamespace + '.', '');
1185
+ let association = parserContext.allAssociations[associationName];
1186
+ let isAssociationSetMissing = false;
1187
+
1188
+ // if association set is missing, use association to extract the informations
1170
1189
  if (associationSet === undefined) {
1171
- throw new Error(messages.MISSING_ASSOCIATION_SETS);
1190
+ isAssociationSetMissing = true;
1172
1191
  }
1173
- let associationName = associationSet.Name;
1192
+
1193
+ let associationEnd = associationSet ? associationSet.End : association.End;
1174
1194
  let entityName = _getAssociatedEntity(
1175
- associationSet.End,
1195
+ associationEnd,
1176
1196
  toRole,
1197
+ isAssociationSetMissing,
1177
1198
  mockServerUc,
1178
1199
  parserContext
1179
1200
  );
@@ -1189,7 +1210,7 @@ function _getCSNAssociatedEntitySet(
1189
1210
  differentAssociationNames = parserContext.allAssociations[array[array.length - 1]];
1190
1211
  }
1191
1212
  } else {
1192
- differentAssociationNames = parserContext.allAssociations[associationName];
1213
+ differentAssociationNames = association;
1193
1214
  }
1194
1215
  return _getCSNAssociatedRefrenentialConstraints(
1195
1216
  differentAssociationNames,
@@ -1203,7 +1224,10 @@ function _getCSNAssociatedEntitySet(
1203
1224
 
1204
1225
  function _findAssociationType(relationshipName, fromRole, parserContext) {
1205
1226
  const associationName = relationshipName.replace(parserContext.serviceNamespace + '.', '');
1206
- const associationEnds = parserContext.allAssociations[associationName].End;
1227
+ const association = parserContext.allAssociations[associationName];
1228
+ if (association === undefined) throw new Error(`'${associationName}' ` + messages.MISSING_ASSOCIATION);
1229
+
1230
+ const associationEnds = association.End;
1207
1231
  let associationType;
1208
1232
 
1209
1233
  for (let i = 0; i < associationEnds.length; i++) {
@@ -1249,6 +1273,7 @@ function _getServiceEntityNavigationProperty(navPropAttributes, mockServerUc, pa
1249
1273
  // if documentation exists for navigation property
1250
1274
  if (navPropDoc)
1251
1275
  csn = csn + '"doc":' + ` "${navPropDoc}",\n`;
1276
+ // this function call can throw error if the association is missing in the edmx file
1252
1277
  csn = csn + _findAssociationType(relationshipName, fromRole, parserContext);
1253
1278
  csn = csn +
1254
1279
  _getCSNAssociatedEntitySet(
@@ -1520,6 +1545,7 @@ function _getEntitesWithNamesFromEntityTypes(entityJson, parserContext) {
1520
1545
  entity: entityJson[i],
1521
1546
  name: [entity]
1522
1547
  });
1548
+ parserContext.allEntities.push(entity);
1523
1549
  }
1524
1550
  }
1525
1551
 
@@ -1619,6 +1645,12 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, mockServerUc, par
1619
1645
  definitions.push(def);
1620
1646
  }
1621
1647
 
1648
+ if (entityJson) {
1649
+ definitions.push(
1650
+ _getServiceEntitites(entityJson, ignorePersistenceSkip, mockServerUc, parserContext)
1651
+ );
1652
+ }
1653
+
1622
1654
  // If complex type exists
1623
1655
  if (complexTypes) {
1624
1656
  definitions.push(_getServiceComplexTypes(parserContext));
@@ -1632,12 +1664,6 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, mockServerUc, par
1632
1664
  );
1633
1665
  }
1634
1666
 
1635
- if (entityJson) {
1636
- definitions.push(
1637
- _getServiceEntitites(entityJson, ignorePersistenceSkip, mockServerUc, parserContext)
1638
- );
1639
- }
1640
-
1641
1667
  try {
1642
1668
  csn.definitions = JSON.parse(`{${definitions.join(",")}}`);
1643
1669
  return JSON.stringify(csn, null, 4);
@@ -13,6 +13,7 @@ const ignoreObjects = ["$Reference"]; // add all the objects that needs to be ig
13
13
  const validEdmDatatypes = ["Edm.DateTimeOffset"];
14
14
  const { warn } = require("../../util/term");
15
15
  const MetadataConverterFactory = require("./metadataconverter/MetadataConverterFactory");
16
+ const cds = require('../../cds');
16
17
 
17
18
  const edmxncdsdatatype = {
18
19
  "Edm.String": "cds.LargeString",
@@ -51,7 +52,7 @@ const known_vocabularies = {
51
52
  'Org.OData.Validation.V1': 'Validation',
52
53
  'Org.OData.Measures.V1': 'Measures',
53
54
  'Org.OData.Repeatability.V1': 'Repeatability',
54
-
55
+
55
56
  'com.sap.vocabularies.Analytics.v1': 'Analytics',
56
57
  'com.sap.vocabularies.CodeList.v1': 'CodeList',
57
58
  'com.sap.vocabularies.Common.v1': 'Common',
@@ -112,7 +113,7 @@ function _isValidJSON(jsonObj, parserContext) {
112
113
  }
113
114
 
114
115
  function _hasEntityContainer(jsonObj, parserContext) {
115
- if (jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] &&
116
+ if (jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] &&
116
117
  jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] instanceof Object
117
118
  ) {
118
119
  return true;
@@ -140,7 +141,7 @@ function _typeWithCollections(property, type, isCollection) {
140
141
  if (isCollection === true) {
141
142
  let typeKeys = Object.keys(type);
142
143
  for (let i = 0; i < typeKeys.length; i++) {
143
- if(typeKeys[i].startsWith("@")){
144
+ if (typeKeys[i].startsWith("@")) {
144
145
  property[typeKeys[i]] = type[typeKeys[i]];
145
146
  delete type[typeKeys[i]];
146
147
  }
@@ -164,6 +165,9 @@ function generatePropertyCsn(propertyType, isPrimaryKey) {
164
165
  // conditions have to be made
165
166
  if (propertyType.$MaxLength) {
166
167
  if (propertyType.$Type) {
168
+ if (propertyType.$Type == "Edm.Binary" && propertyType.$MaxLength >= 5000) {
169
+ console.log(warn("MaxLength for type Edm.Binary should not exceed 5000"));
170
+ }
167
171
  typeProperties.type = edmxncdsdatatype[propertyType.$Type + '_m'];
168
172
  } else {
169
173
  typeProperties.type = 'cds.String'; // if type is missing, then it is String type
@@ -175,7 +179,7 @@ function generatePropertyCsn(propertyType, isPrimaryKey) {
175
179
  typeProperties["@odata.Precision"] = propertyType.$Precision;
176
180
  } else {
177
181
  typeProperties.type = edmxncdsdatatype[propertyType.$Type];
178
- typeProperties["@odata.Precision"] = 0;
182
+ //typeProperties["@odata.Precision"] = 0;
179
183
  }
180
184
  } else if (propertyType.$Precision && !_isValidDataType(propertyType.$Type)) {
181
185
  typeProperties.type = edmxncdsdatatype[propertyType.$Type + '_p'];
@@ -186,7 +190,12 @@ function generatePropertyCsn(propertyType, isPrimaryKey) {
186
190
  } else if (edmxncdsdatatype[propertyType.$Type + "_a"]) {
187
191
  typeProperties.type = edmxncdsdatatype[propertyType.$Type + "_a"];
188
192
  } else if (propertyType.$Type) {
189
- typeProperties.type = edmxncdsdatatype[propertyType.$Type];
193
+ if (edmxncdsdatatype[propertyType.$Type]) {
194
+ typeProperties.type = edmxncdsdatatype[propertyType.$Type];
195
+ }
196
+ else {
197
+ typeProperties.type = propertyType.$Type;
198
+ }
190
199
  } else {
191
200
  typeProperties.type = 'cds.LargeString'; // if type is missing, then it is String type
192
201
  }
@@ -240,7 +249,7 @@ function _parseAssociationProperty(foreignReference, associationNode, mockServer
240
249
  for (let j = 0; j < parserContext.entitySetToEntityTypeMap.get(associationNode.$Type).length; j++) {
241
250
  if (parserContext.entitySetToEntityTypeMap.get(associationNode.$Type)[j] === foreignReference) {
242
251
  associationProperty.target = parserContext.namespace + '.' +
243
- parserContext.entitySetToEntityTypeMap.get(associationNode.$Type)[j];
252
+ parserContext.entitySetToEntityTypeMap.get(associationNode.$Type)[j];
244
253
  }
245
254
  }
246
255
  } else {
@@ -323,6 +332,12 @@ function _generateCSNForEntityType(ignorePersistenceSkip, mockServerUc, parserCo
323
332
  if (!ignorePersistenceSkip) {
324
333
  entityCsn[key]['@cds.persistence.skip'] = true;
325
334
  }
335
+ if (element[key].$Singleton) {
336
+ entityCsn[key]['@odata.singleton'] = true;
337
+ }
338
+ if (element[key].$SingletonNullable) {
339
+ entityCsn[key]['@odata.singleton.nullable'] = true;
340
+ }
326
341
  _includeExternalNamespaceAnnotation(element[key], entityCsn[key]);
327
342
  // inheritance
328
343
  if (baseType) {
@@ -358,7 +373,7 @@ function _generateCSNForEntityType(ignorePersistenceSkip, mockServerUc, parserCo
358
373
  entityCsn[key].elements[property] = generatePropertyCsn(propertyType, false);
359
374
  }
360
375
  } else if (!element[key][property].$Type || parserContext.enumTypes[element[key][property].$Type]) {
361
- enumType.$Type = parserContext.enumTypes[element[key][property].$Type].$UnderlyingType;
376
+ enumType = element[key][property];
362
377
  if (keySet.includes(property)) {
363
378
  entityCsn[key].elements[property] = generatePropertyCsn(enumType, true);
364
379
  } else {
@@ -402,13 +417,24 @@ function _generateEntityType(schemaData, mockServerUc, parserContext) {
402
417
  let entity1 = {};
403
418
  for (let i = 0; i < parserContext.entitySetToEntityTypeMap.get(entityTypeName).length; i++) {
404
419
  entity1 = {};
420
+ let entityDetails = {};
405
421
  let temp1 = parserContext.namespace + '.' + parserContext.entitySetToEntityTypeMap.get(entityTypeName)[i];
406
- entity1[temp1] = schemaData[entityType];
422
+ entity1[temp1] = Object.assign({}, schemaData[entityType]);
423
+ entityDetails = schemaData[parserContext.jsonEntityContainerName][parserContext.entitySetToEntityTypeMap.get(entityTypeName)[i]];
424
+ if (entityDetails.$Singleton)
425
+ entity1[temp1].$Singleton = entityDetails.$Singleton;
426
+ if (entityDetails.$SingletonNullable)
427
+ entity1[temp1].$SingletonNullable = entityDetails.$SingletonNullable;
407
428
  parserContext.entityTypes.push(entity1);
408
429
  }
409
430
  } else {
410
431
  temp = parserContext.namespace + '.' + parserContext.entitySetToEntityTypeMap.get(entityTypeName);
411
432
  entity[temp] = schemaData[entityType];
433
+ let entityDetails = schemaData[parserContext.jsonEntityContainerName][parserContext.entitySetToEntityTypeMap.get(entityTypeName)];
434
+ if (entityDetails.$Singleton)
435
+ entity[temp].$Singleton = entityDetails.$Singleton;
436
+ if (entityDetails.$SingletonNullable)
437
+ entity[temp].$SingletonNullable = entityDetails.$SingletonNullable;
412
438
  parserContext.entityTypes.push(entity);
413
439
  }
414
440
  } else {
@@ -469,6 +495,29 @@ function _collectEnumType(schemaDataList, parserContext) {
469
495
  schemaData = schemaDataList[i];
470
496
  parserContext.enumTypes = _generateEnumType(schemaData, parserContext);
471
497
  }
498
+ return parserContext.enumTypes;
499
+ }
500
+
501
+ function _generateCSNForEnumType(schemaData, parserContext) {
502
+ let enumCsn = {};
503
+ let eTypes;
504
+ eTypes = _collectEnumType(schemaData, parserContext);
505
+ Object.keys(eTypes).forEach(element => {
506
+ enumCsn[element] = {};
507
+ enumCsn[element].enum = {};
508
+ enumCsn[element].type = eTypes[element].$Type != null ? edmxncdsdatatype[eTypes[element].$Type] : 'cds.LargeString';
509
+ Object.keys(eTypes[element]).forEach(property => {
510
+ if (property != "$Kind" && property != "$Type") {
511
+ if (enumCsn[element].type == 'cds.LargeString') {
512
+ enumCsn[element].enum[property] = cds.parse.expr(`'${(eTypes[element][property])}'`);
513
+ }
514
+ else {
515
+ enumCsn[element].enum[property] = cds.parse.expr(`${(eTypes[element][property])}`);
516
+ }
517
+ }
518
+ });
519
+ });
520
+ return enumCsn;
472
521
  }
473
522
 
474
523
  function _generateTypeDefinition(schemaData, parserContext) {
@@ -505,8 +554,8 @@ function _generateBounded(schemaData, flag, parserContext) {
505
554
  kindString = 'Action';
506
555
  }
507
556
  Object.keys(schemaData).forEach(curFunction => {
508
- if (schemaData[curFunction] instanceof Array &&
509
- schemaData[curFunction][0].$Kind === kindString &&
557
+ if (schemaData[curFunction] instanceof Array &&
558
+ schemaData[curFunction][0].$Kind === kindString &&
510
559
  schemaData[curFunction][0].$IsBound === true
511
560
  ) {
512
561
  boundedFunction = [];
@@ -698,6 +747,7 @@ function _generateCSNForComplexType(schemaData, parserContext) {
698
747
  let cTypes;
699
748
  let propertyType;
700
749
  let baseType;
750
+ let enumType;
701
751
  cTypes = _collectComplexType(schemaData, parserContext);
702
752
  Object.keys(cTypes).forEach(element => {
703
753
  complexCsn[element] = {};
@@ -711,8 +761,8 @@ function _generateCSNForComplexType(schemaData, parserContext) {
711
761
  }
712
762
  Object.keys(cTypes[element]).forEach(property => { // cTypes[element][property].$Type.startsWith('Edm.')
713
763
  if (cTypes[element][property] instanceof Object) {
714
- if (!cTypes[element][property].$Type ||
715
- edmxncdsdatatype[cTypes[element][property].$Type] ||
764
+ if (!cTypes[element][property].$Type ||
765
+ edmxncdsdatatype[cTypes[element][property].$Type] ||
716
766
  edmxncdsdatatype[cTypes[element][property].$Type + "_a"]
717
767
  ) {
718
768
  propertyType = cTypes[element][property];
@@ -720,6 +770,9 @@ function _generateCSNForComplexType(schemaData, parserContext) {
720
770
  } else if (parserContext.complexTypes[cTypes[element][property].$Type]) {
721
771
  propertyType = cTypes[element][property];
722
772
  complexCsn[element].elements[property] = _generateComplexTypePropertyCsn(propertyType);
773
+ } else if (parserContext.enumTypes[cTypes[element][property].$Type]) {
774
+ enumType = cTypes[element][property];
775
+ complexCsn[element].elements[property] = generatePropertyCsn(enumType, false);
723
776
  } else {
724
777
  let message = '"' + cTypes[element][property].$Type + '" is not supported (in element:"' + property + '")';
725
778
  console.log(warn(message));
@@ -738,7 +791,7 @@ function _parseTypeDefinition(parserContext) {
738
791
  Object.keys(parserContext.typeDefinitions).forEach(element => {
739
792
  typeDef[element] = {};
740
793
  typeDef[element].kind = 'type';
741
- if (!parserContext.typeDefinitions[element].$Type ||
794
+ if (!parserContext.typeDefinitions[element].$Type ||
742
795
  edmxncdsdatatype[parserContext.typeDefinitions[element].$Type]
743
796
  ) {
744
797
  propertyType = parserContext.typeDefinitions[element];
@@ -873,7 +926,7 @@ function _generateCSN(edmxAsJson, ignorePersistenceSkip, mockServerUc, parserCon
873
926
  });
874
927
  Object.keys(entityContainer).forEach(data => {
875
928
  if (ignoreObjects.indexOf(data) === -1 && entityContainer[data] instanceof Object &&
876
- entityContainer[data].$Type && entityContainer[data].$Collection) {
929
+ entityContainer[data].$Type && (entityContainer[data].$Collection || entityContainer[data].$Singleton)) {
877
930
  parserContext.entitySetToEntityTypeMap.set(entityContainer[data].$Type, data);
878
931
  } else if (ignoreObjects.indexOf(data) === -1 && entityContainer[data] instanceof Object &&
879
932
  entityContainer[data].$Action) {
@@ -905,12 +958,14 @@ function _generateCSN(edmxAsJson, ignorePersistenceSkip, mockServerUc, parserCon
905
958
  // Step 4: get all unbounded action & function
906
959
  csn.definitions = Object.assign(_parseUnbounded(schemaData, 0, parserContext), csn.definitions);
907
960
  csn.definitions = Object.assign(_parseUnbounded(schemaData, 1, parserContext), csn.definitions);
908
- // Step 5: add entity container properties
961
+ // Step 5: get all enum types
962
+ csn.definitions = Object.assign(_generateCSNForEnumType(schemaData, parserContext), csn.definitions);
963
+ // Step 6: add entity container properties
909
964
  csn.definitions = Object.assign(_parseEntityContainer(csn.definitions, schemaData, parserContext, parserContext), csn.definitions);
910
- // Step 6: get all bounded action & function
965
+ // Step 7: get all bounded action & function
911
966
  _parseBounded(csn.definitions, 0, parserContext);
912
967
  _parseBounded(csn.definitions, 1, parserContext);
913
- // Step 7: get all annotations
968
+ // Step 8: get all annotations
914
969
  _generateDocumentation(edmxAsJson, schemaData, csn.definitions, parserContext);
915
970
 
916
971
  return JSON.stringify(csn, null, 4);
@@ -960,9 +1015,9 @@ function _checkAnnotationTarget(annotation, cdsDefs, str, no_of_terms, vocab, pa
960
1015
  }
961
1016
  }
962
1017
  else if (annotation[0].includes("Container")) {
963
- let path = annotation[0].substring(0,annotation[0].lastIndexOf('.'));
1018
+ let path = annotation[0].substring(0, annotation[0].lastIndexOf('.'));
964
1019
  let actualPath = checkEntitySetMap(path, parserContext);
965
- _checkAnnotatationTerm(annotation, cdsDefs[actualPath], no_of_terms, str, vocab);
1020
+ _checkAnnotatationTerm(annotation, cdsDefs[actualPath], no_of_terms, str, vocab);
966
1021
  }
967
1022
  }
968
1023
  else if (annotation[0].indexOf('(') === -1 && !(annotation[0].indexOf('/') === -1)) {
@@ -1058,7 +1113,7 @@ function _generateEDMX2JSON(edmx, name_space, parserContext) {
1058
1113
  // create converter
1059
1114
  const v4Conv = MetadataConverterFactory.createEdmxV40XmlToV40Json(name_space);
1060
1115
  v4Conv.execute(inputBuffer, (error, json, missingReferencedDocuments) => {
1061
- if (missingReferencedDocuments.length > 0) {
1116
+ if (missingReferencedDocuments?.length > 0) {
1062
1117
  console.log(missingReferencedDocuments); // eslint-disable-line no-console
1063
1118
  }
1064
1119
  if (_validateJSON(json, parserContext)) {
@@ -1075,7 +1130,7 @@ async function getEdmxv4CSN(edmx, ignorePersistenceSkip, mockServerUc, context)
1075
1130
  let csn;
1076
1131
  let edmjConverted;
1077
1132
  let name_space = []
1078
-
1133
+
1079
1134
  const parserContext = {};
1080
1135
  _initialize(parserContext);
1081
1136
 
@@ -1083,7 +1138,7 @@ async function getEdmxv4CSN(edmx, ignorePersistenceSkip, mockServerUc, context)
1083
1138
  name_space.push(true);
1084
1139
  else
1085
1140
  name_space = context.namespaces;
1086
-
1141
+
1087
1142
  if (_isJson(edmx)) {
1088
1143
  return new Promise(function getCsn(resolve, reject) {
1089
1144
  try {
@@ -1,6 +1,6 @@
1
1
  const os = require('os');
2
2
 
3
- const MAVEN_ARCHETYPE_VERSION = '1.27.1';
3
+ const MAVEN_ARCHETYPE_VERSION = '1.28.0';
4
4
 
5
5
  const constants = {
6
6
  IS_WIN: (os.platform() === 'win32'),
@@ -14,12 +14,14 @@ const constants = {
14
14
  OPTION_JAVA: 'java',
15
15
  OPTION_HANA: 'hana',
16
16
  OPTION_XSUAA: 'xsuaa',
17
+ OPTION_DESTINATIONS: 'destinations',
17
18
  OPTION_MTA: 'mta',
18
19
  OPTION_MTX: 'mtx',
19
20
  OPTION_MULTITENANCY: 'multitenancy',
20
21
  OPTION_TOGGLES: 'toggles',
21
22
  OPTION_EXTENSIBILITY: 'extensibility',
22
23
  OPTION_AUDITLOG: 'auditlog',
24
+ OPTION_ENTERPRISE_MESSAGING: 'enterprise-messaging',
23
25
  OPTION_APPROUTER: 'approuter',
24
26
  OPTION_KIBANA_LOGGING: 'kibana-logging',
25
27
  OPTION_CF_MANIFEST: 'cf-manifest',
@@ -33,7 +35,6 @@ const constants = {
33
35
  OPTION_JAVA_PACKAGE: 'java:package',
34
36
  OPTION_JAVA_MVN: 'java:mvn',
35
37
  OPTION_HELM: 'helm',
36
- OPTION_HELM_UPDATE: 'helm/update',
37
38
 
38
39
  // node enum
39
40
  PROJECT_TYPE: Object.freeze({ nodejs: 1, java: 2, unknown: 3 }),
@@ -78,7 +79,9 @@ constants.OPTIONS_PRIORITY = [
78
79
  constants.OPTION_XSUAA,
79
80
  constants.OPTION_HANA,
80
81
  constants.OPTION_AUDITLOG,
82
+ constants.OPTION_ENTERPRISE_MESSAGING,
81
83
  constants.OPTION_APPROUTER,
84
+ constants.OPTION_DESTINATIONS,
82
85
  constants.OPTION_SAMPLES,
83
86
  constants.OPTION_DATA,
84
87
  constants.OPTION_KIBANA_LOGGING,
package/lib/init/index.js CHANGED
@@ -130,6 +130,8 @@ module.exports = class CDSGenerator {
130
130
  options._cmd = COMMAND_ADD;
131
131
  options.add = templates;
132
132
 
133
+ if (!templates) throw 'You must specify a facet to add to the project.'
134
+
133
135
  this._initialize(null, options);
134
136
  this._greetings(options._cmd);
135
137
 
@@ -231,13 +233,23 @@ module.exports = class CDSGenerator {
231
233
  this.logger.log();
232
234
  }
233
235
 
234
- _createTemplate(clazz) {
236
+ async _createTemplate(filename) {
235
237
  try {
236
- const TemplateClass = require(`./template/${clazz}`);
238
+ const TemplateClass = require(`./template/${filename}`);
237
239
  return new TemplateClass(this.projectPath, this);
238
240
  } catch (err) {
239
241
  if (err.code === 'MODULE_NOT_FOUND') {
240
- throw new Error(`feature '${clazz}' not found. ${err}`);
242
+ const entries = (await this.fsUtil.readdir(path.join(__dirname, 'template')))
243
+ .filter(entry =>
244
+ !entry.startsWith('_') &&
245
+ !entry.endsWith('.js') &&
246
+ entry !== 'nodejs' &&
247
+ entry !== 'java'
248
+ );
249
+ const fuzzySearch = require('../../bin/util/fuzzySearch');
250
+ const [bestMatch] = fuzzySearch(filename, entries);
251
+ console.log(`Unknown facet '${term.bold(filename)}'. Did you mean ${term.bold(`cds add ${bestMatch}`)}?\n\nHaven't found the proper facet yet? Here are all supported facets:\n\n ${term.bold(entries.join('\n '))}\n`);
252
+ process.exit(1);
241
253
  }
242
254
  throw err;
243
255
  }
@@ -247,7 +259,7 @@ module.exports = class CDSGenerator {
247
259
  const templates = new Map();
248
260
  for (const option of this.options.add) {
249
261
  if (!templates.has(option)) {
250
- const template = this._createTemplate(option);
262
+ const template = await this._createTemplate(option);
251
263
 
252
264
  if (await template.checkEnabled()) {
253
265
  this.logger.debug(`Adding feature '${template.name}'`);
@@ -54,6 +54,18 @@ const auditlog = {
54
54
  }]
55
55
  }
56
56
 
57
+ const enterpriseMessaging = {
58
+ ref: 'enterprise-messaging-resource',
59
+ in: 'resources',
60
+ where: [{
61
+ property: 'type',
62
+ isEqualTo: 'org.cloudfoundry.managed-service',
63
+ }, {
64
+ property: 'parameters.service',
65
+ isEqualTo: 'enterprise-messaging',
66
+ }]
67
+ }
68
+
57
69
  const kibanaLogging = {
58
70
  ref: 'cf-logging',
59
71
  in: 'resources',
@@ -264,6 +276,7 @@ module.exports = {
264
276
  approuter,
265
277
  xsuaa,
266
278
  auditlog,
279
+ enterpriseMessaging,
267
280
  hdbDeployer,
268
281
  hdiContainer,
269
282
  serviceManager,
@@ -17,6 +17,15 @@ module.exports = class ApprouterTemplate extends TemplateBase {
17
17
  this.projectReader = new ProjectReader(this)
18
18
  }
19
19
 
20
+ async checkEnabled() {
21
+ const projectDescriptor = await this.projectReader.read(this.options)
22
+ const { hasMtaDeployment, hasHelmDeployment } = projectDescriptor.cap
23
+ if (hasHelmDeployment && !hasMtaDeployment) {
24
+ throw `'cds add approuter' is not available for Kyma yet`
25
+ }
26
+ return true
27
+ }
28
+
20
29
  async getDependencies() {
21
30
  return [OPTION_XSUAA]
22
31
  }
@@ -1,36 +1,55 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const TemplateBase = require('../templateBase');
4
- const ProjectReader = require('../../util/projectReader');
5
- const { srvNode, srvJava, auditlog } = require('../_merging/registry-mta');
1
+ const path = require('path')
2
+ const TemplateBase = require('../templateBase')
3
+ const ProjectReader = require('../../util/projectReader')
4
+ const { srvNode, srvJava, auditlog } = require('../_merging/registry-mta')
5
+ const cds = require('../../../cds'), { fs } = cds.utils
6
6
 
7
7
  module.exports = class AuditlogTemplate extends TemplateBase {
8
8
  constructor(projectPath, generator) {
9
- super(projectPath, generator, __dirname);
10
- this.projectReader = new ProjectReader(this);
11
- }
12
-
13
- async runDependentMerging() {
14
- const projectDescriptor = await this.projectReader.read(this.options);
15
- const { isNodejs } = projectDescriptor.cap;
16
- const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml');
17
- if (!fs.existsSync(mtaYAMLPath)) return;
18
- const srv = isNodejs ? srvNode : srvJava
19
- await this.templateUtil.mergeYAML(
20
- mtaYAMLPath,
21
- `${__dirname}/files/mta.yaml.hbs`,
22
- projectDescriptor,
23
- {
24
- additions: [srv, auditlog],
25
- relationships: [{
26
- insert: [auditlog, 'name'],
27
- into: [srv, 'requires', 'name']
28
- }]
29
- }
30
- );
9
+ super(projectPath, generator, __dirname)
10
+ this.projectReader = new ProjectReader(this)
31
11
  }
32
12
 
33
13
  async run() {
34
14
  await this.runDependentMerging()
35
15
  }
16
+
17
+ async runDependentMerging() {
18
+ const projectDescriptor = await this.projectReader.read(this.options)
19
+ const { isNodejs, hasMtaDeployment, hasHelmDeployment } = projectDescriptor.cap
20
+
21
+ if (hasMtaDeployment) {
22
+ const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
23
+ const srv = isNodejs ? srvNode : srvJava
24
+ await this.templateUtil.mergeYAML(
25
+ mtaYAMLPath,
26
+ `${__dirname}/files/mta.yaml.hbs`,
27
+ projectDescriptor,
28
+ {
29
+ additions: [srv, auditlog],
30
+ relationships: [{
31
+ insert: [auditlog, 'name'],
32
+ into: [srv, 'requires', 'name']
33
+ }]
34
+ }
35
+ )
36
+ }
37
+
38
+ if (hasHelmDeployment) {
39
+ await this.templateUtil.mergeYAML(
40
+ path.join(this.projectPath, 'chart', 'values.yaml'),
41
+ {
42
+ srv: { bindings: {
43
+ auditlog: { serviceInstanceName: 'auditlog' }
44
+ }},
45
+ auditlog: {
46
+ serviceOfferingName: 'auditlog-api',
47
+ servicePlanName: 'default'
48
+ }
49
+ },
50
+ null, { forceOverwrite: true }
51
+ )
52
+ await fs.copy(path.join(__dirname, 'files', 'auditlog.yaml'), path.join(this.projectPath, 'chart', 'templates', 'auditlog.yaml'))
53
+ }
54
+ }
36
55
  }
@@ -17,4 +17,4 @@ data:
17
17
  onpremise_proxy_rfc_port: "20001"
18
18
  onpremise_socks5_proxy_port: "20004"
19
19
  {{- end }}
20
- {{- end }}
20
+ {{- end }}
@@ -0,0 +1 @@
1
+ {{- include "cap.service-instance" . }}
@@ -0,0 +1,26 @@
1
+ ---
2
+ srv:
3
+ additionalVolumes:
4
+ - name: connectivity-secret
5
+ volumeMount:
6
+ mountPath: /bindings/connectivity
7
+ readOnly: true
8
+ projected:
9
+ sources:
10
+ - secret:
11
+ name: {{cap.appName}}-connectivity-binding
12
+ optional: false
13
+ - secret:
14
+ name: {{cap.appName}}-connectivity-binding
15
+ optional: false
16
+ items:
17
+ - key: token_service_url
18
+ path: url
19
+ - configMap:
20
+ name: {{cap.appName}}-connectivity-proxy-info
21
+ optional: false
22
+ connectivity:
23
+ serviceOfferingName: connectivity
24
+ servicePlanName: connectivity_proxy
25
+ secretName: {{cap.appName}}-connectivity-binding
26
+ configMapName: {{cap.appName}}-connectivity-proxy-info