@sap/cds-dk 6.0.4 → 6.1.3

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 (104) hide show
  1. package/CHANGELOG.md +60 -1
  2. package/bin/add.js +29 -16
  3. package/bin/compile/index.js +7 -2
  4. package/bin/fix-redirects.js +4 -2
  5. package/bin/init.js +5 -0
  6. package/bin/login.js +20 -4
  7. package/bin/pull.js +58 -0
  8. package/bin/push.js +52 -0
  9. package/bin/subscribe.js +45 -0
  10. package/lib/bind/bindingUtil.js +1 -2
  11. package/lib/cds.js +2 -3
  12. package/lib/client/activate.js +17 -16
  13. package/lib/client/auth_manager.js +10 -5
  14. package/lib/client/base_command.js +4 -6
  15. package/lib/client/extend.js +3 -2
  16. package/lib/client/helper/cf_helper.js +1 -0
  17. package/lib/client/helper/errors.js +11 -0
  18. package/lib/client/helper/logging.js +3 -10
  19. package/lib/client/helper/url_helper.js +7 -3
  20. package/lib/client/index.js +1 -1
  21. package/lib/client/params.js +9 -6
  22. package/lib/client/pull.js +48 -0
  23. package/lib/client/push.js +45 -0
  24. package/lib/client/settings_manager.js +81 -27
  25. package/lib/compile/openapi/csdl2openapi.js +135 -163
  26. package/lib/compile/openapi/index.js +0 -1
  27. package/lib/import/common.js +9 -1
  28. package/lib/import/odata/metadataconverter/MetadataConverter.js +17 -4
  29. package/lib/import/odata/v2parser.js +50 -26
  30. package/lib/import/odata/v4parser.js +110 -29
  31. package/lib/import/openapi/importOpenAPI.js +3 -3
  32. package/lib/init/constants.js +9 -3
  33. package/lib/init/template/_merging/registry-mta.js +284 -0
  34. package/lib/init/template/approuter/files/xs-app.json.hbs +7 -7
  35. package/lib/init/template/approuter/index.js +22 -32
  36. package/lib/init/template/auditlog/index.js +7 -9
  37. package/lib/init/template/data/index.js +2 -4
  38. package/lib/init/template/extensibility/files/cds.package.json +7 -0
  39. package/lib/init/template/extensibility/files/cds.package.json.hbs +9 -0
  40. package/lib/init/template/extensibility/files/xs-security.json.hbs +26 -0
  41. package/lib/init/template/extensibility/index.js +48 -0
  42. package/lib/init/template/hana/files/java/cdsrc.json.hbs +1 -1
  43. package/lib/init/template/hana/files/java/profile.cdsrc.json.hbs +2 -2
  44. package/lib/init/template/hana/files/mta.yaml.hbs +10 -0
  45. package/lib/init/template/hana/files/nodejs/cds.package.json.hbs +1 -1
  46. package/lib/init/template/hana/files/nodejs/cds.profile.package.json.hbs +2 -2
  47. package/lib/init/template/hana/index.js +74 -61
  48. package/lib/init/template/kibana-logging/index.js +31 -37
  49. package/lib/init/template/lint/files/.eslint/rules/no-entity-moo.js +14 -14
  50. package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
  51. package/lib/init/template/mta/index.js +13 -7
  52. package/lib/init/template/mtx/index.js +2 -142
  53. package/lib/init/template/multitenancy/files/cds.package.json +7 -0
  54. package/lib/init/template/multitenancy/files/cds.package.json.hbs +9 -0
  55. package/lib/init/template/{mtx → multitenancy}/files/dependencies.package.json +1 -1
  56. package/lib/init/template/multitenancy/files/java/.cdsrc.json +19 -0
  57. package/lib/init/template/multitenancy/files/java/package.json +31 -0
  58. package/lib/init/template/{mtx → multitenancy}/files/mta.yaml.hbs +13 -6
  59. package/lib/init/template/multitenancy/files/xs-security.json.hbs +18 -0
  60. package/lib/init/template/multitenancy/index.js +109 -0
  61. package/lib/init/template/nodejs/files/package.json.hbs +4 -1
  62. package/lib/init/template/templateBase.js +2 -1
  63. package/lib/init/template/toggles/files/cds.package.json +7 -0
  64. package/lib/init/template/toggles/files/cds.package.json.hbs +9 -0
  65. package/lib/init/template/toggles/index.js +24 -0
  66. package/lib/init/template/xsuaa/files/mta.yaml.hbs +10 -0
  67. package/lib/init/template/xsuaa/index.js +44 -33
  68. package/lib/init/util/projectReader.js +12 -7
  69. package/lib/init/util/templateUtil.js +113 -111
  70. package/lib/k8s/ChartAdder.js +13 -3
  71. package/lib/k8s/ChartBuilder.js +6 -0
  72. package/lib/k8s/buildModel.js +1 -3
  73. package/lib/k8s/connectivity/index.js +5 -5
  74. package/lib/k8s/deployment/index.js +2 -4
  75. package/lib/k8s/deployment/subchart/Chart.yaml +1 -1
  76. package/lib/k8s/deployment/subchart/templates/_helpers.tpl +22 -11
  77. package/lib/k8s/deployment/subchart/templates/deployment.yaml +12 -5
  78. package/lib/k8s/deployment/subchart/templates/network-policy.yaml +3 -1
  79. package/lib/k8s/deployment/subchart/templates/pod-disruption-budget.yaml +1 -1
  80. package/lib/k8s/deployment/subchart/values.md +812 -0
  81. package/lib/k8s/deployment/subchart/values.schema.json +125 -30
  82. package/lib/k8s/deployment/subchart/values.yaml +7 -3
  83. package/lib/k8s/hana-deployer/index.js +10 -0
  84. package/lib/k8s/hana-deployer/templates/hana-deployer-job.yaml +8 -0
  85. package/lib/k8s/html5-apps-deployer/index.js +10 -0
  86. package/lib/k8s/html5-apps-deployer/templates/html5-apps-deployer-job.yaml +8 -0
  87. package/lib/k8s/index.js +2 -2
  88. package/lib/k8s/resources/helm/chart/schemas/values.root.schema.json +11 -0
  89. package/lib/k8s/resources/helm/chart/schemas/values.schema.json +479 -0
  90. package/lib/k8s/resources/helm/chart/templates/_deployment_helpers.tpl +1 -159
  91. package/lib/k8s/resources/helm/chart/templates/_helpers.tpl +0 -33
  92. package/lib/k8s/resources/helm/chart/templates/_sapcp_helpers.tpl +1 -1
  93. package/lib/lint/Linter.js +155 -158
  94. package/lib/lint/io.js +12 -5
  95. package/npm-shrinkwrap.json +214 -74
  96. package/package.json +5 -4
  97. package/lib/init/template/_merging/existences.js +0 -297
  98. package/lib/init/template/mtx/files/cds.package.json +0 -12
  99. package/lib/init/template/mtx/files/cds.package.json.hbs +0 -14
  100. package/lib/init/template/mtx/files/java/.cdsrc.json +0 -17
  101. package/lib/init/template/mtx/files/java/package.json +0 -43
  102. package/lib/init/template/mtx/files/java/server.js +0 -30
  103. package/lib/init/template/mtx/files/xs-security.json.hbs +0 -48
  104. package/lib/lint/.eslintrc.js +0 -3
