@sap/cds-dk 9.7.1 → 9.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/bin/bind.js +7 -2
- package/bin/build.js +14 -4
- package/bin/cds.js +2 -2
- package/bin/completion/completionFs.js +1 -1
- package/bin/completion/index.js +2 -2
- package/bin/data-products/get-csn-via-dp-cli.js +1 -1
- package/bin/debug.js +1 -1
- package/bin/deploy/index.js +3 -2
- package/bin/gen.js +1 -1
- package/bin/help.js +1 -1
- package/bin/import.js +3 -0
- package/bin/minify.js +1 -1
- package/bin/mock.js +1 -1
- package/bin/repl.js +212 -39
- package/bin/test.js +0 -2
- package/bin/up.js +27 -3
- package/bin/util/containerize.js +1 -3
- package/bin/version.js +27 -7
- package/bin/watch.js +20 -4
- package/lib/bind/cf.js +2 -2
- package/lib/bind/k8s.js +0 -1
- package/lib/bind/plugin.js +2 -0
- package/lib/bind/shared.js +6 -1
- package/lib/build/constants.js +0 -8
- package/lib/build/index.js +569 -25
- package/lib/build/{provider/edmxBuildPlugin.js → plugins/edmx.js} +6 -15
- package/lib/build/{provider/featureToggleBuildPlugin.js → plugins/featureToggles.js} +3 -23
- package/lib/build/{provider → plugins}/fiori/index.js +27 -38
- package/lib/build/{provider → plugins}/hana/index.js +61 -83
- package/lib/build/{provider → plugins}/hana/migrationtable.js +4 -3
- package/lib/build/plugins/helm/index.js +6 -6
- package/lib/build/{provider/internalBuildPlugin.js → plugins/internal.js} +7 -31
- package/lib/build/{provider → plugins}/java/index.js +18 -26
- package/lib/build/plugins/mtx/index.js +41 -0
- package/lib/build/plugins/mtx/resourcesTarBuilder.js +41 -0
- package/lib/build/{provider → plugins}/mtx-extension/extensionCompilation.js +1 -1
- package/lib/build/{provider → plugins}/mtx-extension/index.js +35 -44
- package/lib/build/{provider → plugins}/mtx-sidecar/index.js +18 -4
- package/lib/build/{provider → plugins}/nodejs/index.js +29 -28
- package/lib/build/{plugin.js → plugins/plugin.js} +45 -59
- package/lib/build/plugins.js +11 -8
- package/lib/build/util.js +18 -16
- package/lib/compile/to-xsuaa.js +2 -2
- package/lib/deploy/to-hana/hana.js +64 -56
- package/lib/import/common.js +1 -1
- package/lib/import/odata/metadataconverter/MetadataConverter.js +4 -3
- package/lib/import/odata/v2parser.js +28 -28
- package/lib/import/odata/v4parser.js +37 -2
- package/lib/import/openapi/index.js +1 -1
- package/lib/init/constants.js +0 -1
- package/lib/init/template/app-frontend/index.js +1 -1
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/approuter/files/values.yaml.hbs +1 -0
- package/lib/init/template/completion/completionSetup.js +1 -1
- package/lib/init/template/data/as-csv.js +1 -1
- package/lib/init/template/github-actions/index.js +1 -1
- package/lib/init/template/handler/index.js +1 -1
- package/lib/init/template/helm/index.js +3 -3
- package/lib/init/template/initial/files/readme.md +2 -4
- package/lib/init/template/kyma/index.js +9 -5
- package/lib/init/template/lint/index.js +7 -21
- package/lib/init/template/multitenancy/files/package.json.hbs +0 -5
- package/lib/init/template/postgres/files/containerize.yaml.hbs +15 -0
- package/lib/init/template/postgres/files/package.json.hbs +35 -0
- package/lib/init/template/postgres/files/values.yaml.hbs +23 -0
- package/lib/init/template/postgres/index.js +34 -9
- package/lib/init/template/test/files/package.json +1 -1
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +1 -0
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/lint/io.js +9 -13
- package/lib/mtx/pull.js +1 -1
- package/lib/mtx/settings_manager.js +11 -5
- package/lib/mtx/tenant_action.js +1 -1
- package/lib/mtx/util/fs.js +2 -2
- package/lib/util/cf.js +1 -1
- package/lib/util/fs.js +3 -3
- package/lib/util/git.js +1 -1
- package/lib/util/glob.js +1 -1
- package/lib/watch/hot-reload.js +202 -0
- package/lib/watch/livereload-server.js +6 -4
- package/lib/watch/node-watch.js +5 -1
- package/lib/watch/watched.js +7 -3
- package/lib/watch/watcher.js +41 -3
- package/npm-shrinkwrap.json +35 -26
- package/package.json +1 -1
- package/lib/build/buildTaskEngine.js +0 -377
- package/lib/build/buildTaskFactory.js +0 -198
- package/lib/build/buildTaskProvider.js +0 -38
- package/lib/build/buildTaskProviderFactory.js +0 -233
- package/lib/build/provider/internalBuildTaskProvider.js +0 -227
- package/lib/build/provider/java-cf/index.js +0 -1
- package/lib/build/provider/mtx/index.js +0 -36
- package/lib/build/provider/mtx/resourcesTarBuilder.js +0 -102
- package/lib/build/provider/node-cf/index.js +0 -1
- package/lib/init/template/lint/files/.eslint/rules/no-entity-moo.js +0 -40
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/fixed/schema.cds +0 -4
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/invalid/schema.cds +0 -4
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/rule.test.js +0 -15
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/valid/schema.cds +0 -6
- package/lib/init/types.d.ts +0 -23
- /package/lib/build/{provider → plugins}/hana/2migration.js +0 -0
- /package/lib/build/{provider → plugins}/hana/template/.hdiconfig-all +0 -0
- /package/lib/build/{provider → plugins}/hana/template/.hdiconfig-cloud +0 -0
- /package/lib/build/{provider → plugins}/hana/template/.hdinamespace +0 -0
- /package/lib/build/{provider → plugins}/hana/template/package.json +0 -0
- /package/lib/build/{provider → plugins}/hana/template/undeploy.json +0 -0
|
@@ -40,7 +40,7 @@ const edmxncdsdatatype = {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
const extendedPrimitiveTypes = [
|
|
43
|
-
|
|
43
|
+
"Edm.Duration",
|
|
44
44
|
"Edm.Geography",
|
|
45
45
|
"Edm.GeographyPoint",
|
|
46
46
|
"Edm.GeographyLineString",
|
|
@@ -84,7 +84,7 @@ function _initialize(parserContext) {
|
|
|
84
84
|
function namespaceAttributeFilter(attributes, parserContext) {
|
|
85
85
|
let namespaceAttributes = parserContext.allowAllNamespaces
|
|
86
86
|
? Object.keys(attributes).filter((attr) => attr.includes(':'))
|
|
87
|
-
: Object.keys(attributes).filter((attr) =>
|
|
87
|
+
: Object.keys(attributes).filter((attr) =>
|
|
88
88
|
attr.includes(':') && parserContext.allowedNamespaces.includes(attr.split(':')[0]));
|
|
89
89
|
|
|
90
90
|
|
|
@@ -104,7 +104,7 @@ function namespaceAttributeFilter(attributes, parserContext) {
|
|
|
104
104
|
return namespaceAttributes;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
//Function to generate CSN for namespace attributes
|
|
107
|
+
//Function to generate CSN for namespace attributes
|
|
108
108
|
function _generateNamespaceAttributes(attributes, isBefore) {
|
|
109
109
|
let csn = "";
|
|
110
110
|
attributes.forEach((attr) => {
|
|
@@ -309,7 +309,7 @@ function _extractFunctionImport(functionImport, parserContext) {
|
|
|
309
309
|
Object.keys(functionImport).forEach((key) => {
|
|
310
310
|
if (key === "_attributes") {
|
|
311
311
|
if (functionImport[key]["sap:action-for"]) {
|
|
312
|
-
//storing bound function imports
|
|
312
|
+
//storing bound function imports
|
|
313
313
|
entityName = _extractEntityFromNamespace(functionImport[key]["sap:action-for"]);
|
|
314
314
|
boundFunctionImports = (parserContext.allFunctionImportsMap[entityName])
|
|
315
315
|
? parserContext.allFunctionImportsMap[entityName] : [];
|
|
@@ -338,7 +338,7 @@ function _checkFunctionImports(functionImports, parserContext) {
|
|
|
338
338
|
throw new Error(messages.UNRESOLVED_TYPE + `'${functionImports._attributes.EntitySet}'`);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
-
}
|
|
341
|
+
}
|
|
342
342
|
|
|
343
343
|
//extracting the function imports from the metadata
|
|
344
344
|
function _extractAllFunctionImports(functionImports, parserContext) {
|
|
@@ -554,9 +554,9 @@ function _getServiceEntityProperty(
|
|
|
554
554
|
}
|
|
555
555
|
// if annotations to be added
|
|
556
556
|
if (edmxncdsdatatype[dataType + "_a"] && cdsDataType != "cds.Date") {
|
|
557
|
-
if (dataType === 'Edm.Stream')
|
|
557
|
+
if (dataType === 'Edm.Stream')
|
|
558
558
|
propertyJson = propertyJson + ',\n"@Core.MediaType": "application/octet-stream"';
|
|
559
|
-
else
|
|
559
|
+
else
|
|
560
560
|
propertyJson = propertyJson + ',\n"@odata.Type": "' + dataType + '"';
|
|
561
561
|
}
|
|
562
562
|
|
|
@@ -732,7 +732,7 @@ function _getServiceComplexTypes(parserContext) {
|
|
|
732
732
|
complexTypeKey += i;
|
|
733
733
|
i++;
|
|
734
734
|
}
|
|
735
|
-
|
|
735
|
+
|
|
736
736
|
//Rename complexType in parserContext for downstream FunctionImport logic
|
|
737
737
|
parserContext.allComplexTypes[complexTypeKey] = parserContext.allComplexTypes[originalName];
|
|
738
738
|
parserContext.allComplexTypes[complexTypeKey]['_attributes'].Name = complexTypeKey
|
|
@@ -763,7 +763,7 @@ function _parseParameter(parameter, parserContext) {
|
|
|
763
763
|
let namespaceAttributes = namespaceAttributeFilter(parameter._attributes, parserContext);
|
|
764
764
|
const parameterNamespaceAttributes = namespaceAttributes.length ? namespaceAttributes : -1;
|
|
765
765
|
|
|
766
|
-
csn = csn +
|
|
766
|
+
csn = csn +
|
|
767
767
|
_getServiceEntityProperty(
|
|
768
768
|
parameter["_attributes"].Name,
|
|
769
769
|
parameter["_attributes"].Type,
|
|
@@ -796,7 +796,7 @@ function _parseParametersFunctionImport(parameters, entityKeysList, parserContex
|
|
|
796
796
|
if (parameters.length) {
|
|
797
797
|
for (let i = 0; i < parameters.length; i++) {
|
|
798
798
|
// check if the parameter is a key of the entity type or not
|
|
799
|
-
// If yes then that paramater is ignored in CSN
|
|
799
|
+
// If yes then that paramater is ignored in CSN
|
|
800
800
|
let isKey = _checkParameterKey(parameters[i], entityKeysList);
|
|
801
801
|
if (isKey == false) {
|
|
802
802
|
parameterCsn = _parseParameter(parameters[i], parserContext);
|
|
@@ -822,7 +822,6 @@ function _parseParametersFunctionImport(parameters, entityKeysList, parserContex
|
|
|
822
822
|
}
|
|
823
823
|
|
|
824
824
|
function _getFunctionImport(functionImport, isBound, entityKeysList, parserContext) {
|
|
825
|
-
let noValue;
|
|
826
825
|
let csn = "";
|
|
827
826
|
csn = csn + '"' + functionImport[0] + '": { \n';
|
|
828
827
|
csn = csn + '"kind": "';
|
|
@@ -832,7 +831,7 @@ function _getFunctionImport(functionImport, isBound, entityKeysList, parserConte
|
|
|
832
831
|
} else if (functionImport[1] === "POST") {
|
|
833
832
|
csn = csn + "action";
|
|
834
833
|
} else {
|
|
835
|
-
let message = functionImport[0].substring(functionImport[0].lastIndexOf(".") + 1) + " has kind " +
|
|
834
|
+
let message = functionImport[0].substring(functionImport[0].lastIndexOf(".") + 1) + " has kind " +
|
|
836
835
|
functionImport[1] + " which is not supported.";
|
|
837
836
|
console.log(warn(message));
|
|
838
837
|
return "";
|
|
@@ -853,9 +852,10 @@ function _getFunctionImport(functionImport, isBound, entityKeysList, parserConte
|
|
|
853
852
|
}
|
|
854
853
|
// if return type exist
|
|
855
854
|
if (functionImport[2] !== -1) {
|
|
856
|
-
let
|
|
855
|
+
let noValue = undefined
|
|
856
|
+
let returnValue = _getServiceEntityProperty(noValue, functionImport[2], noValue, noValue, noValue, noValue,
|
|
857
857
|
noValue, noValue, noValue, noValue, -1, noValue, parserContext);
|
|
858
|
-
|
|
858
|
+
|
|
859
859
|
if (returnValue !== "") {
|
|
860
860
|
csn = csn + ", \n";
|
|
861
861
|
csn = csn + '"returns": { \n';
|
|
@@ -982,7 +982,7 @@ function _getPropertyAttributes(propAttributes, parserContext) {
|
|
|
982
982
|
} else {
|
|
983
983
|
propOthers.push("true");
|
|
984
984
|
}
|
|
985
|
-
|
|
985
|
+
|
|
986
986
|
if (propAttributes.DefaultValue) {
|
|
987
987
|
propOthers.push(propAttributes.DefaultValue);
|
|
988
988
|
} else {
|
|
@@ -1178,7 +1178,7 @@ function _getCSNMultiplicity(associationEnds, toRole, entityName, parserContext)
|
|
|
1178
1178
|
toRole === attributes.Role &&
|
|
1179
1179
|
entityName === attributes.Type
|
|
1180
1180
|
) {
|
|
1181
|
-
|
|
1181
|
+
|
|
1182
1182
|
multiplicity = attributes.Multiplicity;
|
|
1183
1183
|
stop = true;
|
|
1184
1184
|
}
|
|
@@ -1233,7 +1233,7 @@ function _getCSNAssociatedEntitySet(
|
|
|
1233
1233
|
let associationName = relationshipName.replace(parserContext.serviceNamespace + '.', '');
|
|
1234
1234
|
let association = parserContext.allAssociations[associationName];
|
|
1235
1235
|
let isAssociationSetMissing = false;
|
|
1236
|
-
|
|
1236
|
+
|
|
1237
1237
|
// if association set is missing, use association to extract the informations
|
|
1238
1238
|
if (associationSet === undefined) {
|
|
1239
1239
|
isAssociationSetMissing = true;
|
|
@@ -1272,7 +1272,7 @@ function _findAssociationType(relationshipName, fromRole, parserContext) {
|
|
|
1272
1272
|
const associationName = relationshipName.replace(parserContext.serviceNamespace + '.', '');
|
|
1273
1273
|
const association = parserContext.allAssociations[associationName];
|
|
1274
1274
|
if (association === undefined) throw new Error(`'${associationName}' ` + messages.MISSING_ASSOCIATION);
|
|
1275
|
-
|
|
1275
|
+
|
|
1276
1276
|
const associationEnds = association.End;
|
|
1277
1277
|
let associationType;
|
|
1278
1278
|
|
|
@@ -1398,7 +1398,7 @@ function _constructServiceEntity(
|
|
|
1398
1398
|
let csnProperties;
|
|
1399
1399
|
let hasProperties;
|
|
1400
1400
|
csnEntity = csnEntity + '"kind": "entity",\n';
|
|
1401
|
-
csnEntity = csnEntity + '"@cds.external": true,\n';
|
|
1401
|
+
csnEntity = csnEntity + '"@cds.external": true,\n';
|
|
1402
1402
|
if (ignorePersistenceSkip === false) {
|
|
1403
1403
|
csnEntity = csnEntity + '"@cds.persistence.skip": true,\n';
|
|
1404
1404
|
}
|
|
@@ -1474,10 +1474,10 @@ function _constructServiceEntity(
|
|
|
1474
1474
|
}
|
|
1475
1475
|
}
|
|
1476
1476
|
|
|
1477
|
-
// if the function import is bound to entitySet
|
|
1478
|
-
if (parserContext.allFunctionImportsMap[entityName]) {
|
|
1477
|
+
// if the function import is bound to entitySet
|
|
1478
|
+
if (parserContext.allFunctionImportsMap[entityName]) {
|
|
1479
1479
|
csnEntity = csnEntity + ', \n "actions": {\n';
|
|
1480
|
-
csnEntity = csnEntity +
|
|
1480
|
+
csnEntity = csnEntity +
|
|
1481
1481
|
_getAllFunctionImports(parserContext.allFunctionImportsMap[entityName],
|
|
1482
1482
|
1, entityKeysList, parserContext
|
|
1483
1483
|
);
|
|
@@ -1545,7 +1545,7 @@ function _parseServiceEntity(entityName, entity, ignorePersistenceSkip, parserCo
|
|
|
1545
1545
|
// adding blob element if entity has m:HasStream as true
|
|
1546
1546
|
const checkProperty = entityAttributes["allowedNamespaceAttributes"].filter(e => e["m.HasStream"] === 'true');
|
|
1547
1547
|
if (checkProperty.length === 1) _addBlobElement(entityPropertiesMap);
|
|
1548
|
-
|
|
1548
|
+
|
|
1549
1549
|
return _constructServiceEntity(
|
|
1550
1550
|
entityName,
|
|
1551
1551
|
entityKeysList,
|
|
@@ -1686,7 +1686,7 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, parserContext) {
|
|
|
1686
1686
|
|
|
1687
1687
|
// Construct CSN entity based on EDMX entity
|
|
1688
1688
|
let entityJson = jsonObj["edmx:Edmx"]["edmx:DataServices"].Schema.EntityType;
|
|
1689
|
-
// if entityJson exists(ignoring the case of no entity) and is not an array, convert it to an array to handle the case of single entity
|
|
1689
|
+
// if entityJson exists(ignoring the case of no entity) and is not an array, convert it to an array to handle the case of single entity
|
|
1690
1690
|
if (entityJson && !Array.isArray(entityJson)) entityJson = [entityJson];
|
|
1691
1691
|
const definitions = [];
|
|
1692
1692
|
|
|
@@ -1734,7 +1734,7 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, parserContext) {
|
|
|
1734
1734
|
|
|
1735
1735
|
// if there are unbound function imports
|
|
1736
1736
|
if (Object.keys(parserContext.allFunctionImports).length > 0) {
|
|
1737
|
-
// passing 0 for unbound actions/functions and 0 for entityKeysList
|
|
1737
|
+
// passing 0 for unbound actions/functions and 0 for entityKeysList
|
|
1738
1738
|
definitions.push(
|
|
1739
1739
|
_getAllFunctionImports(parserContext.allFunctionImports, 0, 0, parserContext)
|
|
1740
1740
|
);
|
|
@@ -1743,7 +1743,7 @@ function _generateEDMXJSON2CSN(jsonObj, ignorePersistenceSkip, parserContext) {
|
|
|
1743
1743
|
try {
|
|
1744
1744
|
csn.definitions = JSON.parse(`{${definitions.join(",")}}`);
|
|
1745
1745
|
return JSON.stringify(csn, null, 4);
|
|
1746
|
-
} catch
|
|
1746
|
+
} catch {
|
|
1747
1747
|
throw new Error("Unable to convert to csn file.");
|
|
1748
1748
|
}
|
|
1749
1749
|
}
|
|
@@ -1755,7 +1755,7 @@ function getEdmxv2CSN(edmx2jsonModel, ignorePersistenceSkip, mockServerUc, conte
|
|
|
1755
1755
|
const parserContext = {};
|
|
1756
1756
|
_initialize(parserContext);
|
|
1757
1757
|
parserContext.mockServerUc = mockServerUc
|
|
1758
|
-
|
|
1758
|
+
|
|
1759
1759
|
if (!context.include_all_namespaces && context.namespaces.length) {
|
|
1760
1760
|
parserContext.allowedNamespaces = parserContext.allowedNamespaces.concat(context.namespaces)
|
|
1761
1761
|
}
|
|
@@ -1771,7 +1771,7 @@ function getEdmxv2CSN(edmx2jsonModel, ignorePersistenceSkip, mockServerUc, conte
|
|
|
1771
1771
|
let namespaceAlias = edmx2jsonModel["edmx:Edmx"]["edmx:DataServices"].Schema._attributes.Alias;
|
|
1772
1772
|
// replace the namespace alias value with original namespace value
|
|
1773
1773
|
if (namespaceAlias) {
|
|
1774
|
-
edmx2jsonModel = common.replaceAliasValue(JSON.stringify(edmx2jsonModel),
|
|
1774
|
+
edmx2jsonModel = common.replaceAliasValue(JSON.stringify(edmx2jsonModel),
|
|
1775
1775
|
parserContext.serviceNamespace, namespaceAlias);
|
|
1776
1776
|
}
|
|
1777
1777
|
csnDataModel = _generateEDMXJSON2CSN(
|
|
@@ -88,7 +88,7 @@ function _isJson(edmx) {
|
|
|
88
88
|
try {
|
|
89
89
|
JSON.parse(edmx);
|
|
90
90
|
isJson = true;
|
|
91
|
-
} catch
|
|
91
|
+
} catch {
|
|
92
92
|
isJson = false;
|
|
93
93
|
}
|
|
94
94
|
return isJson;
|
|
@@ -792,7 +792,7 @@ function _parsePropertyContent(csnObj, elementObj, parserContext) {
|
|
|
792
792
|
|
|
793
793
|
if (['EnumType', 'TypeDefinition'].includes(dataKind)) {
|
|
794
794
|
csnObj.elements[objKey] = _generateStructuredDataTypeCsn(dataType, contentObj,
|
|
795
|
-
(keySet.includes(
|
|
795
|
+
(keySet.includes(objKey) ? isPrimaryKey : !isPrimaryKey),
|
|
796
796
|
dataKind, 'property', parserContext
|
|
797
797
|
);
|
|
798
798
|
}
|
|
@@ -1713,6 +1713,41 @@ function _generateCSN(edmxAsJson, ignorePersistenceSkip, parserContext, importer
|
|
|
1713
1713
|
if (compTarget.elements[backLink]?.keys && !entityKeys.some(key => compTarget.elements[backLink + '_' + key])) {
|
|
1714
1714
|
delete compTarget.elements[backLink].keys
|
|
1715
1715
|
}
|
|
1716
|
+
|
|
1717
|
+
// 3. View with parameters handling. In OData if the entity has a Composition Set with a backlink Parameters and every
|
|
1718
|
+
// other element is a key, its a View with Parameters. Import it as such to ensure proper outbound handling
|
|
1719
|
+
if (
|
|
1720
|
+
comp === 'Set' && backLink === 'Parameters' &&
|
|
1721
|
+
Object.keys(entity.elements).filter(e => entity.elements[e].key).length + 1 === Object.keys(entity.elements).length
|
|
1722
|
+
) {
|
|
1723
|
+
const actualEntity = csn.definitions[entity.elements[comp].target];
|
|
1724
|
+
const actualEntityName = entity.elements[comp].target
|
|
1725
|
+
// Adjust entity so that the current elements are parameters, remove Set, remove key flags
|
|
1726
|
+
delete entity.elements[comp];
|
|
1727
|
+
entity.params = {}
|
|
1728
|
+
for (const ele in entity.elements) {
|
|
1729
|
+
delete entity.elements[ele].key;
|
|
1730
|
+
entity.params[ele] = entity.elements[ele];
|
|
1731
|
+
}
|
|
1732
|
+
delete entity.elements
|
|
1733
|
+
// Move compTarget out of service
|
|
1734
|
+
// Get rid of service prefix
|
|
1735
|
+
let nameWithoutService = eName.split(parserContext.primarySchema).pop();
|
|
1736
|
+
// Get rid of leading dot
|
|
1737
|
+
nameWithoutService = nameWithoutService.substring(1, nameWithoutService.length)
|
|
1738
|
+
csn.definitions[nameWithoutService] = actualEntity;
|
|
1739
|
+
delete csn.definitions[actualEntityName];
|
|
1740
|
+
delete csn.definitions[nameWithoutService].elements['Parameters'];
|
|
1741
|
+
// Adjust entity to * query from compTarget
|
|
1742
|
+
entity.query = {
|
|
1743
|
+
SELECT: {
|
|
1744
|
+
from: {
|
|
1745
|
+
ref: [nameWithoutService]
|
|
1746
|
+
},
|
|
1747
|
+
columns: ["*"]
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1716
1751
|
}
|
|
1717
1752
|
}
|
|
1718
1753
|
return JSON.stringify(csn, null, 4);
|
package/lib/init/constants.js
CHANGED
|
@@ -9,7 +9,7 @@ const { exists } = require('../../../cds').utils
|
|
|
9
9
|
module.exports = class extends require('../../plugin') {
|
|
10
10
|
|
|
11
11
|
static help() {
|
|
12
|
-
return 'SAP BTP
|
|
12
|
+
return 'SAP BTP Application Frontend service'
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
static hasInProduction(env) {
|
|
@@ -13,7 +13,7 @@ module.exports = async (data={}, csn, { headerOnly=false, separator=',' }={}) =>
|
|
|
13
13
|
// So loop as long as there is some non-string data left.
|
|
14
14
|
while (Object.values(data).some(d => typeof d === 'object')) {
|
|
15
15
|
Object.entries(data)
|
|
16
|
-
.filter(([
|
|
16
|
+
.filter(([, value]) => typeof value === 'object')
|
|
17
17
|
.map(([name]) => csn.definitions[name])
|
|
18
18
|
.forEach(entity => {
|
|
19
19
|
const entityData = data[entity.name]
|
|
@@ -39,7 +39,7 @@ module.exports = class GitHubActionTemplate extends require('../../plugin') {
|
|
|
39
39
|
let githubSlug
|
|
40
40
|
try {
|
|
41
41
|
githubSlug = execSync('git remote get-url origin', { stdio: 'pipe' }).toString().split('/').slice(-2).join('/').trim().replace(/\.git$/, '')
|
|
42
|
-
} catch
|
|
42
|
+
} catch {
|
|
43
43
|
githubSlug = '<org/repo>'
|
|
44
44
|
// console.log(`\ncould not determine GitHub URL for the project – replace '<org/repo>' in ${release}`, DEBUG ? error : '')
|
|
45
45
|
}
|
|
@@ -42,13 +42,13 @@ module.exports = class HelmTemplate extends require('../../plugin') {
|
|
|
42
42
|
async run() {
|
|
43
43
|
console.warn(term.warn(`The "cds add helm" command is deprecated and will be removed in the next major release. Please use the "cds add kyma" command instead.`))
|
|
44
44
|
const project = readProject()
|
|
45
|
-
let
|
|
45
|
+
let registry, domain, tag
|
|
46
46
|
if (!HelmTemplate.hasInProduction() && !project.isBas /* don't run this for the BAS Yeoman generator */) {
|
|
47
47
|
try {
|
|
48
48
|
const domainGuess = execSync(`kubectl config view --minify --output jsonpath="{.clusters[*].cluster.server}"`, { stdio: "pipe" }).toString()
|
|
49
49
|
const domainStartIndex = domainGuess.indexOf('api.')
|
|
50
50
|
if (domainStartIndex !== -1) domain = domainGuess.substring(domainStartIndex + 4)
|
|
51
|
-
} catch
|
|
51
|
+
} catch { /* ignore */ }
|
|
52
52
|
|
|
53
53
|
if (exists('containerize.yaml')) {
|
|
54
54
|
const { repository: r, tag: t } = yaml.parse(join(cds.root, 'containerize.yaml'))
|
|
@@ -62,7 +62,7 @@ module.exports = class HelmTemplate extends require('../../plugin') {
|
|
|
62
62
|
}
|
|
63
63
|
project.registry = registry ?? '<your-container-registry-server>'
|
|
64
64
|
project.domain = domain ?? '<cluster-domain>'
|
|
65
|
-
project.imagePullSecret =
|
|
65
|
+
project.imagePullSecret = 'docker-registry'
|
|
66
66
|
project.tag = tag ?? 'latest'
|
|
67
67
|
await copy(join(__dirname, '../kyma/files/values.schema.json')).to('chart/values.schema.json')
|
|
68
68
|
await merge(__dirname, '../kyma/files/Chart.yaml.hbs').into('chart/Chart.yaml', { with: project })
|
|
@@ -11,14 +11,12 @@ File or Folder | Purpose
|
|
|
11
11
|
`srv/` | your service models and code go here
|
|
12
12
|
`readme.md` | this getting started guide
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
## Next Steps
|
|
16
15
|
|
|
17
16
|
- Open a new terminal and run `cds watch`
|
|
18
17
|
- (in VS Code simply choose _**Terminal** > Run Task > cds watch_)
|
|
19
|
-
- Start
|
|
20
|
-
|
|
18
|
+
- Start with your domain model, in a CDS file in `db/`
|
|
21
19
|
|
|
22
20
|
## Learn More
|
|
23
21
|
|
|
24
|
-
Learn more
|
|
22
|
+
Learn more at <https://cap.cloud.sap>.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
2
|
const cds = require('../../../cds')
|
|
3
|
-
const { exists, rimraf, copy, yaml } = cds.utils
|
|
3
|
+
const { exists, rimraf, copy, yaml, fs } = cds.utils
|
|
4
4
|
const { readProject } = require('../../projectReader')
|
|
5
5
|
const { merge } = require('../../merge')
|
|
6
6
|
const { ask4 } = require('../../../util/question')
|
|
@@ -21,7 +21,11 @@ module.exports = class KymaTemplate extends require('../../plugin') {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
static hasInProduction() {
|
|
24
|
-
|
|
24
|
+
if (exists('chart/Chart.yaml')) {
|
|
25
|
+
const chartYaml = yaml.parse(fs.readFileSync(join(cds.root, 'chart', 'Chart.yaml'), 'utf8'))
|
|
26
|
+
return chartYaml.annotations?.["app.kubernetes.io/managed-by"] === 'cds-dk/helm'
|
|
27
|
+
}
|
|
28
|
+
return false
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
async canRun() {
|
|
@@ -42,13 +46,13 @@ module.exports = class KymaTemplate extends require('../../plugin') {
|
|
|
42
46
|
|
|
43
47
|
async run() {
|
|
44
48
|
const project = readProject()
|
|
45
|
-
let
|
|
49
|
+
let registry, domain, tag
|
|
46
50
|
if (!KymaTemplate.hasInProduction() && !project.isBas /* don't run this for the BAS Yeoman generator */) {
|
|
47
51
|
try {
|
|
48
52
|
const domainGuess = execSync(`kubectl config view --minify --output jsonpath="{.clusters[*].cluster.server}"`, { stdio: "pipe" }).toString()
|
|
49
53
|
const domainStartIndex = domainGuess.indexOf('api.')
|
|
50
54
|
if (domainStartIndex !== -1) domain = domainGuess.substring(domainStartIndex + 4)
|
|
51
|
-
} catch
|
|
55
|
+
} catch { /* ignore */ }
|
|
52
56
|
|
|
53
57
|
// cds10: remove
|
|
54
58
|
if (exists('containerize.yaml')) {
|
|
@@ -63,7 +67,7 @@ module.exports = class KymaTemplate extends require('../../plugin') {
|
|
|
63
67
|
}
|
|
64
68
|
project.registry = registry ?? '<your-container-registry-server>'
|
|
65
69
|
project.domain = domain ?? '<cluster-domain>'
|
|
66
|
-
project.imagePullSecret =
|
|
70
|
+
project.imagePullSecret = 'docker-registry'
|
|
67
71
|
project.tag = tag ?? 'latest'
|
|
68
72
|
await copy(join(__dirname, 'files', 'values.schema.json')).to('chart/values.schema.json')
|
|
69
73
|
await merge(__dirname, 'files/Chart.yaml.hbs').into('chart/Chart.yaml', { with: project })
|
|
@@ -18,7 +18,7 @@ const ESLINT_LANGS_FOR_FILE_TYPE = {
|
|
|
18
18
|
* Searches for ESLint config file types (in order or precedence)
|
|
19
19
|
* and returns corresponding directory (usually project's root dir)
|
|
20
20
|
* https://eslint.org/docs/user-guide/configuring#configuration-file-formats
|
|
21
|
-
* @param {string} currentDir start here
|
|
21
|
+
* @param {string} currentDir start here
|
|
22
22
|
* @returns {string} dir containing ESLint config file (empty if not exists)
|
|
23
23
|
*/
|
|
24
24
|
function getConfigPath(currentDir = '.') {
|
|
@@ -27,15 +27,11 @@ function getConfigPath(currentDir = '.') {
|
|
|
27
27
|
'eslint.config.cjs',
|
|
28
28
|
'eslint.config.mjs'
|
|
29
29
|
]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (fs.existsSync(configPath) && fs.statSync(configPath).isFile()) {
|
|
35
|
-
return configPath
|
|
36
|
-
}
|
|
30
|
+
for (const configFile of configFiles) {
|
|
31
|
+
const configPath = path.join(currentDir, configFile)
|
|
32
|
+
if (fs.existsSync(configPath) && fs.statSync(configPath).isFile()) {
|
|
33
|
+
return configPath
|
|
37
34
|
}
|
|
38
|
-
configDir = path.join(configDir, '..')
|
|
39
35
|
}
|
|
40
36
|
return ''
|
|
41
37
|
}
|
|
@@ -46,14 +42,6 @@ module.exports = class LintTemplate extends require('../../plugin') {
|
|
|
46
42
|
return 'configure cds lint'
|
|
47
43
|
}
|
|
48
44
|
|
|
49
|
-
constructor() {
|
|
50
|
-
super()
|
|
51
|
-
const customPath = path.join(cds.root, '.eslint')
|
|
52
|
-
this.docsPath = path.join(customPath, 'docs')
|
|
53
|
-
this.rulesPath = path.join(customPath, 'rules')
|
|
54
|
-
this.testsPath = path.join(customPath, 'tests')
|
|
55
|
-
}
|
|
56
|
-
|
|
57
45
|
async run() {
|
|
58
46
|
// Require local ESLint plugin installation and corresponding config
|
|
59
47
|
await this.#addEslintPluginConfig()
|
|
@@ -62,8 +50,7 @@ module.exports = class LintTemplate extends require('../../plugin') {
|
|
|
62
50
|
const extensions = new Set(Object.values(ESLINT_LANGS_FOR_FILE_TYPE).flat())
|
|
63
51
|
await io.sanitizeVscodeSettings(
|
|
64
52
|
path.join(cds.root, '.vscode/settings.json'),
|
|
65
|
-
Array.from(extensions)
|
|
66
|
-
this.customRuleExample
|
|
53
|
+
Array.from(extensions)
|
|
67
54
|
)
|
|
68
55
|
|
|
69
56
|
await merge(path.join(__dirname, 'files', 'package.json')).into('package.json')
|
|
@@ -72,8 +59,7 @@ module.exports = class LintTemplate extends require('../../plugin') {
|
|
|
72
59
|
}
|
|
73
60
|
|
|
74
61
|
async #addEslintPluginConfig() {
|
|
75
|
-
const configPath = getConfigPath(cds.root)
|
|
76
|
-
?? path.join(cds.root, 'eslint.config.mjs')
|
|
62
|
+
const configPath = getConfigPath(cds.root) || path.join(cds.root, 'eslint.config.mjs')
|
|
77
63
|
await io.sanitizeEslintConfig(configPath)
|
|
78
64
|
}
|
|
79
65
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
modules:
|
|
3
|
+
- name: {{appName}}-postgres-deployer
|
|
4
|
+
build-parameters:
|
|
5
|
+
buildpack:
|
|
6
|
+
{{#hasHelmUnifiedRuntime}}
|
|
7
|
+
builder: proxy-unified-runtime-dmz.int.repositories.cloud.sap/builder/noble
|
|
8
|
+
{{/hasHelmUnifiedRuntime}}
|
|
9
|
+
{{^hasHelmUnifiedRuntime}}
|
|
10
|
+
type: nodejs
|
|
11
|
+
builder: builder-jammy-base
|
|
12
|
+
{{/hasHelmUnifiedRuntime}}
|
|
13
|
+
path: gen/pg
|
|
14
|
+
env:
|
|
15
|
+
BP_NODE_RUN_SCRIPTS: ""
|
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
+
{{#isNodejs}}
|
|
2
3
|
"dependencies": {
|
|
3
4
|
"@cap-js/postgres": "^2"
|
|
5
|
+
}{{#profile}},
|
|
6
|
+
"cds": {
|
|
7
|
+
"requires": {
|
|
8
|
+
"[{{profile}}]": {
|
|
9
|
+
{{#shortcut}}
|
|
10
|
+
"db": "postgres"
|
|
11
|
+
{{/shortcut}}
|
|
12
|
+
{{^shortcut}}
|
|
13
|
+
"db": {
|
|
14
|
+
"kind": "postgres"
|
|
15
|
+
}
|
|
16
|
+
{{/shortcut}}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
4
19
|
}
|
|
20
|
+
{{/profile}}
|
|
21
|
+
{{/isNodejs}}
|
|
22
|
+
{{#isJava}}
|
|
23
|
+
"requires": {
|
|
24
|
+
{{#profile}}
|
|
25
|
+
"[{{profile}}]": {
|
|
26
|
+
{{/profile}}
|
|
27
|
+
{{#shortcut}}
|
|
28
|
+
"db": "postgres"
|
|
29
|
+
{{/shortcut}}
|
|
30
|
+
{{^shortcut}}
|
|
31
|
+
"db": {
|
|
32
|
+
"kind": "postgres"
|
|
33
|
+
}
|
|
34
|
+
{{/shortcut}}
|
|
35
|
+
{{#profile}}
|
|
36
|
+
}
|
|
37
|
+
{{/profile}}
|
|
38
|
+
}
|
|
39
|
+
{{/isJava}}
|
|
5
40
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
srv:
|
|
3
|
+
bindings:
|
|
4
|
+
postgres:
|
|
5
|
+
serviceInstanceName: postgres
|
|
6
|
+
postgres-db-deployer:
|
|
7
|
+
image:
|
|
8
|
+
repository: {{appName}}-postgres-deployer
|
|
9
|
+
bindings:
|
|
10
|
+
postgres:
|
|
11
|
+
serviceInstanceName: postgres
|
|
12
|
+
resources:
|
|
13
|
+
limits:
|
|
14
|
+
cpu: 2000m
|
|
15
|
+
memory: 1G
|
|
16
|
+
requests:
|
|
17
|
+
cpu: 1000m
|
|
18
|
+
memory: 1G
|
|
19
|
+
postgres:
|
|
20
|
+
serviceOfferingName: postgresql-db
|
|
21
|
+
servicePlanName: standard
|
|
22
|
+
parameters:
|
|
23
|
+
allow_access: "{{KYMA_GATEWAY_IP}}"
|