@sap/cds-dk 6.3.2 → 6.4.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 (93) hide show
  1. package/CHANGELOG.md +31 -7
  2. package/bin/cds.js +2 -0
  3. package/bin/compile/index.js +2 -1
  4. package/bin/deploy/index.js +2 -2
  5. package/bin/deploy/to-sqlite.js +17 -15
  6. package/bin/help.js +7 -4
  7. package/bin/init.js +1 -1
  8. package/bin/login.js +3 -4
  9. package/bin/migrate.js +33 -0
  10. package/bin/pull.js +4 -4
  11. package/bin/push.js +1 -1
  12. package/bin/subscribe.js +58 -66
  13. package/bin/unsubscribe.js +67 -0
  14. package/bin/watch.js +4 -3
  15. package/lib/bind/bindingUtil.js +2 -0
  16. package/lib/bind/cfKeyProvider.js +5 -1
  17. package/lib/client/activate.js +3 -3
  18. package/lib/client/auth_manager.js +2 -2
  19. package/lib/client/base_command.js +7 -6
  20. package/lib/client/extend.js +2 -2
  21. package/lib/client/helper/errors.js +8 -2
  22. package/lib/client/helper/logging.js +13 -11
  23. package/lib/client/params.js +3 -0
  24. package/lib/client/pull.js +1 -1
  25. package/lib/client/push.js +4 -4
  26. package/lib/client/settings_manager.js +13 -6
  27. package/lib/client/subscription.js +81 -0
  28. package/lib/compile/to-xsuaa.js +25 -19
  29. package/lib/import/odata/metadataconverter/MetadataConverter.js +3 -3
  30. package/lib/import/odata/v2parser.js +37 -24
  31. package/lib/import/odata/v4parser.js +106 -37
  32. package/lib/init/constants.js +1 -1
  33. package/lib/init/index.js +2 -2
  34. package/lib/init/template/_merging/registry-mta.js +0 -3
  35. package/lib/init/template/approuter/files/approuter-configmap.yaml +10 -0
  36. package/lib/init/template/approuter/files/approuter-mtxs-configmap.yaml +15 -0
  37. package/lib/init/template/approuter/files/chart.yaml +4 -0
  38. package/lib/init/template/approuter/files/package.json +1 -1
  39. package/lib/init/template/approuter/files/values.yaml.hbs +31 -0
  40. package/lib/init/template/approuter/index.js +60 -12
  41. package/lib/init/template/auditlog/index.js +16 -8
  42. package/lib/init/template/cf-manifest/index.js +3 -3
  43. package/lib/init/template/connectivity/index.js +19 -10
  44. package/lib/init/template/destinations/index.js +23 -7
  45. package/lib/init/template/enterprise-messaging/files/cds.package.json +1 -2
  46. package/lib/init/template/enterprise-messaging/files/cds.profile.package.json.hbs +1 -2
  47. package/lib/init/template/enterprise-messaging/files/cdsrc.json +1 -2
  48. package/lib/init/template/enterprise-messaging/files/cdsrc.json.hbs +1 -2
  49. package/lib/init/template/enterprise-messaging/files/event-mesh.json.hbs +31 -0
  50. package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +1 -0
  51. package/lib/init/template/enterprise-messaging/index.js +26 -13
  52. package/lib/init/template/extensibility/index.js +19 -10
  53. package/lib/init/template/hana/files/mta.yaml.hbs +0 -4
  54. package/lib/init/template/hana/index.js +58 -22
  55. package/lib/init/template/helm/chart/templates/NOTES.txt +4 -3
  56. package/lib/init/template/helm/chart/templates/_deployment_helpers.tpl +25 -2
  57. package/lib/init/template/helm/chart/values.root.schema.json +5 -0
  58. package/lib/init/template/helm/chart/values.schema.json +27 -0
  59. package/lib/init/template/helm/files/values.yaml.hbs +1 -1
  60. package/lib/init/template/helm/index.js +25 -23
  61. package/lib/init/template/helm/subchart/templates/_helpers.tpl +29 -0
  62. package/lib/init/template/helm/subchart/templates/api-rule.yaml +5 -5
  63. package/lib/init/template/helm/subchart/templates/deployment.yaml +12 -9
  64. package/lib/init/template/helm/subchart/values.md +258 -88
  65. package/lib/init/template/helm/subchart/values.schema.json +96 -13
  66. package/lib/init/template/helm/subchart/values.yaml +6 -2
  67. package/lib/init/template/html5-repo/index.js +28 -11
  68. package/lib/init/template/java/index.js +5 -5
  69. package/lib/init/template/kibana-logging/index.js +5 -4
  70. package/lib/init/template/mta/index.js +2 -2
  71. package/lib/init/template/mtx/index.js +1 -1
  72. package/lib/init/template/multitenancy/files/chart.yaml +4 -0
  73. package/lib/init/template/multitenancy/files/java/mtxs-configmap.yaml +20 -0
  74. package/lib/init/template/multitenancy/files/java/package.json +6 -9
  75. package/lib/init/template/multitenancy/files/mtxs-configmap.yaml +15 -0
  76. package/lib/init/template/multitenancy/files/saas-registry.yaml +17 -19
  77. package/lib/init/template/multitenancy/files/values.yaml.hbs +47 -0
  78. package/lib/init/template/multitenancy/files/xs-security.json.hbs +0 -7
  79. package/lib/init/template/multitenancy/index.js +83 -37
  80. package/lib/init/template/nodejs/files/.eslintrc +26 -0
  81. package/lib/init/template/nodejs/files/package.json.hbs +0 -28
  82. package/lib/init/template/nodejs/index.js +7 -10
  83. package/lib/init/template/pipeline/index.js +4 -4
  84. package/lib/init/template/samples/index.js +5 -5
  85. package/lib/init/template/templateBase.js +1 -4
  86. package/lib/init/template/toggles/index.js +5 -5
  87. package/lib/init/template/xsuaa/files/values.yaml.hbs +21 -0
  88. package/lib/init/template/xsuaa/index.js +34 -24
  89. package/lib/init/util/md5Tracking.js +113 -0
  90. package/lib/init/util/merge.js +19 -2
  91. package/lib/init/util/projectReader.js +15 -12
  92. package/npm-shrinkwrap.json +630 -1057
  93. package/package.json +3 -3
