@sap/cds-dk 7.0.1 → 7.0.3
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 +36 -40
- package/bin/bind.js +0 -1
- package/bin/build.js +4 -0
- package/bin/cds.js +14 -8
- package/bin/compile/index.js +3 -3
- package/bin/deploy/to-hana.js +1 -1
- package/bin/help.js +2 -3
- package/bin/init.js +2 -2
- package/lib/bind/cfKeyProvider.js +1 -0
- package/lib/bind/index.js +3 -0
- package/lib/bind/userCdsrcJsonStorageProvider.js +2 -10
- package/lib/build/buildTaskEngine.js +1 -1
- package/lib/build/constants.js +16 -14
- package/lib/build/provider/buildTaskHandlerFeatureToggles.js +2 -1
- package/lib/build/provider/java/index.js +2 -2
- package/lib/build/provider/mtx/resourcesTarBuilder.js +2 -6
- package/lib/build/provider/mtx-sidecar/index.js +15 -11
- package/lib/build/util.js +8 -0
- package/lib/cds.js +2 -2
- package/lib/client/base_command.js +3 -6
- package/lib/compile/asyncapi/components/messages/index.js +41 -18
- package/lib/compile/asyncapi/index.js +23 -2
- package/lib/import/odata/metadataconverter/MetadataConverter.js +1 -0
- package/lib/init/constants.js +5 -5
- package/lib/init/index.js +68 -76
- package/lib/init/template/_merging/registry-mta.js +2 -2
- package/lib/init/template/approuter/index.js +10 -7
- 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 +5 -5
- package/lib/init/template/connectivity/index.js +2 -3
- package/lib/init/template/data/index.js +6 -6
- 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 +6 -6
- package/lib/init/template/kibana/files/mta.yaml.hbs +29 -0
- package/lib/init/template/kibana/index.js +54 -0
- package/lib/init/template/lint/index.js +8 -7
- package/lib/init/template/mta/index.js +3 -2
- package/lib/init/template/multitenancy/files/package.json.hbs +0 -3
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +1 -1
- package/lib/init/template/multitenancy/index.js +25 -40
- package/lib/init/template/nodejs/index.js +4 -5
- package/lib/init/template/pipeline/index.js +3 -3
- package/lib/init/template/redis-messaging/index.js +3 -4
- package/lib/init/template/sample/files/app/_i18n/i18n.properties +3 -32
- package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +2 -2
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +6 -7
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +3 -3
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +3 -11
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +117 -113
- package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +38 -0
- package/lib/init/template/sample/files/app/browse/fiori-service.cds +56 -0
- package/lib/init/template/sample/files/app/browse/webapp/Component.js +7 -0
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n.properties +4 -0
- package/lib/init/template/sample/files/app/browse/webapp/manifest.json +139 -0
- package/lib/init/template/sample/files/app/common.cds +78 -81
- package/lib/init/template/sample/files/app/services.cds +1 -0
- 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 +6 -6
- 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 +71 -15
- package/lib/init/util/mvn.js +24 -10
- package/lib/init/util/projectReader.js +53 -169
- package/lib/init/util/template.js +12 -11
- package/lib/init/util/xml.js +6 -6
- package/lib/util/pruneAxiosErrors.js +22 -0
- package/lib/watch/open.js +6 -3
- package/npm-shrinkwrap.json +20 -37
- package/package.json +1 -2
- package/lib/init/template/kibana-logging/files/cds.package.json +0 -7
- package/lib/init/template/kibana-logging/files/mta.yaml.hbs +0 -14
- package/lib/init/template/kibana-logging/index.js +0 -45
- /package/lib/init/template/{kibana-logging → kibana}/files/package.json.hbs +0 -0
package/bin/add.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const term = require('../lib/util/term')
|
|
1
2
|
|
|
2
3
|
module.exports = Object.assign(add, {
|
|
3
4
|
options: ['--for', '--out', '--data:for'],
|
|
@@ -8,72 +9,68 @@ module.exports = Object.assign(add, {
|
|
|
8
9
|
|
|
9
10
|
*cds add* <feature | comma-separated list of features>
|
|
10
11
|
|
|
11
|
-
Adds one or more features to an existing project
|
|
12
|
-
folder - Grow-as-you-go scenario.
|
|
12
|
+
Adds one or more features to an existing project - grow as you go.
|
|
13
13
|
|
|
14
|
-
The following
|
|
14
|
+
The following features are supported so far:
|
|
15
15
|
|
|
16
|
-
*hana*
|
|
16
|
+
*hana* - add support for SAP HANA
|
|
17
17
|
|
|
18
|
-
*sqlite*
|
|
18
|
+
*sqlite* - add support for SQLite databases
|
|
19
19
|
|
|
20
|
-
*xsuaa*
|
|
20
|
+
*xsuaa* - add support for authentication via XSUAA
|
|
21
21
|
|
|
22
|
-
*multitenancy*
|
|
22
|
+
*multitenancy* - add support for multitenancy
|
|
23
23
|
|
|
24
|
-
*toggles*
|
|
24
|
+
*toggles* - add support for feature toggles
|
|
25
25
|
|
|
26
|
-
*extensibility*
|
|
26
|
+
*extensibility* - add support for extensibility
|
|
27
27
|
|
|
28
|
-
*
|
|
29
|
-
extensibility
|
|
28
|
+
*approuter* - add support for application routing
|
|
30
29
|
|
|
31
|
-
*
|
|
30
|
+
*file-based-messaging* - add support for file-based messaging
|
|
32
31
|
|
|
33
|
-
*
|
|
34
|
-
Technology Platform deployment
|
|
32
|
+
*enterprise-messaging* - add support for SAP Event Mesh
|
|
35
33
|
|
|
36
|
-
*
|
|
37
|
-
Cloud Foundry native deployment
|
|
34
|
+
*redis-messaging* - add support for Redis messaging
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
Plugin' that has to be installed separately using
|
|
41
|
-
_cf install-plugin Create-Service-Push_.
|
|
42
|
-
_cf create-service-push_ creates the service(s) and pushes
|
|
43
|
-
the application(s) to the SAP Business Technology
|
|
44
|
-
Platform.
|
|
36
|
+
*kibana-logging* - add support for Kibana formatting
|
|
45
37
|
|
|
46
|
-
*
|
|
38
|
+
*mta* - add support for MTA-based deployment
|
|
47
39
|
|
|
48
|
-
*
|
|
40
|
+
*cf-manifest* - add support for CF-native deployment
|
|
49
41
|
|
|
50
|
-
*
|
|
42
|
+
*helm* - add support for Helm-based Kyma deployment
|
|
51
43
|
|
|
52
|
-
*
|
|
44
|
+
*html5-repo* - add support for the HTML5 repository
|
|
53
45
|
|
|
54
|
-
*
|
|
55
|
-
deploy the application using Kyma.
|
|
46
|
+
*pipeline* - add files for CI/CD pipeline integration
|
|
56
47
|
|
|
57
|
-
*
|
|
58
|
-
|
|
48
|
+
*tiny-sample* - add minimal sample files
|
|
49
|
+
|
|
50
|
+
*sample* - add sample files including Fiori UI
|
|
51
|
+
|
|
52
|
+
*data* - add CSV headers for modeled entities
|
|
53
|
+
|
|
54
|
+
*typer* - add type generation for CDS models
|
|
55
|
+
|
|
56
|
+
*lint* - add support for CDS Lint
|
|
59
57
|
|
|
60
58
|
|
|
61
59
|
# OPTIONS
|
|
62
60
|
|
|
63
61
|
*--for* <profile>
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
\`"[production]": { "db": "hana" }\`
|
|
63
|
+
Write configuration data for the given profile.
|
|
67
64
|
|
|
68
65
|
*--data:for* <entity name or prefix>
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
Add data content for entities matching the given pattern. If it contains
|
|
71
68
|
meta characters like '^' or '*', it is treated like a regular expression,
|
|
72
69
|
otherwise as a prefix.
|
|
73
70
|
|
|
74
71
|
*-o* | *--out* <target folder>
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
Specify output target folder (applicable to ${term.bold('data')} feature only).
|
|
77
74
|
|
|
78
75
|
*--force*
|
|
79
76
|
|
|
@@ -81,11 +78,10 @@ module.exports = Object.assign(add, {
|
|
|
81
78
|
|
|
82
79
|
# EXAMPLES
|
|
83
80
|
|
|
84
|
-
*cds add*
|
|
85
|
-
*cds add* multitenancy
|
|
86
|
-
*cds add* hana,xsuaa --for production
|
|
87
|
-
*cds add* cf-manifest
|
|
81
|
+
*cds add* sample
|
|
82
|
+
*cds add* multitenancy,hana,xsuaa --for production
|
|
88
83
|
*cds add* data --data:for my.namespace.MyEntity
|
|
84
|
+
*cds add* mta
|
|
89
85
|
*cds add* helm
|
|
90
86
|
|
|
91
87
|
|
|
@@ -95,8 +91,8 @@ module.exports = Object.assign(add, {
|
|
|
95
91
|
|
|
96
92
|
`});
|
|
97
93
|
|
|
98
|
-
async function add(args
|
|
94
|
+
async function add(args) {
|
|
99
95
|
const CDSGenerator = require('../lib/init');
|
|
100
96
|
const generator = new CDSGenerator();
|
|
101
|
-
await generator.addCmd(args[0]
|
|
97
|
+
await generator.addCmd(args[0]);
|
|
102
98
|
}
|
package/bin/bind.js
CHANGED
|
@@ -72,7 +72,6 @@ async function cds_bind(args, options) {
|
|
|
72
72
|
if (process.env.CDS_ENV && process.argv[2] === 'bind') {
|
|
73
73
|
throw new CliError('Option --profile is no longer supported. Use --for instead to specify the profile to use when storing connection settings.');
|
|
74
74
|
}
|
|
75
|
-
options.for = options.for ?? 'hybrid';
|
|
76
75
|
|
|
77
76
|
if (!options.to) {
|
|
78
77
|
throw new CliError(`Use option --to or -2 to specify the target instance, e.g. cds bind --to myInstance:myService`);
|
package/bin/build.js
CHANGED
|
@@ -101,6 +101,10 @@ async function build([project], options = {}) {
|
|
|
101
101
|
const { CliError } = require('../lib/client/helper/errors')
|
|
102
102
|
const { build } = require('../lib/build')
|
|
103
103
|
|
|
104
|
+
const [major] = cds.version.split('.')
|
|
105
|
+
if (Number(major) < 6) {
|
|
106
|
+
throw new CliError("This application uses @sap/cds version < 6, which is not compatible with the installed @sap/cds-dk version >= 7. Update @sap/cds to version >= 6.")
|
|
107
|
+
}
|
|
104
108
|
if (options.clean === "false") {
|
|
105
109
|
throw new CliError("cds build option '--clean' is deprecated - build output folders are always cleaned before build")
|
|
106
110
|
}
|
package/bin/cds.js
CHANGED
|
@@ -54,9 +54,13 @@ const cli = { //NOSONAR
|
|
|
54
54
|
return await task.apply(this, args)
|
|
55
55
|
}
|
|
56
56
|
} catch (e) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const { BuildError } = require('../lib/build')
|
|
58
|
+
const { CliError } = require('../lib/client/helper/errors')
|
|
59
|
+
process.exitCode ??= 1
|
|
60
|
+
if (e.messages?.length) return cds._log(e.messages, { 'log-level': cds.env.log.levels.cli })
|
|
61
|
+
else if (e instanceof CliError || e instanceof BuildError) return console.error(e.message)
|
|
62
|
+
if (cds.watched) throw e // bin/watched.js handles errors
|
|
63
|
+
else return console.error(e)
|
|
60
64
|
}
|
|
61
65
|
},
|
|
62
66
|
|
|
@@ -148,13 +152,15 @@ function _dieForUnknownCommand(cmd) {
|
|
|
148
152
|
|
|
149
153
|
let bestMatchText = '';
|
|
150
154
|
|
|
151
|
-
const excludeList = ['cds.js', 'cds-ts.js', 'fix-redirects.js'];
|
|
155
|
+
const excludeList = ['cds.js', 'cds-ts.js', 'fix-redirects.js', 'util'];
|
|
152
156
|
const { readdirSync } = require('fs');
|
|
153
157
|
const { resolve } = require('path');
|
|
154
|
-
|
|
158
|
+
let commands = readdirSync(__dirname, { withFileTypes: true })
|
|
155
159
|
.concat(readdirSync(resolve(_local('@sap/cds'), '..', '..', 'bin'), { withFileTypes: true }))
|
|
156
|
-
.filter((f) =>
|
|
157
|
-
.map((f) => f.name.split('.')[0])
|
|
160
|
+
.filter((f) => !excludeList.includes(f.name))
|
|
161
|
+
.map((f) => f.name.split('.')[0])
|
|
162
|
+
commands = [...new Set(commands)] // make unique
|
|
163
|
+
.sort();
|
|
158
164
|
|
|
159
165
|
const bestMatches = fuzzySearch(cmd, commands, DEBUG);
|
|
160
166
|
|
|
@@ -180,7 +186,7 @@ function _dieForUnknownCommand(cmd) {
|
|
|
180
186
|
`
|
|
181
187
|
console.error(msg)
|
|
182
188
|
|
|
183
|
-
process.
|
|
189
|
+
process.exit(1)
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
function _require (id,o) {
|
package/bin/compile/index.js
CHANGED
|
@@ -175,7 +175,7 @@ function compile (models, options={}) {
|
|
|
175
175
|
model = readModelFromStdin()
|
|
176
176
|
src = 'stdin'
|
|
177
177
|
} else { // no args, no stdin
|
|
178
|
-
throw
|
|
178
|
+
throw `You must specify a model to compile.\nRun 'cds c -?' to learn more.`
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
let chain = model.then (m => model=m)
|
|
@@ -189,7 +189,7 @@ function compile (models, options={}) {
|
|
|
189
189
|
if (typeof options.to === 'string') for (let each of options.to.split(',')) {
|
|
190
190
|
chain = chain.then (next (processor ('to', _suffix=each)))
|
|
191
191
|
} else if (options.to) {
|
|
192
|
-
|
|
192
|
+
throw `Specify a model processor`
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// add processor for i18n
|
|
@@ -235,7 +235,7 @@ function compile (models, options={}) {
|
|
|
235
235
|
let p = cds.compile[kind]
|
|
236
236
|
for (let each of tail.split('.')) {
|
|
237
237
|
p = p[each]
|
|
238
|
-
if (!p) throw
|
|
238
|
+
if (!p) throw `Unknown model processor: cds.compile.${kind}.${tail}`
|
|
239
239
|
}
|
|
240
240
|
return p
|
|
241
241
|
}
|
package/bin/deploy/to-hana.js
CHANGED
|
@@ -8,6 +8,6 @@ exports.deploy = (model, serviceName, options) => {
|
|
|
8
8
|
tunnelAddress: options['tunnel-address'],
|
|
9
9
|
vcapFile: options['vcap-file'],
|
|
10
10
|
hdiOptions: { autoUndeploy: options['auto-undeploy'] },
|
|
11
|
-
storeCredentials: options['store-credentials']
|
|
11
|
+
storeCredentials: options['store-credentials'] // TODO: Remove with cds-dk 8
|
|
12
12
|
});
|
|
13
13
|
}
|
package/bin/help.js
CHANGED
|
@@ -39,9 +39,8 @@ module.exports = exports = Object.assign (help, {formatHelp, help:`
|
|
|
39
39
|
|
|
40
40
|
function help (topic) {
|
|
41
41
|
if (Array.isArray(topic)) topic = topic[0]
|
|
42
|
-
const task = !topic ? help : this.load
|
|
43
|
-
if (task
|
|
44
|
-
else throw new Error(`Didn't find a help topic for '${ topic.name || topic }'.`)
|
|
42
|
+
const task = !topic ? help : this.load?.(this.Shortcuts[topic] || topic)
|
|
43
|
+
if (task?.help) console.log (formatHelp (task.help))
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
function formatHelp (text) {
|
package/bin/init.js
CHANGED
|
@@ -98,11 +98,11 @@ module.exports = Object.assign(init, {
|
|
|
98
98
|
|
|
99
99
|
`})
|
|
100
100
|
|
|
101
|
-
async function init (args
|
|
101
|
+
async function init (args) {
|
|
102
102
|
if (process.argv.some(a => legacyOptions.includes(a))) return _showWarningMessage()
|
|
103
103
|
const CDSGenerator = require('../lib/init')
|
|
104
104
|
const generator = new CDSGenerator()
|
|
105
|
-
await generator.initCmd(args[0]
|
|
105
|
+
await generator.initCmd(args[0])
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
|
|
@@ -4,6 +4,7 @@ const DEBUG = cds.debug('cli')
|
|
|
4
4
|
const cfUtil = require('../util/cfUtil');
|
|
5
5
|
|
|
6
6
|
const axios = require('axios');
|
|
7
|
+
require('../util/pruneAxiosErrors');
|
|
7
8
|
const { URL } = require('url');
|
|
8
9
|
const { bold, highlight } = require('../util/term');
|
|
9
10
|
const { CliError } = require('../client/helper/errors');
|
package/lib/bind/index.js
CHANGED
|
@@ -58,11 +58,7 @@ class UserCdsrcJsonStorageProvider {
|
|
|
58
58
|
|
|
59
59
|
cdsRoot.requires = cdsRoot.requires || {};
|
|
60
60
|
let section;
|
|
61
|
-
|
|
62
|
-
section = cdsRoot.requires[profileKey] = cdsRoot.requires[profileKey] || {};
|
|
63
|
-
} else {
|
|
64
|
-
section = cdsRoot.requires;
|
|
65
|
-
}
|
|
61
|
+
section = cdsRoot.requires[profileKey] = cdsRoot.requires[profileKey] || {};
|
|
66
62
|
|
|
67
63
|
for (const service of services) {
|
|
68
64
|
const { name, kind, binding, credentials } = service;
|
|
@@ -72,11 +68,7 @@ class UserCdsrcJsonStorageProvider {
|
|
|
72
68
|
}
|
|
73
69
|
|
|
74
70
|
await this.writeJsonFile(jsonPath, jsonObject);
|
|
75
|
-
|
|
76
|
-
logger.log(`Saving bindings to ${highlight(jsonPath)} in profile ${highlight(options.for)}`);
|
|
77
|
-
} else {
|
|
78
|
-
logger.log(`Saving bindings to ${highlight(jsonPath)}`);
|
|
79
|
-
}
|
|
71
|
+
logger.log(`Saving bindings to ${highlight(jsonPath)} in profile ${highlight(options.for)}`);
|
|
80
72
|
}
|
|
81
73
|
|
|
82
74
|
async readJsonSafely(filePath) {
|
|
@@ -30,7 +30,7 @@ class BuildTaskEngine {
|
|
|
30
30
|
const messages = []
|
|
31
31
|
|
|
32
32
|
this.logger.log(`building project [${cds.root}], clean [${this.buildOptions.clean}]`)
|
|
33
|
-
this.logger.log(`cds [${cds.version}], compiler [${cds.compiler.version()}], home [${cds.home}]\n`)
|
|
33
|
+
this.logger.log(`cds-dk [${require('../../package.json').version}], cds [${cds.version}], compiler [${cds.compiler.version()}], home [${cds.home}]\n`)
|
|
34
34
|
|
|
35
35
|
if (!tasks) {
|
|
36
36
|
const buildTaskFactory = new BuildTaskFactory(this.buildOptions)
|
package/lib/build/constants.js
CHANGED
|
@@ -19,20 +19,22 @@ exports.BUILD_TASKS = [this.BUILD_TASK_JAVA, this.BUILD_TASK_JAVA_CF, this.BUILD
|
|
|
19
19
|
exports.ODATA_VERSION_V2 = "v2"
|
|
20
20
|
exports.ODATA_VERSION_V4 = "v4"
|
|
21
21
|
|
|
22
|
-
exports.CONTENT_LANGUAGE_BUNDLES = "contentLanguageBundles"
|
|
23
|
-
exports.CONTENT_DEFAULT_CSN = "contentDefaultCsn"
|
|
24
|
-
exports.CONTENT_EDMX = "contentEdmx"
|
|
25
|
-
exports.CONTENT_PACKAGE_JSON = "contentPackageJson"
|
|
26
|
-
exports.CONTENT_PACKAGELOCK_JSON = "contentPackageLockJson"
|
|
27
|
-
exports.CONTENT_HDBTABLEDATA = "contentHdbtabledata"
|
|
28
|
-
exports.CONTENT_NPMRC = "contentNpmrc"
|
|
29
|
-
exports.CONTENT_CDSRC_JSON = "contentCdsrcJson"
|
|
30
|
-
exports.CONTENT_NODE_MODULES = "contentNodeModules"
|
|
31
|
-
exports.CONTENT_ENV = "contentEnv"
|
|
32
|
-
exports.CONTENT_DEFAULT_ENV_JSON = "contentDefaultEnvJson"
|
|
33
|
-
|
|
34
|
-
exports.
|
|
35
|
-
exports.
|
|
22
|
+
exports.CONTENT_LANGUAGE_BUNDLES = "contentLanguageBundles" // create i18n.json language bundles - build task specific
|
|
23
|
+
exports.CONTENT_DEFAULT_CSN = "contentDefaultCsn" // create default CSN format flavor: "inferred" - build task specific
|
|
24
|
+
exports.CONTENT_EDMX = "contentEdmx" // create EDMX for required languages - build task specific
|
|
25
|
+
exports.CONTENT_PACKAGE_JSON = "contentPackageJson" // create package.json file if not existing, or modify existing package.json - ENABLED by default
|
|
26
|
+
exports.CONTENT_PACKAGELOCK_JSON = "contentPackageLockJson" // copy package-lock.json file if existing into deployment folder - ENABLED by default
|
|
27
|
+
exports.CONTENT_HDBTABLEDATA = "contentHdbtabledata" // create .hdbtabledata files for .csv files if not existing - ENABLED by default
|
|
28
|
+
exports.CONTENT_NPMRC = "contentNpmrc" // copy .npmrc file if existing into deployment folder - ENABLED by default
|
|
29
|
+
exports.CONTENT_CDSRC_JSON = "contentCdsrcJson" // copy .cdsrc.json file if existing into deployment folder - ENABLED by default
|
|
30
|
+
exports.CONTENT_NODE_MODULES = "contentNodeModules" // copy node_modules folder if existing into deployment folder - DISABLED by default
|
|
31
|
+
exports.CONTENT_ENV = "contentEnv" // copy .env file if existing into deployment folder - DISABLED by default
|
|
32
|
+
exports.CONTENT_DEFAULT_ENV_JSON = "contentDefaultEnvJson" // copy default-env.json file if existing into deployment folder - DISABLED by default
|
|
33
|
+
|
|
34
|
+
exports.CSV_FILE_DETECTION = "csvFileDetection" // detect CSV files based on CDS model location - ENABLED by default
|
|
35
|
+
exports.EXTENSION_POINT_VALIDATION = "extensionPointValidation" // validate extension point restrictions defined by the extended SaaS app - ENABLED by default
|
|
36
|
+
exports.DEFAULT_BUILT_IN_MODELS = "defaultBuiltInModels" // add @sap/cds* built-in models to build tasks - ENABLED by default
|
|
37
|
+
exports.MTX_SIDECAR_DB_VALIDATION = "mtxSidecarDbValidation" // validate consistency of app and sidecar db configuration - ENABLED by default
|
|
36
38
|
|
|
37
39
|
exports.FOLDER_GEN = "gen"
|
|
38
40
|
exports.FILE_EXT_CDS = ".cds"
|
|
@@ -3,6 +3,7 @@ const path = require('path')
|
|
|
3
3
|
const cds = require('../../cds')
|
|
4
4
|
const { DEFAULT_CSN_FILE_NAME, OUTPUT_MODE, OUTPUT_MODE_RESULT } = require('../constants')
|
|
5
5
|
const BuildTaskHandlerInternal = require('./buildTaskHandlerInternal')
|
|
6
|
+
const { getI18nDefaultFolder } = require('../util')
|
|
6
7
|
|
|
7
8
|
class FeatureToggleBuilder extends BuildTaskHandlerInternal {
|
|
8
9
|
init() {
|
|
@@ -46,7 +47,7 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
async collectAllLanguageBundles(dictionary, paths, destBase, destFts) {
|
|
49
|
-
const i18nFolder =
|
|
50
|
+
const i18nFolder = getI18nDefaultFolder()
|
|
50
51
|
// create language bundle for base model
|
|
51
52
|
const i18n = await this.collectLanguageBundles(dictionary.base, path.join(destBase, i18nFolder))
|
|
52
53
|
if (i18n && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
@@ -3,6 +3,7 @@ const path = require('path')
|
|
|
3
3
|
const cds = require('../../../cds')
|
|
4
4
|
const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
5
5
|
const { OUTPUT_MODE, OUTPUT_MODE_RESULT, FILE_EXT_CDS, CONTENT_LANGUAGE_BUNDLES, CONTENT_DEFAULT_CSN, DEFAULT_CSN_FILE_NAME } = require('../../constants')
|
|
6
|
+
const { getI18nDefaultFolder } = require('../../util')
|
|
6
7
|
const DEFAULT_COMPILE_DEST_FOLDER = path.normalize('src/main/resources/edmx')
|
|
7
8
|
|
|
8
9
|
class JavaModuleBuilder extends BuildTaskHandlerEdmx {
|
|
@@ -28,8 +29,7 @@ class JavaModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
28
29
|
|
|
29
30
|
if (this.hasBuildOption(CONTENT_LANGUAGE_BUNDLES, true)) {
|
|
30
31
|
// collect and write language bundles into single i18n.json file
|
|
31
|
-
const
|
|
32
|
-
const i18n = await this.collectLanguageBundles(model, path.join(this.task.dest, i18nFolder))
|
|
32
|
+
const i18n = await this.collectLanguageBundles(model, path.join(this.task.dest, getI18nDefaultFolder()))
|
|
33
33
|
if (i18n && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
34
34
|
this._result.languageBundles = i18n.bundles
|
|
35
35
|
}
|
|
@@ -83,12 +83,8 @@ class ResourcesTarBuilder {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
async _getHanaTenantDbDest() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
this.handler.pushMessage(`Found SQLite database configuration. Ensure that productive cloud deployments requiring SAP HANA database are built with 'production' profile.`, WARNING)
|
|
89
|
-
return null
|
|
90
|
-
}
|
|
91
|
-
return hanaTask.dest
|
|
86
|
+
const hanaTask = this.handler.context.tasks.find(task => task.for === BUILD_TASK_HANA)
|
|
87
|
+
return hanaTask?.dest
|
|
92
88
|
}
|
|
93
89
|
}
|
|
94
90
|
module.exports = ResourcesTarBuilder
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
2
|
const cds = require('../../../cds')
|
|
3
3
|
const fs = require('fs')
|
|
4
|
-
const { FOLDER_GEN, DEFAULT_CSN_FILE_NAME } = require('../../constants')
|
|
4
|
+
const { FOLDER_GEN, DEFAULT_CSN_FILE_NAME, MTX_SIDECAR_DB_VALIDATION } = require('../../constants')
|
|
5
5
|
const NodeCfModuleBuilder = require('../nodejs')
|
|
6
6
|
const ResourcesTarProvider = require('../mtx/resourcesTarBuilder')
|
|
7
|
-
const {
|
|
8
|
-
const { relativePaths, BuildError, resolveRequiredSapModels } = require('../../util')
|
|
7
|
+
const { ERROR } = NodeCfModuleBuilder
|
|
8
|
+
const { relativePaths, BuildError, resolveRequiredSapModels, getI18nDefaultFolder } = require('../../util')
|
|
9
9
|
|
|
10
10
|
const DEFAULT_MAIN_FOLDER = "_main"
|
|
11
11
|
|
|
@@ -45,11 +45,10 @@ class MtxSidecarModuleBuilder extends NodeCfModuleBuilder {
|
|
|
45
45
|
async _buildNodeApp(sidecarEnv) {
|
|
46
46
|
const destSidecar = this.task.dest
|
|
47
47
|
const destSidecarSrc = path.join(destSidecar, cds.env.folders.srv)
|
|
48
|
-
const i18nFolder = cds.env.i18n.folders?.[0] || 'i18n'
|
|
49
48
|
const model = this._compileSidecarSync(sidecarEnv)
|
|
50
49
|
await this.compileToJson(model, path.join(destSidecarSrc, DEFAULT_CSN_FILE_NAME))
|
|
51
50
|
|
|
52
|
-
await this.collectLanguageBundles(model, path.join(destSidecarSrc,
|
|
51
|
+
await this.collectLanguageBundles(model, path.join(destSidecarSrc, getI18nDefaultFolder()))
|
|
53
52
|
await this.copySrvContent(this.task.src, destSidecar, destSidecar)
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -62,13 +61,18 @@ class MtxSidecarModuleBuilder extends NodeCfModuleBuilder {
|
|
|
62
61
|
if (!main) {
|
|
63
62
|
throw new BuildError(`Invalid MTX sidecar configuration. Make sure that the profile 'mtx-sidecar' is configured and an up-to-date version of @sap/cds-mtxs is installed.`)
|
|
64
63
|
}
|
|
65
|
-
|
|
64
|
+
if (!this.hasBuildOption(MTX_SIDECAR_DB_VALIDATION, false)
|
|
65
|
+
&& !cds.env.build.tasks?.length // disable if custom build tasks exist
|
|
66
|
+
&& sidecarEnv.requires.db && cds.env.requires.db // ensure database is configured
|
|
67
|
+
&& sidecarEnv.requires.db.kind !== cds.env.requires.db.kind) {
|
|
68
|
+
throw new BuildError(`Inconsistent database configuration found - application db '${cds.env.requires.db?.kind}', sidecar db '${sidecarEnv.requires.db?.kind}'`)
|
|
69
|
+
}
|
|
70
|
+
const profiles = cds.env.profiles ?? []
|
|
71
|
+
if (!profiles.includes("production") && !profiles.includes("prod")) {
|
|
72
|
+
// need to overwrite 'development' profile setting '../..' with '_main', although it is questionable why cds build is executed with development profile
|
|
73
|
+
main = DEFAULT_MAIN_FOLDER
|
|
74
|
+
}
|
|
66
75
|
|
|
67
|
-
if (!profiles.includes("production") && !profiles.includes("prod")) {
|
|
68
|
-
main = DEFAULT_MAIN_FOLDER
|
|
69
|
-
// root should represent the production use case and not development
|
|
70
|
-
this.pushMessage(`MTX sidecar build results are created in folder '${main}'. Enable 'production' or 'prod' profile if the folder is configured differently.`, WARNING)
|
|
71
|
-
}
|
|
72
76
|
const destRoot = this.task.dest
|
|
73
77
|
const destMain = path.join(destRoot, main)
|
|
74
78
|
const destMainSrv = path.join(destMain, cds.env.folders.srv)
|
package/lib/build/util.js
CHANGED
|
@@ -170,6 +170,13 @@ async function copy(src, dest) {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
function getI18nDefaultFolder() {
|
|
174
|
+
// keep '_i18n' as preferred folder for compatibility reasons
|
|
175
|
+
if (cds.env.i18n.folders.includes('_i18n')) return '_i18n'
|
|
176
|
+
if (cds.env.i18n.folders.includes('i18n')) return 'i18n'
|
|
177
|
+
return cds.env.i18n.folders[0] ?? 'i18n'
|
|
178
|
+
}
|
|
179
|
+
|
|
173
180
|
/**
|
|
174
181
|
* Return gnu-style error string for location `loc`:
|
|
175
182
|
* - 'File:Line:Col' without `loc.end`
|
|
@@ -258,6 +265,7 @@ module.exports = {
|
|
|
258
265
|
getDefaultModelOptions,
|
|
259
266
|
flatten,
|
|
260
267
|
copy,
|
|
268
|
+
getI18nDefaultFolder,
|
|
261
269
|
BuildMessage,
|
|
262
270
|
BuildError
|
|
263
271
|
}
|
package/lib/cds.js
CHANGED
|
@@ -3,8 +3,8 @@ const cds = _local ('@sap/cds')
|
|
|
3
3
|
|
|
4
4
|
module.exports = Object.defineProperties (cds, {
|
|
5
5
|
// for internal use in cds-dk only
|
|
6
|
-
_log: { value: _local ('../bin/util/log') },
|
|
7
|
-
_local: { value: _local },
|
|
6
|
+
_log: { value: _local ('../bin/util/log'), configurable: true },
|
|
7
|
+
_local: { value: _local, configurable: true },
|
|
8
8
|
})
|
|
9
9
|
|
|
10
10
|
function _local (id) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs').promises;
|
|
3
3
|
|
|
4
|
+
require('../util/pruneAxiosErrors');
|
|
5
|
+
|
|
4
6
|
const { CliError } = require('./helper/errors');
|
|
5
7
|
|
|
6
8
|
const MTX_URL_PATH_PREFIX = 'mtx/v1/model/';
|
|
@@ -26,17 +28,12 @@ module.exports = class BaseCommand {
|
|
|
26
28
|
case 403:
|
|
27
29
|
throw new CliError(prefix + ': insufficient authorization. Ensure client has all necessary roles.', { error, command });
|
|
28
30
|
case 404:
|
|
29
|
-
throw new CliError(prefix + ': resource not found.', { command });
|
|
31
|
+
throw new CliError(prefix + ': resource not found.', { error, command });
|
|
30
32
|
case 422:
|
|
31
33
|
// Compilation or native-extension error.
|
|
32
34
|
throw new CliError(prefix + '.', { error, command });
|
|
33
35
|
default:
|
|
34
36
|
// Unexpected error should be transparent to user.
|
|
35
|
-
if (!require('..').debug('axios')) {
|
|
36
|
-
error.config?.auth && (error.config.auth = '...'); // TODO use &&= with Node > 14
|
|
37
|
-
delete error.request;
|
|
38
|
-
delete error.response;
|
|
39
|
-
}
|
|
40
37
|
throw error;
|
|
41
38
|
}
|
|
42
39
|
}
|
|
@@ -16,11 +16,31 @@ function getHeaderProperties(name) {
|
|
|
16
16
|
return { type: { const: name } };
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
function nestedAnnotation(resObj, asyncapiProperty, keys, value) {
|
|
20
|
+
if (resObj[asyncapiProperty] === undefined) {
|
|
21
|
+
resObj[asyncapiProperty] = {};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let node = resObj[asyncapiProperty];
|
|
25
|
+
|
|
26
|
+
// traverse the annotation property and define the objects if they're not defined
|
|
27
|
+
for (let nestedIndex = 1; nestedIndex < keys.length - 1; nestedIndex++) {
|
|
28
|
+
const nestedElement = keys[nestedIndex];
|
|
29
|
+
if (node[nestedElement] === undefined) {
|
|
30
|
+
node[nestedElement] = {};
|
|
31
|
+
}
|
|
32
|
+
node = node[nestedElement];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// set value annotation property
|
|
36
|
+
node[keys[keys.length - 1]] = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
function readAnnotations(definition, presets) {
|
|
20
40
|
let resObj = {};
|
|
21
41
|
|
|
22
42
|
for (const [key, value] of Object.entries(definition)) {
|
|
23
|
-
if (key.startsWith('@AsyncAPI')) {
|
|
43
|
+
if (key.startsWith('@AsyncAPI') && !key.startsWith('@AsyncAPI.Extensions')) {
|
|
24
44
|
// get annotation value after @AsyncAPI
|
|
25
45
|
const annotationProperties = key.split('@AsyncAPI.')[1];
|
|
26
46
|
const keys = annotationProperties.split('.');
|
|
@@ -35,23 +55,22 @@ function readAnnotations(definition, presets) {
|
|
|
35
55
|
if (keys.length === 1) {
|
|
36
56
|
resObj[asyncapiProperty] = value;
|
|
37
57
|
} else {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let node = resObj[asyncapiProperty];
|
|
58
|
+
nestedAnnotation(resObj, asyncapiProperty, keys, value)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
43
61
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
node[nestedElement] = {};
|
|
49
|
-
}
|
|
50
|
-
node = node[nestedElement];
|
|
51
|
-
}
|
|
62
|
+
else if (key.startsWith('@AsyncAPI.Extensions')) {
|
|
63
|
+
const annotationProperties = key.split('@AsyncAPI.Extensions.')[1];
|
|
64
|
+
const keys = annotationProperties.split('.');
|
|
65
|
+
keys[0] = "x-" + keys[0];
|
|
52
66
|
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
if (keys.length === 1) {
|
|
68
|
+
// if the key is already present, that means, Annotations have already been considered
|
|
69
|
+
if (resObj[keys[0]]) continue;
|
|
70
|
+
// else we populate
|
|
71
|
+
resObj[keys[0]] = value;
|
|
72
|
+
} else {
|
|
73
|
+
nestedAnnotation(resObj, keys[0], keys, value);
|
|
55
74
|
}
|
|
56
75
|
}
|
|
57
76
|
}
|
|
@@ -142,9 +161,13 @@ function entriesToMessages(definitions, events, presets) {
|
|
|
142
161
|
/**
|
|
143
162
|
* Combining the definition objects from CSN into one schema
|
|
144
163
|
*/
|
|
145
|
-
|
|
164
|
+
function definitionsToMessages(definitions, events, presets) {
|
|
146
165
|
const messages = {};
|
|
147
|
-
|
|
148
166
|
Object.assign(messages, entriesToMessages(definitions, events, presets));
|
|
149
167
|
return messages;
|
|
150
168
|
}
|
|
169
|
+
|
|
170
|
+
module.exports = {
|
|
171
|
+
definitionsToMessages,
|
|
172
|
+
nestedAnnotation
|
|
173
|
+
}
|