@@ -7,10 +7,9 @@ var pluralize = require('pluralize')
7
7
  //TODO
8
8
  // - Core.Example for complex types
9
9
  // - reduce number of loops over schemas
10
- // - inject $Name or $$Name into each model element to make parameter passing easier?
10
+ // - inject $$name into each model element to make parameter passing easier?
11
11
  // - allow passing additional files for referenced documents
12
12
  // - delta: headers Prefer and Preference-Applied
13
- // - response codes and descriptions - https://issues.oasis-open.org/browse/ODATA-884
14
13
  // - inline definitions for Edm.* to make OpenAPI documents self-contained
15
14
  // - both "clickable" and freestyle $expand, $select, $orderby - does not work yet, open issue for OpenAPI UI
16
15
  // - system query options for actions/functions/imports depending on $Collection
@@ -21,6 +20,18 @@ var pluralize = require('pluralize')
21
20
  // - InsertRestrictions/NonInsertableNavigationProperties
22
21
  // - see //TODO comments below
23
22
 
23
+ const SUFFIX = {
24
+ read: "",
25
+ create: "-create",
26
+ update: "-update",
27
+ };
28
+
29
+ const TITLE_SUFFIX = {
30
+ "": "",
31
+ "-create": " (for create)",
32
+ "-update": " (for update)",
33
+ };
34
+
24
35
  /**
25
36
  * Construct an OpenAPI description from a CSDL document
26
37
  * @param {object} csdl CSDL document
@@ -31,6 +42,7 @@ module.exports.csdl2openapi = function (
31
42
  csdl,
32
43
  {
33
44
  url: serviceRoot,
45
+ servers: serversObject,
34
46
  scheme: scheme = 'https',
35
47
  host: host = 'localhost',
36
48
  basePath: basePath = '/service-root',
@@ -47,6 +59,8 @@ module.exports.csdl2openapi = function (
47
59
  const namespace = { 'Edm': 'Edm' };
48
60
  const namespaceUrl = {};
49
61
  const voc = {};
62
+ const requiredSchemas = { list: [], used: {} };
63
+
50
64
  preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc);
51
65
 
52
66
  const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {};
@@ -59,7 +73,7 @@ module.exports.csdl2openapi = function (
59
73
  'x-sap-api-type': 'ODATAV4',
60
74
  'x-odata-version': '4.0',
61
75
  'x-sap-shortText': getShortText(csdl, entityContainer),
62
- servers: getServers(serviceRoot),
76
+ servers: getServers(serviceRoot, serversObject),
63
77
  tags: entityContainer ? getTags(entityContainer) : {},
64
78
  paths: entityContainer ? getPaths(entityContainer) : {},
65
79
  components: getComponents(csdl, entityContainer)
@@ -152,7 +166,7 @@ module.exports.csdl2openapi = function (
152
166
  );
153
167
  }
154
168
  if (!element) {
155
- // console.warn(`Invalid annotation target '${target}'`)
169
+ console.warn(`Invalid annotation target '${target}'`);
156
170
  } else if (Array.isArray(element)) {
157
171
  //TODO: action or function:
158
172
  //- loop over all overloads
@@ -165,7 +179,8 @@ module.exports.csdl2openapi = function (
165
179
  case 2:
166
180
  if (['Action', 'Function'].includes(element.$Kind)) {
167
181
  if (segments[1] == '$ReturnType') {
168
- Object.assign(element.$ReturnType, annotations);
182
+ if (element.$ReturnType)
183
+ Object.assign(element.$ReturnType, annotations);
169
184
  } else {
170
185
  const parameter = element.$Parameter.find(p => p.$Name == segments[1]);
171
186
  Object.assign(parameter, annotations);
@@ -407,12 +422,27 @@ module.exports.csdl2openapi = function (
407
422
 
408
423
  /**
409
424
  * Construct an array of Server Objects
410
- * @param {object} csdl The CSDL document
411
- * @param {object} options Optional parameters
425
+ * @param {object} serviceRoot The service root
426
+ * @param {object} serversObject Input servers object
412
427
  * @return {Array} The list of servers
413
428
  */
