@sap/cds-dk 6.5.2 → 6.6.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/CHANGELOG.md +40 -0
- package/bin/activate.js +7 -0
- package/bin/add.js +1 -2
- package/bin/build/all.js +14 -9
- package/bin/cds.js +11 -8
- package/bin/compile/index.js +13 -3
- package/bin/env.js +16 -25
- package/bin/extend.js +8 -0
- package/bin/init.js +0 -3
- package/bin/login.js +3 -7
- package/bin/logout.js +2 -7
- package/bin/watch.js +4 -5
- package/lib/client/activate.js +1 -1
- package/lib/client/helper/errors.js +4 -1
- package/lib/client/params.js +4 -3
- package/lib/client/pull.js +31 -5
- package/lib/client/push.js +3 -3
- package/lib/client/settings_manager.js +6 -6
- package/lib/client/subscription.js +1 -1
- package/lib/compile/asyncapi/channels.js +22 -0
- package/lib/compile/asyncapi/components/messageTraits/index.js +89 -0
- package/lib/compile/asyncapi/components/messages/index.js +150 -0
- package/lib/compile/asyncapi/components/schemas/annotations.js +13 -0
- package/lib/compile/asyncapi/components/schemas/array.js +8 -0
- package/lib/compile/asyncapi/components/schemas/cache.js +14 -0
- package/lib/compile/asyncapi/components/schemas/definition.js +187 -0
- package/lib/compile/asyncapi/components/schemas/enum.js +16 -0
- package/lib/compile/asyncapi/components/schemas/examples.js +10 -0
- package/lib/compile/asyncapi/components/schemas/index.js +14 -0
- package/lib/compile/asyncapi/components/schemas/localized.js +29 -0
- package/lib/compile/asyncapi/components/schemas/primitiveElement.js +41 -0
- package/lib/compile/asyncapi/components/schemas/ref.js +45 -0
- package/lib/compile/asyncapi/components/schemas/utils.js +108 -0
- package/lib/compile/asyncapi/index.js +226 -0
- package/lib/compile/asyncapi/message.js +13 -0
- package/lib/compile/asyncapi/utils.js +27 -0
- package/lib/compile/index.js +1 -0
- package/lib/compile/openapi/csdl2openapi.js +42 -18
- package/lib/import/message.js +4 -1
- package/lib/import/odata/metadataconverter/MetadataConverter.js +8 -3
- package/lib/import/odata/v2parser.js +131 -50
- package/lib/import/odata/v4parser.js +292 -112
- package/lib/import/openapi/importOpenAPI.js +14 -14
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +11 -21
- package/lib/init/template/_merging/registry-mta.js +15 -26
- package/lib/init/template/approuter/files/package.json +2 -2
- package/lib/init/template/approuter/index.js +6 -12
- package/lib/init/template/auditlog/files/auditlog.yaml +4 -1
- package/lib/init/template/auditlog/index.js +23 -8
- package/lib/init/template/cf-manifest/index.js +4 -14
- package/lib/init/template/connectivity/files/connectivity-proxy-info.yaml +2 -6
- package/lib/init/template/connectivity/files/values.yaml.hbs +5 -8
- package/lib/init/template/connectivity/index.js +2 -9
- package/lib/init/template/data/index.js +0 -4
- package/lib/init/template/destinations/files/destination.yaml +4 -1
- package/lib/init/template/destinations/index.js +25 -10
- package/lib/init/template/enterprise-messaging/files/event-mesh.yaml +4 -1
- package/lib/init/template/enterprise-messaging/files/values.yaml +1 -2
- package/lib/init/template/enterprise-messaging/index.js +28 -20
- package/lib/init/template/extensibility/index.js +23 -31
- package/lib/init/template/hana/files/hana.yaml +4 -1
- package/lib/init/template/hana/index.js +44 -24
- package/lib/init/template/helm/chart/templates/_helpers.tpl +12 -0
- package/lib/init/template/helm/chart/values.root.schema.json +40 -0
- package/lib/init/template/helm/chart/values.schema.json +32 -69
- package/lib/init/template/helm/index.js +26 -16
- package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +13 -26
- package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +3 -3
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-account.yaml +2 -0
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/content-deployment/templating.md +37 -0
- package/lib/init/template/helm/subcharts/content-deployment/values.md +182 -185
- package/lib/init/template/helm/subcharts/content-deployment/values.schema.json +18 -22
- package/lib/init/template/helm/subcharts/content-deployment/values.yaml +2 -0
- package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +5 -0
- package/lib/init/template/helm/subcharts/service-instance/templates/_helpers.tpl +65 -0
- package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +23 -0
- package/lib/init/template/helm/subcharts/service-instance/templating.md +18 -0
- package/lib/init/template/helm/subcharts/service-instance/values-lint.yaml +2 -0
- package/lib/init/template/helm/subcharts/service-instance/values.md +186 -0
- package/lib/init/template/helm/subcharts/service-instance/values.schema.json +102 -0
- package/lib/init/template/helm/subcharts/service-instance/values.yaml +15 -0
- package/lib/init/template/html5-repo/files/html5-apps-deployer-configmap.yaml +2 -2
- package/lib/init/template/html5-repo/files/html5-apps-repo-host.yaml +4 -1
- package/lib/init/template/html5-repo/index.js +30 -21
- package/lib/init/template/java/index.js +3 -6
- package/lib/init/template/kibana-logging/index.js +7 -10
- package/lib/init/template/lint/index.js +2 -3
- package/lib/init/template/mta/files/mta.yaml.hbs +4 -2
- package/lib/init/template/mta/index.js +7 -11
- package/lib/init/template/mtx/index.js +0 -5
- package/lib/init/template/multitenancy/files/java/package.json +16 -7
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +11 -3
- package/lib/init/template/multitenancy/files/saas-registry-secret.yaml +9 -0
- package/lib/init/template/multitenancy/files/saas-registry.yaml +4 -17
- package/lib/init/template/multitenancy/files/service-manager.yaml +4 -1
- package/lib/init/template/multitenancy/files/values.yaml.hbs +15 -3
- package/lib/init/template/multitenancy/index.js +56 -31
- package/lib/init/template/nodejs/index.js +4 -7
- package/lib/init/template/notebook/index.js +1 -3
- package/lib/init/template/pipeline/index.js +2 -5
- package/lib/init/template/samples/index.js +6 -11
- package/lib/init/template/templateBase.js +10 -17
- package/lib/init/template/toggles/index.js +2 -6
- package/lib/init/template/xsuaa/files/values.yaml.hbs +0 -1
- package/lib/init/template/xsuaa/files/xsuaa.yaml +4 -1
- package/lib/init/template/xsuaa/index.js +27 -23
- package/lib/init/types.d.ts +0 -81
- package/lib/init/util/merge.js +23 -25
- package/lib/init/util/mvnArchetypeUtil.js +34 -2
- package/lib/init/util/projectReader.js +27 -24
- package/lib/lint/Linter.js +31 -13
- package/lib/watch/livereload-server.js +29 -17
- package/lib/watch/node-watch.js +51 -49
- package/npm-shrinkwrap.json +548 -467
- package/package.json +4 -4
- package/readme.md +5 -0
- package/lib/init/template/connectivity/files/connectivity-binding.yaml +0 -9
- package/lib/init/template/connectivity/files/connectivity.yaml +0 -1
- package/lib/init/template/multitenancy/files/xsuaa.yaml +0 -1
- /package/lib/init/template/hana/files/{chart.yaml → hana-deployer.yaml} +0 -0
- /package/lib/init/template/html5-repo/files/{chart.yaml → html5-apps-deployer.yaml} +0 -0
- /package/lib/init/template/multitenancy/files/{chart.yaml → sidecar.yaml} +0 -0
|
@@ -6,12 +6,10 @@ const term = require('../../../util/term');
|
|
|
6
6
|
const { PROJECT_TYPE, OPTION_JAVA, URLS } = require('../../constants');
|
|
7
7
|
|
|
8
8
|
module.exports = class SamplesTemplate extends require('../templateBase') {
|
|
9
|
-
|
|
10
|
-
super(projectPath, generator, __dirname);
|
|
11
|
-
}
|
|
9
|
+
|
|
12
10
|
|
|
13
11
|
async run() {
|
|
14
|
-
switch (
|
|
12
|
+
switch (this.getProjectType()) {
|
|
15
13
|
case PROJECT_TYPE.java:
|
|
16
14
|
return await this._addJavaSamples();
|
|
17
15
|
|
|
@@ -49,16 +47,13 @@ module.exports = class SamplesTemplate extends require('../templateBase') {
|
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
async _addNodejsSamples() {
|
|
52
|
-
const
|
|
53
|
-
const dbFolder = join(this.projectPath,
|
|
50
|
+
const { db, srv } = (await this.getEnv()).folders;
|
|
51
|
+
const dbFolder = join(this.projectPath, db);
|
|
54
52
|
await copyFiles(join(__dirname, 'files', 'nodejs', 'db'), dbFolder, {}, this.options.force);
|
|
55
53
|
|
|
56
|
-
const srvFolder = join(this.projectPath,
|
|
54
|
+
const srvFolder = join(this.projectPath, srv);
|
|
57
55
|
await copyFiles(join(__dirname, 'files', 'nodejs', 'srv'), srvFolder, {
|
|
58
|
-
dbFolder:
|
|
56
|
+
dbFolder: db.replace(/[\\/]+$/, '')
|
|
59
57
|
}, this.options.force);
|
|
60
58
|
}
|
|
61
|
-
|
|
62
|
-
async finalize() {
|
|
63
|
-
}
|
|
64
59
|
}
|
|
@@ -8,19 +8,18 @@ module.exports = class TemplateBase {
|
|
|
8
8
|
/**
|
|
9
9
|
* @constructor
|
|
10
10
|
*/
|
|
11
|
-
constructor(
|
|
12
|
-
if (generator.options
|
|
11
|
+
constructor(generator) {
|
|
12
|
+
if (generator.options?.for && typeof generator.options?.for !== 'string') {
|
|
13
13
|
throw new Error('The --for argument must not be empty.')
|
|
14
14
|
}
|
|
15
|
-
this.projectPath =
|
|
15
|
+
this.projectPath = cds.root;
|
|
16
16
|
this.options = generator.options || {};
|
|
17
|
-
this.projectPath = path.resolve(projectPath);
|
|
18
17
|
this.generator = generator;
|
|
18
|
+
this.name = this.constructor.name.replace(/template/i, '').replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
|
19
19
|
|
|
20
20
|
this.cwd = this.options.cwd || process.cwd();
|
|
21
|
-
this.name = (dirName ? path.basename(dirName) : this.constructor.name.replace(/template/i, '').toLowerCase());
|
|
22
21
|
|
|
23
|
-
this.projectName = path.basename(
|
|
22
|
+
this.projectName = path.basename(cds.root);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
/**
|
|
@@ -40,7 +39,7 @@ module.exports = class TemplateBase {
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
// eslint-disable-next-line no-unused-vars
|
|
43
|
-
static hasFacet(env,
|
|
42
|
+
static hasFacet(env, options) {
|
|
44
43
|
return true;
|
|
45
44
|
}
|
|
46
45
|
|
|
@@ -52,7 +51,7 @@ module.exports = class TemplateBase {
|
|
|
52
51
|
const cdsEnvVar = process.env.CDS_ENV
|
|
53
52
|
process.env.CDS_ENV = profile
|
|
54
53
|
try {
|
|
55
|
-
return cds.env.for('cds'
|
|
54
|
+
return cds.env.for('cds');
|
|
56
55
|
} finally {
|
|
57
56
|
cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
|
|
58
57
|
}
|
|
@@ -93,15 +92,9 @@ module.exports = class TemplateBase {
|
|
|
93
92
|
* @see PROJECT_TYPE
|
|
94
93
|
* @returns PROJECT_TYPE for current project
|
|
95
94
|
*/
|
|
96
|
-
|
|
97
|
-
if (exists(
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (exists(path.join(this.projectPath, 'package.json'))) {
|
|
102
|
-
return PROJECT_TYPE.nodejs;
|
|
103
|
-
}
|
|
104
|
-
|
|
95
|
+
getProjectType() {
|
|
96
|
+
if (exists('pom.xml')) return PROJECT_TYPE.java;
|
|
97
|
+
if (exists('package.json')) return PROJECT_TYPE.nodejs;
|
|
105
98
|
return PROJECT_TYPE.unknown;
|
|
106
99
|
}
|
|
107
100
|
}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
|
-
const
|
|
2
|
+
const { readProject } = require('../../util/projectReader')
|
|
3
3
|
const { mergeJSON, sortDependencies } = require('../../util/merge')
|
|
4
4
|
|
|
5
5
|
module.exports = class TogglesTemplate extends require('../templateBase') {
|
|
6
|
-
constructor(projectPath, generator) {
|
|
7
|
-
super(projectPath, generator, __dirname)
|
|
8
|
-
this.projectReader = new ProjectReader(projectPath)
|
|
9
|
-
}
|
|
10
6
|
|
|
11
7
|
static hasFacet(env) {
|
|
12
8
|
return !!env.requires?.toggles
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
async run() {
|
|
16
|
-
const projectDescriptor = await
|
|
12
|
+
const projectDescriptor = await readProject(this.options)
|
|
17
13
|
const { for: forProfile, isNodejs, isJava } = projectDescriptor.cap
|
|
18
14
|
if (isNodejs) {
|
|
19
15
|
const packageJSONPath = join(this.projectPath, 'package.json')
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
|
-
const
|
|
2
|
+
const { readProject } = require('../../util/projectReader')
|
|
3
3
|
const { mergeJSON, mergeYAML } = require('../../util/merge')
|
|
4
|
-
const {
|
|
4
|
+
const { parseMd5File, writeMd5File } = require('../../util/md5Tracking')
|
|
5
5
|
const { srvNode, srvJava, xsuaa, mtxSidecar } = require('../_merging/registry-mta')
|
|
6
6
|
const { PROJECT_TYPE } = require('../../constants')
|
|
7
7
|
|
|
8
8
|
module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
9
|
-
constructor(projectPath, generator) {
|
|
10
|
-
super(projectPath, generator, __dirname)
|
|
11
|
-
this.projectReader = new ProjectReader(projectPath)
|
|
12
|
-
}
|
|
13
9
|
|
|
14
10
|
static hasFacet(env) {
|
|
15
11
|
return env.requires?.auth?.kind === 'xsuaa'
|
|
@@ -18,8 +14,8 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
18
14
|
async run() {
|
|
19
15
|
const { projectPath } = this
|
|
20
16
|
const templatePath = join(__dirname, 'files')
|
|
21
|
-
const projectDescriptor = await
|
|
22
|
-
const projectType =
|
|
17
|
+
const projectDescriptor = await readProject(this.options)
|
|
18
|
+
const projectType = this.getProjectType();
|
|
23
19
|
const { for: forProfile } = projectDescriptor.cap
|
|
24
20
|
|
|
25
21
|
if (projectType === PROJECT_TYPE.java) {
|
|
@@ -40,7 +36,7 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
async runDependentMerging( context = {}) {
|
|
43
|
-
const projectDescriptor = await
|
|
39
|
+
const projectDescriptor = await readProject(this.options)
|
|
44
40
|
const { isMultitenant, isExtensible, hasMta, hasHelm, isNodejs, isJava } = projectDescriptor.cap
|
|
45
41
|
|
|
46
42
|
const cds = require('../../../../lib/compile')
|
|
@@ -50,7 +46,6 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
50
46
|
} catch (error) { /* ignore */ }
|
|
51
47
|
})() || { scopes: [], attributes: [], 'role-templates': [], 'authorities-inheritance': false }
|
|
52
48
|
const mergingSemantics = { additions: xsSecurity.scopes.map(scope => ({
|
|
53
|
-
ref: scope.name,
|
|
54
49
|
in: 'scopes',
|
|
55
50
|
where: [{
|
|
56
51
|
property: 'name',
|
|
@@ -77,7 +72,7 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
77
72
|
|
|
78
73
|
await mergeYAML(
|
|
79
74
|
mtaYAMLPath,
|
|
80
|
-
|
|
75
|
+
join(__dirname, 'files', 'mta.yaml.hbs'),
|
|
81
76
|
projectDescriptor,
|
|
82
77
|
{
|
|
83
78
|
additions,
|
|
@@ -94,22 +89,31 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
94
89
|
context.projectPath = this.projectPath;
|
|
95
90
|
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'));
|
|
96
91
|
}
|
|
97
|
-
|
|
92
|
+
|
|
93
|
+
// copy service-instance chart
|
|
94
|
+
const HelmTemplate = require(`../helm`);
|
|
95
|
+
const helmTemplate = new HelmTemplate(this.generator, context.oldTrackingData, context.newTrackingData);
|
|
96
|
+
isIndependentCommand = isIndependentCommand | await helmTemplate.addSubChart('service-instance');
|
|
97
|
+
|
|
98
|
+
// add dependency entry in chart.yaml
|
|
99
|
+
await mergeYAML(
|
|
100
|
+
join(this.projectPath, 'chart', 'Chart.yaml'),
|
|
98
101
|
join(__dirname, 'files', 'xsuaa.yaml'),
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
projectDescriptor,
|
|
103
|
+
{ additions: [{
|
|
104
|
+
in: `dependencies`,
|
|
105
|
+
where: [{
|
|
106
|
+
property: 'alias',
|
|
107
|
+
isEqualTo: 'xsuaa'
|
|
108
|
+
}]
|
|
109
|
+
}]}
|
|
110
|
+
);
|
|
111
|
+
|
|
102
112
|
await mergeYAML(
|
|
103
113
|
join(this.projectPath, 'chart', 'values.yaml'),
|
|
104
114
|
join(__dirname, 'files', 'values.yaml.hbs'),
|
|
105
115
|
projectDescriptor
|
|
106
116
|
)
|
|
107
|
-
// REVISIT: Shared xs-security.json location for Helm and MTA?
|
|
108
|
-
await copyAndTrack(
|
|
109
|
-
join(this.projectPath, 'xs-security.json'),
|
|
110
|
-
join(this.projectPath, 'chart', 'xs-security.json'),
|
|
111
|
-
context
|
|
112
|
-
)
|
|
113
117
|
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData);
|
|
114
118
|
}
|
|
115
119
|
|
|
@@ -118,13 +122,13 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
118
122
|
// TODO: Find a generic solution for situation like these.
|
|
119
123
|
if (isMultitenant) {
|
|
120
124
|
const MultitenancyTemplate = require(`../multitenancy`)
|
|
121
|
-
const multitenancyTemplate = new MultitenancyTemplate(this.
|
|
125
|
+
const multitenancyTemplate = new MultitenancyTemplate(this.generator)
|
|
122
126
|
await multitenancyTemplate.runDependentMerging(context)
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
if (isExtensible) {
|
|
126
130
|
const ExtensibilityTemplate = require(`../extensibility`)
|
|
127
|
-
const extensibilityTemplate = new ExtensibilityTemplate(this.
|
|
131
|
+
const extensibilityTemplate = new ExtensibilityTemplate(this.generator)
|
|
128
132
|
await extensibilityTemplate.runDependentMerging(context)
|
|
129
133
|
}
|
|
130
134
|
}
|
package/lib/init/types.d.ts
CHANGED
|
@@ -27,84 +27,3 @@ export interface CDSGenerator {
|
|
|
27
27
|
*/
|
|
28
28
|
uiConfig?: any;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* This is a helper interface to provide support for different file system implementations.
|
|
33
|
-
* Depending on the scenario different file systems will be used, e.g. Yeoman vs. native FS.
|
|
34
|
-
*/
|
|
35
|
-
export interface FsUtil {
|
|
36
|
-
/**
|
|
37
|
-
* Writes the given string into a file.
|
|
38
|
-
* @param filepath the absolute file path
|
|
39
|
-
* @param content the string to serialize to JSON
|
|
40
|
-
*/
|
|
41
|
-
writeFile(filePath: string, content: string, skipLogFile?: boolean): Promise<void>;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Writes the given object as JSON into a file.
|
|
45
|
-
* @param filepath the absolute file path
|
|
46
|
-
* @param object the object to serialize to JSON
|
|
47
|
-
*/
|
|
48
|
-
writeJSON(filepath: string, object: any, options?: any): Promise<void>;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Writes YAML object
|
|
52
|
-
* @param filepath the absolute file path
|
|
53
|
-
* @param yaml the yaml object
|
|
54
|
-
* @param skipFileLog do not log files if true
|
|
55
|
-
*/
|
|
56
|
-
writeYAML(filepath: string, yaml: any, skipFileLog?: boolean): Promise<void>;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Reads a file from given path.
|
|
60
|
-
* @param filePath the absolute file path
|
|
61
|
-
* @param options optional read options
|
|
62
|
-
* @returns the file content as string
|
|
63
|
-
*/
|
|
64
|
-
readFile(filePath: string, options?: any): Promise<string>;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Reads a JSON object from a file.
|
|
68
|
-
* @param filePath the absolute file path
|
|
69
|
-
* @param projectDescriptor a project descriptor
|
|
70
|
-
* @returns the file content as object
|
|
71
|
-
*/
|
|
72
|
-
readJSON(filePath: string, projectDescriptor: any): Promise<any>;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Reads a JSON object from a file.
|
|
76
|
-
* @param filePath the absolute file path
|
|
77
|
-
* @returns the file content as object
|
|
78
|
-
*/
|
|
79
|
-
readJSONC(filePath: string): Promise<any>;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Reads a JSON object from a file.
|
|
83
|
-
* @param filePath the absolute file path
|
|
84
|
-
* @param projectDescriptor a project descriptor
|
|
85
|
-
* @returns the file content as yaml object
|
|
86
|
-
*/
|
|
87
|
-
readYAML(filePath: string, projectDescriptor: any): Promise<any>;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Copies a file or folder from given source to destination.
|
|
91
|
-
* @param source the source path
|
|
92
|
-
* @param destination the destination path
|
|
93
|
-
* @param options optional copy options
|
|
94
|
-
* @param skipFileLog do not log files if true
|
|
95
|
-
*/
|
|
96
|
-
copy(source: string, destination: string, options?: any, skipFileLog?: boolean): Promise<void>;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Helper for managing npm related tasks
|
|
101
|
-
* @deprecated
|
|
102
|
-
*/
|
|
103
|
-
export interface NpmUtil {
|
|
104
|
-
/**
|
|
105
|
-
* Installs npm packages
|
|
106
|
-
* @param cwd working folder
|
|
107
|
-
* @param options npm install options, e.g. force
|
|
108
|
-
*/
|
|
109
|
-
install(cwd?: string, options?: any): Promise<void>
|
|
110
|
-
}
|
package/lib/init/util/merge.js
CHANGED
|
@@ -76,17 +76,17 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
76
76
|
|
|
77
77
|
const { additions, overwrites, deletions, relationships } = semantics
|
|
78
78
|
additions?.forEach(existence => {
|
|
79
|
-
existenceMap.set(existence
|
|
80
|
-
templateExistenceMap.set(existence
|
|
79
|
+
existenceMap.set(existence, undefined)
|
|
80
|
+
templateExistenceMap.set(existence, undefined)
|
|
81
81
|
})
|
|
82
82
|
deletions?.forEach(deletion => {
|
|
83
|
-
existenceMap.set(deletion.item
|
|
83
|
+
existenceMap.set(deletion.item, undefined)
|
|
84
84
|
})
|
|
85
85
|
relationships?.forEach(relationship => {
|
|
86
86
|
const [existence] = relationship.into
|
|
87
87
|
const [insertExistence] = relationship.insert
|
|
88
|
-
const
|
|
89
|
-
existenceMap.set(
|
|
88
|
+
const hash = insertExistence + ' -> ' + existence
|
|
89
|
+
existenceMap.set(hash, undefined)
|
|
90
90
|
})
|
|
91
91
|
|
|
92
92
|
let collectionStack = [target.contents]
|
|
@@ -99,17 +99,17 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
99
99
|
let where = existence.in
|
|
100
100
|
if (typeof where === 'string') return true // just a key path on the document root
|
|
101
101
|
else where = where[0] // a more complex list of constraints, a sequence/array is involved
|
|
102
|
-
const neededParent = dict.get(where
|
|
102
|
+
const neededParent = dict.get(where)?.node
|
|
103
103
|
return collectionStack.includes(neededParent) // lookbehind in parent collection stack
|
|
104
104
|
// REVISIT: Only look behind until sequence is reached?
|
|
105
|
-
}).forEach(
|
|
105
|
+
}).forEach(item => {
|
|
106
106
|
const json = JSON.parse(String(node))
|
|
107
|
-
const whereFulfilled = where.every(constraint =>
|
|
107
|
+
const whereFulfilled = item.where.every(constraint =>
|
|
108
108
|
constraint.isEqualTo === _getProperty(json, constraint.property)
|
|
109
109
|
)
|
|
110
110
|
if (whereFulfilled) {
|
|
111
111
|
const [collection] = collectionStack
|
|
112
|
-
dict.set(
|
|
112
|
+
dict.set(item, { json, node, index, collection })
|
|
113
113
|
}
|
|
114
114
|
})
|
|
115
115
|
if (additions) _addToMap(additions)
|
|
@@ -212,7 +212,7 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
212
212
|
overwrites?.forEach(({ item, withValue }) => {
|
|
213
213
|
const keyPath = Array.isArray(item) && typeof item[0] === 'string' ? item[0] : typeof item === 'string' ? item : item[1]
|
|
214
214
|
const inExistence = Array.isArray(item) && typeof item[0] === 'object' ? item[0] : typeof item === 'object' ? item : item[1]
|
|
215
|
-
const node = inExistence && existenceMap.get(inExistence
|
|
215
|
+
const node = inExistence && existenceMap.get(inExistence) ? existenceMap.get(inExistence).node : collectionStack[collectionStack.length - 1]
|
|
216
216
|
const keys = keyPath.split('.')
|
|
217
217
|
if (!node.getIn(keys)) return
|
|
218
218
|
_getYAMLProperty(node, keys.slice(0, keys.length - 1).join('.'))
|
|
@@ -220,8 +220,8 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
220
220
|
})
|
|
221
221
|
|
|
222
222
|
// 4. Delete existences from the project (e.g. separate deployer module when adding mtx)
|
|
223
|
-
deletions?.forEach(({ item
|
|
224
|
-
const existence = existenceMap.get(
|
|
223
|
+
deletions?.forEach(({ item, relationships }) => {
|
|
224
|
+
const existence = existenceMap.get(item)
|
|
225
225
|
if (!existence) return
|
|
226
226
|
existence.collection.delete(existence.index)
|
|
227
227
|
|
|
@@ -250,7 +250,7 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
250
250
|
let [,parent] = collectionStack
|
|
251
251
|
additions?.filter(addition => {
|
|
252
252
|
if (typeof addition.in === 'string' || Array.isArray(addition.in) && typeof addition.in[0] === 'string') return true
|
|
253
|
-
const inExistence = Array.isArray(addition.in) ? existenceMap.get(addition.in[0]
|
|
253
|
+
const inExistence = Array.isArray(addition.in) ? existenceMap.get(addition.in[0]) : existenceMap.get(addition.in)
|
|
254
254
|
return inExistence?.node === parent
|
|
255
255
|
})
|
|
256
256
|
.filter(addition => {
|
|
@@ -260,12 +260,10 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
260
260
|
if (keys.length > 1) parent = collectionStack[keys.length]
|
|
261
261
|
return _getYAMLProperty(parent, keyPath) === targetNode
|
|
262
262
|
})
|
|
263
|
-
.filter(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const templateNode = templateExistenceMap.get(ref).node
|
|
268
|
-
at !== undefined ? targetNode.items.splice(at, 0, templateNode) : targetNode.add(templateNode)
|
|
263
|
+
.filter(item => !existenceMap.get(item))
|
|
264
|
+
.forEach(item => {
|
|
265
|
+
const templateNode = templateExistenceMap.get(item).node
|
|
266
|
+
item.at !== undefined ? targetNode.items.splice(item.at, 0, templateNode) : targetNode.add(templateNode)
|
|
269
267
|
})
|
|
270
268
|
}
|
|
271
269
|
},
|
|
@@ -286,8 +284,8 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
286
284
|
const relationship = semantics.relationships?.filter(r => r)
|
|
287
285
|
.find(relationship => {
|
|
288
286
|
const [existence, keyPath] = relationship.into
|
|
289
|
-
if (!existenceMap.get(existence
|
|
290
|
-
const existingNode = _getYAMLProperty(existenceMap.get(existence
|
|
287
|
+
if (!existenceMap.get(existence)) return false
|
|
288
|
+
const existingNode = _getYAMLProperty(existenceMap.get(existence).node, keyPath)
|
|
291
289
|
return targetNode === existingNode
|
|
292
290
|
})
|
|
293
291
|
if (!relationship) return
|
|
@@ -295,12 +293,12 @@ async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
|
|
|
295
293
|
const intoKey = relationship.into[relationship.into.length - 1]
|
|
296
294
|
const [existence, existenceKeyPath] = relationship.insert
|
|
297
295
|
const missingPairs = [existence]
|
|
298
|
-
.filter(
|
|
299
|
-
!targetJSON.some(
|
|
300
|
-
_getProperty(existenceMap.get(
|
|
296
|
+
.filter(item =>
|
|
297
|
+
!targetJSON.some(targetItem =>
|
|
298
|
+
_getProperty(existenceMap.get(item).json, existenceKeyPath) === targetItem[intoKey]
|
|
301
299
|
)
|
|
302
300
|
)
|
|
303
|
-
.map(
|
|
301
|
+
.map(item => existenceMap.get(item).node.get(intoKey))
|
|
304
302
|
missingPairs.forEach(pair => {
|
|
305
303
|
targetNode.add({ [intoKey]: pair })
|
|
306
304
|
})
|
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
const { MAVEN_ARCHETYPE_VERSION, OPTION_JAVA_MVN,
|
|
3
3
|
OPTION_JAVA_PACKAGE, OPTION_SAMPLES, REGEX_JAVA_PACKAGE, OPTION_HANA } = require('../constants');
|
|
4
4
|
|
|
5
|
+
const { CliError } = require('../../client/helper/errors');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const cp = require('child_process');
|
|
9
|
+
const util = require('util');
|
|
10
|
+
const execAsync = util.promisify(cp.exec);
|
|
11
|
+
|
|
12
|
+
|
|
5
13
|
const DEFAULT_GROUP_ID = 'customer';
|
|
6
14
|
|
|
7
15
|
const LOG = console
|
|
8
|
-
const
|
|
16
|
+
const cds = require('../../cds')
|
|
17
|
+
const DEBUG = cds.debug('cli')
|
|
9
18
|
|
|
10
19
|
class MvnArchetypeUtil {
|
|
11
20
|
|
|
@@ -88,7 +97,7 @@ class MvnArchetypeUtil {
|
|
|
88
97
|
return packageName.toLowerCase().replace(/-/g, '_').replace(/\.([0-9])/g, '._$1').replace(/^([0-9])/, '_$1').replace(/\.+/g, '.');
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
getGenerateCmdArgs(projectName, options) {
|
|
100
|
+
async getGenerateCmdArgs(projectName, options) {
|
|
92
101
|
const params = new Map();
|
|
93
102
|
|
|
94
103
|
// set header
|
|
@@ -115,6 +124,29 @@ class MvnArchetypeUtil {
|
|
|
115
124
|
this._scanMvnParams(options[OPTION_JAVA_MVN], params);
|
|
116
125
|
}
|
|
117
126
|
|
|
127
|
+
// -DjdkVersion=[11|17]
|
|
128
|
+
if (!params.get('-DjdkVersion')) {
|
|
129
|
+
try {
|
|
130
|
+
const javaVersion = await execAsync('java -version');
|
|
131
|
+
const match = javaVersion?.stderr?.match(/version\s*"?(\d+\.\d+\.\d+)"?/);
|
|
132
|
+
if (match?.[1]) {
|
|
133
|
+
const segments = match[1]?.split('.');
|
|
134
|
+
const version = new Number(segments?.[0]);
|
|
135
|
+
switch (true) {
|
|
136
|
+
case (version < 11): throw new CliError(`Java version ${match[1]} is not supported. Use Java 11 or higher.`);
|
|
137
|
+
case (version <= 16): params.set(`-DjdkVersion`, 11); break;
|
|
138
|
+
case (version > 16): params.set(`-DjdkVersion`, 17); break;
|
|
139
|
+
default:
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
if (err instanceof CliError) {
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
DEBUG?.(err);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
118
150
|
if (options[OPTION_JAVA_PACKAGE]) {
|
|
119
151
|
params.set(`-Dpackage`, options[OPTION_JAVA_PACKAGE]);
|
|
120
152
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
1
|
const cds = require('../../cds')
|
|
2
|
+
const { path, read, exists } = cds.utils
|
|
3
3
|
const { BuildTaskFactory } = cds.build
|
|
4
|
-
const { read, exists } = cds.utils
|
|
5
4
|
const P_LANGUAGE_JAVA = 'java'
|
|
6
5
|
const P_LANGUAGE_NODEJS = 'nodejs'
|
|
7
6
|
const DEFAULT_P_LANGUAGE = P_LANGUAGE_NODEJS
|
|
@@ -16,31 +15,34 @@ const BUILD_TASK_MTX_SIDECAR = "mtx-sidecar"
|
|
|
16
15
|
const DEBUG = /\b(y|all|cli)\b/.test(process.env.DEBUG) && console.debug
|
|
17
16
|
const LOG = console
|
|
18
17
|
|
|
19
|
-
module.exports = class ProjectReader {
|
|
18
|
+
module.exports = new class ProjectReader {
|
|
20
19
|
|
|
21
|
-
constructor(
|
|
22
|
-
this.
|
|
20
|
+
constructor() {
|
|
21
|
+
this.readProject = this.readProject.bind(this)
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
// REVISIT: There should be a better (and parallelizable) API provided by cds.env
|
|
25
25
|
/**
|
|
26
26
|
* Returns cds.env using 'production' profile by default as mta deployment is executed with having production profile set.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
getEnv(profile = 'production') {
|
|
29
29
|
const cdsEnvVar = process.env.CDS_ENV
|
|
30
30
|
process.env.CDS_ENV = profile
|
|
31
31
|
try {
|
|
32
|
-
return cds.env.for('cds'
|
|
32
|
+
return cds.env.for('cds')
|
|
33
33
|
} finally {
|
|
34
34
|
cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
async
|
|
39
|
-
|
|
38
|
+
async readProject(options) {
|
|
39
|
+
if (options?.cwd) cds.root = options.cwd
|
|
40
|
+
|
|
41
|
+
const env = this.getEnv()
|
|
40
42
|
DEBUG && DEBUG({ env })
|
|
41
43
|
|
|
42
44
|
const cap = await this._getCapDescriptor(env, options)
|
|
43
|
-
const ui =
|
|
45
|
+
const ui = this._getUiDescriptor(env)
|
|
44
46
|
const projectDescriptor = { cap, ui }
|
|
45
47
|
this._validateDbFolders(cap)
|
|
46
48
|
|
|
@@ -49,28 +51,27 @@ module.exports = class ProjectReader {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
_validateDbFolders(cap) {
|
|
52
|
-
const {
|
|
54
|
+
const { db: dbs, isJava } = cap
|
|
53
55
|
if (isJava) {
|
|
54
|
-
for (const db of dbs) if (!exists(path.join(
|
|
56
|
+
for (const db of dbs) if (!exists(path.join(db.path, 'package.json'))) {
|
|
55
57
|
LOG.error(`Missing 'package.json' in folder ${db.path} - 'cds add hana' adds configuration for SAP HANA`)
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
async _getCapDescriptor(env, options) {
|
|
61
|
-
const
|
|
62
|
-
const _hasFacet = template => require(`../template/${template}`).hasFacet(env, projectPath, options)
|
|
63
|
+
const _hasFacet = template => require(`../template/${template}`).hasFacet(env, options)
|
|
63
64
|
const cap = {
|
|
64
65
|
for: options?.for,
|
|
65
66
|
pLanguage: DEFAULT_P_LANGUAGE,
|
|
66
67
|
srv: {},
|
|
67
68
|
db: [],
|
|
68
69
|
requires: [],
|
|
69
|
-
get root() { return projectPath },
|
|
70
70
|
get hasRequires() { return this.requires.length > 0 },
|
|
71
71
|
get needsSidecar() { return (options?.add.has('hana') || this.db.length > 0) && (this.isJava || !this.isMultitenant) },
|
|
72
72
|
get isNodejs() { return this.pLanguage === P_LANGUAGE_NODEJS },
|
|
73
73
|
get isJava() { return this.pLanguage === P_LANGUAGE_JAVA },
|
|
74
|
+
get hasSidecar() { return exists('mtx', 'sidecar') },
|
|
74
75
|
get isMultitenant() { return _hasFacet('multitenancy') },
|
|
75
76
|
get isExtensible() { return _hasFacet('extensibility') },
|
|
76
77
|
get hasHana() { return _hasFacet('hana') },
|
|
@@ -92,13 +93,15 @@ module.exports = class ProjectReader {
|
|
|
92
93
|
const nullLogger = { debug: () => { }, log: () => { }, warn: () => { }, error: () => { }, write: () => { } }
|
|
93
94
|
|
|
94
95
|
// no file path resolving as the directories might not exist - e.g. cds add will create the mtx/sidecar folder
|
|
95
|
-
|
|
96
|
+
// REVISIT: Leaner API from cds.build
|
|
97
|
+
const buildTasks = await new BuildTaskFactory(nullLogger, cds).getTasks({ root: cds.root, resolve: false, mta: false })
|
|
96
98
|
|
|
97
99
|
await Promise.all(buildTasks.map(async (task) => {
|
|
98
|
-
const srcPath = path.resolve(
|
|
100
|
+
const srcPath = path.resolve(cds.root, task.src)
|
|
99
101
|
const srcFolder = path.basename(srcPath)
|
|
100
102
|
const relDestPath = path.join(env?.build?.target ?? "gen", task.dest || task.src)?.replace(/\\/g, '/')
|
|
101
103
|
|
|
104
|
+
|
|
102
105
|
switch (task.for) {
|
|
103
106
|
case BUILD_TASK_HANA:
|
|
104
107
|
// check whether we have a hana service binding defined as a hana build task is returned by default for compatibility reasons if neither hana, nor sqlite has been defined
|
|
@@ -158,7 +161,7 @@ module.exports = class ProjectReader {
|
|
|
158
161
|
throw new Error("Projects using the classic CAP Java SDK are not supported")
|
|
159
162
|
}
|
|
160
163
|
|
|
161
|
-
const descriptor = { archiveName: path.basename(
|
|
164
|
+
const descriptor = { archiveName: path.basename(cds.root) + "-exec.jar" }
|
|
162
165
|
const archiveName = pomJson?.project?.artifactId?.[0]
|
|
163
166
|
const suffix = pomJson?.project?.packaging?.[0]
|
|
164
167
|
if (archiveName) descriptor.archiveName = archiveName + '-exec.' + suffix
|
|
@@ -166,8 +169,8 @@ module.exports = class ProjectReader {
|
|
|
166
169
|
}
|
|
167
170
|
}
|
|
168
171
|
|
|
169
|
-
|
|
170
|
-
const absoluteAppPath = path.join(
|
|
172
|
+
_getUiDescriptor(env) {
|
|
173
|
+
const absoluteAppPath = path.join(cds.root, env.folders.app)
|
|
171
174
|
return {
|
|
172
175
|
appPath: exists(absoluteAppPath) ? env.folders.app : null
|
|
173
176
|
}
|
|
@@ -180,7 +183,7 @@ module.exports = class ProjectReader {
|
|
|
180
183
|
|
|
181
184
|
// 1.1. java - use parent pom.xml
|
|
182
185
|
if (cap.pLanguage === P_LANGUAGE_JAVA) {
|
|
183
|
-
const pomXmlPath = path.join(
|
|
186
|
+
const pomXmlPath = path.join(cds.root, 'pom.xml')
|
|
184
187
|
try {
|
|
185
188
|
if (exists(pomXmlPath)) {
|
|
186
189
|
const pomJson = await this._parseXml(pomXmlPath)
|
|
@@ -213,7 +216,7 @@ module.exports = class ProjectReader {
|
|
|
213
216
|
|
|
214
217
|
// 1.2. use package.json
|
|
215
218
|
if (!cap.appName) {
|
|
216
|
-
const packageJsonPath = path.join(
|
|
219
|
+
const packageJsonPath = path.join(cds.root, 'package.json')
|
|
217
220
|
if (exists(packageJsonPath)) {
|
|
218
221
|
try {
|
|
219
222
|
const { name, version, description } = await read(packageJsonPath)
|
|
@@ -233,7 +236,7 @@ module.exports = class ProjectReader {
|
|
|
233
236
|
}
|
|
234
237
|
|
|
235
238
|
// 2. use project name and static default values
|
|
236
|
-
cap.appName = cap.appName ?? path.basename(
|
|
239
|
+
cap.appName = cap.appName ?? path.basename(cds.root)
|
|
237
240
|
cap.appDescription = cap.appDescription ?? cap.appName + " application"
|
|
238
241
|
cap.appId = cap.appId ?? cap.appName
|
|
239
242
|
cap.appVersion = cap.appVersion ?? '1.0.0'
|
|
@@ -304,7 +307,7 @@ module.exports = class ProjectReader {
|
|
|
304
307
|
*/
|
|
305
308
|
async _parseXml(pomXmlPath) {
|
|
306
309
|
const xmljs = require('xml-js');
|
|
307
|
-
|
|
310
|
+
const xmljsParse = {};
|
|
308
311
|
try {
|
|
309
312
|
const xml = await read(pomXmlPath, 'utf-8')
|
|
310
313
|
xmljsParse.project = JSON.parse(await xmljs.xml2json(xml, {
|