@sap/cds-dk 8.9.15 → 8.9.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  The format is based on [Keep a Changelog](https://keepachangelog.com/).
9
9
 
10
+ ## Version 8.9.17 - 2026-04-02
11
+
12
+ ### Fixed
13
+
14
+ - Dependency updates, e.g. for CVE-2026-33937.
15
+
16
+ ## Version 8.9.16 - 2026-03-12
17
+
18
+ ### Fixed
19
+
20
+ - `cds import` now correctly imports views with parameters
21
+ - `cds import` now correctly handles OData referential constraints
22
+
10
23
  ## Version 8.9.15 - 2026-02-27
11
24
 
12
25
  ### Fixed
@@ -407,7 +407,7 @@ function _validateAnnotationNamespace(annotationTerm, vocabNamespaceToAlias) {
407
407
  if (aliasOrNamespace === "cds") {
408
408
  return
409
409
  }
410
-
410
+
411
411
  for (let alias of Object.values(known_vocabularies)) {
412
412
  if (alias === aliasOrNamespace) {
413
413
  return;
@@ -673,6 +673,19 @@ function _parseAssociationProperty(foreignReference, associationNode, parserCont
673
673
  '=',
674
674
  {ref: ['$self']}
675
675
  ]
676
+ } else if (associationNode.$ReferentialConstraint) {
677
+ associationProperty.on = []
678
+ for (const constraint in associationNode.$ReferentialConstraint) {
679
+ if (associationProperty.on.length) {
680
+ associationProperty.on.push('and')
681
+ }
682
+ associationProperty.on.push(
683
+ { ref: [foreignReference, associationNode.$ReferentialConstraint[constraint]] },
684
+ '=',
685
+ { ref: [constraint] }
686
+ )
687
+ }
688
+
676
689
  } else if (common.checkForEmptyKeys(associationProperty, "V4")) {
677
690
  associationProperty.keys = [];
678
691
  }
@@ -719,52 +732,63 @@ function _parsePropertyContent(csnObj, elementObj, parserContext) {
719
732
  const isPrimaryKey = true;
720
733
  let dataType, isPrimitiveType, keySet = [];
721
734
 
722
- Object.keys(elementObj).forEach(objKey => {
723
- const contentKind = elementObj[objKey].$Kind;
724
- contentObj = elementObj[objKey];
725
-
726
- if ((objKey.indexOf('@') === -1) && (objKey.indexOf('.') === -1)) {
727
- if (contentObj instanceof Object) {
728
- if (contentObj.$Type) {
729
- dataType = contentObj.$Type;
730
- isPrimitiveType = dataType.startsWith('Edm') ? true : false;
731
- }
732
- if (objKey === '$Key') {
733
- keySet.push(...elementObj.$Key);
734
- }
735
- // primitive datatypes
736
- else if (isPrimitiveType) {
737
- if (edmPrimitiveTypes.includes(dataType)) {
738
- csnObj.elements[objKey] = _generatePrimitiveDataTypeCsn(contentObj,
739
- (keySet.includes(objKey) ? isPrimaryKey : !isPrimaryKey),
740
- parserContext
741
- );
742
- } else {
743
- throw new Error(messages.INVALID_DATATYPE + `'${dataType}' in element: '${objKey}'`)
735
+ const sortedElements = Object.keys(elementObj)
736
+ .sort((ele1, ele2) => {
737
+ if (elementObj[ele1]?.$Kind === elementObj[ele2]?.$Kind) {
738
+ return 0
739
+ } else if (elementObj[ele1]?.$Kind === 'NavigationProperty') {
740
+ return 1
741
+ } else if (elementObj[ele2]?.$Kind === 'NavigationProperty') {
742
+ return -1
743
+ }
744
+ return 0
745
+ })
746
+ sortedElements.forEach(objKey => {
747
+ const contentKind = elementObj[objKey].$Kind;
748
+ contentObj = elementObj[objKey];
749
+
750
+ if ((objKey.indexOf('@') === -1) && (objKey.indexOf('.') === -1)) {
751
+ if (contentObj instanceof Object) {
752
+ if (contentObj.$Type) {
753
+ dataType = contentObj.$Type;
754
+ isPrimitiveType = dataType.startsWith('Edm') ? true : false;
744
755
  }
745
- }
746
- // structured datatypes
747
- else if (!isPrimitiveType && !(contentKind === 'NavigationProperty')) {
748
- const dataKind = _checkIsStructureTypeAndReturnDataKind(dataType, contentObj, 'property', parserContext);
749
-
750
- if (['EnumType', 'TypeDefinition'].includes(dataKind)) {
751
- csnObj.elements[objKey] = _generateStructuredDataTypeCsn(dataType, contentObj,
752
- (keySet.includes(dataType) ? isPrimaryKey : !isPrimaryKey),
753
- dataKind, 'property', parserContext
754
- );
756
+ if (objKey === '$Key') {
757
+ keySet.push(...elementObj.$Key);
755
758
  }
756
- else {
757
- csnObj.elements[objKey] = _generateStructuredDataTypeCsn(dataType, contentObj,
758
- !isPrimaryKey, dataKind, 'property', parserContext
759
- );
759
+ // primitive datatypes
760
+ else if (isPrimitiveType) {
761
+ if (edmPrimitiveTypes.includes(dataType)) {
762
+ csnObj.elements[objKey] = _generatePrimitiveDataTypeCsn(contentObj,
763
+ (keySet.includes(objKey) ? isPrimaryKey : !isPrimaryKey),
764
+ parserContext
765
+ );
766
+ } else {
767
+ throw new Error(messages.INVALID_DATATYPE + `'${dataType}' in element: '${objKey}'`)
768
+ }
769
+ }
770
+ // structured datatypes
771
+ else if (!isPrimitiveType && !(contentKind === 'NavigationProperty')) {
772
+ const dataKind = _checkIsStructureTypeAndReturnDataKind(dataType, contentObj, 'property', parserContext);
773
+
774
+ if (['EnumType', 'TypeDefinition'].includes(dataKind)) {
775
+ csnObj.elements[objKey] = _generateStructuredDataTypeCsn(dataType, contentObj,
776
+ (keySet.includes(objKey) ? isPrimaryKey : !isPrimaryKey),
777
+ dataKind, 'property', parserContext
778
+ );
779
+ }
780
+ else {
781
+ csnObj.elements[objKey] = _generateStructuredDataTypeCsn(dataType, contentObj,
782
+ !isPrimaryKey, dataKind, 'property', parserContext
783
+ );
784
+ }
785
+ }
786
+ else if (contentKind === 'NavigationProperty') {
787
+ csnObj.elements[objKey] = _parseAssociationProperty(objKey, elementObj[objKey], parserContext);
760
788
  }
761
- }
762
- else if (contentKind === 'NavigationProperty') {
763
- csnObj.elements[objKey] = _parseAssociationProperty(objKey, elementObj[objKey], parserContext);
764
789
  }
765
790
  }
766
- }
767
- });
791
+ });
768
792
  }
769
793
 
770
794
  function _addBlobElement() {
@@ -1433,7 +1457,7 @@ function _collectBoundActionFunction(isAction, currNamespace, elementName, eleme
1433
1457
 
1434
1458
  // binding parameter type should be within the available namespaces in the scope of a document.
1435
1459
  if (entityTypeNamespace !== schemaName && entityTypeNamespace !== parserContext.schemaAliasToNamespace[schemaName]) {
1436
-
1460
+
1437
1461
  // checking if the namespace is available in other schema of the document
1438
1462
  if (parserContext.schemaToSchemaDataIndex.hasOwnProperty(schemaName)) {
1439
1463
  entityTypeNamespace = schemaName;
@@ -1603,8 +1627,7 @@ function _preProcess(edmxAsJson, parserContext, importerContext) {
1603
1627
  parserContext.entityToEntitySetMap._.size === 0 &&
1604
1628
  parserContext.entityToSingletonMap._.size === 0 &&
1605
1629
  parserContext.actionToActionImportMap._.size === 0 &&
1606
- parserContext.functionToFunctionImportMap._.size === 0)
1607
- {
1630
+ parserContext.functionToFunctionImportMap._.size === 0) {
1608
1631
  parserContext.mockServerUc = false;
1609
1632
  }
1610
1633
 
@@ -1666,22 +1689,57 @@ function _generateCSN(edmxAsJson, ignorePersistenceSkip, parserContext, importer
1666
1689
  //
1667
1690
  // This happens after Step 8 because that adjusts the names of entity container entities where
1668
1691
  // entity type and entity set differ in naming
1669
- for (const entity in csn.definitions) {
1670
- if (entity.type !== 'entity') continue;
1671
-
1672
- const containingCompositions = Object.keys(csn.definitions[entity].elements).filter(e =>
1673
- csn.definitions[entity].elements[e].type === 'cds.Composition' &&
1674
- csn.definitions[entity].elements[e].on
1692
+ for (const [eName, entity] of Object.entries(csn.definitions)) {
1693
+ if (entity.kind !== 'entity') continue;
1694
+ const containingCompositions = Object.keys(entity.elements).filter(e =>
1695
+ entity.elements[e].type === 'cds.Composition' &&
1696
+ entity.elements[e].on
1675
1697
  );
1676
1698
  for (const comp of containingCompositions) {
1677
- const compTarget = csn.definitions[csn.definitions[entity].elements[comp].target];
1678
- const backLink = Object.keys(compTarget.elements).find(e =>
1679
- compTarget.elements[e].type === 'cds.Association' &&
1680
- compTarget.elements[e].target === entity
1699
+ const compTarget = csn.definitions[entity.elements[comp].target];
1700
+ const backLink = Object.keys(compTarget.elements).find(e =>
1701
+ compTarget.elements[e].type === 'cds.Association' &&
1702
+ compTarget.elements[e].target === eName
1681
1703
  )
1682
- if (compTarget.elements[backLink].keys) {
1704
+ const entityKeys = Object.keys(entity.elements).filter(ele => entity.elements[ele].key)
1705
+ if (compTarget.elements[backLink]?.keys && !entityKeys.some(key => compTarget.elements[backLink + '_' + key])) {
1683
1706
  delete compTarget.elements[backLink].keys
1684
1707
  }
1708
+
1709
+ // 3. View with parameters handling. In OData if the entity has a Composition Set with a backlink Parameters and every
1710
+ // other element is a key, its a View with Parameters. Import it as such to ensure proper outbound handling
1711
+ if (
1712
+ comp === 'Set' && backLink === 'Parameters' &&
1713
+ Object.keys(entity.elements).filter(e => entity.elements[e].key).length + 1 === Object.keys(entity.elements).length
1714
+ ) {
1715
+ const actualEntity = csn.definitions[entity.elements[comp].target];
1716
+ const actualEntityName = entity.elements[comp].target
1717
+ // Adjust entity so that the current elements are parameters, remove Set, remove key flags
1718
+ delete entity.elements[comp];
1719
+ entity.params = {}
1720
+ for (const ele in entity.elements) {
1721
+ delete entity.elements[ele].key;
1722
+ entity.params[ele] = entity.elements[ele];
1723
+ }
1724
+ delete entity.elements
1725
+ // Move compTarget out of service
1726
+ // Get rid of service prefix
1727
+ let nameWithoutService = eName.split(parserContext.primarySchema).pop();
1728
+ // Get rid of leading dot
1729
+ nameWithoutService = nameWithoutService.substring(1, nameWithoutService.length)
1730
+ csn.definitions[nameWithoutService] = actualEntity;
1731
+ delete csn.definitions[actualEntityName];
1732
+ delete csn.definitions[nameWithoutService].elements['Parameters'];
1733
+ // Adjust entity to * query from compTarget
1734
+ entity.query = {
1735
+ SELECT: {
1736
+ from: {
1737
+ ref: [nameWithoutService]
1738
+ },
1739
+ columns: ["*"]
1740
+ }
1741
+ }
1742
+ }
1685
1743
  }
1686
1744
  }
1687
1745
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "8.9.15",
3
+ "version": "8.9.17",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sap/cds-dk",
9
- "version": "8.9.15",
9
+ "version": "8.9.17",
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "dependencies": {
12
12
  "@cap-js/asyncapi": "^1.0.0",
@@ -54,7 +54,7 @@
54
54
  }
55
55
  },
56
56
  "node_modules/@cap-js/openapi": {
57
- "version": "1.3.1",
57
+ "version": "1.4.0",
58
58
  "license": "Apache-2.0",
59
59
  "dependencies": {
60
60
  "pluralize": "^8.0.0"
@@ -109,12 +109,12 @@
109
109
  }
110
110
  },
111
111
  "node_modules/@eslint/config-array": {
112
- "version": "0.21.1",
112
+ "version": "0.21.2",
113
113
  "license": "Apache-2.0",
114
114
  "dependencies": {
115
115
  "@eslint/object-schema": "^2.1.7",
116
116
  "debug": "^4.3.1",
117
- "minimatch": "^3.1.2"
117
+ "minimatch": "^3.1.5"
118
118
  },
119
119
  "engines": {
120
120
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -141,7 +141,7 @@
141
141
  }
142
142
  },
143
143
  "node_modules/@eslint/eslintrc": {
144
- "version": "3.3.4",
144
+ "version": "3.3.5",
145
145
  "license": "MIT",
146
146
  "dependencies": {
147
147
  "ajv": "^6.14.0",
@@ -151,7 +151,7 @@
151
151
  "ignore": "^5.2.0",
152
152
  "import-fresh": "^3.2.1",
153
153
  "js-yaml": "^4.1.1",
154
- "minimatch": "^3.1.3",
154
+ "minimatch": "^3.1.5",
155
155
  "strip-json-comments": "^3.1.1"
156
156
  },
157
157
  "engines": {
@@ -162,7 +162,7 @@
162
162
  }
163
163
  },
164
164
  "node_modules/@eslint/js": {
165
- "version": "9.39.3",
165
+ "version": "9.39.4",
166
166
  "license": "MIT",
167
167
  "engines": {
168
168
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -230,7 +230,7 @@
230
230
  }
231
231
  },
232
232
  "node_modules/@sap/cds": {
233
- "version": "8.9.8",
233
+ "version": "8.9.9",
234
234
  "license": "SEE LICENSE IN LICENSE",
235
235
  "dependencies": {
236
236
  "@sap/cds-compiler": "^5",
@@ -476,12 +476,12 @@
476
476
  "license": "MIT"
477
477
  },
478
478
  "node_modules/axios": {
479
- "version": "1.13.5",
479
+ "version": "1.14.0",
480
480
  "license": "MIT",
481
481
  "dependencies": {
482
482
  "follow-redirects": "^1.15.11",
483
483
  "form-data": "^4.0.5",
484
- "proxy-from-env": "^1.1.0"
484
+ "proxy-from-env": "^2.1.0"
485
485
  }
486
486
  },
487
487
  "node_modules/balanced-match": {
@@ -580,7 +580,7 @@
580
580
  "license": "MIT"
581
581
  },
582
582
  "node_modules/brace-expansion": {
583
- "version": "1.1.12",
583
+ "version": "1.1.13",
584
584
  "license": "MIT",
585
585
  "dependencies": {
586
586
  "balanced-match": "^1.0.0",
@@ -921,22 +921,22 @@
921
921
  }
922
922
  },
923
923
  "node_modules/eslint": {
924
- "version": "9.39.3",
924
+ "version": "9.39.4",
925
925
  "license": "MIT",
926
926
  "dependencies": {
927
927
  "@eslint-community/eslint-utils": "^4.8.0",
928
928
  "@eslint-community/regexpp": "^4.12.1",
929
- "@eslint/config-array": "^0.21.1",
929
+ "@eslint/config-array": "^0.21.2",
930
930
  "@eslint/config-helpers": "^0.4.2",
931
931
  "@eslint/core": "^0.17.0",
932
- "@eslint/eslintrc": "^3.3.1",
933
- "@eslint/js": "9.39.3",
932
+ "@eslint/eslintrc": "^3.3.5",
933
+ "@eslint/js": "9.39.4",
934
934
  "@eslint/plugin-kit": "^0.4.1",
935
935
  "@humanfs/node": "^0.16.6",
936
936
  "@humanwhocodes/module-importer": "^1.0.1",
937
937
  "@humanwhocodes/retry": "^0.4.2",
938
938
  "@types/estree": "^1.0.6",
939
- "ajv": "^6.12.4",
939
+ "ajv": "^6.14.0",
940
940
  "chalk": "^4.0.0",
941
941
  "cross-spawn": "^7.0.6",
942
942
  "debug": "^4.3.2",
@@ -955,7 +955,7 @@
955
955
  "is-glob": "^4.0.0",
956
956
  "json-stable-stringify-without-jsonify": "^1.0.1",
957
957
  "lodash.merge": "^4.6.2",
958
- "minimatch": "^3.1.2",
958
+ "minimatch": "^3.1.5",
959
959
  "natural-compare": "^1.4.0",
960
960
  "optionator": "^0.9.3"
961
961
  },
@@ -1217,7 +1217,7 @@
1217
1217
  }
1218
1218
  },
1219
1219
  "node_modules/flatted": {
1220
- "version": "3.3.3",
1220
+ "version": "3.4.2",
1221
1221
  "license": "ISC"
1222
1222
  },
1223
1223
  "node_modules/follow-redirects": {
@@ -1354,7 +1354,7 @@
1354
1354
  }
1355
1355
  },
1356
1356
  "node_modules/handlebars": {
1357
- "version": "4.7.8",
1357
+ "version": "4.7.9",
1358
1358
  "license": "MIT",
1359
1359
  "dependencies": {
1360
1360
  "minimist": "^1.2.5",
@@ -1755,7 +1755,7 @@
1755
1755
  "license": "MIT"
1756
1756
  },
1757
1757
  "node_modules/node-abi": {
1758
- "version": "3.87.0",
1758
+ "version": "3.89.0",
1759
1759
  "license": "MIT",
1760
1760
  "optional": true,
1761
1761
  "dependencies": {
@@ -1883,11 +1883,11 @@
1883
1883
  }
1884
1884
  },
1885
1885
  "node_modules/path-to-regexp": {
1886
- "version": "0.1.12",
1886
+ "version": "0.1.13",
1887
1887
  "license": "MIT"
1888
1888
  },
1889
1889
  "node_modules/picomatch": {
1890
- "version": "2.3.1",
1890
+ "version": "2.3.2",
1891
1891
  "license": "MIT",
1892
1892
  "engines": {
1893
1893
  "node": ">=8.6"
@@ -1947,11 +1947,14 @@
1947
1947
  }
1948
1948
  },
1949
1949
  "node_modules/proxy-from-env": {
1950
- "version": "1.1.0",
1951
- "license": "MIT"
1950
+ "version": "2.1.0",
1951
+ "license": "MIT",
1952
+ "engines": {
1953
+ "node": ">=10"
1954
+ }
1952
1955
  },
1953
1956
  "node_modules/pump": {
1954
- "version": "3.0.3",
1957
+ "version": "3.0.4",
1955
1958
  "license": "MIT",
1956
1959
  "optional": true,
1957
1960
  "dependencies": {
@@ -2064,7 +2067,7 @@
2064
2067
  "license": "MIT"
2065
2068
  },
2066
2069
  "node_modules/sax": {
2067
- "version": "1.4.4",
2070
+ "version": "1.6.0",
2068
2071
  "license": "BlueOak-1.0.0",
2069
2072
  "engines": {
2070
2073
  "node": ">=11.0.0"
@@ -2457,7 +2460,7 @@
2457
2460
  "optional": true
2458
2461
  },
2459
2462
  "node_modules/ws": {
2460
- "version": "8.19.0",
2463
+ "version": "8.20.0",
2461
2464
  "license": "MIT",
2462
2465
  "engines": {
2463
2466
  "node": ">=10.0.0"
@@ -2493,7 +2496,7 @@
2493
2496
  }
2494
2497
  },
2495
2498
  "node_modules/yaml": {
2496
- "version": "2.8.2",
2499
+ "version": "2.8.3",
2497
2500
  "license": "ISC",
2498
2501
  "bin": {
2499
2502
  "yaml": "bin.mjs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "8.9.15",
3
+ "version": "8.9.17",
4
4
  "description": "Command line client and development toolkit for the SAP Cloud Application Programming Model",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "keywords": [