414
- function getServers(serviceRoot) {
415
- return [{ url: serviceRoot }];
429
+ function getServers(serviceRoot, serversObject) {
430
+ let servers;
431
+
432
+ if (serversObject) {
433
+ try {
434
+ servers = JSON.parse(serversObject);
435
+ } catch (err) {
436
+ throw new Error(`The input server object is invalid.`);
437
+ }
438
+
439
+ if(!servers.length){
440
+ throw new Error(`The input server object should be an array.`);
441
+ }
442
+ } else {
443
+ servers = [{ url: serviceRoot }];
444
+ }
445
+ return servers;
416
446
  }
417
447
 
418
448
  /**
@@ -484,7 +514,7 @@ module.exports.csdl2openapi = function (
484
514
  const nonExpandable = nonExpandableProperties(root, navigationPath);
485
515
 
486
516
  paths[prefix] = pathItem;
487
- if (prefixParameters.length > 0) paths[prefix].parameters = prefixParameters;
517
+ if (prefixParameters.length > 0) pathItem.parameters = prefixParameters;
488
518
 
489
519
  operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, false, nonExpandable);
490
520
  if (element.$Collection && (element.$ContainsTarget || level < 2 && target)) {
@@ -505,6 +535,9 @@ module.exports.csdl2openapi = function (
505
535
  pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPath);
506
536
  }
507
537
  }
538
+
539
+ if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0)
540
+ delete paths[prefix];
508
541
  }
509
542
 
510
543
  /**
@@ -568,6 +601,8 @@ module.exports.csdl2openapi = function (
568
601
  operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, true, nonExpandable);
569
602
  operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true);
570
603
  operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true);
604
+ if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0)
605
+ delete paths[path];
571
606
 
572
607
  pathItemsForBoundOperations(paths, path, parameters, element, sourceName, true);
573
608
  pathItemsWithNavigation(paths, path, parameters, type, root, sourceName, level, navigationPath);
@@ -600,11 +635,11 @@ module.exports.csdl2openapi = function (
600
635
  required: true,
601
636
  content: {
602
637
  'application/json': {
603
- schema: ref(element.$Type, '-create')
638
+ schema: ref(element.$Type, SUFFIX.create),
604
639
  }
605
640
  }
606
641
  },
607
- responses: response(201, 'Created ' + lname, { $Type: element.$Type })
642
+ responses: response(201, 'Created ' + lname, { $Type: element.$Type }, insertRestrictions.ErrorResponses),
608
643
  };
609
644
  if (insertRestrictions.LongDescription) pathItem.post.description = insertRestrictions.LongDescription;
610
645
  if (targetName && sourceName != targetName) pathItem.post.tags.push(targetName);
@@ -657,7 +692,7 @@ module.exports.csdl2openapi = function (
657
692
  * @param {array} nonExpandable Non-expandable navigation properties
658
693
  */
659
694
  function operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, byKey, nonExpandable) {
660
- const targetRestrictions = target && target[voc.Capabilities.ReadRestrictions];
695
+ const targetRestrictions = target?.[voc.Capabilities.ReadRestrictions];
661
696
  const readRestrictions = restrictions.ReadRestrictions || targetRestrictions || {};
662
697
  const readByKeyRestrictions = readRestrictions.ReadByKeyRestrictions;
663
698
  let readable = true;
@@ -675,7 +710,8 @@ module.exports.csdl2openapi = function (
675
710
  summary: descriptions.Description || operationSummary('Retrieve', name, sourceName, level, element.$Collection, byKey),
676
711
  tags: [sourceName],
677
712
  parameters: [],
678
- responses: response(200, 'Retrieved ' + (byKey ? pluralize.singular(lname) : lname), { $Type: element.$Type, $Collection: collection })
713
+ responses: response(200, 'Retrieved ' + (byKey ? pluralize.singular(lname) : lname), { $Type: element.$Type, $Collection: collection },
714
+ byKey ? readByKeyRestrictions?.ErrorResponses : readRestrictions?.ErrorResponses)
679
715
  };
680
716
  const deltaSupported = element[voc.Capabilities.ChangeTracking] && element[voc.Capabilities.ChangeTracking].Supported;
681
717
  if (!byKey && deltaSupported) {
@@ -1125,11 +1161,11 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1125
1161
  required: true,
1126
1162
  content: {
1127
1163
  'application/json': {
1128
- schema: ref(element.$Type, '-update')
1164
+ schema: ref(element.$Type, SUFFIX.update),
1129
1165
  }
1130
1166
  }
1131
1167
  },
1132
- responses: response(204, 'Success')
1168
+ responses: response(204, "Success", undefined, updateRestrictions.ErrorResponses),
1133
1169
  };
