@sap/cds-dk 7.0.2 → 7.1.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/bin/add.js +2 -2
- package/bin/bind.js +5 -7
- package/bin/build.js +2 -7
- package/bin/cds.js +6 -8
- package/bin/deploy/to-hana.js +1 -1
- package/bin/init.js +2 -2
- package/bin/subscribe.js +4 -4
- package/bin/unsubscribe.js +4 -4
- package/bin/upgrade.js +4 -4
- package/lib/bind/cfKeyProvider.js +10 -10
- package/lib/bind/index.js +4 -3
- package/lib/bind/userCdsrcJsonStorageProvider.js +2 -10
- package/lib/build/buildTaskEngine.js +9 -22
- package/lib/build/buildTaskFactory.js +18 -27
- package/lib/build/constants.js +16 -14
- package/lib/build/index.js +12 -3
- package/lib/build/provider/buildTaskProviderInternal.js +23 -15
- package/lib/build/provider/mtx/index.js +8 -2
- package/lib/build/provider/mtx/resourcesTarBuilder.js +2 -6
- package/lib/build/provider/mtx-sidecar/index.js +13 -8
- package/lib/build/util.js +13 -0
- package/lib/client/activate.js +7 -7
- package/lib/client/auth_manager.js +5 -5
- package/lib/client/base_command.js +7 -10
- package/lib/client/extend.js +2 -2
- package/lib/client/helper/logging.js +7 -2
- package/lib/client/params.js +2 -3
- package/lib/client/pull.js +3 -3
- package/lib/client/push.js +3 -3
- package/lib/client/settings_manager.js +7 -8
- package/lib/client/tenant_action.js +3 -3
- package/lib/compile/asyncapi/components/messages/index.js +41 -18
- package/lib/compile/asyncapi/index.js +23 -2
- package/lib/deploy/to-hana/hana.js +1 -2
- package/lib/import/common.js +3 -0
- package/lib/import/message.js +2 -1
- package/lib/import/odata/metadataconverter/MetadataConverter.js +1 -0
- package/lib/import/odata/v4parser.js +85 -95
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +78 -73
- package/lib/init/template/approuter/index.js +3 -4
- package/lib/init/template/auditlog/index.js +3 -4
- package/lib/init/template/cf-manifest/files/manifest.yml.hbs +15 -23
- package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +22 -17
- package/lib/init/template/cf-manifest/index.js +2 -2
- package/lib/init/template/connectivity/index.js +2 -3
- package/lib/init/template/data/index.js +7 -8
- package/lib/init/template/destination/index.js +3 -5
- package/lib/init/template/enterprise-messaging/index.js +4 -5
- package/lib/init/template/enterprise-messaging-shared/index.js +3 -4
- package/lib/init/template/extensibility/index.js +2 -3
- package/lib/init/template/file-based-messaging/index.js +2 -2
- package/lib/init/template/hana/files/mta.yaml.hbs +1 -1
- package/lib/init/template/hana/index.js +39 -63
- package/lib/init/template/helm/index.js +15 -14
- package/lib/init/template/html5-repo/index.js +3 -7
- package/lib/init/template/java/index.js +3 -3
- package/lib/init/template/kibana/index.js +3 -4
- package/lib/init/template/lint/index.js +13 -13
- package/lib/init/template/mta/index.js +3 -2
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +1 -1
- package/lib/init/template/multitenancy/index.js +16 -37
- package/lib/init/template/nodejs/index.js +4 -6
- package/lib/init/template/pipeline/index.js +3 -4
- package/lib/init/template/redis-messaging/index.js +3 -4
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +1 -1
- package/lib/init/template/sample/files/app/browse/webapp/manifest.json +1 -1
- package/lib/init/template/sample/files/srv/admin-service.cds +1 -1
- package/lib/init/template/sample/files/srv/cat-service.cds +1 -1
- package/lib/init/template/sample/index.js +6 -5
- package/lib/init/template/sqlite/index.js +1 -1
- package/lib/init/template/templateBase.js +9 -19
- package/lib/init/template/tiny-sample/index.js +5 -5
- package/lib/init/template/toggles/index.js +1 -2
- package/lib/init/template/typer/files/xsconfig.json +0 -1
- package/lib/init/template/typer/index.js +1 -1
- package/lib/init/template/xsuaa/index.js +3 -4
- package/lib/init/util/indent.js +57 -0
- package/lib/init/util/merge.js +72 -16
- package/lib/init/util/mvn.js +40 -31
- package/lib/init/util/projectReader.js +52 -168
- package/lib/init/util/template.js +12 -11
- package/lib/init/util/xml.js +6 -6
- package/lib/util/cfUtil.js +1 -2
- package/lib/util/pruneAxiosErrors.js +22 -0
- package/lib/watch/open.js +6 -3
- package/npm-shrinkwrap.json +356 -309
- package/package.json +1 -2
- package/lib/client/helper/errors.js +0 -26
- package/lib/util/version.js +0 -27
|
@@ -6,7 +6,7 @@ const { copyFiles } = require('../../util/template')
|
|
|
6
6
|
module.exports = class SampleTemplate extends require('../templateBase') {
|
|
7
7
|
|
|
8
8
|
async canRun() {
|
|
9
|
-
const { isJava } = await readProject(
|
|
9
|
+
const { isJava } = await readProject()
|
|
10
10
|
if (isJava) throw `'cds add sample' is not available for Java yet`
|
|
11
11
|
return true
|
|
12
12
|
}
|
|
@@ -14,11 +14,12 @@ module.exports = class SampleTemplate extends require('../templateBase') {
|
|
|
14
14
|
async run() {
|
|
15
15
|
const { db, srv, app } = (await this.getEnv()).folders
|
|
16
16
|
const language = exists('pom.xml') ? 'java' : 'nodejs'
|
|
17
|
+
const { force } = cds.cli.options
|
|
17
18
|
await Promise.all([
|
|
18
|
-
copyFiles(join(__dirname, 'files', 'db'), db, {},
|
|
19
|
-
copyFiles(join(__dirname, 'files', 'app'), app, {},
|
|
20
|
-
copyFiles(join(__dirname, 'files', 'srv'), srv, {},
|
|
21
|
-
copyFiles(join(__dirname, 'files', language), srv, {},
|
|
19
|
+
copyFiles(join(__dirname, 'files', 'db'), db, {}, force),
|
|
20
|
+
copyFiles(join(__dirname, 'files', 'app'), app, {}, force),
|
|
21
|
+
copyFiles(join(__dirname, 'files', 'srv'), srv, {}, force),
|
|
22
|
+
copyFiles(join(__dirname, 'files', language), srv, {}, force)
|
|
22
23
|
])
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -7,7 +7,7 @@ const { mergeJSON } = require('../../util/merge')
|
|
|
7
7
|
module.exports = class SQLiteTemplate extends require('../templateBase') {
|
|
8
8
|
|
|
9
9
|
async run() {
|
|
10
|
-
const project = await readProject(
|
|
10
|
+
const project = await readProject()
|
|
11
11
|
const { configFile } = project
|
|
12
12
|
project.shortcut = !(await read(configFile)).cds?.requires?.db?.kind
|
|
13
13
|
await mergeJSON(configFile, join(__dirname, 'files', `package.json.hbs`), project)
|
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
const { PROJECT_TYPE } = require('../constants');
|
|
5
|
-
const { exists } = require('../../cds').utils;
|
|
1
|
+
const cds = require('../../cds')
|
|
2
|
+
const { exists } = require('../../cds').utils
|
|
3
|
+
const { PROJECT_TYPE } = require('../constants')
|
|
6
4
|
|
|
7
5
|
module.exports = class TemplateBase {
|
|
6
|
+
|
|
8
7
|
/**
|
|
9
8
|
* @constructor
|
|
10
9
|
*/
|
|
11
|
-
constructor(
|
|
12
|
-
if (generator.options?.for && typeof generator.options?.for !== 'string') {
|
|
13
|
-
throw 'The --for argument must not be empty.'
|
|
14
|
-
}
|
|
15
|
-
this.projectPath = cds.root;
|
|
16
|
-
this.options = generator.options || {};
|
|
17
|
-
this.generator = generator;
|
|
10
|
+
constructor() {
|
|
18
11
|
this.name = this.constructor.name.replace(/template/i, '').replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
|
19
|
-
|
|
20
|
-
this.cwd = this.options.cwd || process.cwd();
|
|
21
|
-
|
|
22
|
-
this.projectName = path.basename(cds.root);
|
|
23
12
|
}
|
|
24
13
|
|
|
25
14
|
/**
|
|
@@ -51,7 +40,7 @@ module.exports = class TemplateBase {
|
|
|
51
40
|
}
|
|
52
41
|
|
|
53
42
|
// eslint-disable-next-line no-unused-vars
|
|
54
|
-
static hasFacet(env
|
|
43
|
+
static hasFacet(env) {
|
|
55
44
|
return true;
|
|
56
45
|
}
|
|
57
46
|
|
|
@@ -85,13 +74,14 @@ module.exports = class TemplateBase {
|
|
|
85
74
|
}
|
|
86
75
|
|
|
87
76
|
/**
|
|
77
|
+
* @abstract
|
|
88
78
|
* Executes steps for related facets that are set up for the project.
|
|
89
79
|
*/
|
|
90
80
|
async runRelatedMerging() {
|
|
91
81
|
for (const facet of this.getRelatedFacets()) {
|
|
92
82
|
const Template = require('./'+facet)
|
|
93
|
-
const template = new Template(
|
|
94
|
-
if (Template.hasFacet(await this.getEnv()
|
|
83
|
+
const template = new Template()
|
|
84
|
+
if (Template.hasFacet(await this.getEnv())) await template.runDependentMerging()
|
|
95
85
|
}
|
|
96
86
|
}
|
|
97
87
|
|
|
@@ -16,11 +16,11 @@ module.exports = class TinySampleTemplate extends require('../templateBase') {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
async _addJavaSamples() {
|
|
19
|
-
if (!
|
|
20
|
-
const mvnAddSamplesArgs = mvnArchetypes.getAddSamplesCmdArgs(
|
|
19
|
+
if (!cds.cli.options.add.has(JAVA)) {
|
|
20
|
+
const mvnAddSamplesArgs = mvnArchetypes.getAddSamplesCmdArgs()
|
|
21
21
|
try {
|
|
22
22
|
await commandUtil.spawnCommand('mvn', mvnAddSamplesArgs, { cwd: cds.root })
|
|
23
|
-
const mvnAddTestsArgs = mvnArchetypes.getAddTestsCmdArgs(
|
|
23
|
+
const mvnAddTestsArgs = mvnArchetypes.getAddTestsCmdArgs()
|
|
24
24
|
await commandUtil.spawnCommand('mvn', mvnAddTestsArgs, { cwd: cds.root })
|
|
25
25
|
} catch (err) {
|
|
26
26
|
if (err.code === 'ENOENT' && err.path === 'mvn') {
|
|
@@ -33,7 +33,7 @@ module.exports = class TinySampleTemplate extends require('../templateBase') {
|
|
|
33
33
|
|
|
34
34
|
async _addNodejsSamples() {
|
|
35
35
|
const { db, srv } = (await this.getEnv()).folders
|
|
36
|
-
await copyFiles(join(__dirname, 'files', 'nodejs', 'db'), db, {},
|
|
37
|
-
await copyFiles(join(__dirname, 'files', 'nodejs', 'srv'), srv, { dbFolder: db.replace(/[\\/]+$/, '') },
|
|
36
|
+
await copyFiles(join(__dirname, 'files', 'nodejs', 'db'), db, {}, cds.cli.options.force)
|
|
37
|
+
await copyFiles(join(__dirname, 'files', 'nodejs', 'srv'), srv, { dbFolder: db.replace(/[\\/]+$/, '') }, cds.cli.options.force)
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -9,10 +9,9 @@ module.exports = class TogglesTemplate extends require('../templateBase') {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
async run() {
|
|
12
|
-
const project = await readProject(
|
|
12
|
+
const project = await readProject()
|
|
13
13
|
const { isNodejs , configFile} = project
|
|
14
14
|
await mergeJSON(configFile, join(__dirname, 'files', 'package.json.hbs'), project)
|
|
15
15
|
if (isNodejs) await sort('package.json', 'dependencies')
|
|
16
|
-
await this.runDependentMerging()
|
|
17
16
|
}
|
|
18
17
|
}
|
|
@@ -7,7 +7,7 @@ const { exists, read } = require('../../../cds').utils
|
|
|
7
7
|
|
|
8
8
|
module.exports = class TyperTemplate extends require('../templateBase') {
|
|
9
9
|
async canRun() {
|
|
10
|
-
const { isJava } = await readProject(
|
|
10
|
+
const { isJava } = await readProject()
|
|
11
11
|
if (isJava) {
|
|
12
12
|
console.warn(warn(`This appears to be a Java project. 'cds add ${TYPER}' is intended to be used in Node.js projects. Proceeding anyway.\n`))
|
|
13
13
|
}
|
|
@@ -17,15 +17,14 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
async run() {
|
|
20
|
-
const project = await readProject(
|
|
20
|
+
const project = await readProject()
|
|
21
21
|
const { configFile } = project
|
|
22
22
|
project.shortcut = !(await read(configFile)).cds?.requires?.auth?.kind
|
|
23
23
|
await mergeJSON(configFile, join(__dirname, 'files', 'package.json.hbs'), project, { forceOverwrite: true })
|
|
24
|
-
await this.runDependentMerging()
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
async runDependentMerging( context = {}) {
|
|
28
|
-
const project = await readProject(
|
|
27
|
+
const project = await readProject()
|
|
29
28
|
const { isMultitenant, hasMta, hasHelm, isJava, srvPath } = project
|
|
30
29
|
|
|
31
30
|
const cds = require('../../../../lib')
|
|
@@ -71,7 +70,7 @@ module.exports = class XsuaaTemplate extends require('../templateBase') {
|
|
|
71
70
|
|
|
72
71
|
// copy service-instance chart
|
|
73
72
|
const HelmTemplate = require(`../helm`);
|
|
74
|
-
const helmTemplate = new HelmTemplate(
|
|
73
|
+
const helmTemplate = new HelmTemplate(context.oldTrackingData, context.newTrackingData);
|
|
75
74
|
isIndependentCommand = isIndependentCommand | await helmTemplate.addSubChart('service-instance');
|
|
76
75
|
|
|
77
76
|
// add dependency entry in chart.yaml
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const indentRegEx = new RegExp(/^(\s*)/)
|
|
2
|
+
const leadingSpacesRegEx = new RegExp(/^( +)/)
|
|
3
|
+
const leadingTabsRegEx = new RegExp(/^(\t+)/)
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Greatest Common Divisor Euclidean algorithm
|
|
7
|
+
* @param {number[]} xs - list of number to find the gcd of.
|
|
8
|
+
* @returns {number} - greatest common divisor of all numbers in xs.
|
|
9
|
+
*/
|
|
10
|
+
function gcd (xs) {
|
|
11
|
+
const euclid = (a, b) => b === 0 ? a : euclid(b, a % b)
|
|
12
|
+
const [a, b, ...tail] = xs
|
|
13
|
+
return tail.length
|
|
14
|
+
? gcd([euclid(a, b)].concat(tail))
|
|
15
|
+
: euclid(a, b ?? 0) // coalesce in case xs consists of exactly one element
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Detects indent used for a file.
|
|
20
|
+
* The algorithm inspects the indentation of every line to find whether tabs or spaces are more prevalent.
|
|
21
|
+
* Once that has been determined, it derives the spacing by calculating the gcd of all relevant lines.
|
|
22
|
+
* I.e. if there are lines indented with 2, 4, or 8 spaces, it will find ' ' as indent.
|
|
23
|
+
* If lines are indented using 1 or 2 tabs, '\t' will be returned.
|
|
24
|
+
* TODO: filter out outliers, i.e. if the user used three spaces in one line, should ' ' space be used for spacing? Or should that be ignored?
|
|
25
|
+
* @param {string[]} file - lines of a file.
|
|
26
|
+
* @returns {string | null} - the string used to space (e.g. 2 spaces, 4 spaces, 1 tab, etc.) or null if the file was empty.
|
|
27
|
+
*/
|
|
28
|
+
function detectIndent (file) {
|
|
29
|
+
if (file.length === 0) return null
|
|
30
|
+
if (file.length === 1) return indentRegEx.exec(file[0])[0]
|
|
31
|
+
|
|
32
|
+
const indents = file
|
|
33
|
+
.map(line => indentRegEx.exec(line)[0])
|
|
34
|
+
.filter(Boolean)
|
|
35
|
+
.reduce((bins, indent) => {
|
|
36
|
+
const type = leadingSpacesRegEx.test(indent)
|
|
37
|
+
? 'spaces'
|
|
38
|
+
: leadingTabsRegEx.test(indent)
|
|
39
|
+
? 'tabs'
|
|
40
|
+
: undefined
|
|
41
|
+
if (type) {
|
|
42
|
+
const length = indent.split('').length
|
|
43
|
+
const bin = bins[type]
|
|
44
|
+
bin.total++
|
|
45
|
+
bin.indents[length] = (bin.indents[length] ?? 0) + 1
|
|
46
|
+
}
|
|
47
|
+
return bins
|
|
48
|
+
}, { tabs: { indents: {}, total: 0, character: '\t' }, spaces: { indents: {}, total: 0, character: ' ' } })
|
|
49
|
+
|
|
50
|
+
const preferred = indents.tabs.total > indents.spaces.total ? indents.tabs : indents.spaces
|
|
51
|
+
const width = gcd(Object.keys(preferred.indents)) ?? 2
|
|
52
|
+
return preferred.character.repeat(width)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
detectIndent
|
|
57
|
+
}
|
package/lib/init/util/merge.js
CHANGED
|
@@ -2,7 +2,7 @@ const YAML = require('@sap/cds-foss').yaml
|
|
|
2
2
|
const { copy, read, write, exists } = require('../../cds').utils
|
|
3
3
|
const { readYAML, writeYAML, readJSON } = require('../../util/fs')
|
|
4
4
|
const { EOL } = require('node:os')
|
|
5
|
-
|
|
5
|
+
const { detectIndent } = require('../util/indent')
|
|
6
6
|
|
|
7
7
|
function _isObject(item) {
|
|
8
8
|
return item && typeof item === 'object' && !Array.isArray(item)
|
|
@@ -53,37 +53,93 @@ async function mergeGitignore (into, from) {
|
|
|
53
53
|
return enhanced
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {Object} MatchedNode
|
|
58
|
+
* @property {string | MatchedNode} in - key path or matched node to start search from
|
|
59
|
+
* @property {Object[]} where - list of constraints
|
|
60
|
+
* @property {string} where[].property - property key path
|
|
61
|
+
* @property {string} where[].isEqualTo - comparison string
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @typedef {Object} Overwrites
|
|
66
|
+
* @property {(string | MatchedNode)[]} item - path to item to be overwritten
|
|
67
|
+
* @property {string} withValue - replacement string
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @typedef {Object} Deletion
|
|
72
|
+
* @property {MatchedNode} item - matched node to delete
|
|
73
|
+
* @property {Object[]} relationships - list of relationships to delete
|
|
74
|
+
* @property {string} relationships[].removeProperty - key path to to-be-removed property
|
|
75
|
+
* @property {string[]} relationships[].allWithin - key path to relationship
|
|
76
|
+
*/
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @typedef {Object} Relationship
|
|
80
|
+
* @property {(string | MatchedNode)[]} insert - source path to matched node
|
|
81
|
+
* @property {(string | MatchedNode)[]} into - target path for inserted relationship
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @typedef {Object} MergingSemantics
|
|
86
|
+
* @property {boolean} [forceOverwrite] - overwrite values for existing keys
|
|
87
|
+
* @property {MatchedNode[]} [additions] - matched nodes to be added from source template
|
|
88
|
+
* @property {Overwrites[]} [overwrites] - matched keys to be overwritten with given string
|
|
89
|
+
* @property {Deletion[]} [deletions] - matched nodes to be deleted
|
|
90
|
+
* @property {Relationship[]} [relationships] - relationships to be inserted
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {string | JSON} into - file path or JSON to merge into
|
|
95
|
+
* @param {string | JSON} from - file path or JSON to merge from
|
|
96
|
+
* @param {import('./projectReader').readProject} [project] - project descriptor used for Mustache replacements
|
|
97
|
+
* @param {MergingSemantics} [semantics] - merging algorithm semantics
|
|
98
|
+
* @returns {Promise<JSON>} - merged JSON
|
|
99
|
+
*/
|
|
56
100
|
async function mergeJSON(into, from, project, semantics) {
|
|
57
101
|
const source = typeof from === 'string' ? await readJSON(from, project) : from
|
|
58
102
|
|
|
59
|
-
if (typeof into === 'string' && !exists(into)) {
|
|
60
|
-
return write(into, source, { spaces: 2 })
|
|
61
|
-
}
|
|
62
|
-
|
|
63
103
|
let result
|
|
64
|
-
if (
|
|
104
|
+
if (typeof into === 'string' && !exists(into)) {
|
|
105
|
+
result = source
|
|
106
|
+
} else if (semantics) {
|
|
65
107
|
const target = await read(into)
|
|
66
108
|
const targetYAML = YAML.parseDocument(YAML.stringify(target))
|
|
67
109
|
const sourceYAML = YAML.parseDocument(YAML.stringify(source))
|
|
68
110
|
const resultYAML = await mergeYAML(targetYAML, sourceYAML, project, semantics)
|
|
69
111
|
result = YAML.parse(YAML.stringify(resultYAML))
|
|
70
112
|
} else {
|
|
71
|
-
const target = typeof into === 'string' ? await read(into) : into
|
|
113
|
+
const target = typeof into === 'string' ? await read(into, 'json') : into
|
|
72
114
|
result = _deepMerge(target, source)
|
|
73
115
|
}
|
|
74
|
-
|
|
116
|
+
// we need to stringify result on site to be able to apply the appropriate indentation.
|
|
117
|
+
// cds-utils.write is currently hardcoded to use spaces for indentation.
|
|
118
|
+
if (typeof into === 'string') {
|
|
119
|
+
const indent = exists(into) && detectIndent((await read(into, 'utf-8')).split(EOL)) || ' '
|
|
120
|
+
await write(into, JSON.stringify(result, null, indent) + EOL)
|
|
121
|
+
}
|
|
75
122
|
return result
|
|
76
123
|
}
|
|
77
124
|
|
|
125
|
+
/**
|
|
126
|
+
* @param {string | YAML.Document} into - file path or YAML to merge into
|
|
127
|
+
* @param {string | YAML.Document} from - file path or YAML to merge from
|
|
128
|
+
* @param {Object} [project] - project descriptor used for Mustache replacements
|
|
129
|
+
* @param {MergingSemantics} [semantics] - merging algorithm semantics
|
|
130
|
+
* @returns {Promise<YAML.Document>} - merged YAML
|
|
131
|
+
* @throws {Error} Throws an error if empty target YAML is passed in
|
|
132
|
+
*/
|
|
78
133
|
async function mergeYAML(into, from, project, semantics = {}) {
|
|
79
134
|
const target = typeof into === 'string' ? await readYAML(into) : into instanceof YAML.Document ? into : new YAML.Document(into)
|
|
80
135
|
const source = typeof from === 'string' ? await readYAML(from, project) : from instanceof YAML.Document ? from : new YAML.Document(from)
|
|
81
136
|
|
|
82
|
-
if (!target
|
|
137
|
+
if (!target?.contents) {
|
|
83
138
|
if (typeof into === 'string' && typeof from === 'string') {
|
|
84
|
-
|
|
139
|
+
project ? await writeYAML(into, source) : await copy(from, into)
|
|
140
|
+
return source
|
|
85
141
|
}
|
|
86
|
-
|
|
142
|
+
throw new Error(`Target YAML doesn't exist`)
|
|
87
143
|
}
|
|
88
144
|
|
|
89
145
|
const entryMap = new Map, templateEntryMap = new Map()
|
|
@@ -148,7 +204,7 @@ async function mergeYAML(into, from, project, semantics = {}) {
|
|
|
148
204
|
|
|
149
205
|
if (node.items) {
|
|
150
206
|
if (YAML.isSeq(node) && templateNode?.items) {
|
|
151
|
-
actions
|
|
207
|
+
actions.mergeCollection?.(node, templateNode)
|
|
152
208
|
_traverseYAMLCollection(node, actions, templateNode)
|
|
153
209
|
} else {
|
|
154
210
|
_traverseYAMLCollection(node, actions, templateNode)
|
|
@@ -194,12 +250,12 @@ async function mergeYAML(into, from, project, semantics = {}) {
|
|
|
194
250
|
const targetNode = collection.items?.[i]
|
|
195
251
|
if (targetNode) {
|
|
196
252
|
_traverseYAMLNode(targetNode, templateIndex, actions, templateNode)
|
|
197
|
-
} else
|
|
198
|
-
actions.mergePair(collection, templateNode)
|
|
253
|
+
} else {
|
|
254
|
+
actions.mergePair?.(collection, templateNode)
|
|
199
255
|
}
|
|
200
256
|
} else if (YAML.isMap(templateNode)) {
|
|
201
257
|
const targetNode = collection.items[templateIndexToIndex.get(templateIndex)]
|
|
202
|
-
|
|
258
|
+
actions.mergeCollection?.(targetNode, templateNode)
|
|
203
259
|
if (targetNode) {
|
|
204
260
|
_traverseYAMLNode(targetNode, templateIndex, actions, templateNode)
|
|
205
261
|
}
|
|
@@ -266,7 +322,7 @@ async function mergeYAML(into, from, project, semantics = {}) {
|
|
|
266
322
|
.filter(addition => {
|
|
267
323
|
const keyPath = typeof addition.in === 'string' ? addition.in : Array.isArray(addition.in) && typeof addition.in[0] === 'string' ? addition.in[0] : addition.in[1]
|
|
268
324
|
const keys = keyPath.split('.')
|
|
269
|
-
if (keys.length > collectionStack.length + 1) return
|
|
325
|
+
if (keys.length > collectionStack.length + 1) return false
|
|
270
326
|
if (keys.length > 1) parent = collectionStack[keys.length]
|
|
271
327
|
return _getYAMLProperty(parent, keyPath) === targetNode
|
|
272
328
|
})
|
package/lib/init/util/mvn.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
|
-
const { MAVEN_ARCHETYPE_VERSION, OPTIONS: { JAVA_MVN, JAVA_PACKAGE, SAMPLES, HANA }, REGEX_JAVA_PACKAGE } = require('../constants');
|
|
3
|
-
|
|
4
|
-
const { CliError } = require('../../client/helper/errors');
|
|
5
|
-
|
|
2
|
+
const { URLS, MAVEN_ARCHETYPE_VERSION, OPTIONS: { JAVA_MVN, JAVA_PACKAGE, SAMPLES, HANA }, REGEX_JAVA_PACKAGE } = require('../constants');
|
|
6
3
|
|
|
7
4
|
const cp = require('child_process');
|
|
8
5
|
const util = require('util');
|
|
9
6
|
const execAsync = util.promisify(cp.exec);
|
|
10
|
-
|
|
7
|
+
const term = require('../../util/term');
|
|
8
|
+
const cmd = require('../../util/command');
|
|
11
9
|
|
|
12
10
|
const DEFAULT_GROUP_ID = 'customer';
|
|
13
11
|
|
|
@@ -15,7 +13,6 @@ const LOG = console
|
|
|
15
13
|
const cds = require('../../cds')
|
|
16
14
|
const DEBUG = cds.debug('cli')
|
|
17
15
|
|
|
18
|
-
|
|
19
16
|
class MvnArchetypeUtil {
|
|
20
17
|
|
|
21
18
|
_scanMvnParams(mvnParams, params) {
|
|
@@ -51,11 +48,12 @@ class MvnArchetypeUtil {
|
|
|
51
48
|
return Array.from(params, ([arg, val]) => val !== null && val !== undefined ? `${arg}=${val}` : arg)
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
getAddSamplesCmdArgs(
|
|
51
|
+
getAddSamplesCmdArgs() {
|
|
55
52
|
const params = new Map();
|
|
56
53
|
|
|
57
54
|
params.set(`com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:addSample`);
|
|
58
55
|
|
|
56
|
+
const { options } = cds.cli
|
|
59
57
|
if (options[JAVA_MVN]) {
|
|
60
58
|
this._scanMvnParams(options[JAVA_MVN], params);
|
|
61
59
|
}
|
|
@@ -67,11 +65,12 @@ class MvnArchetypeUtil {
|
|
|
67
65
|
return this._finalize(params);
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
getAddTestsCmdArgs(
|
|
68
|
+
getAddTestsCmdArgs() {
|
|
71
69
|
const params = new Map();
|
|
72
70
|
|
|
73
71
|
params.set(`com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:addIntegrationTest`);
|
|
74
72
|
|
|
73
|
+
const { options } = cds.cli
|
|
75
74
|
if (options[JAVA_MVN]) {
|
|
76
75
|
this._scanMvnParams(options[JAVA_MVN], params);
|
|
77
76
|
}
|
|
@@ -83,14 +82,15 @@ class MvnArchetypeUtil {
|
|
|
83
82
|
return this._finalize(params);
|
|
84
83
|
}
|
|
85
84
|
|
|
86
|
-
getAddHanaCmdArgs(
|
|
85
|
+
getAddHanaCmdArgs() {
|
|
87
86
|
const params = new Map();
|
|
88
87
|
|
|
89
88
|
params.set(`com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:addTargetPlatform`);
|
|
90
89
|
params.set(`-DtargetPlatform`, `cloudfoundry`);
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
const javaMvn = cds.cli.options[JAVA_MVN]
|
|
92
|
+
if (javaMvn) {
|
|
93
|
+
this._scanMvnParams(javaMvn, params);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
return this._finalize(params);
|
|
@@ -100,7 +100,7 @@ class MvnArchetypeUtil {
|
|
|
100
100
|
return packageName.toLowerCase().replace(/-/g, '_').replace(/\.([0-9])/g, '._$1').replace(/^([0-9])/, '_$1').replace(/\.+/g, '.');
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
async getGenerateCmdArgs(projectName, options) {
|
|
103
|
+
async getGenerateCmdArgs(projectName, options = cds.cli.options) {
|
|
104
104
|
const params = new Map();
|
|
105
105
|
|
|
106
106
|
// set header
|
|
@@ -129,29 +129,27 @@ class MvnArchetypeUtil {
|
|
|
129
129
|
|
|
130
130
|
// -DjdkVersion=[11|17]
|
|
131
131
|
if (!params.get('-DjdkVersion')) {
|
|
132
|
+
let javaVersion
|
|
132
133
|
try {
|
|
133
|
-
|
|
134
|
-
const match = javaVersion?.stderr?.match(/version\s*"?(\d+\.\d+\.\d+)"?/);
|
|
135
|
-
if (match?.[1]) {
|
|
136
|
-
const segments = match[1]?.split('.');
|
|
137
|
-
const version = new Number(segments?.[0]);
|
|
138
|
-
switch (true) {
|
|
139
|
-
case (version < 17):
|
|
140
|
-
if (process.env.WS_BASE_URL) {
|
|
141
|
-
throw new CliError(`Java version ${match[1]} is not supported. Use Java 17 or higher. You can use command 'Java: Set Default JDK' to switch to Java 17.`)
|
|
142
|
-
}
|
|
143
|
-
throw new CliError(`Java version ${match[1]} is not supported. Use Java 17 or higher.`)
|
|
144
|
-
case (version < 20): params.set(`-DjdkVersion`, 17); break;
|
|
145
|
-
case (version >= 20): params.set(`-DjdkVersion`, 20); break;
|
|
146
|
-
default:
|
|
147
|
-
}
|
|
148
|
-
}
|
|
134
|
+
javaVersion = await execAsync('java -version');
|
|
149
135
|
} catch (err) {
|
|
150
|
-
if (err instanceof CliError) {
|
|
151
|
-
throw err;
|
|
152
|
-
}
|
|
153
136
|
DEBUG?.(err);
|
|
154
137
|
}
|
|
138
|
+
const match = javaVersion?.stderr?.match(/version\s*"?(\d+\.\d+\.\d+)"?/);
|
|
139
|
+
if (match?.[1]) {
|
|
140
|
+
const segments = match[1]?.split('.');
|
|
141
|
+
const version = new Number(segments?.[0]);
|
|
142
|
+
switch (true) {
|
|
143
|
+
case (version < 17):
|
|
144
|
+
if (process.env.WS_BASE_URL) {
|
|
145
|
+
throw `Java version ${match[1]} is not supported. Use Java 17 or higher. You can use command 'Java: Set Default JDK' to switch to Java 17.`
|
|
146
|
+
}
|
|
147
|
+
throw `Java version ${match[1]} is not supported. Use Java 17 or higher.`
|
|
148
|
+
case (version < 20): params.set(`-DjdkVersion`, 17); break;
|
|
149
|
+
case (version >= 20): params.set(`-DjdkVersion`, 20); break;
|
|
150
|
+
default:
|
|
151
|
+
}
|
|
152
|
+
}
|
|
155
153
|
}
|
|
156
154
|
|
|
157
155
|
if (options[JAVA_PACKAGE]) {
|
|
@@ -184,6 +182,17 @@ class MvnArchetypeUtil {
|
|
|
184
182
|
artifactId
|
|
185
183
|
};
|
|
186
184
|
}
|
|
185
|
+
|
|
186
|
+
async execMvn(args) {
|
|
187
|
+
try {
|
|
188
|
+
await cmd.spawnCommand('mvn', args, { cwd: cds.root });
|
|
189
|
+
} catch (err) {
|
|
190
|
+
if (err.code === 'ENOENT' && err.path === 'mvn') {
|
|
191
|
+
throw `Maven executable 'mvn' not found, follow ${term.info(URLS.MAVEN_INSTALL_HELP)} and install Maven on your machine.`;
|
|
192
|
+
}
|
|
193
|
+
throw err;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
187
196
|
}
|
|
188
197
|
|
|
189
198
|
module.exports = new MvnArchetypeUtil();
|