@sap/cds-dk 7.8.1 → 7.9.1
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/bin/add.js +28 -7
- package/bin/bind.js +64 -21
- package/bin/build.js +35 -3
- package/bin/cds.js +32 -13
- package/bin/compile/index.js +44 -3
- package/bin/completion/completionFs.js +61 -0
- package/bin/completion/index.js +212 -0
- package/bin/completion/scripts/cds-bash.sh +17 -0
- package/bin/completion/scripts/cds-ps.ps1 +18 -0
- package/bin/completion/scripts/cds-zsh.sh +12 -0
- package/bin/help.js +8 -2
- package/bin/init.js +34 -4
- package/bin/subscribe.js +5 -1
- package/bin/watch.js +4 -2
- package/lib/bind/KubernetesApiAccessor.js +3 -2
- package/lib/bind/bindingResolver.js +3 -2
- package/lib/bind/bindingUtil.js +10 -8
- package/lib/bind/cfKeyProvider.js +58 -153
- package/lib/bind/index.js +46 -36
- package/lib/bind/kubernetesCredentialsProvider.js +6 -5
- package/lib/bind/userCdsrcJsonStorageProvider.js +25 -3
- package/lib/build/buildTaskEngine.js +1 -1
- package/lib/build/provider/hana/index.js +1 -1
- package/lib/build/provider/hana/template/undeploy.json +3 -1
- package/lib/build/provider/nodejs/index.js +1 -1
- package/lib/compile/openapi/csdl2openapi.js +4 -0
- package/lib/compile/openapi/index.js +5 -0
- package/lib/deploy/to-hana/hana.js +25 -7
- package/lib/env/schemas/cds-rc.js +29 -2
- package/lib/import/odata/v4parser.js +78 -25
- package/lib/init/constants.js +2 -1
- package/lib/init/index.js +18 -13
- package/lib/init/merge.js +1 -0
- package/lib/init/mvn.js +8 -47
- package/lib/init/plugin.js +0 -4
- package/lib/init/projectReader.js +17 -10
- package/lib/init/template/approuter/files/values.yaml.hbs +6 -12
- package/lib/init/template/approuter/index.js +1 -7
- package/lib/init/template/completion/completionSetup.js +184 -0
- package/lib/init/template/completion/index.js +22 -0
- package/lib/init/template/data/as-csv.js +25 -17
- package/lib/init/template/data/as-json.js +115 -30
- package/lib/init/template/data/index.js +28 -15
- package/lib/init/template/hana/files/undeploy.json +2 -1
- package/lib/init/template/helm/files/chart/values.schema.json +1 -1
- package/lib/init/template/helm/files/content-deployment/Chart.yaml +0 -2
- package/lib/init/template/helm/files/content-deployment/values.schema.json +0 -1
- package/lib/init/template/helm/files/service-instance/Chart.yaml +0 -2
- package/lib/init/template/helm/files/service-instance/values.schema.json +0 -1
- package/lib/init/template/helm/files/web-application/Chart.yaml +1 -3
- package/lib/init/template/helm/files/web-application/templates/_helpers.tpl +23 -0
- package/lib/init/template/helm/files/web-application/templates/deployment.yaml +3 -29
- package/lib/init/template/helm/files/web-application/values.schema.json +17 -2
- package/lib/init/template/helm/files/web-application/values.yaml +10 -2
- package/lib/init/template/helm-unified-runtime/files/templates/NOTES.txt +2 -0
- package/lib/init/template/helm-unified-runtime/files/templates/_deployment_helpers.tpl +10 -2
- package/lib/init/template/helm-unified-runtime/files/values.schema.json +1 -1
- package/lib/init/template/http/index.js +150 -104
- package/lib/init/template/kafka/index.js +6 -0
- package/lib/init/template/lint/index.js +12 -13
- package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
- package/lib/init/template/multitenancy/files/mtxs-configmap-java.yaml +1 -1
- package/lib/init/template/multitenancy/files/values.yaml.hbs +0 -5
- package/lib/init/template/multitenancy/index.js +13 -5
- package/lib/init/template/nodejs/files/.vscode/settings.json +11 -0
- package/lib/init/template/nodejs/files/eslint.config.js +13 -0
- package/lib/init/template/nodejs/files/package.json.hbs +3 -1
- package/lib/init/template/sample/index.js +18 -20
- package/lib/init/template/tiny-sample/index.js +1 -2
- package/lib/init/template/typer/index.js +2 -2
- package/lib/lint/Linter.js +133 -55
- package/lib/lint/checks.js +5 -6
- package/lib/lint/io.js +119 -10
- package/lib/mtx/auth_manager.js +5 -5
- package/lib/mtx/params.js +4 -2
- package/lib/mtx/settings_manager.js +1 -1
- package/lib/mtx/tenant_action.js +12 -2
- package/lib/mtx/util/logging.js +10 -4
- package/lib/util/axios.js +2 -1
- package/lib/util/cf.js +32 -37
- package/lib/util/fs.js +1 -1
- package/lib/util/git.js +1 -1
- package/lib/util/term.js +1 -1
- package/{bin → lib/watch}/watched.js +2 -2
- package/npm-shrinkwrap.json +317 -293
- package/package.json +2 -2
- package/lib/init/template/approuter/files/approuter-mtxs-configmap.yaml +0 -19
- package/lib/init/template/nodejs/files/.eslintrc +0 -26
- /package/lib/init/template/{approuter/files/mtxs-configmap-java.yaml → multitenancy/files/mtxs-configmap-java-approuter.yaml} +0 -0
- /package/lib/init/template/{approuter/files/mtxs-configmap-nodejs.yaml → multitenancy/files/mtxs-configmap-nodejs-approuter.yaml} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
title: "JSON schema for CDS-DK configuration",
|
|
3
|
-
$schema: "https://json-schema.org/draft
|
|
3
|
+
$schema: "https://json-schema.org/draft-07/schema",
|
|
4
4
|
description: "Build overlay",
|
|
5
5
|
$defs: {
|
|
6
6
|
cdsRoot: {
|
|
@@ -8,22 +8,25 @@ module.exports = {
|
|
|
8
8
|
// declaration for schema node for cds plugins contributing cds configuration
|
|
9
9
|
schema: {
|
|
10
10
|
type: "object",
|
|
11
|
+
default: {},
|
|
11
12
|
description: "Schema declaration for cds plugins contributing cds configuration",
|
|
12
13
|
additionalProperties: false,
|
|
13
14
|
properties: {
|
|
14
15
|
cds: {
|
|
15
16
|
type: "object",
|
|
17
|
+
default: {},
|
|
16
18
|
description: "Containing json schema declarations for root level entries under cds node.",
|
|
17
19
|
patternProperties: {
|
|
18
20
|
// new keyword must start with word character or opening brackets
|
|
19
21
|
"^[\\[\\(\\w].*": {
|
|
20
|
-
$ref: "https://json-schema.org/draft
|
|
22
|
+
$ref: "https://json-schema.org/draft-07/schema"
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
},
|
|
24
26
|
|
|
25
27
|
buildTaskType: {
|
|
26
28
|
type: "object",
|
|
29
|
+
default: {},
|
|
27
30
|
additionalProperties: false,
|
|
28
31
|
required: ["name"],
|
|
29
32
|
properties: {
|
|
@@ -41,6 +44,7 @@ module.exports = {
|
|
|
41
44
|
|
|
42
45
|
databaseType: {
|
|
43
46
|
type: "object",
|
|
47
|
+
default: {},
|
|
44
48
|
additionalProperties: false,
|
|
45
49
|
required: ["name"],
|
|
46
50
|
properties: {
|
|
@@ -61,8 +65,16 @@ module.exports = {
|
|
|
61
65
|
// build specific schema
|
|
62
66
|
build: {
|
|
63
67
|
type: "object",
|
|
68
|
+
default: {},
|
|
64
69
|
description: "Customize CDS build settings.",
|
|
65
70
|
additionalProperties: true,
|
|
71
|
+
patternProperties: {
|
|
72
|
+
'\\[.+\\]': {
|
|
73
|
+
default: {},
|
|
74
|
+
description: 'Generic build profile',
|
|
75
|
+
$ref: '#/$defs/cdsRoot/properties/build'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
66
78
|
properties: {
|
|
67
79
|
target: {
|
|
68
80
|
type: "string",
|
|
@@ -79,6 +91,13 @@ module.exports = {
|
|
|
79
91
|
items: {
|
|
80
92
|
type: "object",
|
|
81
93
|
additionalProperties: true,
|
|
94
|
+
patternProperties: {
|
|
95
|
+
'\\[.+\\]': {
|
|
96
|
+
default: {},
|
|
97
|
+
description: 'Generic tasks profile',
|
|
98
|
+
$ref: '#/$defs/cdsRoot/properties/build/properties/tasks/items'
|
|
99
|
+
}
|
|
100
|
+
},
|
|
82
101
|
properties: {
|
|
83
102
|
dest: {
|
|
84
103
|
type: "string",
|
|
@@ -115,8 +134,16 @@ module.exports = {
|
|
|
115
134
|
// deploy specific schema
|
|
116
135
|
deploy: {
|
|
117
136
|
type: "object",
|
|
137
|
+
default: {},
|
|
118
138
|
description: "Customize 'cds deploy' settings.",
|
|
119
139
|
additionalProperties: true,
|
|
140
|
+
patternProperties: {
|
|
141
|
+
'\\[.+\\]': {
|
|
142
|
+
default: {},
|
|
143
|
+
description: 'Generic deploy profile',
|
|
144
|
+
$ref: '#/$defs/cdsRoot/properties/deploy'
|
|
145
|
+
}
|
|
146
|
+
},
|
|
120
147
|
properties: {
|
|
121
148
|
no_save: {
|
|
122
149
|
type: "boolean",
|
|
@@ -99,7 +99,7 @@ function _initialize(parserContext) {
|
|
|
99
99
|
parserContext.primarySchema = "";
|
|
100
100
|
parserContext.schemaAliasToNamespace = {};
|
|
101
101
|
parserContext.schemaToSchemaDataIndex = {};
|
|
102
|
-
parserContext.
|
|
102
|
+
parserContext.vocabNamespaceToAlias = {};
|
|
103
103
|
parserContext.entityToBoundedActions = {};
|
|
104
104
|
parserContext.entityToBoundedFunctions = {};
|
|
105
105
|
parserContext.entityContainerAnnotations = {};
|
|
@@ -425,23 +425,62 @@ function _parseAnnotationTerms(annotationTerm, annotationTermObject, csnDefsTarg
|
|
|
425
425
|
}
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
function
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
428
|
+
function _validateAnnotationNamespace(annotationTerm, vocabNamespaceToAlias) {
|
|
429
|
+
let aliasOrNamespace = annotationTerm.substring(1, annotationTerm.lastIndexOf('.'));
|
|
430
|
+
|
|
431
|
+
for (let alias of Object.values(known_vocabularies)) {
|
|
432
|
+
if (alias === aliasOrNamespace) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
for (let [namespace, alias] of Object.entries(vocabNamespaceToAlias)) {
|
|
438
|
+
if (alias === aliasOrNamespace || namespace === aliasOrNamespace) {
|
|
439
|
+
console.log(warn(annotationTerm + " AnnotationTerm belongs to an unknown namespace: " + namespace));
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
console.log(warn(annotationTerm + ": Reference of this AnnotationTerm is not present in the edmx file."));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function _resolveAnnotationTerm(schemaDataAnnotation, parserContext) {
|
|
448
|
+
|
|
449
|
+
for (const [namespace, alias] of Object.entries(parserContext.vocabNamespaceToAlias)) {
|
|
450
|
+
if (known_vocabularies[namespace]) {
|
|
451
|
+
// Case 1: Namespace belongs to known vocabularies. Replacing the namespace/alias of the doc with standard alias
|
|
452
|
+
if (schemaDataAnnotation.includes('@' + alias + '.')) {
|
|
453
|
+
schemaDataAnnotation = schemaDataAnnotation.split('@' + alias + '.').join('@' + known_vocabularies[namespace] + '.');
|
|
454
|
+
}
|
|
455
|
+
if (schemaDataAnnotation.includes('@' + namespace + '.')) {
|
|
456
|
+
schemaDataAnnotation = schemaDataAnnotation.split('@' + namespace + '.').join('@' + known_vocabularies[namespace] + '.');
|
|
457
|
+
}
|
|
458
|
+
} else {
|
|
459
|
+
// Case 2: Namespace doesn't belong to known vocabularies. Replacing the namespace with alias(if provided) in the doc.
|
|
460
|
+
if (schemaDataAnnotation.includes('@' + namespace + '.') && alias) {
|
|
461
|
+
schemaDataAnnotation = schemaDataAnnotation.split('@' + namespace + '.').join('@' + alias + '.');
|
|
462
|
+
}
|
|
433
463
|
}
|
|
434
464
|
}
|
|
435
465
|
/**
|
|
436
|
-
* Case
|
|
437
|
-
*
|
|
466
|
+
* Case 3: Namespace doesn't have edmx:Reference. But it is present in known_vocabularies.
|
|
467
|
+
* Replacing it with standard alias.
|
|
438
468
|
*/
|
|
439
|
-
for (const [
|
|
440
|
-
if (schemaDataAnnotation.includes(
|
|
441
|
-
schemaDataAnnotation = schemaDataAnnotation.split(
|
|
469
|
+
for (const [namespace, alias] of Object.entries(known_vocabularies)) {
|
|
470
|
+
if (schemaDataAnnotation.includes(namespace)) {
|
|
471
|
+
schemaDataAnnotation = schemaDataAnnotation.split(namespace).join(alias);
|
|
442
472
|
}
|
|
443
473
|
}
|
|
444
474
|
|
|
475
|
+
let index = 0;
|
|
476
|
+
while (schemaDataAnnotation.indexOf('@', index) != -1) {
|
|
477
|
+
|
|
478
|
+
let i = schemaDataAnnotation.indexOf('@', index);
|
|
479
|
+
let annotationTerm = schemaDataAnnotation.substring(i, schemaDataAnnotation.indexOf('"', i));
|
|
480
|
+
_validateAnnotationNamespace(annotationTerm, parserContext.vocabNamespaceToAlias);
|
|
481
|
+
index = i+1;
|
|
482
|
+
}
|
|
483
|
+
|
|
445
484
|
return JSON.parse(schemaDataAnnotation);
|
|
446
485
|
}
|
|
447
486
|
|
|
@@ -459,7 +498,7 @@ function _captureAnnotationWithinElement(sourceObject, targetObject, parserConte
|
|
|
459
498
|
|
|
460
499
|
Object.keys(sourceObject).forEach(key => {
|
|
461
500
|
if (key.startsWith('@')) {
|
|
462
|
-
element =
|
|
501
|
+
element = _resolveAnnotationTerm(JSON.stringify(key), parserContext);
|
|
463
502
|
_parseAnnotationTerms(element, sourceObject[key], targetObject, parserContext);
|
|
464
503
|
}
|
|
465
504
|
});
|
|
@@ -1309,7 +1348,7 @@ function _parseEntityContainer(csnDefs, entityContainerElements, parserContext)
|
|
|
1309
1348
|
if (Object.keys(possibleAnnotations).length > 0) {
|
|
1310
1349
|
let entityContainerAnnotations = {};
|
|
1311
1350
|
let annotationTarget = parserContext.primarySchema + '.' + parserContext.entityContainerName;
|
|
1312
|
-
possibleAnnotations =
|
|
1351
|
+
possibleAnnotations = _resolveAnnotationTerm(
|
|
1313
1352
|
JSON.stringify(possibleAnnotations), parserContext
|
|
1314
1353
|
);
|
|
1315
1354
|
/**
|
|
@@ -1447,16 +1486,28 @@ function _collectBoundedActionFunction(isAction, currNamespace, elementName, ele
|
|
|
1447
1486
|
for (let i = 0; i < elementDataList.length; i++) {
|
|
1448
1487
|
let dataObj = elementDataList[i];
|
|
1449
1488
|
let boundedEntityName = dataObj.$Parameter[0].$Type;
|
|
1489
|
+
let entityTypeNamespace = currNamespace;
|
|
1450
1490
|
let [schemaName, entityName] = _extractSchemaNameAndElementName(boundedEntityName);
|
|
1451
1491
|
|
|
1452
|
-
// binding parameter type should be within the
|
|
1453
|
-
if (
|
|
1454
|
-
|
|
1492
|
+
// binding parameter type should be within the available namespaces in the scope of a document.
|
|
1493
|
+
if (entityTypeNamespace !== schemaName && entityTypeNamespace !== parserContext.schemaAliasToNamespace[schemaName]) {
|
|
1494
|
+
|
|
1495
|
+
// checking if the namespace is available in other schema of the document
|
|
1496
|
+
if (parserContext.schemaToSchemaDataIndex.hasOwnProperty(schemaName)) {
|
|
1497
|
+
entityTypeNamespace = schemaName;
|
|
1498
|
+
}
|
|
1499
|
+
// checking if the alias is present for the schema name and assigning the actual namespace
|
|
1500
|
+
else if (parserContext.schemaAliasToNamespace[schemaName]) {
|
|
1501
|
+
entityTypeNamespace = parserContext.schemaAliasToNamespace[schemaName];
|
|
1502
|
+
} else {
|
|
1503
|
+
throw new Error(messages.INVALID_BOUNDED_PARAM_TYPE + ` Check the Element: ${elementName} of Schema: ${currNamespace} `);
|
|
1504
|
+
}
|
|
1455
1505
|
}
|
|
1456
|
-
|
|
1506
|
+
|
|
1507
|
+
if (!parserContext.entityTypes.includes(entityTypeNamespace + '.' + entityName)) {
|
|
1457
1508
|
throw new Error(messages.UNRESOLVED_TYPE + boundedEntityName);
|
|
1458
1509
|
}
|
|
1459
|
-
boundedEntityName =
|
|
1510
|
+
boundedEntityName = entityTypeNamespace + '.' + entityName;
|
|
1460
1511
|
|
|
1461
1512
|
if (isAction) {
|
|
1462
1513
|
if (!parserContext.entityToBoundedActions[boundedEntityName]?.[elementName]) {
|
|
@@ -1501,17 +1552,15 @@ function _collectBoundedActionFunction(isAction, currNamespace, elementName, ele
|
|
|
1501
1552
|
* @param {Object} parserContext, contains parser level context informations
|
|
1502
1553
|
*/
|
|
1503
1554
|
function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
1555
|
+
// This array is used to store the parameter values which will be used later to call _collectBoundedActionFunction.
|
|
1556
|
+
let boundActionFunctionDetails = [];
|
|
1504
1557
|
|
|
1505
1558
|
_collectUnboundedActionFunction(schemaDataList, parserContext);
|
|
1506
1559
|
|
|
1507
1560
|
// capture all the references
|
|
1508
1561
|
if (edmxAsJson.$Reference) {
|
|
1509
1562
|
Object.entries(edmxAsJson.$Reference).forEach(ref => {
|
|
1510
|
-
|
|
1511
|
-
known_vocabularies.hasOwnProperty(ref[1].$Include[0].$Namespace)
|
|
1512
|
-
) {
|
|
1513
|
-
parserContext.vocabAliasToNamespace[ref[1].$Include[0].$Alias] = ref[1].$Include[0].$Namespace;
|
|
1514
|
-
}
|
|
1563
|
+
parserContext.vocabNamespaceToAlias[ref[1].$Include[0].$Namespace] = ref[1].$Include[0].$Alias;
|
|
1515
1564
|
});
|
|
1516
1565
|
}
|
|
1517
1566
|
|
|
@@ -1532,12 +1581,12 @@ function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
|
1532
1581
|
else if (elementData instanceof Array) {
|
|
1533
1582
|
let isAction = elementData[0].$Kind === 'Action' ? true : false;
|
|
1534
1583
|
if (elementData[0].$IsBound) {
|
|
1535
|
-
|
|
1584
|
+
boundActionFunctionDetails.push([isAction, currNamespace, elementName, elementData]);
|
|
1536
1585
|
}
|
|
1537
1586
|
}
|
|
1538
1587
|
// annotations
|
|
1539
1588
|
else if (elementName === '$Annotations') {
|
|
1540
|
-
schemaData.$Annotations =
|
|
1589
|
+
schemaData.$Annotations = _resolveAnnotationTerm(JSON.stringify(schemaData.$Annotations), parserContext);
|
|
1541
1590
|
/**
|
|
1542
1591
|
* collect entity container annotations with the assumption that
|
|
1543
1592
|
* we only have a single entity container
|
|
@@ -1558,6 +1607,10 @@ function _collectSchemaElements(edmxAsJson, schemaDataList, parserContext) {
|
|
|
1558
1607
|
}
|
|
1559
1608
|
});
|
|
1560
1609
|
}
|
|
1610
|
+
// This will delay the execution of _collectBoundedActionFunction, as we need to collect all the entityTypes first.
|
|
1611
|
+
boundActionFunctionDetails.forEach(paramValues => {
|
|
1612
|
+
_collectBoundedActionFunction(...paramValues, parserContext);
|
|
1613
|
+
});
|
|
1561
1614
|
}
|
|
1562
1615
|
|
|
1563
1616
|
function _preProcess(edmxAsJson, parserContext, importerContext) {
|
package/lib/init/constants.js
CHANGED
package/lib/init/index.js
CHANGED
|
@@ -109,7 +109,11 @@ module.exports = class CDSGenerator {
|
|
|
109
109
|
this._initialize(null);
|
|
110
110
|
this._greetings();
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
// `add completion` configures global shell completion and not project settings
|
|
113
|
+
// `add data` can live without project metadata
|
|
114
|
+
const nonProjectFacets = { completion:1, data:1 }
|
|
115
|
+
const needsProject = facets.some(facet => !nonProjectFacets[facet])
|
|
116
|
+
if (needsProject && !PROJECT_FILES.find(exists)) {
|
|
113
117
|
throw `The current folder doesn't seem to contain a project. None of the following files found: ${PROJECT_FILES.join(', ')}.`
|
|
114
118
|
}
|
|
115
119
|
|
|
@@ -165,7 +169,7 @@ module.exports = class CDSGenerator {
|
|
|
165
169
|
if (cds.cli.options.for && typeof cds.cli.options.for !== 'string') {
|
|
166
170
|
throw 'The --for argument must not be empty.'
|
|
167
171
|
}
|
|
168
|
-
if (cds.cli.options.force) {
|
|
172
|
+
if (cds.cli.options.force && !cds.cli.options.dry) {
|
|
169
173
|
console.log(`Using '--force' ... existing files will be overwritten`)
|
|
170
174
|
}
|
|
171
175
|
}
|
|
@@ -174,10 +178,14 @@ module.exports = class CDSGenerator {
|
|
|
174
178
|
DEBUG?.(`Project path: ${cds.root}`);
|
|
175
179
|
|
|
176
180
|
await this._validateOptions();
|
|
177
|
-
await this._fillTemplateList(facets);
|
|
178
181
|
|
|
179
|
-
|
|
180
|
-
|
|
182
|
+
const { command, options } = cds.cli
|
|
183
|
+
const plugins = command === COMMAND_INIT ? options.add : new Set(facets)
|
|
184
|
+
await this._fillTemplateList(plugins)
|
|
185
|
+
|
|
186
|
+
for (const [i, facet] of Object.entries(Array.from(plugins))) {
|
|
187
|
+
if (!cds.cli.options.dry) console.log(`Adding feature '${facet}'...`);
|
|
188
|
+
const template = this.templateList[i]
|
|
181
189
|
await template.run();
|
|
182
190
|
await template.combine();
|
|
183
191
|
await template.combineSupported();
|
|
@@ -190,7 +198,7 @@ module.exports = class CDSGenerator {
|
|
|
190
198
|
message = message + ` Continue with '${term.bold('cd ' + relativeProjectPath)}'.`
|
|
191
199
|
}
|
|
192
200
|
console.log('\n' + message)
|
|
193
|
-
} else {
|
|
201
|
+
} else if (!cds.cli.options.dry) {
|
|
194
202
|
console.log(`\nSuccessfully added features to your project.`)
|
|
195
203
|
}
|
|
196
204
|
}
|
|
@@ -216,11 +224,8 @@ module.exports = class CDSGenerator {
|
|
|
216
224
|
}
|
|
217
225
|
}
|
|
218
226
|
|
|
219
|
-
async _fillTemplateList(
|
|
227
|
+
async _fillTemplateList(plugins) {
|
|
220
228
|
const templates = new Map
|
|
221
|
-
const { command, options } = cds.cli
|
|
222
|
-
|
|
223
|
-
const plugins = command === COMMAND_INIT ? options.add : new Set(facets)
|
|
224
229
|
|
|
225
230
|
for (let plugin of plugins) {
|
|
226
231
|
// Compat
|
|
@@ -230,13 +235,13 @@ module.exports = class CDSGenerator {
|
|
|
230
235
|
cds.cli.options.add.add('helm-unified-runtime')
|
|
231
236
|
}
|
|
232
237
|
if (plugin === 'sample-tiny') plugin = 'tiny-sample'
|
|
233
|
-
if (plugin in { 'kibana-logging':1, 'kibana':1 }) plugin = 'application-logging'
|
|
238
|
+
if (plugin in { 'kibana-logging': 1, 'kibana': 1 }) plugin = 'application-logging'
|
|
234
239
|
if (plugin === 'postgresql') plugin = 'postgres'
|
|
235
240
|
|
|
236
241
|
if (!templates.has(plugin)) {
|
|
237
242
|
const template = await this._createTemplate(plugin)
|
|
238
243
|
if (await template.canRun()) {
|
|
239
|
-
DEBUG?.(`Adding feature '${
|
|
244
|
+
DEBUG?.(`Adding feature '${plugin}'`)
|
|
240
245
|
templates.set(plugin, template)
|
|
241
246
|
const dependencies = await template.requires()
|
|
242
247
|
dependencies?.forEach(d => plugins.add(d))
|
|
@@ -256,7 +261,7 @@ module.exports = class CDSGenerator {
|
|
|
256
261
|
.map((entry) => entry[1])
|
|
257
262
|
|
|
258
263
|
// check debug to avoid lengthy computation when not in debug mode
|
|
259
|
-
DEBUG?.(`Features: ${this.templateList.map(({name}) => name).join(', ')}`);
|
|
264
|
+
DEBUG?.(`Features: ${this.templateList.map(({ name }) => name).join(', ')}`);
|
|
260
265
|
}
|
|
261
266
|
|
|
262
267
|
// CAP Generator API
|
package/lib/init/merge.js
CHANGED
|
@@ -182,6 +182,7 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
182
182
|
if (additions) _addToMap(additions)
|
|
183
183
|
if (deletions) _addToMap(deletions.map(deletion => deletion.item))
|
|
184
184
|
if (relationships) _addToMap(relationships?.map(({into: [entry]}) => entry).filter(e => e))
|
|
185
|
+
if (overwrites) _addToMap(overwrites.map(overwrite => overwrite.item[0]))
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
function _traverseYAMLNode(node, index, actions, templateNode) {
|
package/lib/init/mvn.js
CHANGED
|
@@ -72,40 +72,6 @@ class MvnArchetypeUtil {
|
|
|
72
72
|
return this._finalize(params);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
getAddSamplesCmdArgs() {
|
|
76
|
-
const params = new Map();
|
|
77
|
-
|
|
78
|
-
params.set(`com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:addSample`);
|
|
79
|
-
|
|
80
|
-
const { options } = cds.cli
|
|
81
|
-
if (options[JAVA_MVN]) {
|
|
82
|
-
this._scanMvnParams(options[JAVA_MVN], params);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (options.force) {
|
|
86
|
-
params.set(`-Doverwrite`, true);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return this._finalize(params);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getAddTestsCmdArgs() {
|
|
93
|
-
const params = new Map();
|
|
94
|
-
|
|
95
|
-
params.set(`com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:addIntegrationTest`);
|
|
96
|
-
|
|
97
|
-
const { options } = cds.cli
|
|
98
|
-
if (options[JAVA_MVN]) {
|
|
99
|
-
this._scanMvnParams(options[JAVA_MVN], params);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (options.force) {
|
|
103
|
-
params.set(`-Doverwrite`, true);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return this._finalize(params);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
75
|
getAddHanaCmdArgs() {
|
|
110
76
|
const params = new Map();
|
|
111
77
|
|
|
@@ -155,19 +121,14 @@ class MvnArchetypeUtil {
|
|
|
155
121
|
} catch (err) {
|
|
156
122
|
DEBUG?.(err);
|
|
157
123
|
}
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
throw `Java version ${match[1]} is not supported. Use Java 17 or higher.`
|
|
168
|
-
case (version < 20): params.set(`-DjdkVersion`, 17); break;
|
|
169
|
-
case (version >= 20): params.set(`-DjdkVersion`, 20); break;
|
|
170
|
-
default:
|
|
124
|
+
const [,version] = javaVersion?.stderr?.match(/version\s*"?(\d+\.\d+\.\d+)"?/) ?? [];
|
|
125
|
+
if (version) {
|
|
126
|
+
const [major] = version.split('.').map(Number);
|
|
127
|
+
if (major < 17) {
|
|
128
|
+
if (process.env.WS_BASE_URL) {
|
|
129
|
+
throw `Java version ${version} is not supported. Use Java 17 or higher. You can use command 'Java: Set Default JDK' to switch to Java 17.`
|
|
130
|
+
}
|
|
131
|
+
throw `Java version ${version} is not supported. Use Java 17 or higher.`
|
|
171
132
|
}
|
|
172
133
|
}
|
|
173
134
|
}
|
package/lib/init/plugin.js
CHANGED
|
@@ -6,10 +6,6 @@ const { env4 } = require('./projectReader')
|
|
|
6
6
|
|
|
7
7
|
module.exports = class Plugin {
|
|
8
8
|
|
|
9
|
-
constructor() {
|
|
10
|
-
this.name = this.constructor.name.replace(/template/i, '').replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
|
11
|
-
}
|
|
12
|
-
|
|
13
9
|
/**
|
|
14
10
|
* Provides command-line options for the plugin.
|
|
15
11
|
* @returns {Array.<{option: string, flag: string, shortcut?: string, help: string}>}
|
|
@@ -2,7 +2,7 @@ const cds = require('../cds')
|
|
|
2
2
|
const { join, resolve, basename } = require('path')
|
|
3
3
|
const { fs, exists, isdir, path } = cds.utils
|
|
4
4
|
const { parseXml } = require('./xml')
|
|
5
|
-
const { REGEX_JAVA_VERSION } = require('./constants')
|
|
5
|
+
const { REGEX_JAVA_VERSION, JAVA_LTS_VERSIONS } = require('./constants')
|
|
6
6
|
const DEBUG = cds.debug('cli')
|
|
7
7
|
|
|
8
8
|
module.exports = new class ProjectReader {
|
|
@@ -15,18 +15,24 @@ module.exports = new class ProjectReader {
|
|
|
15
15
|
this.appName = this.appId = basename(cds.root)
|
|
16
16
|
this.appDescription = 'A simple CAP project.'
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const isJava = exists('pom.xml') || cds.cli.options?.add?.has('java')
|
|
19
|
+
if (isJava) {
|
|
20
|
+
let artifactId, description, version, properties
|
|
21
|
+
try {
|
|
22
|
+
({ artifactId, description, version, properties } = parseXml(resolve(cds.root, 'pom.xml')) ?? {})
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (e.code !== 'ENOENT') throw e
|
|
25
|
+
}
|
|
26
|
+
const v = version?.[0] === '${revision}' ? properties?.[0]?.revision[0] : version?.[0] ?? '1.0.0-SNAPSHOT'
|
|
22
27
|
if (v && REGEX_JAVA_VERSION.test(v)) this.appVersion = v
|
|
23
|
-
|
|
24
|
-
if (
|
|
28
|
+
this.jdkVersion = properties?.[0]?.['jdk.version']?.[0]?._text?.[0] ?? JAVA_LTS_VERSIONS[JAVA_LTS_VERSIONS.length - 1]
|
|
29
|
+
if (artifactId?.[0]) this.appName = this.appId = artifactId?.[0]?.split(/-parent/)[0]
|
|
30
|
+
if (description?.[0]) this.appDescription = description[0]
|
|
25
31
|
}
|
|
26
32
|
else if (exists('package.json')) {
|
|
27
33
|
const { name, version, description } = JSON.parse(fs.readFileSync(join(cds.root, 'package.json')))
|
|
28
|
-
this.appVersion = version
|
|
29
|
-
const segments = name.trim().replace(/@/g, '').split('/').map(encodeURIComponent)
|
|
34
|
+
this.appVersion = version ?? this.appVersion
|
|
35
|
+
const segments = (name ?? this.appName).trim().replace(/@/g, '').split('/').map(encodeURIComponent)
|
|
30
36
|
this.appName = segments[segments.length - 1]
|
|
31
37
|
this.appId = segments.join('.')
|
|
32
38
|
this.appDescription = description ?? this.appDescription
|
|
@@ -90,7 +96,7 @@ module.exports = new class ProjectReader {
|
|
|
90
96
|
*/
|
|
91
97
|
readProject() {
|
|
92
98
|
const env = this.env4('production')
|
|
93
|
-
const { appVersion, appName, appId, appDescription } = this
|
|
99
|
+
const { appVersion, appName, appId, appDescription, jdkVersion } = this
|
|
94
100
|
DEBUG?.({ env })
|
|
95
101
|
|
|
96
102
|
const _inProd = plugin => require(`./template/${plugin}`).hasInProduction(env)
|
|
@@ -121,6 +127,7 @@ module.exports = new class ProjectReader {
|
|
|
121
127
|
),
|
|
122
128
|
appPath: () => env.folders.app,
|
|
123
129
|
appVersion: () => appVersion,
|
|
130
|
+
jdkVersion: () => jdkVersion,
|
|
124
131
|
approuterPath: () => join(env.folders.app, 'router'),
|
|
125
132
|
appName: () => appName,
|
|
126
133
|
cleanedAppName: () => appName.replaceAll('_', '-'),
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
{{#hasXsuaa}}
|
|
3
|
-
xsuaa:
|
|
4
|
-
parameters:
|
|
5
|
-
oauth2-configuration:
|
|
6
|
-
redirect-uris:
|
|
7
|
-
- https://*.<your-cluster-domain>/**
|
|
8
|
-
{{/hasXsuaa}}
|
|
9
2
|
approuter:
|
|
10
|
-
{{#hasXsuaa}}
|
|
11
|
-
bindings:
|
|
12
|
-
auth:
|
|
13
|
-
serviceInstanceName: xsuaa
|
|
14
|
-
{{/hasXsuaa}}
|
|
15
3
|
image:
|
|
16
4
|
repository: <your-container-registry>/{{appName}}-approuter
|
|
17
5
|
tag: latest
|
|
6
|
+
{{#hasMultitenancy}}
|
|
7
|
+
{{=<% %>=}}
|
|
8
|
+
env:
|
|
9
|
+
TENANT_HOST_PATTERN: ^(.*)-{{ .Release.Name }}-approuter-{{ .Release.Namespace }}.{{ .Values.global.domain }} # change if expose.host is set
|
|
10
|
+
<%={{ }}=%>
|
|
11
|
+
{{/hasMultitenancy}}
|
|
18
12
|
resources:
|
|
19
13
|
limits:
|
|
20
14
|
ephemeral-storage: 1G
|
|
@@ -63,13 +63,7 @@ module.exports = class ApprouterTemplate extends require('../../plugin') {
|
|
|
63
63
|
}
|
|
64
64
|
}]}}).into('chart/values.yaml', { with: project })
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
await copy(join(__dirname, 'files', fileName)).to('chart', 'templates', 'approuter-configmap.yaml')
|
|
68
|
-
|
|
69
|
-
if (hasMultitenancy) {
|
|
70
|
-
const mtxsConfigMapFileName = isNodejs ? 'mtxs-configmap-nodejs.yaml' : 'mtxs-configmap-java.yaml'
|
|
71
|
-
await copy(join(__dirname, 'files', mtxsConfigMapFileName)).to('chart', 'templates', 'mtxs-configmap.yaml')
|
|
72
|
-
}
|
|
66
|
+
await copy(join(__dirname, 'files/approuter-configmap.yaml')).to('chart', 'templates', 'approuter-configmap.yaml')
|
|
73
67
|
}
|
|
74
68
|
|
|
75
69
|
const xsAppPath = join(approuterPath, 'xs-app.json')
|