1134
1170
  if (updateRestrictions.LongDescription) operation.description = updateRestrictions.LongDescription;
1135
1171
  customParameters(operation, updateRestrictions);
@@ -1156,7 +1192,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1156
1192
  pathItem.delete = {
1157
1193
  summary: deleteRestrictions.Description || operationSummary('Delete', name, sourceName, level, element.$Collection, byKey),
1158
1194
  tags: [sourceName],
1159
- responses: response(204, 'Success')
1195
+ responses: response(204, "Success", undefined, deleteRestrictions.ErrorResponses),
1160
1196
  };
1161
1197
  if (deleteRestrictions.LongDescription) pathItem.delete.description = deleteRestrictions.LongDescription;
1162
1198
  customParameters(pathItem.delete, deleteRestrictions);
@@ -1374,9 +1410,8 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1374
1410
  post: {
1375
1411
  summary: actionImport[voc.Core.Description] || overload[voc.Core.Description] || 'Invoke action ' + name,
1376
1412
  tags: [overload[voc.Common.Label] || sourceName || 'Service Operations'],
1377
- responses: overload.$ReturnType
1378
- ? response(200, 'Success', overload.$ReturnType)
1379
- : response(204, 'Success')
1413
+ responses: overload.$ReturnType ? response(200, "Success", overload.$ReturnType, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses)
1414
+ : response(204, "Success", undefined, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses),
1380
1415
  }
1381
1416
  };
1382
1417
  const description = actionImport[voc.Core.LongDescription] || overload[voc.Core.LongDescription];
