@sap/cds-dk 7.3.2 → 7.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/build.js +22 -13
- package/bin/cds.js +3 -3
- package/bin/migrate.js +2 -2
- package/bin/push.js +3 -3
- package/bin/repl.js +0 -2
- package/bin/subscribe.js +10 -5
- package/bin/unsubscribe.js +10 -5
- package/bin/upgrade.js +10 -5
- package/bin/watch.js +5 -0
- package/bin/watched.js +1 -1
- package/lib/bind/bindingUtil.js +4 -2
- package/lib/build/buildTaskFactory.js +1 -1
- package/lib/build/constants.js +1 -0
- package/lib/build/provider/hana/2migration.js +4 -4
- package/lib/build/provider/hana/index.js +20 -10
- package/lib/build/provider/java/index.js +2 -2
- package/lib/build/provider/mtx-extension/index.js +5 -2
- package/lib/build/provider/nodejs/index.js +78 -53
- package/lib/client/auth_manager.js +1 -1
- package/lib/client/params.js +1 -0
- package/lib/client/pull.js +9 -1
- package/lib/client/push.js +2 -2
- package/lib/compile/asyncapi/components/schemas/annotations.js +20 -0
- package/lib/compile/openapi/csdl2openapi.js +3 -3
- package/lib/deploy/to-hana/hana.js +3 -1
- package/lib/index.js +5 -3
- package/lib/init/constants.js +1 -3
- package/lib/init/index.js +9 -4
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/hana/files/db/package.json +1 -1
- package/lib/init/template/multitenancy/index.js +3 -5
- package/lib/init/template/postgres/index.js +4 -3
- package/lib/init/template/templateBase.js +0 -13
- package/lib/init/util/projectReader.js +1 -1
- package/npm-shrinkwrap.json +21 -54
- package/package.json +10 -1
package/bin/build.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = Object.assign(build, {
|
|
2
2
|
options: ['--project', '--src', '--dest', '--for', '--use', '--opts', '--log-level', '--options-model'],
|
|
3
3
|
shortcuts: ['-in', '-s', '-o', '-4'],
|
|
4
|
-
flags: ['--
|
|
4
|
+
flags: ['--clean', '--no-clean', '--ws'], // REVISIT: --clean is deprecated, backward compatibility
|
|
5
5
|
help: `
|
|
6
6
|
# SYNOPSIS
|
|
7
7
|
|
|
@@ -16,7 +16,6 @@ module.exports = Object.assign(build, {
|
|
|
16
16
|
# OPTIONS
|
|
17
17
|
|
|
18
18
|
*-4 | --for* hana | java | nodejs | mtx | mtx-sidecar | mtx-extension
|
|
19
|
-
|
|
20
19
|
Name of the build task that is applied to the source folder, either
|
|
21
20
|
explicitly configured in the build task list or generated out of the
|
|
22
21
|
project setup
|
|
@@ -25,7 +24,6 @@ module.exports = Object.assign(build, {
|
|
|
25
24
|
otherwise.
|
|
26
25
|
|
|
27
26
|
*-s | --src* <folder>
|
|
28
|
-
|
|
29
27
|
The module folder to build using the build task defined by option
|
|
30
28
|
'--for'.
|
|
31
29
|
This option is only supported when building an individual module of the
|
|
@@ -36,7 +34,6 @@ module.exports = Object.assign(build, {
|
|
|
36
34
|
*hana* build task, 'srv' for *nodejs* or *java* build task.
|
|
37
35
|
|
|
38
36
|
*-o | --dest* <folder>
|
|
39
|
-
|
|
40
37
|
Output folder of the build task. The type of build task is defined by
|
|
41
38
|
option '--for'.
|
|
42
39
|
The folder is resolved based on '<project>/<cds.env.build.target>'.
|
|
@@ -49,14 +46,12 @@ module.exports = Object.assign(build, {
|
|
|
49
46
|
'<project>/*<dest>*/*'.
|
|
50
47
|
|
|
51
48
|
*--opts* <build task specific options>
|
|
52
|
-
|
|
53
49
|
Add a comma-separated list of build task specific options in the format
|
|
54
50
|
<opt1>=[value1,value2],<opt2>=value.
|
|
55
51
|
For example, --opts model=[db,srv,schema.cds] loads and compiles the CDS
|
|
56
52
|
model based on the given sources.
|
|
57
53
|
|
|
58
54
|
*--profile* <profile,...>
|
|
59
|
-
|
|
60
55
|
Loads the configuration data for the specified profile(s) and executes
|
|
61
56
|
'cds build' based on this profile settings.
|
|
62
57
|
E.g. you may want to create the HANA deployment artefacts only if the
|
|
@@ -64,18 +59,28 @@ module.exports = Object.assign(build, {
|
|
|
64
59
|
The *development* profile is used by default.
|
|
65
60
|
|
|
66
61
|
*--production*
|
|
67
|
-
|
|
68
62
|
Shortcut for '--profile production'
|
|
69
63
|
|
|
70
64
|
*--log-level* <debug | info | warn | error>
|
|
71
|
-
|
|
72
65
|
Choose which level of cds build messages to log, default is *warn*.
|
|
73
66
|
|
|
74
67
|
*-in | --project* [<project>]
|
|
75
|
-
|
|
76
68
|
Runs 'cds build' for the specified project, default is current working
|
|
77
69
|
directory.
|
|
78
|
-
|
|
70
|
+
|
|
71
|
+
*--no-clean* (beta)
|
|
72
|
+
Skips cleaning the build output folder before running the actual build
|
|
73
|
+
operation. Clients need to clean the output folder upfront to ensure
|
|
74
|
+
consistent build results.
|
|
75
|
+
|
|
76
|
+
*--ws* (beta)
|
|
77
|
+
Enable tarball based packaging of npm workspace dependencies - typically defined for
|
|
78
|
+
Node.js mono or multi-repo setups.
|
|
79
|
+
For each workspace dependency of your project using '*' as version identifier,
|
|
80
|
+
a tarball will be created in folder 'gen/srv'. Dependencies in package.json
|
|
81
|
+
will be adapted to point to the correct tarball file URL.
|
|
82
|
+
Contents is packaged based on the rules of the 'npm pack' command.
|
|
83
|
+
See 'npm workspaces' and 'npm pack' for further details.
|
|
79
84
|
|
|
80
85
|
# EXAMPLES
|
|
81
86
|
|
|
@@ -105,13 +110,17 @@ async function build([project], options = {}) {
|
|
|
105
110
|
if (Number(major) < 6) {
|
|
106
111
|
throw "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
112
|
}
|
|
108
|
-
if (options.clean === "false") {
|
|
109
|
-
throw "cds build option '--clean' is deprecated - build output folders are always cleaned before build"
|
|
110
|
-
}
|
|
111
113
|
if (typeof options["options-model"] === "string") {
|
|
112
114
|
options.opts = "model=[" + options["options-model"].split(",").map((entry) => entry.trim()) + "]"
|
|
113
115
|
delete options["options-model"]
|
|
114
116
|
}
|
|
117
|
+
if (options["no-clean"]) {
|
|
118
|
+
// mapping to the existing 'clean' option
|
|
119
|
+
if (options["no-clean"] === "true" || options["no-clean"] === true) {
|
|
120
|
+
options.clean = false
|
|
121
|
+
}
|
|
122
|
+
delete options["no-clean"]
|
|
123
|
+
}
|
|
115
124
|
|
|
116
125
|
await build(options)
|
|
117
126
|
}
|
package/bin/cds.js
CHANGED
|
@@ -93,8 +93,8 @@ const cli = { //NOSONAR
|
|
|
93
93
|
|
|
94
94
|
function add (k,v) { options[k.slice(2)] = v || true }
|
|
95
95
|
function add_global (k,v='') {
|
|
96
|
-
if (k === '--production') return process.env.CDS_ENV = [...process.env.CDS_ENV?.split(',') ?? [], 'production']
|
|
97
|
-
if (k === '--profile')
|
|
96
|
+
if (k === '--production') return process.env.CDS_ENV = Array.from(new Set([...process.env.CDS_ENV?.split(',') ?? [], 'production']))
|
|
97
|
+
if (k === '--profile') return process.env.CDS_ENV = Array.from(new Set([...process.env.CDS_ENV?.split(',') ?? [], ...v.split(',')]))
|
|
98
98
|
if (k === '--odata') v = { flavor:v }
|
|
99
99
|
let e=env || (env={}), path = k.slice(2).split('-')
|
|
100
100
|
while (path.length > 1) { let p = path.shift(); e = e[p]||(e[p]={}) }
|
|
@@ -103,7 +103,7 @@ const cli = { //NOSONAR
|
|
|
103
103
|
|
|
104
104
|
// if (env) require('../lib/cds').env.add (env) //> avoid loading env
|
|
105
105
|
// unless it has already explicitly been set by the user
|
|
106
|
-
process.env.CDS_CONFIG ??= JSON.stringify(env)
|
|
106
|
+
if (env) process.env.CDS_CONFIG ??= JSON.stringify(env)
|
|
107
107
|
return [ args, options ]
|
|
108
108
|
},
|
|
109
109
|
|
package/bin/migrate.js
CHANGED
|
@@ -43,11 +43,11 @@ module.exports = Object.assign(migrate, {
|
|
|
43
43
|
Skip verification step. Does not check for potential deployment
|
|
44
44
|
differences.
|
|
45
45
|
|
|
46
|
-
*--cleanup*
|
|
46
|
+
*--cleanup*
|
|
47
47
|
|
|
48
48
|
Removes all metadata containers created by @sap/cds-mtx.
|
|
49
49
|
|
|
50
|
-
*--resolve-bindings*
|
|
50
|
+
*--resolve-bindings*
|
|
51
51
|
|
|
52
52
|
Resolve remote service bindings configured via *cds bind*.
|
|
53
53
|
|
package/bin/push.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module.exports = Object.assign(push, {
|
|
2
|
-
options: ['--subdomain', '--passcode', '--user', '--client', '--to', '--sync'],
|
|
2
|
+
options: ['--subdomain', '--passcode', '--user', '--client', '--to', '--async', '--sync'],
|
|
3
3
|
flags: [],
|
|
4
4
|
shortcuts: ['-s', '-p', '-u', '-c', '-2'],
|
|
5
5
|
help: `
|
|
@@ -48,9 +48,9 @@ module.exports = Object.assign(push, {
|
|
|
48
48
|
|
|
49
49
|
Client ID and optionally Client Secret for authentication.
|
|
50
50
|
|
|
51
|
-
*--
|
|
51
|
+
*--async*
|
|
52
52
|
|
|
53
|
-
Use the
|
|
53
|
+
Use the asynchronous server API to upload extensions.
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
# SEE ALSO
|
package/bin/repl.js
CHANGED
|
@@ -17,8 +17,6 @@ async function repl (_, options={}) {
|
|
|
17
17
|
const cds = require('../lib/cds')
|
|
18
18
|
console.log('\x1b[32m\x1b[1m'+'Welcome to cds repl v', cds.version, '\x1b[0m')
|
|
19
19
|
|
|
20
|
-
await cds.plugins
|
|
21
|
-
|
|
22
20
|
const { inspect } = require('util')
|
|
23
21
|
inspect.defaultOptions.colors = true
|
|
24
22
|
inspect.defaultOptions.depth = 11
|
package/bin/subscribe.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module.exports = Object.assign(subscribe, {
|
|
2
2
|
init: cmd => new (require('../lib/client/tenant_action'))(cmd),
|
|
3
3
|
options: ['--to', '--user'],
|
|
4
|
-
flags: ['--local'],
|
|
5
|
-
shortcuts: ['-2', '-u', '-l'],
|
|
4
|
+
flags: ['--local', '--resolve-bindings'],
|
|
5
|
+
shortcuts: ['-2', '-u', '-l', '-b'],
|
|
6
6
|
help: `
|
|
7
7
|
# SYNOPSIS
|
|
8
8
|
|
|
@@ -24,10 +24,10 @@ module.exports = Object.assign(subscribe, {
|
|
|
24
24
|
|
|
25
25
|
Username and optionally password for authentication with Basic Auth in
|
|
26
26
|
test scenarios.
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
Only relevant if <url> is given. May be omitted in case of dummy
|
|
29
29
|
authentication.
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
Tokens saved with *cds login* are not used for this command.
|
|
32
32
|
|
|
33
33
|
*-l* | *--local*
|
|
@@ -35,11 +35,15 @@ module.exports = Object.assign(subscribe, {
|
|
|
35
35
|
Run a locally-installed @sap/cds-mtxs and connect to it instead of a
|
|
36
36
|
URL. Ignore settings saved with *cds login*.
|
|
37
37
|
|
|
38
|
+
*-b* | *--resolve-bindings*
|
|
39
|
+
|
|
40
|
+
Resolve remote service bindings configured via *cds bind*.
|
|
41
|
+
|
|
38
42
|
|
|
39
43
|
# SEE ALSO
|
|
40
44
|
|
|
41
45
|
*cds login* for more information on authentication options.
|
|
42
|
-
|
|
46
|
+
|
|
43
47
|
*cds login* to save project settings and Basic-Auth data, simplifying multiple runs of this command.
|
|
44
48
|
|
|
45
49
|
`});
|
|
@@ -63,6 +67,7 @@ async function subscribe([tenant], options = {}) {
|
|
|
63
67
|
}
|
|
64
68
|
const [username, password] = options.user?.split(':') ?? [];
|
|
65
69
|
delete options.user;
|
|
70
|
+
delete options['resolve-bindings'];
|
|
66
71
|
|
|
67
72
|
await subscribe.init('subscribe').run({
|
|
68
73
|
...options,
|
package/bin/unsubscribe.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module.exports = Object.assign(unsubscribe, {
|
|
2
2
|
init: cmd => new (require('../lib/client/tenant_action'))(cmd),
|
|
3
3
|
options: ['--from', '--user'],
|
|
4
|
-
flags: ['--local'],
|
|
5
|
-
shortcuts: ['-f', '-u', '-l'],
|
|
4
|
+
flags: ['--local', '--resolve-bindings'],
|
|
5
|
+
shortcuts: ['-f', '-u', '-l', '-b'],
|
|
6
6
|
help: `
|
|
7
7
|
# SYNOPSIS
|
|
8
8
|
|
|
@@ -25,10 +25,10 @@ module.exports = Object.assign(unsubscribe, {
|
|
|
25
25
|
|
|
26
26
|
Username and optionally password for authentication with Basic Auth in
|
|
27
27
|
test scenarios.
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
Only relevant if <url> is given. May be omitted in case of dummy
|
|
30
30
|
authentication.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
Tokens saved with *cds login* are not used for this command.
|
|
33
33
|
|
|
34
34
|
*-l* | *--local*
|
|
@@ -36,11 +36,15 @@ module.exports = Object.assign(unsubscribe, {
|
|
|
36
36
|
Run a locally-installed @sap/cds-mtxs and connect to it instead of a
|
|
37
37
|
URL. Ignore settings saved with *cds login*.
|
|
38
38
|
|
|
39
|
+
*-b* | *--resolve-bindings*
|
|
40
|
+
|
|
41
|
+
Resolve remote service bindings configured via *cds bind*.
|
|
42
|
+
|
|
39
43
|
|
|
40
44
|
# SEE ALSO
|
|
41
45
|
|
|
42
46
|
*cds login* for more information on authentication options.
|
|
43
|
-
|
|
47
|
+
|
|
44
48
|
*cds login* to save project settings and Basic-Auth data, simplifying multiple runs of this command.
|
|
45
49
|
|
|
46
50
|
`});
|
|
@@ -64,6 +68,7 @@ async function unsubscribe([tenant], options = {}) {
|
|
|
64
68
|
}
|
|
65
69
|
const [username, password] = options.user?.split(':') ?? [];
|
|
66
70
|
delete options.user;
|
|
71
|
+
delete options['resolve-bindings'];
|
|
67
72
|
|
|
68
73
|
await unsubscribe.init('unsubscribe').run({
|
|
69
74
|
...options,
|
package/bin/upgrade.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module.exports = Object.assign(upgrade, {
|
|
2
2
|
init: cmd => new (require('../lib/client/tenant_action'))(cmd),
|
|
3
3
|
options: ['--at', '--user'],
|
|
4
|
-
flags: ['--local'],
|
|
5
|
-
shortcuts: ['-a', '-u', '-l'],
|
|
4
|
+
flags: ['--local', '--resolve-bindings'],
|
|
5
|
+
shortcuts: ['-a', '-u', '-l', '-b'],
|
|
6
6
|
help: `
|
|
7
7
|
# SYNOPSIS
|
|
8
8
|
|
|
@@ -25,10 +25,10 @@ module.exports = Object.assign(upgrade, {
|
|
|
25
25
|
|
|
26
26
|
Username and optionally password for authentication with Basic Auth in
|
|
27
27
|
test scenarios.
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
Only relevant if <url> is given. May be omitted in case of dummy
|
|
30
30
|
authentication.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
Tokens saved with *cds login* are not used for this command.
|
|
33
33
|
|
|
34
34
|
*-l* | *--local*
|
|
@@ -36,11 +36,15 @@ module.exports = Object.assign(upgrade, {
|
|
|
36
36
|
Run a locally-installed @sap/cds-mtxs and connect to it instead of a
|
|
37
37
|
URL. Ignore settings saved with *cds login*.
|
|
38
38
|
|
|
39
|
+
*-b* | *--resolve-bindings*
|
|
40
|
+
|
|
41
|
+
Resolve remote service bindings configured via *cds bind*.
|
|
42
|
+
|
|
39
43
|
|
|
40
44
|
# SEE ALSO
|
|
41
45
|
|
|
42
46
|
*cds login* for more information on authentication options.
|
|
43
|
-
|
|
47
|
+
|
|
44
48
|
*cds login* to save project settings and Basic-Auth data, simplifying multiple runs of this command.
|
|
45
49
|
|
|
46
50
|
`});
|
|
@@ -64,6 +68,7 @@ async function upgrade([tenant], options = {}) {
|
|
|
64
68
|
}
|
|
65
69
|
const [username, password] = options.user?.split(':') ?? [];
|
|
66
70
|
delete options.user;
|
|
71
|
+
delete options['resolve-bindings'];
|
|
67
72
|
|
|
68
73
|
await upgrade.init('upgrade').run({
|
|
69
74
|
...options,
|
package/bin/watch.js
CHANGED
|
@@ -37,6 +37,11 @@ module.exports = Object.assign ( watch, {
|
|
|
37
37
|
Open the given URL (suffix) in the browser after starting.
|
|
38
38
|
If none is given, the default application URL will be opened.
|
|
39
39
|
|
|
40
|
+
*--profile* <profile,...>
|
|
41
|
+
|
|
42
|
+
Specify from which profile(s) the binding information is taken.
|
|
43
|
+
*Example:* cds w --profile hybrid,production
|
|
44
|
+
|
|
40
45
|
# SEE ALSO
|
|
41
46
|
|
|
42
47
|
*cds serve --help* for the different start options.
|
package/bin/watched.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
// run through cli in order to use its error handling
|
|
9
9
|
const args = JSON.parse(process.env._args)
|
|
10
|
+
const cds = require('../lib/cds'); cds.watched = true
|
|
10
11
|
const bootstrap = require('./cds')(...args)
|
|
11
|
-
const {cds} = global; cds.watched = true
|
|
12
12
|
|
|
13
13
|
cds.once('listening', ({server}) => {
|
|
14
14
|
process.send ({ code:'listening', port: server.address().port })
|
package/lib/bind/bindingUtil.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
const KindToRequiresNameMap = {
|
|
3
|
-
xsuaa: 'auth',
|
|
3
|
+
xsuaa: 'auth', // REVISIT: remove with ^8
|
|
4
|
+
'xsuaa-auth': 'auth',
|
|
4
5
|
'ias-auth': 'auth',
|
|
5
6
|
'hana-cloud': 'db',
|
|
6
7
|
hana: 'db',
|
|
@@ -17,7 +18,8 @@ const KindToRequiresNameMap = {
|
|
|
17
18
|
|
|
18
19
|
const PreferredKinds = [
|
|
19
20
|
'hana-cloud',
|
|
20
|
-
'xsuaa'
|
|
21
|
+
'xsuaa', // REVISIT: remove with ^8
|
|
22
|
+
'xsuaa-auth'
|
|
21
23
|
];
|
|
22
24
|
|
|
23
25
|
const PLATFORM_TYPES = {
|
|
@@ -230,7 +230,7 @@ class BuildTaskFactory {
|
|
|
230
230
|
|
|
231
231
|
static _scanTaskOptionParams(optsParams) {
|
|
232
232
|
// need to create new regex every call since a constant would keep the match state
|
|
233
|
-
const quoteRegex = /([\w-]+)=([\w
|
|
233
|
+
const quoteRegex = /([\w-]+)=([\w/.-]+|\[([\w/,.-]+)\])/g
|
|
234
234
|
|
|
235
235
|
// captures a=1 => a:1
|
|
236
236
|
// a=[x,y,z] => a:[x,y,z]
|
package/lib/build/constants.js
CHANGED
|
@@ -34,6 +34,7 @@ exports.CONTENT_NODE_MODULES = "contentNodeModules" // copy node_mod
|
|
|
34
34
|
exports.CONTENT_ENV = "contentEnv" // copy .env file if existing into deployment folder - DISABLED by default
|
|
35
35
|
exports.CONTENT_DEFAULT_ENV_JSON = "contentDefaultEnvJson" // copy default-env.json file if existing into deployment folder - DISABLED by default
|
|
36
36
|
|
|
37
|
+
exports.CSV_FILE_TARGET = "csvFileTarget" // target folder when copying CSV files to the deployment target folder ./db/src/gen/*, default is 'data'
|
|
37
38
|
exports.CSV_FILE_DETECTION = "csvFileDetection" // detect CSV files based on CDS model location - ENABLED by default
|
|
38
39
|
exports.EXTENSION_POINT_VALIDATION = "extensionPointValidation" // validate extension point restrictions defined by the extended SaaS app - ENABLED by default
|
|
39
40
|
exports.MTX_SIDECAR_DB_VALIDATION = "mtxSidecarDbValidation" // validate consistency of app and sidecar db configuration - ENABLED by default
|
|
@@ -13,8 +13,7 @@ module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
|
|
|
13
13
|
logger = options.logger
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const journalFileNames =
|
|
17
|
-
const { definitions, deletions, migrations, afterImage } = _toHdiMigration(model, lastDevVersion, journalFileNames, options)
|
|
16
|
+
const { definitions, deletions, migrations, afterImage, journalFileNames } = _toHdiMigration(model, lastDevVersion, options)
|
|
18
17
|
const definitionResult = []
|
|
19
18
|
|
|
20
19
|
for (const { name, suffix, sql } of definitions) {
|
|
@@ -33,8 +32,9 @@ module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
|
|
|
33
32
|
return { definitions: definitionResult, deletions, afterImage: _filterJournalArtifacts(afterImage) }
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
function _toHdiMigration(model, lastDevVersion,
|
|
35
|
+
function _toHdiMigration(model, lastDevVersion, options) {
|
|
37
36
|
const result = cdsc.to.hdi.migration(cds.minify(model), options, lastDevVersion);
|
|
37
|
+
const journalFileNames = _getJournalFileNames(result.afterImage);
|
|
38
38
|
if (logger._debug) {
|
|
39
39
|
logger.debug('cdsc.to.hdi.migration returned')
|
|
40
40
|
for (const { name, suffix, sql } of result.definitions) {
|
|
@@ -50,7 +50,7 @@ ${migration ? migration.changeset.map(change => change.sql).join('\n') : 'Empty
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
return result
|
|
53
|
+
return { ...result, journalFileNames };
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -6,7 +6,7 @@ const InternalBuildPlugin = require('../internalBuildPlugin')
|
|
|
6
6
|
const { BuildError, relativePaths, BuildMessage } = require('../../util')
|
|
7
7
|
|
|
8
8
|
const { OUTPUT_MODE_NONE, OUTPUT_MODE, CONTENT_PACKAGE_JSON, CONTENT_HDBTABLEDATA, CSV_FILE_DETECTION,
|
|
9
|
-
CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, OUTPUT_MODE_RESULT, CONTINUE_UNRESOLVED_SCHEMA_CHANGES } = require('../../constants')
|
|
9
|
+
CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, OUTPUT_MODE_RESULT, CONTINUE_UNRESOLVED_SCHEMA_CHANGES, CSV_FILE_TARGET } = require('../../constants')
|
|
10
10
|
const { WARNING } = InternalBuildPlugin
|
|
11
11
|
|
|
12
12
|
const DEFAULT_COMPILE_DEST_FOLDER = path.normalize("src/gen")
|
|
@@ -90,18 +90,28 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
90
90
|
*/
|
|
91
91
|
async _copyResourcesExt(src, dest, model) {
|
|
92
92
|
const resources = Object.keys(await cds.deploy.resources(model)).reverse() // reverse to get reuse resources first and app resources last
|
|
93
|
-
const
|
|
94
|
-
// determine subfolder name used by the application for backward compatibility
|
|
95
|
-
const csvFolder = resources.some(res => res && res.startsWith(csvPath)) ? "data" : "csv"
|
|
93
|
+
const dbSrc = path.join(src, 'src')
|
|
96
94
|
|
|
97
95
|
// 1. copy csv files into 'src/gen/data' or 'src/gen/csv' subfolder
|
|
98
|
-
|
|
96
|
+
if (resources.length) {
|
|
97
|
+
// determine the CSV folder from the location of the CSVs defined in this build task db folder, use subfolder data by default
|
|
98
|
+
const dbCSVs = resources.filter(res => res.startsWith(src) && !res.startsWith(dbSrc))
|
|
99
|
+
let csvFolder = this.getBuildOption(CSV_FILE_TARGET)
|
|
100
|
+
if (csvFolder && !["data", "csv"].includes(csvFolder)) {
|
|
101
|
+
throw new BuildError("Invalid value for option 'csvFileTarget'. Valid values are 'data' or 'csv'.")
|
|
102
|
+
}
|
|
103
|
+
if (!csvFolder) {
|
|
104
|
+
const csvPath = path.join(src, "data")
|
|
105
|
+
// determine subfolder name used by the application for backward compatibility
|
|
106
|
+
csvFolder = !dbCSVs.length || dbCSVs.some(res => res && res.startsWith(csvPath)) ? "data" : "csv"
|
|
107
|
+
}
|
|
99
108
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
// await each copy as order is important - reuse resources first and app resources last
|
|
110
|
+
for (const res of resources) {
|
|
111
|
+
// do not duplicate resources that are already contained in db/src/**
|
|
112
|
+
if (res && /\.csv$/.test(res) && !res.startsWith(dbSrc)) {
|
|
113
|
+
await this.copy(res).to(path.join(this.task.options.compileDest, csvFolder, path.basename(res)))
|
|
114
|
+
}
|
|
105
115
|
}
|
|
106
116
|
}
|
|
107
117
|
|
|
@@ -24,12 +24,12 @@ class JavaBuildPlugin extends EdmxBuildPlugin {
|
|
|
24
24
|
|
|
25
25
|
if (!this.hasBuildOption(CONTENT_EDMX, false)) {
|
|
26
26
|
// generate edmx files containing all features
|
|
27
|
-
// localized edmx for backward compatibility
|
|
27
|
+
// REVISIT: localized edmx for backward compatibility
|
|
28
28
|
if (!this.hasBuildOption(CONTENT_LOCALIZED_EDMX, false)) {
|
|
29
29
|
await this.compileToEdmx(odata, compileDest, { [FLAVOR_LOCALIZED_EDMX]: true })
|
|
30
30
|
}
|
|
31
31
|
// non-localized edmx
|
|
32
|
-
await this.compileToEdmx(odata, path.join(compileDest, 'odata', cds.env.odata.version), { [FLAVOR_LOCALIZED_EDMX]:
|
|
32
|
+
await this.compileToEdmx(odata, path.join(compileDest, 'odata', cds.env.odata.version), { [FLAVOR_LOCALIZED_EDMX]: this.hasBuildOption(FLAVOR_LOCALIZED_EDMX, true) })
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (!this.hasBuildOption(CONTENT_LANGUAGE_BUNDLES, false)) {
|
|
@@ -37,12 +37,14 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
|
|
|
37
37
|
extModel.requires.length = 0
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
// perform all model operations before the linter is called as the linter
|
|
40
|
+
// IMPORTANT NOTE: perform all model operations before the linter is called as the linter
|
|
42
41
|
// will modify the model causing the creation of 'unresolved' associations
|
|
43
42
|
await this.compileToJson(extModel, path.join(destExt, 'extension.csn'))
|
|
44
43
|
await this.collectLanguageBundles(extModel, path.join(destExt, 'i18n'))
|
|
45
44
|
|
|
45
|
+
// perform SQL backend validation to prevent extension deployment problems later on
|
|
46
|
+
cds.compile.to.sql(model)
|
|
47
|
+
|
|
46
48
|
const files = Object.keys(await cds.deploy.resources(model))
|
|
47
49
|
if (files.length > 0) {
|
|
48
50
|
const dataDest = path.join(destExt, 'data')
|
|
@@ -54,6 +56,7 @@ class MtxExtensionBuildPlugin extends InternalBuildPlugin {
|
|
|
54
56
|
})
|
|
55
57
|
)
|
|
56
58
|
}
|
|
59
|
+
|
|
57
60
|
if (!this.hasBuildOption(EXTENSION_POINT_VALIDATION, false)) {
|
|
58
61
|
try {
|
|
59
62
|
// throws error in case of linting errors
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const cds = require('../../../cds')
|
|
4
|
+
const cmd = require('../../../util/command');
|
|
4
5
|
const EdmxBuildPlugin = require('../edmxBuildPlugin')
|
|
5
6
|
const { BuildError } = require('../../util')
|
|
6
7
|
const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTENT_EDMX, CONTENT_PACKAGELOCK_JSON,
|
|
@@ -61,59 +62,6 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
61
62
|
return this._result
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
// REVISIT: fix for simple mono repos using npm workspaces
|
|
65
|
-
// Support for HANA native artifacts defined in sub-modules required
|
|
66
|
-
async _addWorkspaceDependencies(dest) {
|
|
67
|
-
try {
|
|
68
|
-
const workspaceRoot = path.resolve(cds.root, this.getBuildOption("workspaceRoot") ?? '.')
|
|
69
|
-
if (workspaceRoot !== cds.root && !fs.existsSync(workspaceRoot)) {
|
|
70
|
-
throw new BuildError(`The given workspaceRoot path ${workspaceRoot} does not exist`)
|
|
71
|
-
}
|
|
72
|
-
const packageJson = require(path.join(dest, 'package.json'))
|
|
73
|
-
const workspaces = workspaceRoot === cds.root ? packageJson.workspaces : require(path.join(workspaceRoot, 'package.json')).workspaces
|
|
74
|
-
if (workspaces?.length) {
|
|
75
|
-
this.logger._debug && this.logger.debug(`Existing npm workspace configuration '${JSON.stringify(workspaces, ' ')}'`)
|
|
76
|
-
const { tar } = require('../../../../lib').utils
|
|
77
|
-
const { dependencies } = packageJson
|
|
78
|
-
const folders = fs.readdirSync(workspaceRoot).filter(res => {
|
|
79
|
-
try {
|
|
80
|
-
return fs.lstatSync(path.join(workspaceRoot, res)).isDirectory()
|
|
81
|
-
} catch (e) {
|
|
82
|
-
return false
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
this.logger._debug && this.logger.debug(`Existing workspace subfolders '${JSON.stringify(folders, ' ')}'`)
|
|
86
|
-
|
|
87
|
-
const workspaceNames = new Set()
|
|
88
|
-
let changed
|
|
89
|
-
for (const workspace of workspaces) {
|
|
90
|
-
//REVISIT: workspaces must only use simple glob like 'foo*', nested folders are not supported
|
|
91
|
-
const regex = new RegExp('^' + workspace.split('/').pop().replace(/\*/g, '.*') + '$')
|
|
92
|
-
for (const folder of folders) {
|
|
93
|
-
if (!workspaceNames.has(folder) && folder.match(regex)) {
|
|
94
|
-
workspaceNames.add(folder)
|
|
95
|
-
const plugin = require(require.resolve(path.join(workspaceRoot, folder, 'package.json')))
|
|
96
|
-
const tarFile = `${plugin.name.replace(/\//g, '-').replace(/@/, '')}-${plugin.version}.tgz`
|
|
97
|
-
if (dependencies[plugin.name] === '*') {
|
|
98
|
-
const tarFilePath = path.join(dest, tarFile)
|
|
99
|
-
dependencies[plugin.name] = `file:${tarFile}`
|
|
100
|
-
await tar.czfd(tarFilePath, path.join(workspaceRoot, folder))
|
|
101
|
-
this.pushFile(tarFilePath)
|
|
102
|
-
changed = true
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (changed) {
|
|
108
|
-
return this.write(JSON.stringify(packageJson, null, ' ')).to(path.join(dest, 'package.json'))
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
} catch (e) {
|
|
112
|
-
this.pushMessage(`Failed to add npm workspace dependencies: ${e.message}`)
|
|
113
|
-
this.logger.debug(e)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
65
|
async clean() {
|
|
118
66
|
// staging build content is deleted by BuildTaskEngine
|
|
119
67
|
if (cds.env.build.target === '.') {
|
|
@@ -209,6 +157,83 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
209
157
|
return srvAllowList.test(entry) && (!filter || filter.call(this, entry))
|
|
210
158
|
})
|
|
211
159
|
}
|
|
160
|
+
|
|
161
|
+
async _addWorkspaceDependencies(dest) {
|
|
162
|
+
const wsRoot = this._findWorkspaceRoot(cds.root)
|
|
163
|
+
const appPkg = require(path.join(dest, 'package.json'))
|
|
164
|
+
let workspaces
|
|
165
|
+
if (this.task.options?.workspaces) {
|
|
166
|
+
workspaces = Array.isArray(this.task.options.workspaces) ? this.task.options.workspaces : [this.task.options.workspaces]
|
|
167
|
+
}
|
|
168
|
+
if (!workspaces) {
|
|
169
|
+
workspaces = []
|
|
170
|
+
for (const name in appPkg.dependencies) {
|
|
171
|
+
if (appPkg.dependencies[name] === '*') {
|
|
172
|
+
try {
|
|
173
|
+
const pkg = require.resolve(path.join(name, 'package.json'), { paths: [wsRoot] })
|
|
174
|
+
workspaces.push(path.dirname(path.relative(wsRoot, pkg)))
|
|
175
|
+
} catch(e) {
|
|
176
|
+
if (e.code === 'MODULE_NOT_FOUND') {
|
|
177
|
+
throw new BuildError(`Workspace packaging failed - module '${name}' not found. Make sure that configured npm workspaces are installed.`)
|
|
178
|
+
}
|
|
179
|
+
throw e
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (workspaces.length) {
|
|
185
|
+
let pkgDescriptors
|
|
186
|
+
try {
|
|
187
|
+
pkgDescriptors = await this._execNpmPack(dest, wsRoot, workspaces)
|
|
188
|
+
} catch (e) {
|
|
189
|
+
this.logger.debug(e)
|
|
190
|
+
throw new BuildError(`Failed to package npm workspace dependencies\n${e.message}`)
|
|
191
|
+
}
|
|
192
|
+
if (pkgDescriptors?.length) {
|
|
193
|
+
let changed
|
|
194
|
+
for (const pkgDescriptor of pkgDescriptors) {
|
|
195
|
+
const {name, filename: fileName} = pkgDescriptor
|
|
196
|
+
const filePath = path.join(dest, fileName)
|
|
197
|
+
if (appPkg.dependencies?.[name] === '*') {
|
|
198
|
+
appPkg.dependencies[name] = `file:${fileName}`
|
|
199
|
+
this.pushFile(filePath)
|
|
200
|
+
changed |= true
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (changed) {
|
|
204
|
+
await this.write(JSON.stringify(appPkg, 0, 2)).to(path.join(dest, 'package.json'))
|
|
205
|
+
} else {
|
|
206
|
+
throw new BuildError('No matching workspaces found!')
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
_findWorkspaceRoot(dir) {
|
|
213
|
+
try {
|
|
214
|
+
if(require(path.join(dir, 'package.json')).workspaces) {
|
|
215
|
+
return dir
|
|
216
|
+
}
|
|
217
|
+
} catch(err) {
|
|
218
|
+
// ignore
|
|
219
|
+
}
|
|
220
|
+
if(fs.existsSync(path.join(dir, '.gitmodules')) || fs.existsSync(path.join(dir, 'node_modules'))) {
|
|
221
|
+
return // project root reached
|
|
222
|
+
}
|
|
223
|
+
if (path.dirname(dir) !== dir) {
|
|
224
|
+
return this._findWorkspaceRoot(path.dirname(dir))
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async _execNpmPack(dest, wsRoot, workspaces) {
|
|
229
|
+
const args = ['pack', '-ws', '--json', `--pack-destination=${dest}`]
|
|
230
|
+
workspaces.forEach(w => args.push(`-w=${w}`))
|
|
231
|
+
|
|
232
|
+
this.logger._debug && this.logger.debug(`execute command: npm ${args}`)
|
|
233
|
+
const result = await cmd.spawnCommand( 'npm', args, { cwd: wsRoot }, true, !!this.logger._debug)
|
|
234
|
+
this.logger._debug && this.logger.debug(result)
|
|
235
|
+
return JSON.parse(result)
|
|
236
|
+
}
|
|
212
237
|
}
|
|
213
238
|
|
|
214
239
|
module.exports = NodejsBuildPlugin
|
|
@@ -66,7 +66,7 @@ async function retrieveTokenOrPasscodeUrl(params) {
|
|
|
66
66
|
let response;
|
|
67
67
|
for (const { method, url, data } of reqParams(params)) {
|
|
68
68
|
try {
|
|
69
|
-
DEBUG?.(`Getting authentication token or passcode URL from ${method.toUpperCase()} ${
|
|
69
|
+
DEBUG?.(`Getting authentication token or passcode URL from ${method.toUpperCase()} ${params.obfuscateQueryParams(url)}`);
|
|
70
70
|
response = await axios[method](url, data);
|
|
71
71
|
} catch (error) {
|
|
72
72
|
if (error.status === 404) { // may represent 405 in case of wrong method
|
package/lib/client/params.js
CHANGED
|
@@ -216,6 +216,7 @@ class AllParams extends BasicParams {
|
|
|
216
216
|
this.undeploy = new Param('undeploy', false);
|
|
217
217
|
this.wsdl = new Param('wsdl', false);
|
|
218
218
|
this.sync = new Param('sync', false);
|
|
219
|
+
this.async = new Param('async', false);
|
|
219
220
|
|
|
220
221
|
// `login` PARAMS
|
|
221
222
|
this.skipToken = new Param('skipToken', false, { internal: true });
|
package/lib/client/pull.js
CHANGED
|
@@ -49,6 +49,14 @@ module.exports = class Pull extends BaseCommand {
|
|
|
49
49
|
.catch(error => this.handleHttpError(error, params, { url: pullUrl }));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
static getPackageJsonIndentation(packageContents) {
|
|
53
|
+
return /^ +/m.exec(packageContents)?.[0].length ?? 2;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static formatPackageJson(newObj, oldContents) {
|
|
57
|
+
return JSON.stringify(newObj, undefined, this.getPackageJsonIndentation(oldContents));
|
|
58
|
+
}
|
|
59
|
+
|
|
52
60
|
static amendPackageJson(projectFolder, env) {
|
|
53
61
|
if ('extends' in env) {
|
|
54
62
|
return;
|
|
@@ -61,7 +69,7 @@ module.exports = class Pull extends BaseCommand {
|
|
|
61
69
|
} catch (error) {
|
|
62
70
|
throw getMessage('package.json missing or unreadable', { error });
|
|
63
71
|
}
|
|
64
|
-
fs.writeFileSync(packageJson,
|
|
72
|
+
fs.writeFileSync(packageJson, this.formatPackageJson({
|
|
65
73
|
...packageContents,
|
|
66
74
|
cds: {
|
|
67
75
|
...(packageContents.cds ?? {}),
|
package/lib/client/push.js
CHANGED
|
@@ -35,7 +35,7 @@ module.exports = class Push extends BaseCommand {
|
|
|
35
35
|
|
|
36
36
|
console.log(`\nPushing extension '${extensionName}' from`, { src }, 'to', target);
|
|
37
37
|
const push = await this.pushTgz(params, content, extensionName);
|
|
38
|
-
const async =
|
|
38
|
+
const async = params.get('async');
|
|
39
39
|
if (async) {
|
|
40
40
|
await this.pollUntilFinished(push.headers.location, params)
|
|
41
41
|
}
|
|
@@ -72,7 +72,7 @@ module.exports = class Push extends BaseCommand {
|
|
|
72
72
|
static async pushTgz(params, tgz, extensionName) {
|
|
73
73
|
const pushUrl = `${params.get('appUrl')}/-/cds/extensibility/push`;
|
|
74
74
|
const options = { ...params.get('reqAuth') };
|
|
75
|
-
const async =
|
|
75
|
+
const async = params.get('async');
|
|
76
76
|
if (async) {
|
|
77
77
|
options.headers = { prefer: 'respond-async', ...options.headers }
|
|
78
78
|
}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
const odmAnnotationsMapping = Object.freeze({
|
|
3
|
+
'@ODM.entityName': 'x-sap-odm-entity-name',
|
|
4
|
+
'@ODM.oid': 'x-sap-odm-oid'
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
function addOdmExtensions(definition, object) {
|
|
8
|
+
for (const [annotation, asyncApiExtension] of Object.entries(odmAnnotationsMapping)) {
|
|
9
|
+
if (definition[annotation]) {
|
|
10
|
+
object[asyncApiExtension] = definition[annotation];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
module.exports = function addAnnotations(definition, object) {
|
|
2
16
|
if (typeof (definition['@title']) === 'string') {
|
|
3
17
|
object.title = definition['@title'];
|
|
@@ -9,5 +23,11 @@ module.exports = function addAnnotations(definition, object) {
|
|
|
9
23
|
object.description = definition.doc.replace(/\n/g, ' ');
|
|
10
24
|
}
|
|
11
25
|
|
|
26
|
+
if (definition['@ODM.root']) {
|
|
27
|
+
object['x-sap-root-entity'] = definition['@ODM.root']
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
addOdmExtensions(definition, object);
|
|
31
|
+
|
|
12
32
|
return object;
|
|
13
33
|
}
|
|
@@ -479,7 +479,7 @@ module.exports.csdl2openapi = function (
|
|
|
479
479
|
if (description) tag.description = description;
|
|
480
480
|
tags.push(tag);
|
|
481
481
|
})
|
|
482
|
-
return tags.sort(function(pre, next){return pre.name.localeCompare(next.name)});
|
|
482
|
+
return tags.sort(function (pre, next) { return pre.name.localeCompare(next.name) });
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
/**
|
|
@@ -655,7 +655,7 @@ module.exports.csdl2openapi = function (
|
|
|
655
655
|
schema: ref(element.$Type, SUFFIX.create),
|
|
656
656
|
}
|
|
657
657
|
}
|
|
658
|
-
},
|
|
658
|
+
},
|
|
659
659
|
responses: response(201, 'Created ' + lname, { $Type: element.$Type }, insertRestrictions.ErrorResponses, !countRestrictions),
|
|
660
660
|
};
|
|
661
661
|
if (insertRestrictions.LongDescription) pathItem.post.description = insertRestrictions.LongDescription;
|
|
@@ -1620,7 +1620,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot
|
|
|
1620
1620
|
r[code] = {
|
|
1621
1621
|
description: description
|
|
1622
1622
|
};
|
|
1623
|
-
let CountPropertyObj = {[csdl.$Version > '4.0' ? '@count' : '@odata.count']
|
|
1623
|
+
let CountPropertyObj = { [csdl.$Version > '4.0' ? '@count' : '@odata.count']: ref('count') };
|
|
1624
1624
|
if (code != 204) {
|
|
1625
1625
|
const s = getSchema(type);
|
|
1626
1626
|
r[code].content = {
|
|
@@ -48,7 +48,9 @@ class HanaDeployer {
|
|
|
48
48
|
let { model, serviceName, tunnelAddress, vcapFile, undeployWhitelist, hdiOptions, dry } = options;
|
|
49
49
|
|
|
50
50
|
if (model) {
|
|
51
|
-
throw
|
|
51
|
+
throw `Specifying a CDS model for HANA deployment is not supported.
|
|
52
|
+
'cds deploy --to hana' performs 'cds build --for hana' which in turn uses the configured HANA build task.
|
|
53
|
+
Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
if (dry) {
|
package/lib/index.js
CHANGED
|
@@ -19,13 +19,15 @@ if (cds.compile.to.constructor.name === 'Object') { // not a class as in cds 7
|
|
|
19
19
|
cds.compile.to.xsuaa = require('./compile/to-xsuaa')
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
cds
|
|
22
|
+
// add overlay4 method to cds.schema to retrieve schema with cds-dk features
|
|
23
|
+
// schema is cds version specific; add cds-dk parts not present in cds, e.g. build
|
|
24
|
+
// failsafe for legacy cds without schema.constructor
|
|
25
|
+
cds.extend(cds.schema?.constructor || {}).with(class {
|
|
24
26
|
get overlay4() { return super.overlay4 = require('./env/schema') }
|
|
25
27
|
})
|
|
26
28
|
|
|
27
29
|
// set build API, potentially removing the old API facade from sap/cds 7
|
|
28
|
-
delete cds.__proto__?.build
|
|
30
|
+
// delete cds.__proto__?.build //> not required, as its overriden below anyways
|
|
29
31
|
cds.extend (cds.constructor) .with (class {
|
|
30
32
|
get build() { return super.build = require('./build') }
|
|
31
33
|
})
|
package/lib/init/constants.js
CHANGED
|
@@ -4,7 +4,7 @@ module.exports = {
|
|
|
4
4
|
COMMAND_INIT: 'init',
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
|
-
MAVEN_ARCHETYPE_VERSION: '2.
|
|
7
|
+
MAVEN_ARCHETYPE_VERSION: '2.4.0',
|
|
8
8
|
|
|
9
9
|
OPTIONS: Object.freeze({
|
|
10
10
|
JAVA: 'java',
|
|
@@ -45,8 +45,6 @@ module.exports = {
|
|
|
45
45
|
NOTIFICATIONS: 'notifications'
|
|
46
46
|
}),
|
|
47
47
|
|
|
48
|
-
PROJECT_TYPE: Object.freeze({ nodejs: 1, java: 2, unknown: 3 }),
|
|
49
|
-
|
|
50
48
|
REGEX_JAVA_PACKAGE: /^[a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*)*$/g,
|
|
51
49
|
// copied from mbt error message
|
|
52
50
|
REGEX_JAVA_VERSION: /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/,
|
package/lib/init/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const { OPTIONS, COMMAND_INIT, PROJECT_FILES, REGEX_PROJECT_NAME } = require('./
|
|
|
6
6
|
const {
|
|
7
7
|
NODEJS, JAVA,
|
|
8
8
|
HANA, APPROUTER, XSUAA, KIBANA, ENTERPRISE_MESSAGING,
|
|
9
|
-
MTA,
|
|
9
|
+
MTA, MULTITENANCY, PIPELINE,
|
|
10
10
|
TINY_SAMPLE, SAMPLE
|
|
11
11
|
} = OPTIONS
|
|
12
12
|
|
|
@@ -23,7 +23,7 @@ module.exports = class CDSGenerator {
|
|
|
23
23
|
default: '',
|
|
24
24
|
target: 'projectName',
|
|
25
25
|
validate: async (value) => {
|
|
26
|
-
try {
|
|
26
|
+
try {
|
|
27
27
|
cds.root = path.resolve(this.cwd, value || '.');
|
|
28
28
|
|
|
29
29
|
await this._validateProjectName(value);
|
|
@@ -74,7 +74,7 @@ module.exports = class CDSGenerator {
|
|
|
74
74
|
default: '',
|
|
75
75
|
choices: [
|
|
76
76
|
{ name: 'Cloud Foundry: MTA Deployment', value: MTA },
|
|
77
|
-
{ name: 'Kyma: Helm Deployment', value: HELM },
|
|
77
|
+
// { name: 'Kyma: Helm Deployment', value: HELM },
|
|
78
78
|
{ name: 'Multitenancy', value: MULTITENANCY },
|
|
79
79
|
{ name: 'CI/CD Pipeline Integration', value: PIPELINE },
|
|
80
80
|
],
|
|
@@ -182,7 +182,11 @@ module.exports = class CDSGenerator {
|
|
|
182
182
|
|
|
183
183
|
if (cds.cli.command === COMMAND_INIT) {
|
|
184
184
|
const relativeProjectPath = path.relative(this.cwd, cds.root)
|
|
185
|
-
|
|
185
|
+
let message = 'Successfully created project.'
|
|
186
|
+
if (relativeProjectPath) {
|
|
187
|
+
message = message + ` Continue with '${term.bold('cd ' + relativeProjectPath)}'.`
|
|
188
|
+
}
|
|
189
|
+
console.log('\n' + message)
|
|
186
190
|
} else {
|
|
187
191
|
console.log(`\nSuccessfully added features to your project.`)
|
|
188
192
|
}
|
|
@@ -219,6 +223,7 @@ module.exports = class CDSGenerator {
|
|
|
219
223
|
// Compat
|
|
220
224
|
if (facet === 'sample-tiny') facet = 'tiny-sample'
|
|
221
225
|
if (facet === 'kibana-logging') facet = 'kibana'
|
|
226
|
+
if (facet === 'postgresql') facet = 'postgres'
|
|
222
227
|
|
|
223
228
|
if (!templates.has(facet)) {
|
|
224
229
|
const template = await this._createTemplate(facet)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
2
|
const cds = require('../../../cds')
|
|
3
|
-
const {
|
|
3
|
+
const { read, write } = cds.utils
|
|
4
4
|
const { APPROUTER, HANA, KIBANA } = require('../../constants').OPTIONS
|
|
5
5
|
const mvn = require('../../util/mvn')
|
|
6
6
|
const { readProject } = require('../../util/projectReader')
|
|
@@ -17,11 +17,9 @@ const {
|
|
|
17
17
|
module.exports = class MultitenancyTemplate extends require('../templateBase') {
|
|
18
18
|
|
|
19
19
|
static hasFacet(env) {
|
|
20
|
-
// REVISIT: Check if this can be simplified
|
|
21
20
|
const { options } = cds.cli.options
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
exists(join('mtx', 'sidecar')) || false
|
|
21
|
+
// REVISIT: Check if this can be simplified
|
|
22
|
+
return options?.add?.has('mtx') || options?.add?.has('multitenancy') || !!env.requires?.multitenancy || false
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
getRelatedFacets() {
|
|
@@ -3,13 +3,13 @@ const cds = require('../../../cds')
|
|
|
3
3
|
const { read } = cds.utils
|
|
4
4
|
const { readProject } = require('../../util/projectReader')
|
|
5
5
|
const { mergeJSON, mergeYAML } = require('../../util/merge')
|
|
6
|
+
const mvn = require('../../util/mvn')
|
|
6
7
|
const { srvNode4, srvJava4, postgres, postgresDeployer } = require('../_merging/registry-mta')
|
|
7
8
|
|
|
8
9
|
module.exports = class PostgresTemplate extends require('../templateBase') {
|
|
9
10
|
|
|
10
11
|
async canRun() {
|
|
11
|
-
const { hasMta, hasHelm
|
|
12
|
-
if (isJava) throw `'cds add postgres' is not available for Java yet`
|
|
12
|
+
const { hasMta, hasHelm } = await readProject(this.options)
|
|
13
13
|
if (hasHelm && !hasMta) throw `'cds add postgres' is not available for Kyma yet`
|
|
14
14
|
return true
|
|
15
15
|
}
|
|
@@ -20,9 +20,10 @@ module.exports = class PostgresTemplate extends require('../templateBase') {
|
|
|
20
20
|
|
|
21
21
|
async run() {
|
|
22
22
|
const project = await readProject(this.options)
|
|
23
|
-
const { configFile } = project
|
|
23
|
+
const { configFile, isJava } = project
|
|
24
24
|
project.shortcut = !(await read(configFile)).cds?.requires?.db?.kind
|
|
25
25
|
await mergeJSON(configFile, join(__dirname, 'files', 'package.json.hbs'), project)
|
|
26
|
+
if (isJava) await mvn.add('postgresql')
|
|
26
27
|
await this.runDependentMerging()
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
-
const { exists } = require('../../cds').utils
|
|
3
|
-
const { PROJECT_TYPE } = require('../constants')
|
|
4
2
|
|
|
5
3
|
module.exports = class TemplateBase {
|
|
6
4
|
|
|
@@ -99,15 +97,4 @@ module.exports = class TemplateBase {
|
|
|
99
97
|
*/
|
|
100
98
|
async finalize() {
|
|
101
99
|
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Returns the project type
|
|
105
|
-
* @see PROJECT_TYPE
|
|
106
|
-
* @returns PROJECT_TYPE for current project
|
|
107
|
-
*/
|
|
108
|
-
getProjectType() {
|
|
109
|
-
if (exists('pom.xml')) return PROJECT_TYPE.java;
|
|
110
|
-
if (exists('package.json')) return PROJECT_TYPE.nodejs;
|
|
111
|
-
return PROJECT_TYPE.unknown;
|
|
112
|
-
}
|
|
113
100
|
}
|
|
@@ -83,7 +83,7 @@ module.exports = new class ProjectReader {
|
|
|
83
83
|
get appPath() { return env.folders.app ?? 'app' },
|
|
84
84
|
get appVersion() { return appVersion },
|
|
85
85
|
get appName() { return appName },
|
|
86
|
-
get cleanedAppName() { return appName.
|
|
86
|
+
get cleanedAppName() { return appName.replaceAll('_', '-') }, // Required when _ isn't allowed in the namespace
|
|
87
87
|
get appId() { return appId },
|
|
88
88
|
get appDescription() { return appDescription },
|
|
89
89
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-dk",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@sap/cds-dk",
|
|
9
|
-
"version": "7.
|
|
9
|
+
"version": "7.4.1",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@sap/cds": "^7",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"node_modules/@eslint/eslintrc": {
|
|
63
|
-
"version": "2.1.
|
|
63
|
+
"version": "2.1.3",
|
|
64
64
|
"license": "MIT",
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"ajv": "^6.12.4",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"node_modules/@eslint/js": {
|
|
84
|
-
"version": "8.
|
|
84
|
+
"version": "8.54.0",
|
|
85
85
|
"license": "MIT",
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
|
@@ -152,14 +152,6 @@
|
|
|
152
152
|
"url": "https://github.com/sponsors/sindresorhus"
|
|
153
153
|
}
|
|
154
154
|
},
|
|
155
|
-
"node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": {
|
|
156
|
-
"version": "6.3.1",
|
|
157
|
-
"license": "ISC",
|
|
158
|
-
"optional": true,
|
|
159
|
-
"bin": {
|
|
160
|
-
"semver": "bin/semver.js"
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
155
|
"node_modules/@nodelib/fs.scandir": {
|
|
164
156
|
"version": "2.1.5",
|
|
165
157
|
"license": "MIT",
|
|
@@ -211,12 +203,12 @@
|
|
|
211
203
|
}
|
|
212
204
|
},
|
|
213
205
|
"node_modules/@sap/cds": {
|
|
214
|
-
"version": "7.
|
|
206
|
+
"version": "7.4.2",
|
|
215
207
|
"license": "SEE LICENSE IN LICENSE",
|
|
216
208
|
"dependencies": {
|
|
217
209
|
"@sap/cds-compiler": "^4",
|
|
218
210
|
"@sap/cds-fiori": "^1",
|
|
219
|
-
"@sap/cds-foss": "^
|
|
211
|
+
"@sap/cds-foss": "^5.0.0"
|
|
220
212
|
},
|
|
221
213
|
"bin": {
|
|
222
214
|
"cds-deploy": "lib/dbs/cds-deploy.js",
|
|
@@ -227,7 +219,7 @@
|
|
|
227
219
|
}
|
|
228
220
|
},
|
|
229
221
|
"node_modules/@sap/cds-compiler": {
|
|
230
|
-
"version": "4.
|
|
222
|
+
"version": "4.4.4",
|
|
231
223
|
"license": "SEE LICENSE IN LICENSE",
|
|
232
224
|
"dependencies": {
|
|
233
225
|
"antlr4": "4.9.3"
|
|
@@ -242,7 +234,7 @@
|
|
|
242
234
|
}
|
|
243
235
|
},
|
|
244
236
|
"node_modules/@sap/cds-fiori": {
|
|
245
|
-
"version": "1.1
|
|
237
|
+
"version": "1.2.1",
|
|
246
238
|
"license": "SEE LICENSE IN LICENSE",
|
|
247
239
|
"peerDependencies": {
|
|
248
240
|
"@sap/cds": ">=7",
|
|
@@ -263,7 +255,7 @@
|
|
|
263
255
|
}
|
|
264
256
|
},
|
|
265
257
|
"node_modules/@sap/cds-mtxs": {
|
|
266
|
-
"version": "1.
|
|
258
|
+
"version": "1.13.1",
|
|
267
259
|
"license": "SEE LICENSE IN LICENSE",
|
|
268
260
|
"dependencies": {
|
|
269
261
|
"@sap/hdi-deploy": "^4",
|
|
@@ -274,29 +266,15 @@
|
|
|
274
266
|
"cds-mtx-migrate": "bin/cds-mtx-migrate.js"
|
|
275
267
|
}
|
|
276
268
|
},
|
|
277
|
-
"node_modules/@sap/cds/node_modules/@sap/cds-foss": {
|
|
278
|
-
"version": "4.0.2",
|
|
279
|
-
"license": "See LICENSE in LICENSE",
|
|
280
|
-
"dependencies": {
|
|
281
|
-
"big.js": "^6.1.1",
|
|
282
|
-
"generic-pool": "^3.8.2",
|
|
283
|
-
"uuid": "^9.0.0",
|
|
284
|
-
"xmlbuilder": "^15.1.1",
|
|
285
|
-
"yaml": "^2.2.2"
|
|
286
|
-
},
|
|
287
|
-
"engines": {
|
|
288
|
-
"node": ">=14"
|
|
289
|
-
}
|
|
290
|
-
},
|
|
291
269
|
"node_modules/@sap/eslint-plugin-cds": {
|
|
292
|
-
"version": "2.6.
|
|
270
|
+
"version": "2.6.4",
|
|
293
271
|
"license": "See LICENSE file",
|
|
294
272
|
"dependencies": {
|
|
295
273
|
"@sap/cds": ">=5.6.0",
|
|
296
274
|
"semver": "^7.3.4"
|
|
297
275
|
},
|
|
298
276
|
"engines": {
|
|
299
|
-
"node": ">=
|
|
277
|
+
"node": ">=18"
|
|
300
278
|
},
|
|
301
279
|
"peerDependencies": {
|
|
302
280
|
"eslint": ">=7"
|
|
@@ -615,7 +593,7 @@
|
|
|
615
593
|
}
|
|
616
594
|
},
|
|
617
595
|
"node_modules/acorn": {
|
|
618
|
-
"version": "8.
|
|
596
|
+
"version": "8.11.2",
|
|
619
597
|
"license": "MIT",
|
|
620
598
|
"bin": {
|
|
621
599
|
"acorn": "bin/acorn"
|
|
@@ -736,7 +714,7 @@
|
|
|
736
714
|
"license": "MIT"
|
|
737
715
|
},
|
|
738
716
|
"node_modules/axios": {
|
|
739
|
-
"version": "1.
|
|
717
|
+
"version": "1.6.2",
|
|
740
718
|
"license": "MIT",
|
|
741
719
|
"dependencies": {
|
|
742
720
|
"follow-redirects": "^1.15.0",
|
|
@@ -1131,13 +1109,13 @@
|
|
|
1131
1109
|
}
|
|
1132
1110
|
},
|
|
1133
1111
|
"node_modules/eslint": {
|
|
1134
|
-
"version": "8.
|
|
1112
|
+
"version": "8.54.0",
|
|
1135
1113
|
"license": "MIT",
|
|
1136
1114
|
"dependencies": {
|
|
1137
1115
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
1138
1116
|
"@eslint-community/regexpp": "^4.6.1",
|
|
1139
|
-
"@eslint/eslintrc": "^2.1.
|
|
1140
|
-
"@eslint/js": "8.
|
|
1117
|
+
"@eslint/eslintrc": "^2.1.3",
|
|
1118
|
+
"@eslint/js": "8.54.0",
|
|
1141
1119
|
"@humanwhocodes/config-array": "^0.11.13",
|
|
1142
1120
|
"@humanwhocodes/module-importer": "^1.0.1",
|
|
1143
1121
|
"@nodelib/fs.walk": "^1.2.8",
|
|
@@ -1396,7 +1374,7 @@
|
|
|
1396
1374
|
}
|
|
1397
1375
|
},
|
|
1398
1376
|
"node_modules/flat-cache": {
|
|
1399
|
-
"version": "3.
|
|
1377
|
+
"version": "3.2.0",
|
|
1400
1378
|
"license": "MIT",
|
|
1401
1379
|
"dependencies": {
|
|
1402
1380
|
"flatted": "^3.2.9",
|
|
@@ -1404,7 +1382,7 @@
|
|
|
1404
1382
|
"rimraf": "^3.0.2"
|
|
1405
1383
|
},
|
|
1406
1384
|
"engines": {
|
|
1407
|
-
"node": ">=12.0.0"
|
|
1385
|
+
"node": "^10.12.0 || >=12.0.0"
|
|
1408
1386
|
}
|
|
1409
1387
|
},
|
|
1410
1388
|
"node_modules/flatted": {
|
|
@@ -1691,7 +1669,7 @@
|
|
|
1691
1669
|
}
|
|
1692
1670
|
},
|
|
1693
1671
|
"node_modules/ignore": {
|
|
1694
|
-
"version": "5.
|
|
1672
|
+
"version": "5.3.0",
|
|
1695
1673
|
"license": "MIT",
|
|
1696
1674
|
"engines": {
|
|
1697
1675
|
"node": ">= 4"
|
|
@@ -2410,7 +2388,7 @@
|
|
|
2410
2388
|
"license": "MIT"
|
|
2411
2389
|
},
|
|
2412
2390
|
"node_modules/punycode": {
|
|
2413
|
-
"version": "2.3.
|
|
2391
|
+
"version": "2.3.1",
|
|
2414
2392
|
"license": "MIT",
|
|
2415
2393
|
"engines": {
|
|
2416
2394
|
"node": ">=6"
|
|
@@ -2951,17 +2929,6 @@
|
|
|
2951
2929
|
"node": ">= 0.4.0"
|
|
2952
2930
|
}
|
|
2953
2931
|
},
|
|
2954
|
-
"node_modules/uuid": {
|
|
2955
|
-
"version": "9.0.1",
|
|
2956
|
-
"funding": [
|
|
2957
|
-
"https://github.com/sponsors/broofa",
|
|
2958
|
-
"https://github.com/sponsors/ctavan"
|
|
2959
|
-
],
|
|
2960
|
-
"license": "MIT",
|
|
2961
|
-
"bin": {
|
|
2962
|
-
"uuid": "dist/bin/uuid"
|
|
2963
|
-
}
|
|
2964
|
-
},
|
|
2965
2932
|
"node_modules/vary": {
|
|
2966
2933
|
"version": "1.1.2",
|
|
2967
2934
|
"license": "MIT",
|
|
@@ -3045,7 +3012,7 @@
|
|
|
3045
3012
|
}
|
|
3046
3013
|
},
|
|
3047
3014
|
"node_modules/yaml": {
|
|
3048
|
-
"version": "2.3.
|
|
3015
|
+
"version": "2.3.4",
|
|
3049
3016
|
"license": "ISC",
|
|
3050
3017
|
"engines": {
|
|
3051
3018
|
"node": ">= 14"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-dk",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.1",
|
|
4
4
|
"description": "Command line client and development toolkit for the SAP Cloud Application Programming Model",
|
|
5
5
|
"homepage": "https://cap.cloud.sap/",
|
|
6
6
|
"keywords": [
|
|
@@ -40,5 +40,14 @@
|
|
|
40
40
|
"npm-shrinkwrap.json",
|
|
41
41
|
"LICENSE"
|
|
42
42
|
],
|
|
43
|
+
"overrides": {
|
|
44
|
+
"sqlite3": {
|
|
45
|
+
"@mapbox/node-pre-gyp": {
|
|
46
|
+
"make-dir": {
|
|
47
|
+
"semver": "^7"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
43
52
|
"_hasShrinkwrap": true
|
|
44
53
|
}
|