@@ -4,7 +4,6 @@
4
4
  */
5
5
 
6
6
  "use strict";
7
-
8
7
  let messages = require("../message").getMessages();
9
8
  let common = require("../common");
10
9
  let versionInfo = require("../../../package.json").version;
@@ -71,6 +70,8 @@ function _initialize(parserContext) {
71
70
  parserContext.unboundedFunctions = {};
72
71
  parserContext.boundedFunctions = {};
73
72
  parserContext.entityTypes = [];
73
+ parserContext.entityTypeOpenEntries = [];
74
+ parserContext.complexTypeOpenEntries = [];
74
75
  parserContext.namespace = "";
75
76
  parserContext.complexTypes = {};
76
77
  parserContext.enumTypes = {};
@@ -100,11 +101,7 @@ function _isValidDataType(propertyType) {
100
101
  }
101
102
 
102
103
  function _isValidJSON(jsonObj, parserContext) {
103
- let tempNamespace = jsonObj.$EntityContainer;
104
- parserContext.namespace = tempNamespace.substring(0, tempNamespace.lastIndexOf('.'));
105
- parserContext.jsonEntityContainerName = tempNamespace.substring(tempNamespace.lastIndexOf('.') + 1);
106
-
107
- if (jsonObj.$Version && jsonObj.$EntityContainer && jsonObj[parserContext.namespace]) {
104
+ if (jsonObj.$Version && _hasEntityContainer(jsonObj, parserContext) && jsonObj[parserContext.namespace]) {
108
105
  return true;
109
106
  }
110
107
  else {
@@ -113,22 +110,19 @@ function _isValidJSON(jsonObj, parserContext) {
113
110
  }
114
111
 
115
112
  function _hasEntityContainer(jsonObj, parserContext) {
116
- if (jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] &&
117
- jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] instanceof Object
118
- ) {
119
- return true;
120
- } else {
113
+ let jsonObjEntityContainer = jsonObj.$EntityContainer;
114
+ try {
115
+ if (jsonObjEntityContainer) [parserContext.namespace, parserContext.jsonEntityContainerName] = jsonObjEntityContainer.split('.');
116
+ if (jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] &&
117
+ jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] instanceof Object
118
+ ) {
119
+ return true;
120
+ }
121
+ } catch (err) {
121
122
  throw new Error(messages.MISSING_ENTITY_CONTAINER);
122
123
  }
123
124
  }
124
125
 
125
- function _validateJSON(jsonObj, parserContext) {
126
- return (
127
- _isValidJSON(jsonObj, parserContext) &&
128
- _hasEntityContainer(jsonObj, parserContext)
129
- );
130
- }
131
-
132
126
  function _includeExternalNamespaceAnnotation(source, target) {
133
127
  Object.entries(source).forEach(element => {
134
128
  if (element[0].startsWith('@')) {
@@ -137,6 +131,11 @@ function _includeExternalNamespaceAnnotation(source, target) {
137
131
  });
138
132
  }
139
133
 
134
+ function _addNotNull(property, isCollection) {
135
+ if (isCollection) property.items["notNull"] = true;
136
+ else property["notNull"] = true;
137
+ }
138
+
140
139
  function _typeWithCollections(property, type, isCollection) {
141
140
  if (isCollection === true) {
142
141
  let typeKeys = Object.keys(type);
@@ -166,7 +165,9 @@ function generatePropertyCsn(propertyType, isPrimaryKey) {
166
165
  typeProperties["notNull"] = true;
167
166
  }
168
167
  else {
169
- typeProperties["notNull"] = propertyType.$Nullable ? false : true;
168
+ if ((propertyType.$Nullable !== true) && (propertyType.$Kind !== 'TypeDefinition')) {
169
+ typeProperties["notNull"] = true;
170
+ }
170
171
  }
171
172
  _includeExternalNamespaceAnnotation(propertyType, property);
172
173
  // conditions have to be made
@@ -225,16 +226,18 @@ function _generateComplexTypePropertyCsn(propertyType) {
225
226
  let property = {};
226
227
  let type = { type: propertyType.$Type }
227
228
  _typeWithCollections(property, type, propertyType.$Collection);
229
+ if (!propertyType.$Nullable) _addNotNull(property, propertyType.$Collection);
228
230
 
229
231
  return property;
230
232
  }
231
233
 
232
234
  function _generateTypeDefinitionPropertyCsn(propertyType) {
233
235
  let property = {};
234
- let type = { type: propertyType.$Type }
236
+ let type = { type: propertyType.$Type };
235
237
 
236
238
  _includeExternalNamespaceAnnotation(propertyType, property);
237
239
  _typeWithCollections(property, type, propertyType.$Collection);
240
+ if (!propertyType.$Nullable) _addNotNull(property, propertyType.$Collection);
238
241
 
239
242
  return property;
240
243
  }
@@ -251,6 +254,11 @@ function _parseAssociationProperty(foreignReference, associationNode, mockServer
251
254
  // annotation for ON condition
252
255
  associationProperty["@cds.ambiguous"] = 'missing on condition?';
253
256
  // associationProperty.target = associationNode.$Type;
257
+
258
+ //Code for NavigationProperty for notNull
259
+ /*if(associationProperty.$Nullable != true){
260
+ associationProperty["notNull"] = true;
261
+ }*/
254
262
  if (mockServerUc && parserContext.entitySetToEntityTypeMap && parserContext.entitySetToEntityTypeMap.get(associationNode.$Type)) {
255
263
  if (parserContext.entitySetToEntityTypeMap.get(associationNode.$Type).length > 1) {
256
264
  for (let j = 0; j < parserContext.entitySetToEntityTypeMap.get(associationNode.$Type).length; j++) {
@@ -333,6 +341,7 @@ function _generateCSNForEntityType(ignorePersistenceSkip, mockServerUc, parserCo
333
341
  let key = Object.keys(element)[0];
334
342
  let baseType = element[key].$BaseType;
335
343
  let isAbstract = element[key].$Abstract;
344
+ let isOpenType = element[key].$OpenType;
336
345
  if (key) {
337
346
  entityCsn[key] = {};
338
347
  entityCsn[key].kind = 'entity';
@@ -355,9 +364,10 @@ function _generateCSNForEntityType(ignorePersistenceSkip, mockServerUc, parserCo
355
364
  baseType = _getBaseTypeEntityName(baseType, parserContext);
356
365
  }
357
366
  entityCsn[key].includes.push(baseType);
367
+ if (!parserContext.entityTypeOpenEntries.includes(baseType)) parserContext.entityTypeOpenEntries.push(baseType);
358
368
  }
359
- if (isAbstract) {
360
- entityCsn[key].abstract = isAbstract;
369
+ if ((isAbstract || isOpenType) && !parserContext.entityTypeOpenEntries.includes(key)) {
370
+ parserContext.entityTypeOpenEntries.push(key);
361
371
  }
362
372
  entityCsn[key].elements = {};
363
373
  keySet = [];
@@ -408,6 +418,12 @@ function _generateCSNForEntityType(ignorePersistenceSkip, mockServerUc, parserCo
408
418
  }
409
419
  }
410
420
  });
421
+
422
+ // add @open annotations
423
+ parserContext.entityTypeOpenEntries.forEach(key => {
424
+ if (entityCsn[key]) entityCsn[key]['@open'] = true;
425
+ });
426
+
411
427
  return entityCsn;
412
428
  }
413
429
 
@@ -579,6 +595,26 @@ function _generateBounded(schemaData, flag, parserContext) {
579
595
  return bFunction;
580
596
  }
581
597
 
598
+ function _captureOptionalParameter(annotation, path) {
599
+ let param = annotation[0].split('/');
600
+ let defaultvalue = annotation[1]["@Core.OptionalParameter"]["DefaultValue"];
601
+ if (path.params === undefined) {
602
+ _addDefaultValueObject(path, defaultvalue);
603
+ }
604
+ else {
605
+ _addDefaultValueObject(path.params[param[1]], defaultvalue);
606
+ }
607
+ return path;
608
+ }
609
+
610
+ function _addDefaultValueObject(path, defaultvalue) {
611
+ // for collection, default value isin't expected
612
+ if (path.items === undefined) {
613
+ path.default = {};
614
+ path.default.val = (defaultvalue) ? defaultvalue : null;
615
+ }
616
+ }
617
+
582
618
  function _collectBounded(schemaDataList, flag, parserContext) {
583
619
  let schemaData;
584
620
  for (let i = 0; i < schemaDataList.length; i++) {
@@ -677,14 +713,16 @@ function _parseBounded(csnDefs, flag, parserContext) {
677
713
  if (paramObj.$Collection && !paramType.items) {
678
714
  csnDefs[boundedEntityName].actions[name].params[paramName] = {};
679
715
  csnDefs[boundedEntityName].actions[name].params[paramName].items = paramType;
680
- csnDefs[boundedEntityName].actions[name].params[paramName].items["notNull"] = paramObj?.$Nullable ? false : true;
681
-
716
+ if(paramObj.$Nullable != true){
717
+ csnDefs[boundedEntityName].actions[name].params[paramName].items["notNull"] = true;
718
+ }
682
719
  } else {
683
720
  csnDefs[boundedEntityName].actions[name].params[paramName] = paramType;
684
721
  if (!paramType.items) {
685
- csnDefs[boundedEntityName].actions[name].params[paramName].notNull = paramObj?.$Nullable ? false : true;
722
+ if(paramObj.$Nullable != true){
723
+ csnDefs[boundedEntityName].actions[name].params[paramName].notNull = true;
724
+ }
686
725
  }
687
- }
688
726
  }
689
727
  }
690
728
  else {
@@ -718,12 +756,16 @@ function _parseBounded(csnDefs, flag, parserContext) {
718
756
  // check if return type is a collection
719
757
  if (obj[j].$ReturnType.$Collection && !returnType.items) {
720
758
  csnDefs[boundedEntityName].actions[name].returns.items = returnType;
721
- csnDefs[boundedEntityName].actions[name].returns.items["notNull"] = obj[j].$ReturnType?.$Nullable ? false : true
759
+ if(obj[j].$ReturnType.$Nullable != true){
760
+ csnDefs[boundedEntityName].actions[name].returns.items["notNull"] = true;
761
+ }
722
762
  }
723
763
  else {
724
764
  csnDefs[boundedEntityName].actions[name].returns = returnType;
725
765
  if (!returnType.items) {
726
- csnDefs[boundedEntityName].actions[name].returns["notNull"] = obj[j].$ReturnType?.$Nullable ? false : true
766
+ if(obj[j].$ReturnType.$Nullable != true){
767
+ csnDefs[boundedEntityName].actions[name].returns["notNull"] = true;
768
+ }
727
769
  }
728
770
  }
729
771
  }
@@ -736,6 +778,7 @@ function _parseBounded(csnDefs, flag, parserContext) {
736
778
  }
737
779
  }
738
780
  }
781
+ }
739
782
  });
740
783
  }
741
784
  }
@@ -768,7 +811,7 @@ function _generateCSNForComplexType(schemaData, parserContext) {
768
811
  let complexCsn = {};
769
812
  let cTypes;
770
813
  let propertyType;
771
- let baseType;
814
+ let baseType, isAbstract, isOpenType;
772
815
  let enumType;
773
816
  cTypes = _collectComplexType(schemaData, parserContext);
774
817
  Object.keys(cTypes).forEach(element => {
@@ -778,10 +821,16 @@ function _generateCSNForComplexType(schemaData, parserContext) {
778
821
  complexCsn[element].elements = {};
779
822
  // inheritance handling
780
823
  baseType = cTypes[element].$BaseType;
824
+ isAbstract = cTypes[element].$Abstract;
825
+ isOpenType = cTypes[element].$OpenType;
781
826
  if (baseType) {
782
827
  complexCsn[element].includes = [];
783
828
  complexCsn[element].includes.push(baseType);
829
+ if (!parserContext.complexTypeOpenEntries.includes(baseType)) parserContext.complexTypeOpenEntries.push(baseType);
784
830
  }
831
+ if ((isAbstract || isOpenType) && !parserContext.complexTypeOpenEntries.includes(element)) {
832
+ parserContext.complexTypeOpenEntries.push(element);
833
+ }
785
834
  Object.keys(cTypes[element]).forEach(property => { // cTypes[element][property].$Type.startsWith('Edm.')
786
835
  if (cTypes[element][property] instanceof Object) {
787
836
  if (!cTypes[element][property].$Type ||
@@ -793,6 +842,9 @@ function _generateCSNForComplexType(schemaData, parserContext) {
793
842
  } else if (parserContext.complexTypes[cTypes[element][property].$Type]) {
794
843
  propertyType = cTypes[element][property];
795
844
  complexCsn[element].elements[property] = _generateComplexTypePropertyCsn(propertyType);
845
+ } else if (parserContext.typeDefinitions[cTypes[element][property].$Type]) {
846
+ propertyType = cTypes[element][property];
847
+ complexCsn[element].elements[property] = _generateTypeDefinitionPropertyCsn(propertyType);
796
848
  } else if (parserContext.enumTypes[cTypes[element][property].$Type]) {
797
849
  enumType = cTypes[element][property];
798
850
  complexCsn[element].elements[property] = generatePropertyCsn(enumType, false);
@@ -805,6 +857,12 @@ function _generateCSNForComplexType(schemaData, parserContext) {
805
857
  }
806
858
  });
807
859
  });
860
+
861
+ // add @open annotations
862
+ parserContext.complexTypeOpenEntries.forEach(key => {
863
+ if (complexCsn[key]) complexCsn[key]['@open'] = true;
864
+ });
865
+
808
866
  return complexCsn;
809
867
  }
810
868
 
@@ -870,11 +928,15 @@ function _parseUnbounded(schemaData, flag, parserContext) {
870
928
  if (objData.$Parameter[i].$Collection && !paramType.items) {
871
929
  obj[objType].params[objData.$Parameter[i].$Name] = {};
872
930
  obj[objType].params[objData.$Parameter[i].$Name].items = paramType;
873
- obj[objType].params[objData.$Parameter[i].$Name].items["notNull"] = objData.$Parameter[i]?.$Nullable ? false : true;
931
+ if(objData.$Parameter[i].$Nullable != true){
932
+ obj[objType].params[objData.$Parameter[i].$Name].items["notNull"] = true;
933
+ }
874
934
  } else {
875
935
  obj[objType].params[objData.$Parameter[i].$Name] = paramType;
876
936
  if (!paramType.items) {
877
- obj[objType].params[objData.$Parameter[i].$Name]["notNull"] = objData.$Parameter[i]?.$Nullable ? false : true;
937
+ if(objData.$Parameter[i].$Nullable != true){
938
+ obj[objType].params[objData.$Parameter[i].$Name]["notNull"] = true;
939
+ }
878
940
  }
879
941
  }
880
942
  }
@@ -909,11 +971,15 @@ function _parseUnbounded(schemaData, flag, parserContext) {
909
971
  if (objData.$ReturnType.$Collection && !returnValue.items) {
910
972
  obj[objType].returns.items = {};
911
973
  obj[objType].returns.items = returnValue;
912
- obj[objType].returns.items["notNull"] = objData.$ReturnType?.$Nullable ? false : true;
974
+ if(objData.$ReturnType.$Nullable != true){
975
+ obj[objType].returns.items["notNull"] = true;
976
+ }
913
977
  } else {
914
978
  obj[objType].returns = returnValue;
915
979
  if (!returnValue.items) {
916
- obj[objType].returns["notNull"] = objData.$ReturnType?.$Nullable ? false : true;
980
+ if(objData.$ReturnType.$Nullable != true){
981
+ obj[objType].returns["notNull"] = true;
982
+ }
917
983
  }
918
984
  }
919
985
  }
@@ -1021,9 +1087,12 @@ function _checkAnnotatationTerm(annotation, path, no_of_terms, targetString, voc
1021
1087
  else if (targetString === "@Core.LongDescription" && annotation[1]["@Core.LongDescription"]) {
1022
1088
  _generateLongDescription(annotation, path, no_of_terms);
1023
1089
  }
1024
- else if (vocab) {
1090
+ else if (targetString === "@Core.OptionalParameter" && annotation[1]["@Core.OptionalParameter"]) {
1091
+ _captureOptionalParameter(annotation, path);
1092
+ }
1093
+ else if (vocab) {
1025
1094
  if (vocab.includes(targetString.substring(targetString.indexOf('@') + 1, targetString.lastIndexOf('.')))) {
1026
- path[targetString] = annotation[1][targetString];
1095
+ path[targetString] = annotation[1][targetString] === null ? true : annotation[1][targetString];
1027
1096
  }
1028
1097
  }
1029
1098
  }
@@ -1194,7 +1263,7 @@ function _generateEDMX2JSON(edmx, name_space, parserContext) {
1194
1263
  if (missingReferencedDocuments?.length > 0) {
1195
1264
  console.log(missingReferencedDocuments); // eslint-disable-line no-console
1196
1265
  }
1197
- if (_validateJSON(json, parserContext)) {
1266
+ if (_isValidJSON(json, parserContext)) {
1198
1267
  resolve(json);
1199
1268
  }
1200
1269
  });
@@ -1221,7 +1290,7 @@ async function getEdmxv4CSN(edmx, ignorePersistenceSkip, mockServerUc, context)
1221
1290
  return new Promise(function getCsn(resolve, reject) {
1222
1291
  try {
1223
1292
  edmjConverted = JSON.parse(edmx);
1224
- if (_validateJSON(edmjConverted, parserContext)) {
1293
+ if (_isValidJSON(edmjConverted, parserContext)) {
1225
1294
  csn = _generateCSN(edmjConverted, ignorePersistenceSkip, mockServerUc, parserContext);
1226
1295
  if (csn) resolve(csn);
1227
1296
  }
@@ -1,6 +1,6 @@
1
1
  const os = require('os');
2
2
 
3
- const MAVEN_ARCHETYPE_VERSION = '1.29.0';
3
+ const MAVEN_ARCHETYPE_VERSION = '1.30.0';
4
4
 
5
5
  const constants = {
6
6
  IS_WIN: (os.platform() === 'win32'),
package/lib/init/index.js CHANGED
@@ -267,8 +267,8 @@ module.exports = class CDSGenerator {
267
267
  }
268
268
  }
269
269
 
270
- this.templateList = Array.from(templates.entries()).sort((a, b) => {
271
- return OPTIONS_PRIORITY.indexOf(a[0]) - OPTIONS_PRIORITY.indexOf(b[0]);
270
+ this.templateList = Array.from(templates.entries()).sort(([a], [b]) => {
271
+ return OPTIONS_PRIORITY.indexOf(a) - OPTIONS_PRIORITY.indexOf(b);
272
272
  }).map((entry) => entry[1]);
273
273
 
274
274
  // check debug to avoid lengthy computation when not in debug mode
@@ -123,9 +123,6 @@ const saasRegistry = {
123
123
  }, {
124
124
  property: 'parameters.service',
125
125
  isEqualTo: 'saas-registry',
126
- }, {
127
- property: 'parameters.service-plan',
128
- isEqualTo: 'application'
129
126
  }]
130
127
  }
131
128
 
@@ -0,0 +1,10 @@
1
+ # Please do not modify this file. This file may be overwritten.
2
+
3
+ apiVersion: v1
4
+ kind: ConfigMap
5
+ metadata:
6
+ name: "{{ .Release.Name }}-approuter-configmap"
7
+ namespace: "{{ .Release.Namespace }}"
8
+ data:
9
+ destinations: >
10
+ {{ include "cap.approuterDestinations" . }}
@@ -0,0 +1,15 @@
1
+ # Please do not modify this file. This file may be overwritten.
2
+
3
+ {{- $deployment := .Values.approuter }}
4
+ {{- $ := merge (dict "name" "approuter" "deployment" $deployment) . }}
5
+ {{- $approuterUrl := (include "cap.deploymentHostFull" $ )}}
6
+
7
+ apiVersion: v1
8
+ kind: ConfigMap
9
+ metadata:
10
+ name: "{{ .Release.Name }}-approuter-configmap"
11
+ namespace: "{{ .Release.Namespace }}"
12
+ data:
13
+ destinations: >
14
+ {{ include "cap.approuterDestinations" . }}
15
+ TENANT_HOST_PATTERN: {{ printf "^(.*)-%s" $approuterUrl }}
@@ -0,0 +1,4 @@
1
+ dependencies:
2
+ - name: web-application
3
+ alias: approuter
4
+ version: 0.1.0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "approuter",
3
3
  "dependencies": {
4
- "@sap/approuter": "^11.0.0"
4
+ "@sap/approuter": "^12.0.0"
5
5
  },
6
6
  "engines": {
7
7
  "node": "^16"
@@ -0,0 +1,31 @@
1
+ ---
2
+ {{#cap.hasXsuaa}}
3
+ xsuaa:
4
+ parameters:
5
+ oauth2-configuration:
6
+ redirect-uris:
7
+ - https://*.<your-cluster-domain>/**
8
+ {{/cap.hasXsuaa}}
9
+ approuter:
10
+ {{#cap.hasXsuaa}}
11
+ bindings:
12
+ auth:
13
+ serviceInstanceName: xsuaa
14
+ {{/cap.hasXsuaa}}
15
+ image:
16
+ repository: <your-container-registry>/{{cap.appName}}-approuter
17
+ tag: latest
18
+ resources:
19
+ limits:
20
+ ephemeral-storage: 1G
21
+ memory: 500M
22
+ requests:
23
+ ephemeral-storage: 1G
24
+ cpu: 500m
25
+ memory: 500M
26
+ health:
27
+ liveness:
28
+ path: /
29
+ readiness:
30
+ path: /
31
+ approuterDestinations: {}
@@ -9,6 +9,7 @@ const {
9
9
  requiredAppAPI, providedAppAPI,
10
10
  approuterExtensibility, approuterExtensibilityJava // xs-app.json config
11
11
  } = require('../_merging/registry-mta')
12
+ const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
12
13
 
13
14
  module.exports = class ApprouterTemplate extends require('../templateBase') {
14
15
 
@@ -21,16 +22,7 @@ module.exports = class ApprouterTemplate extends require('../templateBase') {
21
22
  return !!env.requires?.approuter
22
23
  }
23
24
 
24
- async canRun() {
25
- const projectDescriptor = await this.projectReader.read(this.options)
26
- const { hasMta, hasHelm } = projectDescriptor.cap
27
- if (hasHelm && !hasMta) {
28
- throw `'cds add approuter' is not available for Kyma yet`
29
- }
30
- return true
31
- }
32
-
33
- async getDependencies() {
25
+ getDependencies() {
34
26
  return [OPTION_XSUAA]
35
27
  }
36
28
 
@@ -66,9 +58,9 @@ module.exports = class ApprouterTemplate extends require('../templateBase') {
66
58
  await this.runDependentMerging()
67
59
  }
68
60
 
69
- async runDependentMerging() {
61
+ async runDependentMerging(context = {}) {
70
62
  const projectDescriptor = await this.projectReader.read(this.options)
71
- const { isNodejs, isJava, isExtensible, isMultitenant, hasMta } = projectDescriptor.cap
63
+ const { isNodejs, isJava, isExtensible, isMultitenant, hasMta, hasHelm } = projectDescriptor.cap
72
64
 
73
65
  if (hasMta) {
74
66
  const srv = isNodejs ? srvNode : srvJava
@@ -89,6 +81,62 @@ module.exports = class ApprouterTemplate extends require('../templateBase') {
89
81
  })
90
82
  }
91
83
 
84
+ if (hasHelm) {
85
+ let isIndependentCommand = false;
86
+ if (Object.keys(context).length == 0) {
87
+ isIndependentCommand = true;
88
+ context.projectPath = this.projectPath;
89
+ context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'));
90
+ }
91
+
92
+ await mergeYAML(
93
+ join(this.projectPath, 'chart', 'values.yaml'),
94
+ join(__dirname, 'files', 'values.yaml.hbs'),
95
+ projectDescriptor
96
+ )
97
+
98
+ await mergeYAML(
99
+ join(this.projectPath, 'chart', 'Chart.yaml'),
100
+ join(__dirname, 'files', 'chart.yaml'),
101
+ projectDescriptor,
102
+ { additions: [{
103
+ ref: `web-application-approuter`,
104
+ in: `dependencies`,
105
+ where: [{
106
+ property: 'alias',
107
+ isEqualTo: 'approuter'
108
+ }]
109
+ }]}
110
+ )
111
+ await mergeYAML(
112
+ join(this.projectPath, 'chart', 'values.yaml'),
113
+ {
114
+ approuter: {
115
+ envFrom: [
116
+ {
117
+ configMapRef: {
118
+ name: "{{ .Release.Name }}-approuter-configmap",
119
+ tpl: true
120
+ }
121
+ }
122
+ ]
123
+ }
124
+ },
125
+ projectDescriptor
126
+ )
127
+
128
+ const fileName = isMultitenant ? 'approuter-mtxs-configmap.yaml' : 'approuter-configmap.yaml';
129
+
130
+ await copyAndTrack(
131
+ join(__dirname, 'files', fileName),
132
+ join(this.projectPath, 'chart', 'templates', 'approuter-configmap.yaml'),
133
+ context,
134
+ true
135
+ )
136
+
137
+ if (isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData);
138
+ }
139
+
92
140
  const appPath = join(this.projectPath, projectDescriptor.ui.appPath || 'app')
93
141
  const additions = isExtensible && isJava ? [{ ...approuterExtensibilityJava, at: 0 }] :
94
142
  isExtensible && isNodejs ? [{ ...approuterExtensibility, at: 0 }] : []
@@ -1,7 +1,7 @@
1
- const path = require('path')
2
- const { copy } = require('../../../cds').utils
1
+ const { join } = require('path')
3
2
  const ProjectReader = require('../../util/projectReader')
4
3
  const { mergeYAML } = require('../../util/merge')
4
+ const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
5
5
  const { srvNode, srvJava, auditlog } = require('../_merging/registry-mta')
6
6
 
7
7
  module.exports = class AuditlogTemplate extends require('../templateBase') {
@@ -18,12 +18,12 @@ module.exports = class AuditlogTemplate extends require('../templateBase') {
18
18
  await this.runDependentMerging()
19
19
  }
20
20
 
21
- async runDependentMerging() {
21
+ async runDependentMerging(context = {}) {
22
22
  const projectDescriptor = await this.projectReader.read(this.options)
23
23
  const { isNodejs, hasMta, hasHelm } = projectDescriptor.cap
24
24
 
25
25
  if (hasMta) {
26
- const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
26
+ const mtaYAMLPath = join(this.projectPath, 'mta.yaml')
27
27
  const srv = isNodejs ? srvNode : srvJava
28
28
  await mergeYAML(
29
29
  mtaYAMLPath,
@@ -40,8 +40,16 @@ module.exports = class AuditlogTemplate extends require('../templateBase') {
40
40
  }
41
41
 
42
42
  if (hasHelm) {
43
+ //in case facet is being added to the already exisiting charts folder
44
+ let isIndependentCommand = false
45
+ if(Object.keys(context).length == 0){
46
+ isIndependentCommand = true
47
+ context.projectPath = this.projectPath
48
+ context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
49
+ }
50
+
43
51
  await mergeYAML(
44
- path.join(this.projectPath, 'chart', 'values.yaml'),
52
+ join(this.projectPath, 'chart', 'values.yaml'),
45
53
  {
46
54
  srv: { bindings: {
47
55
  auditlog: { serviceInstanceName: 'auditlog' }
@@ -50,10 +58,10 @@ module.exports = class AuditlogTemplate extends require('../templateBase') {
50
58
  serviceOfferingName: 'auditlog-api',
51
59
  servicePlanName: 'default'
52
60
  }
53
- },
54
- null, { forceOverwrite: true }
61
+ }
55
62
  )
56
- await copy(path.join(__dirname, 'files', 'auditlog.yaml'), path.join(this.projectPath, 'chart', 'templates', 'auditlog.yaml'))
63
+ await copyAndTrack(join(__dirname, 'files', 'auditlog.yaml'), join(this.projectPath, 'chart', 'templates', 'auditlog.yaml'), context)
64
+ if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
57
65
  }
58
66
  }
59
67
  }
@@ -1,4 +1,4 @@
1
- const path = require('path')
1
+ const { join } = require('path')
2
2
  const { exists } = require('../../../cds').utils
3
3
  const ProjectReader = require('../../util/projectReader');
4
4
  const { copyFiles } = require('../../util/templateUtil')
@@ -21,7 +21,7 @@ module.exports = class ManifestTemplate extends require('../templateBase') {
21
21
  return true;
22
22
  }
23
23
 
24
- if (exists(path.join(this.projectPath, MANIFEST_FILE)) || exists(path.join(this.projectPath, SERVICES_MANIFEST_FILE))) {
24
+ if (exists(join(this.projectPath, MANIFEST_FILE)) || exists(join(this.projectPath, SERVICES_MANIFEST_FILE))) {
25
25
  throw new Error(`File ${MANIFEST_FILE} or ${SERVICES_MANIFEST_FILE} already exist in current folder. Use --force to overwrite.`);
26
26
  }
27
27
  return true;
@@ -29,6 +29,6 @@ module.exports = class ManifestTemplate extends require('../templateBase') {
29
29
 
30
30
  async run() {
31
31
  const projectDescriptor = await this.projectReader.read()
32
- await copyFiles(path.join(__dirname, 'files'), this.projectPath, projectDescriptor, this.options.force);
32
+ await copyFiles(join(__dirname, 'files'), this.projectPath, projectDescriptor, this.options.force);
33
33
  }
34
34
  }