@@ -1487,7 +1522,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1487
1522
  summary: functionImport[voc.Core.Description] || overload[voc.Core.Description] || 'Invoke function ' + name,
1488
1523
  tags: [overload[voc.Common.Label] || sourceName || 'Service Operations'],
1489
1524
  parameters: prefixParameters.concat(params),
1490
- responses: response(200, 'Success', overload.$ReturnType)
1525
+ responses: response(200, "Success", overload.$ReturnType, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses),
1491
1526
  }
1492
1527
  };
1493
1528
  const iDescription = functionImport[voc.Core.LongDescription] || overload[voc.Core.LongDescription];
@@ -1561,8 +1596,9 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1561
1596
  * @param {string} code HTTP response code
1562
1597
  * @param {string} description Description
1563
1598
  * @param {object} type Response type object
1599
+ * @param {array} errors Array of operation-specific status codes with descriptions
1564
1600
  */
1565
- function response(code, description, type = {}) {
1601
+ function response(code, description, type, errors) {
1566
1602
  const r = {};
1567
1603
  r[code] = {
1568
1604
  description: description
@@ -1584,8 +1620,21 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1584
1620
  }
1585
1621
  };
1586
1622
  }
1587
- r['4XX'] = {
1588
- $ref: '#/components/responses/error'
1623
+ if (errors) {
1624
+ for (const e of errors) {
1625
+ r[e.StatusCode] = {
1626
+ description: e.Description,
1627
+ content: {
1628
+ "application/json": {
1629
+ schema: { $ref: "#/components/schemas/error" },
1630
+ },
1631
+ },
1632
+ };
1633
+ }
1634
+ } else {
1635
+ r["4XX"] = {
1636
+ $ref: "#/components/responses/error",
1637
+ };
1589
1638
  }
1590
1639
  return r;
1591
1640
  }
@@ -1626,34 +1675,37 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1626
1675
  * @return {object} Map of Schema Objects
1627
1676
  */
1628
1677
  function getSchemas(csdl) {
1629
- const s = {};
1630
-
1631
- Object.keys(csdl).filter(key => isIdentifier(key)).forEach(namespace => {
1632
- Object.keys(csdl[namespace]).filter(key => isIdentifier(key)).forEach(name => {
1633
- const type = csdl[namespace][name];
1634
- switch (type.$Kind) {
1635
- case 'ComplexType':
1636
- case 'EntityType':
1637
- schemasForStructuredType(s, namespace, name, type);
1638
- break;
1639
- case 'EnumType':
1640
- schemaForEnumerationType(s, namespace, name, type);
1641
- break;
1642
- case 'TypeDefinition':
1643
- schemaForTypeDefinition(s, namespace, name, type);
1644
- break;
1645
- }
1646
- });
1647
- });
1678
+ const unordered = {};
1679
+
1680
+ for (const r of requiredSchemas.list) {
1681
+ const type = modelElement(`${r.namespace}.${r.name}`);
1682
+ if (!type) continue;
1683
+ switch (type.$Kind) {
1684
+ case "ComplexType":
1685
+ case "EntityType":
1686
+ schemasForStructuredType(unordered, r.namespace, r.name, type, r.suffix);
1687
+ break;
1688
+ case "EnumType":
1689
+ schemaForEnumerationType(unordered, r.namespace, r.name, type);
1690
+ break;
1691
+ case "TypeDefinition":
1692
+ schemaForTypeDefinition(unordered, r.namespace, r.name, type);
1693
+ break;
1694
+ }
1695
+ }
1696
+ const ordered = {};
1697
+ for (const name of Object.keys(unordered).sort()) {
1698
+ ordered[name] = unordered[name];
1699
+ }
1648
1700
 
1649
- inlineTypes(s);
1701
+ inlineTypes(ordered);
1650
1702
 
1651
1703
  if (csdl.$EntityContainer) {
1652
- s.count = count();
1653
- s.error = error();
1704
+ ordered.count = count();
1705
+ ordered.error = error();
1654
1706
  }
1655
1707
 
1656
- return s;
1708
+ return ordered;
1657
1709
  }
1658
1710
 
1659
1711
  /**
@@ -1729,87 +1781,66 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
1729
1781
  * @param {object} schemas Map of Schema Objects to augment
1730
1782
  * @param {string} qualifier Qualifier for structured type
1731
1783
  * @param {string} name Simple name of structured type
1784
+ * @param {string} suffix Suffix for read/create/update
1732
1785
  * @param {object} type Structured type
1733
1786
  * @return {object} Map of Schemas Objects
1734
1787
  */
1735
- function schemasForStructuredType(schemas, qualifier, name, type) {
1736
- const allName = qualifier + '.' + name;
1737
- const creName = allName + '-create';
1738
- const updName = allName + '-update';
1788
+ function schemasForStructuredType(schemas, qualifier, name, type, suffix) {
1789
+ const schemaName = qualifier + "." + name + suffix;
1790
+ const baseName = qualifier + "." + name;
1739
1791
  const isKey = keyMap(type);
1740
1792
  const required = Object.keys(isKey);
1741
- const allProperties = {};
1742
- const creProperties = {};
1743
- const updProperties = {};
1793
+ const schemaProperties = {};
1744
1794
 
1745
1795
  const properties = propertiesOfStructuredType(type);
1746
1796
  Object.keys(properties).forEach(iName => {
1747
1797
  const property = properties[iName];
1748
- allProperties[iName] = getSchema(property);
1749
- if ((Object.prototype.hasOwnProperty.call(property, '@Common.FieldControl')) && property['@Common.FieldControl'] === 'Mandatory') {
1750
- required.push(iName)
1751
- }
1798
+ if (suffix === SUFFIX.read) schemaProperties[iName] = getSchema(property);
1799
+ if((Object.prototype.hasOwnProperty.call(property, '@Common.FieldControl')) && property['@Common.FieldControl'] === 'Mandatory')
1800
+ { required.push(iName) }
1752
1801
  if (property.$Kind == 'NavigationProperty') {
1753
- if (property.$Collection) {
1754
- allProperties[`${iName}@${csdl.$Version === '4.0' ? 'odata.' : ''}count`] = ref('count');
1802
+ if (property.$Collection && suffix === "") {
1803
+ schemaProperties[`${iName}@${csdl.$Version === '4.0' ? 'odata.' : ''}count`] = ref('count');
1755
1804
  }
1756
- creProperties[iName] = getSchema(property, '-create');
1757
- if (deepUpdate)
1758
- updProperties[iName] = getSchema(property, '-create');
1805
+ if (suffix === SUFFIX.create)
1806
+ schemaProperties[iName] = getSchema(property, SUFFIX.create);
1807
+ if (suffix === SUFFIX.update && deepUpdate)
1808
+ schemaProperties[iName] = getSchema(property, SUFFIX.create);
1759
1809
  } else {
1760
- if (property[voc.Core.Permissions] == 'Read' || property[voc.Core.Computed]) {
1810
+ if (property[voc.Core.Permissions] != "Read" && !property[voc.Core.Computed] && property.$ContainsTarget) {
1761
1811
  let index = required.indexOf(iName);
1762
1812
  if (index != -1) required.splice(index, 1);
1763
1813
  } else {
1764
- creProperties[iName] = getSchema(property, '-create');
1765
- if (!isKey[iName] && !property[voc.Core.Immutable])
1766
- updProperties[iName] = getSchema(property, '-update');
1814
+ if (suffix === SUFFIX.create)
1815
+ schemaProperties[iName] = getSchema(property, SUFFIX.create);
1816
+ if (suffix === SUFFIX.update && !isKey[iName] && !property[voc.Core.Immutable])
1817
+ schemaProperties[iName] = getSchema(property, SUFFIX.update);
1767
1818
  }
1768
1819
  }
1769
1820
  });
1770
1821
 
1771
- const title = name;
1772
1822
 
1773
- schemas[allName] = {
1774
- title: title,
1823
+ schemas[schemaName] = {
1824
+ title: (type[voc.Core.Description] || name) + TITLE_SUFFIX[suffix],
1775
1825
  type: 'object'
1776
1826
  };
1777
- if (Object.keys(allProperties).length > 0) schemas[allName].properties = allProperties;
1827
+ if (Object.keys(schemaProperties).length > 0)
1828
+ schemas[schemaName].properties = schemaProperties;
1778
1829
 
1779
- schemas[creName] = {
1780
- title: title + ' (for create)',
1781
- type: 'object',
1782
- };
1783
- if (Object.keys(creProperties).length > 0) schemas[creName].properties = creProperties;
1784
- if (required.length > 0) schemas[creName].required = required;
1785
-
1786
- schemas[updName] = {
1787
- title: title + ' (for update)',
1788
- type: 'object'
1789
- };
1790
- if (Object.keys(updProperties).length > 0) schemas[updName].properties = updProperties;
1830
+ if (suffix === SUFFIX.create && required.length > 0)
1831
+ schemas[schemaName].required = required;
1791
1832
 
1792
1833
  const description = type[voc.Core.Description];
1793
1834
  if (description) {
1794
- schemas[allName].description = description;
1795
- schemas[creName].description = description;
1796
- schemas[updName].description = description;
1835
+ schemas[schemaName].description = description;
1797
1836
  }
1798
1837
 
1799
- if (derivedTypes[allName]) {
1800
- schemas[allName].anyOf = [];
1801
- schemas[creName].anyOf = [];
1802
- schemas[updName].anyOf = [];
1803
- derivedTypes[allName].forEach(derivedType => {
1804
- schemas[allName].anyOf.push(ref(derivedType));
1805
- schemas[creName].anyOf.push(ref(derivedType, '-create'));
1806
- schemas[updName].anyOf.push(ref(derivedType, '-update'));
1838
+ if (derivedTypes[baseName]) {
1839
+ schemas[schemaName].anyOf = [];
1840
+ derivedTypes[baseName].forEach((derivedType) => {
1841
+ schemas[schemaName].anyOf.push(ref(derivedType, suffix));
1807
1842
  });
1808
- if (!type.$Abstract) {
1809
- schemas[allName].anyOf.push({});
1810
- schemas[creName].anyOf.push({});
1811
- schemas[updName].anyOf.push({});
1812
- }
1843
+ if (!type.$Abstract) schemas[schemaName].anyOf.push({});
1813
1844
  }
1814
1845
  }
1815
1846
 
@@ -2215,6 +2246,10 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
2215
2246
  nsp = namespace[parts.qualifier];
2216
2247
  name = nsp + '.' + parts.name;
2217
2248
  url = namespaceUrl[nsp] || '';
2249
+ if (url === "" && !requiredSchemas.used[name + suffix]) {
2250
+ requiredSchemas.used[name + suffix] = true;
2251
+ requiredSchemas.list.push({ namespace: nsp, name: parts.name, suffix });
2252
+ }
2218
2253
  //TODO: introduce better way than guessing
2219
2254
  if (url.endsWith('.xml')) url = url.substring(0, url.length - 3) + "openapi3.json";
2220
2255
  }
@@ -2347,67 +2382,4 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
2347
2382
  return !name.startsWith('$') && !name.includes('@');
2348
2383
  }
2349
2384
 
2350
- }
2351
-
2352
-
2353
- /**
2354
- * Delete referenced Schema and Parameter Objects from an OpenAPI description
2355
- * @param {object} openapi OpenAPI description
2356
- */
2357
- module.exports.deleteUnreferencedSchemas = function (openapi) {
2358
- var gReferenced;
2359
- var gDeleted;
2360
-
2361
- do {
2362
- gReferenced = {};
2363
- getReferencedSchemas(openapi, gReferenced);
2364
- gDeleted = deleteUnreferenced(openapi.components.schemas, gReferenced, '#/components/schemas/');
2365
- } while (gDeleted)
2366
-
2367
- deleteUnreferenced(openapi.components.parameters, gReferenced, '#/components/parameters/');
2368
- if (Object.keys(openapi.components.parameters || {}).length == 0) {
2369
- delete openapi.components.parameters;
2370
- }
2371
-
2372
- return;
2373
-
2374
-
2375
- /**
2376
- * Get unreferenced Schema and Parameter Objects recursively
2377
- * @param {object} openapi OpenAPI description
2378
- * @param {object} referenced Map of referenced objects
2379
- */
2380
- function getReferencedSchemas(document, referenced) {
2381
- Object.keys(document).forEach(key => {
2382
- let value = document[key];
2383
- if (key == '$ref') {
2384
- referenced[value] = true;
2385
- } else {
2386
- if (Array.isArray(value)) {
2387
- value.forEach(item => getReferencedSchemas(item, referenced))
2388
- } else if (typeof value == 'object' && value != null) {
2389
- getReferencedSchemas(value, referenced);
2390
- }
2391
- }
2392
- });
2393
- }
2394
-
2395
- /**
2396
- * Delete unreferenced Schema and Parameter Objects recursively
2397
- * @param {object} schemas Map of Schema and Parameter Objects
2398
- * @param {object} referenced Map of referenced objects
2399
- * @param {string} prefix Prefix used within referenced
2400
- */
2401
- function deleteUnreferenced(schemas, referenced, prefix) {
2402
- var deleted = false;
2403
-
2404
- Object.keys(schemas || {}).forEach(key => {
2405
- if (!referenced[prefix + key]) {
2406
- delete schemas[key];
2407
- deleted = true;
2408
- }
2409
- });
2410
-
2411
- return deleted;
2412
- }
2413
- }
2385
+ };
@@ -31,7 +31,6 @@ function* _iterate(csdl, csn, options) {
31
31
 
32
32
  function _getOpenApi(csdl, options) {
33
33
  const openapi = csdl2openapi.csdl2openapi(csdl, options);
34
- csdl2openapi.deleteUnreferencedSchemas(openapi);
35
34
  return openapi;
36
35
  }
37
36
 
@@ -373,7 +373,8 @@ async function _updatePackageJson(dest, service, version, cwd) {
373
373
  version = (version === "V2") ? 'odata-v2' : 'odata';
374
374
  }
375
375
  if (!requires[service]) {
376
- const model = path.relative(cwd, dest);
376
+ const initial_model = path.relative(cwd, dest);
377
+ const model = isLinux() ? initial_model.replace(/\\/g, '/') : initial_model;
377
378
  cds.env.requires[service] = requires[service] = { kind: version, model };
378
379
  await write(package_json, JSON.stringify(conf, null, ' '));
379
380
  console.log(`[cds] - updated ./package.json`);
@@ -409,6 +410,13 @@ async function identifyFile(filepath) {
409
410
  return extension;
410
411
  }
411
412
 
413
+ function isLinux(){
414
+ let platform = process.platform
415
+ if (platform === 'linux' || platform === 'win32'){
416
+ return true;
417
+ }
418
+ }
419
+
412
420
  function readEnvVariables(options, cliCheck) {
413
421
  if (cds.env.import) {
414
422
  if (cliCheck) {
@@ -579,18 +579,28 @@ class Expression {
579
579
  const nonStdAttributes = this.getNonStdAttributes(element.attributes);
580
580
  for (let i = 0; i < nonStdAttributes.length; i++) {
581
581
  let attr = nonStdAttributes[i];
582
+ let check = 0;
582
583
  let [prefix, attrName] = attr.split(':');
583
- if(attrName)
584
+ if (attrName)
584
585
  attrName = attrName.replace(/-/g,'.');
585
586
  let attribute;
586
587
  if ((MetadataConverter.custom_namespace.includes(prefix) || MetadataConverter.custom_namespace.includes(true)) && attrName !== undefined)
587
588
  attribute = "@" + prefix + "." + attrName;
588
589
  else if (attrName === undefined)
589
590
  attribute = "$" + prefix;
590
- if (attribute !== undefined)
591
- target[attribute] = element.attributes[attr];
591
+ if (attribute !== undefined && attribute.startsWith('$') === false) {
592
+ Object.entries(target).forEach(a => {
593
+ if (Object.keys(a[1]).length === 0 && typeof(a[1]) != 'boolean' ) {
594
+ a[1][attribute] = element.attributes[attr];
595
+ check = 1;
596
+ }
597
+ });
598
+ if (check == 0 )
599
+ target[attribute] = element.attributes[attr];
600
+ }
592
601
  }
593
602
  }
603
+
594
604
  getNonStdAttributes(attributes) {
595
605
  const attributeList = [];
596
606
  const standardArrtibutes = ['MaxLength', 'Precision', 'Scale', 'Nullable', 'DefaultValue',
@@ -1667,7 +1677,10 @@ class PropertyValueExpression extends Expression {
1667
1677
  this.setTarget(target);
1668
1678
  this.buildTypeCollectionAndFacets('$Type');
1669
1679
 
1670
- if (element.attributes.Path) target[name].$Path = element.attributes.Path;
1680
+ if (element.attributes.Path) target[name] = {"=": element.attributes.Path};
1681
+ if (element.attributes.PropertyPath) target[name] = {"=": element.attributes.PropertyPath};
1682
+ if (element.attributes.EnumMember) target[name] = {"#": element.attributes.EnumMember.substring(element.attributes.EnumMember.lastIndexOf('/')+1)};
1683
+ if (element.attributes.NavigationPropertyPath) target[name] = {"=": element.attributes.NavigationPropertyPath};
1671
1684
  if (element.attributes.String) target[name] = element.attributes.String;
1672
1685
  if (element.attributes.Bool) target[name] = element.attributes.Bool === 'true';
1673
1686