@sap/cds-dk 4.8.0 → 4.9.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/CHANGELOG.md +57 -0
- package/bin/activate.js +8 -7
- package/bin/bind.js +12 -12
- package/bin/build/all.js +3 -5
- package/bin/build/index.js +1 -1
- package/bin/cds.js +1 -1
- package/bin/deploy/index.js +7 -1
- package/bin/deploy/to-hana.js +5 -4
- package/bin/deploy/to-sqlite.js +2 -1
- package/bin/extend.js +5 -5
- package/bin/help.js +1 -0
- package/bin/import.js +45 -31
- package/bin/login.js +5 -6
- package/bin/logout.js +2 -2
- package/bin/parse.js +19 -0
- package/lib/bind/bindingUtil.js +47 -50
- package/lib/bind/cfKeyProvider.js +9 -17
- package/lib/bind/userCdsrcJsonStorageProvider.js +1 -0
- package/lib/client/activate.js +3 -2
- package/lib/client/auth_manager.js +1 -0
- package/lib/client/extend.js +6 -6
- package/lib/client/helper/fs_helper.js +8 -8
- package/lib/client/settings_manager.js +12 -9
- package/lib/compile/openapi/csdl2openapi.js +213 -165
- package/lib/compile/openapi/index.js +1 -2
- package/lib/compile/to-xsuaa.js +1 -1
- package/lib/import/index.js +22 -15
- package/lib/import/message.js +3 -1
- package/lib/import/utils/MetadataConverter.js +1 -1
- package/lib/import/v2parser.js +112 -56
- package/lib/import/v4parser.js +152 -99
- package/lib/init/constants.js +6 -2
- package/lib/init/index.js +3 -2
- package/lib/init/template/_merging/existences.js +80 -4
- package/lib/init/template/approuter/files/cds.cdsrc.json +7 -0
- package/lib/init/template/approuter/files/cds.cdsrc.json.hbs +9 -0
- package/lib/init/template/approuter/files/cds.package.json +9 -0
- package/lib/init/template/approuter/files/cds.package.json.hbs +11 -0
- package/lib/init/template/approuter/files/index.html +1 -0
- package/lib/init/template/approuter/files/mta.yaml.hbs +35 -21
- package/lib/init/template/approuter/files/package.json +3 -0
- package/lib/init/template/approuter/files/xs-app.json.hbs +19 -0
- package/lib/init/template/approuter/index.js +47 -18
- package/lib/init/template/auditlog/index.js +5 -5
- package/lib/init/template/hana/files/java/cdsrc.json.hbs +7 -0
- package/lib/init/template/hana/files/java/profile.cdsrc.json.hbs +12 -0
- package/lib/init/template/hana/files/mta.yaml.hbs +10 -17
- package/lib/init/template/hana/files/nodejs/cds.package.json.hbs +9 -0
- package/lib/init/template/hana/files/nodejs/cds.profile.package.json.hbs +14 -0
- package/lib/init/template/hana/files/nodejs/dependencies.package.json +1 -1
- package/lib/init/template/hana/index.js +59 -85
- package/lib/init/template/java/index.js +5 -2
- package/lib/init/template/kibana-logging/files/cds.package.json +7 -0
- package/lib/init/template/kibana-logging/files/cds.profile.package.json.hbs +9 -0
- package/lib/init/template/kibana-logging/files/mta.yaml.hbs +13 -0
- package/lib/init/template/kibana-logging/index.js +64 -0
- package/lib/init/template/mta/files/mta.yaml.hbs +3 -8
- package/lib/init/template/mta/index.js +8 -2
- package/lib/init/template/mtx/files/cds.package.json +0 -12
- package/lib/init/template/mtx/files/cds.package.json.hbs +14 -0
- package/lib/init/template/mtx/files/java/.cdsrc.json +17 -0
- package/lib/init/template/mtx/files/java/package.json +43 -0
- package/lib/init/template/mtx/files/java/server.js +30 -0
- package/lib/init/template/mtx/files/mta.yaml.hbs +6 -6
- package/lib/init/template/mtx/index.js +41 -22
- package/lib/init/template/templateBase.js +4 -1
- package/lib/init/template/xsuaa/files/cds.cdsrc.json +7 -0
- package/lib/init/template/xsuaa/files/cds.cdsrc.json.hbs +9 -0
- package/lib/init/template/xsuaa/files/cds.package.json +1 -1
- package/lib/init/template/xsuaa/files/cds.package.json.hbs +11 -0
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +2 -2
- package/lib/init/template/xsuaa/index.js +43 -27
- package/lib/init/types.d.ts +43 -19
- package/lib/init/util/fsUtil.js +15 -4
- package/lib/init/util/projectReader.js +21 -18
- package/lib/init/util/templateUtil.js +78 -28
- package/lib/util/exec.js +2 -2
- package/lib/watch/livereload-server.js +3 -0
- package/lib/watch/node-watch.js +8 -1
- package/npm-shrinkwrap.json +942 -1259
- package/package.json +3 -3
- package/lib/init/template/approuter/files/xs-app.json +0 -8
- package/lib/init/template/nodejs/files/.vscode/settings.json +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,62 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
8
8
|
|
|
9
|
+
## Version 4.9.0 - 2022-03-28
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `cds parse` as convenient shortcut to `cds compile --flavor parsed`.
|
|
14
|
+
- `cds compile --to openapi` uses value of annotation `@Common.Label` on entities, actions, and functions for operation tags, diagram includes non-primitive action and function import parameters.
|
|
15
|
+
- `cds add` now accepts `--for <profile>` argument to create Node,js project configuration for a given profile
|
|
16
|
+
- `cds add approuter` allows for serving your application’s UI using SAP approuter.
|
|
17
|
+
- `cds add kibana-logging` adds Kibana-friendly logging in a more convenient way than having to manually alter the package.json.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- `cds init` does not create `VS Code` file exclusions anymore, so that `.vscode/` and `.gitignore` are visible by default, allowing easier editing of these files.
|
|
22
|
+
- `cds init` reports Maven archetype version in console if called with `--add java`.
|
|
23
|
+
- `cds init` uses latest Maven Java archetype version 1.22.2 for creating Java projects.
|
|
24
|
+
- `cds import` modified documentation for namespace option.
|
|
25
|
+
- `cds import` does not create bound function imports key parameters in CSN for OData V2.
|
|
26
|
+
- `cds import` now when `--keep-namespace` option is not given validates the file name and then converts it to complier supported format as service name .
|
|
27
|
+
- add new methods from `FsUtil` to typescript interface.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- `cds compile --to openapi` now correctly treats `null` and the empty string as function parameters.
|
|
31
|
+
- `cds bind --exec` no command output (STDOUT) displayed on Windows.
|
|
32
|
+
- `cds watch` now gracefully shuts down the live reload server before exiting
|
|
33
|
+
- `cds import` now generates correct csn for both OData V2 and V4 EDMX files where the EntityType has a BaseType entry.
|
|
34
|
+
- `cds import` now throws an error in case of missing Association Sets.
|
|
35
|
+
- `cds import` bug fixed for `--force` flag. Now overwrites the correct file content.
|
|
36
|
+
- `cds import` fix will no longer capture unwanted annotations in the CSN for OData V4.
|
|
37
|
+
- `cds import` now support annotations for properties of type `Type Definition`
|
|
38
|
+
- `cds import` fix for supporting valid datatypes in unbounded function imports for OData V4.
|
|
39
|
+
- `cds import` bug fixed for missing data imports for parameters with entity type not mapped to an entity set.
|
|
40
|
+
- `cds import` now supports properties with complex type for OData V4.
|
|
41
|
+
- `cds import` fix will now throw error if the key property of an entity is of type `Collection` for both OData V2 and V4 edmx.
|
|
42
|
+
- `cds bind --to hana` provides more comprehensive error message in case Cloud Foundry `org` or `space` are not set.
|
|
43
|
+
|
|
44
|
+
## Version 4.8.2 - 2022-03-07
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- `cds import` can now capture the data for any given `EntityContainer Name` for OData V4. Earlier it only worked when the name was `EntityContainer`.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- `cds init` uses latest Maven Java archetype version 1.22.1 for creating Java projects.
|
|
53
|
+
|
|
54
|
+
## Version 4.8.1 - 2022-02-15
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- `cds init` uses latest Maven Java archetype version `1.22.0` for creating Java projects.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- Bump `follow-redirects` package to 1.14.8 (CVE-2022-0536)
|
|
63
|
+
- `cds bind --exec` no command output (STDOUT) displayed on Windows.
|
|
64
|
+
|
|
9
65
|
## Version 4.8.0 - 2022-01-28
|
|
10
66
|
|
|
11
67
|
### Added
|
|
@@ -17,6 +73,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
|
17
73
|
|
|
18
74
|
- The forked package `@mendix/sqlite3` is now used instead of `sqlite3` to overcome CVE-2021-32804. No code changes in applications are needed, as the new package installed by `npm` with the same name `sqlite3`.
|
|
19
75
|
- [beta] The templating for `cds init` and `cds add` has been rewritten from scratch. This will allow for some new, more complex commands, such as `cds add mtx` or `cds add xsuaa`.
|
|
76
|
+
- Use `cds bind` during `cds deploy` to store connection information in file `.cdsrc-private.json`.
|
|
20
77
|
|
|
21
78
|
### Fixed
|
|
22
79
|
|
package/bin/activate.js
CHANGED
|
@@ -8,7 +8,7 @@ module.exports = Object.assign(activate, {
|
|
|
8
8
|
*cds activate* [ <extension-project-directory> ]
|
|
9
9
|
|
|
10
10
|
Activate an extension project.
|
|
11
|
-
|
|
11
|
+
By default, the current working directory is used as project directory.
|
|
12
12
|
|
|
13
13
|
To facilitate running this multiple times against the same app, refer to the *cds login* command.
|
|
14
14
|
|
|
@@ -16,16 +16,17 @@ module.exports = Object.assign(activate, {
|
|
|
16
16
|
# OPTIONS
|
|
17
17
|
|
|
18
18
|
*--to* <url>
|
|
19
|
-
Specify the URL of the extension project that you want to activate.
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
Specify the URL of the extensible SaaS app. By default, it's determined from project settings.
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
*-s* | *--subdomain* <tenant-subdomain>
|
|
23
|
+
|
|
24
|
+
Specify your tenant's subdomain. By default, it's determined from project settings.
|
|
24
25
|
|
|
25
26
|
*-p* | *--passcode* <passcode>
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
Also see cds login --help or https://cap.cloud.sap/docs/guides/extensibility
|
|
28
|
+
Tenant-specific passcode for authentication.
|
|
29
|
+
Also see cds login --help or https://cap.cloud.sap/docs/guides/extensibility/#save-an-authentication-token-for-a-simplified-workflow
|
|
29
30
|
|
|
30
31
|
*-u* | *--username* <name>
|
|
31
32
|
|
|
@@ -37,7 +38,7 @@ module.exports = Object.assign(activate, {
|
|
|
37
38
|
|
|
38
39
|
*--undeploy*
|
|
39
40
|
|
|
40
|
-
Undeploy a previously deployed extension.
|
|
41
|
+
Undeploy a previously deployed extension, e.g. to remove a renamed or otherwise obsolete extension.
|
|
41
42
|
|
|
42
43
|
*--sync*
|
|
43
44
|
|
package/bin/bind.js
CHANGED
|
@@ -60,7 +60,7 @@ const { determineKinds, getRequiresNameFromKind, execAndExit, checkIsJavaProject
|
|
|
60
60
|
|
|
61
61
|
const VCAP_LABEL_PLACEHOLDER = '<replace with service label>';
|
|
62
62
|
|
|
63
|
-
async function cds_bind(args, options) {
|
|
63
|
+
async function cds_bind(args, options, logger = LOG) {
|
|
64
64
|
options.profile = parseProfile(options.profile);
|
|
65
65
|
setProfile(options.profile);
|
|
66
66
|
|
|
@@ -92,7 +92,7 @@ async function cds_bind(args, options) {
|
|
|
92
92
|
throw new Error(`The option '--kind' cannot be specified together with multiple targets ('--to') services. Use one service per call or omit the '--kind' option.`);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
const spinner = new Spinner(
|
|
95
|
+
const spinner = new Spinner(logger);
|
|
96
96
|
|
|
97
97
|
let on;
|
|
98
98
|
if (options.on === 'k8s' || options.on === 'kubernetes') {
|
|
@@ -105,7 +105,7 @@ async function cds_bind(args, options) {
|
|
|
105
105
|
|
|
106
106
|
const onText = { 'cf': 'Cloud Foundry', 'k8s': 'Kubernetes' }[on];
|
|
107
107
|
const resolvedServices = await spinner.run(`Retrieving data from ${onText}...`, async () => { // NOSONAR
|
|
108
|
-
return await Promise.all(
|
|
108
|
+
return await Promise.all(targets.map(async target => {
|
|
109
109
|
|
|
110
110
|
let binding;
|
|
111
111
|
if (on === 'k8s') {
|
|
@@ -126,9 +126,9 @@ async function cds_bind(args, options) {
|
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
if (options.kind) {
|
|
129
|
-
resolvedServices.forEach(
|
|
129
|
+
resolvedServices.forEach(service => service.kind = options.kind);
|
|
130
130
|
} else {
|
|
131
|
-
determineKinds(resolvedServices);
|
|
131
|
+
determineKinds(resolvedServices, LOG);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
for (const resolvedService of resolvedServices) {
|
|
@@ -152,11 +152,11 @@ async function cds_bind(args, options) {
|
|
|
152
152
|
const kindText = kind && `with kind ${highlight(kind)}`;
|
|
153
153
|
const nameText = !isJavaProject && highlight(name);
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
logger.log(['Binding', nameText, 'to', platformText(binding), bindingText(binding, highlight), kindText].filter(t => t).join(' '));
|
|
156
156
|
|
|
157
157
|
if (isJavaProject && !hasVcapLabel(binding) && !hasVcapLabel(env.requires[resolvedService.name]) && !(kind && hasVcapLabel(env.requires[kind]))) {
|
|
158
158
|
resolvedService.vcap = { label: VCAP_LABEL_PLACEHOLDER };
|
|
159
|
-
|
|
159
|
+
logger.log(`${info('INFO:')} Please add a "vcap.label" property to the binding for consumption in CAP Java projects`);
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -165,18 +165,18 @@ async function cds_bind(args, options) {
|
|
|
165
165
|
|
|
166
166
|
await userCdsrcJsonStorageProvider.storeServices(resolvedServices, {
|
|
167
167
|
...options,
|
|
168
|
-
logger
|
|
168
|
+
logger
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
logger.log();
|
|
172
|
+
logger.log(`${info('TIP:')} Run with cloud bindings: ${bold(runCmd(options, isJavaProject))}`);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
async function cds_bind_exec(command) { // eslint-disable-lint
|
|
176
176
|
const cds = require('@sap/cds/lib');
|
|
177
177
|
const env = cds.env.for('cds', process.cwd());
|
|
178
178
|
env._emulate_vcap_services();
|
|
179
|
-
await require('../lib/bind/bindingResolver').applyTo({env, output: 'info'});
|
|
179
|
+
await require('../lib/bind/bindingResolver').applyTo({ env, output: 'info' });
|
|
180
180
|
execAndExit(...command);
|
|
181
181
|
}
|
|
182
182
|
|
|
@@ -184,7 +184,7 @@ function hasVcapLabel(service) {
|
|
|
184
184
|
return service && service.vcap && service.vcap.label && service.vcap.label != VCAP_LABEL_PLACEHOLDER;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
function runCmd({profile}, isJavaProject) {
|
|
187
|
+
function runCmd({ profile }, isJavaProject) {
|
|
188
188
|
if (isJavaProject) {
|
|
189
189
|
const p = profile === 'hybrid' ? '' : ` --profile ${profile}`;
|
|
190
190
|
return `cds bind exec${p} mvn spring-boot:run`;
|
package/bin/build/all.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const _cds = require('@sap/cds/lib')
|
|
2
|
-
|
|
3
1
|
module.exports = Object.assign(build, {
|
|
4
2
|
options: ['--project', '--for', '--use', '--src', '--dest', '--options-model'],
|
|
5
3
|
flags: ['--clean'],
|
|
@@ -34,8 +32,8 @@ module.exports = Object.assign(build, {
|
|
|
34
32
|
|
|
35
33
|
*-o* | *--dest* <folder>
|
|
36
34
|
|
|
37
|
-
writes output to the given folder
|
|
38
|
-
|
|
35
|
+
writes output to the given folder. The folder is resolved based on "<project>/<cds.env.build.target>".
|
|
36
|
+
|
|
39
37
|
|
|
40
38
|
*--options-model*
|
|
41
39
|
|
|
@@ -68,7 +66,7 @@ function build([project], options = {}, /* for unit tests only: */ _env = null)
|
|
|
68
66
|
}
|
|
69
67
|
|
|
70
68
|
try {
|
|
71
|
-
return
|
|
69
|
+
return require('@sap/cds').build.build(options, _env)
|
|
72
70
|
} catch (error) {
|
|
73
71
|
return Promise.reject(error.message)
|
|
74
72
|
}
|
package/bin/build/index.js
CHANGED
|
@@ -22,7 +22,7 @@ module.exports = Object.assign(build, {
|
|
|
22
22
|
*--use* <qualified node module name>
|
|
23
23
|
|
|
24
24
|
Fully qualified name of the build task that is applied to the source folder.
|
|
25
|
-
For example, "@sap/cds/
|
|
25
|
+
For example, "@sap/cds/build/hana" represents the fully qualified name of the "hana" build task.
|
|
26
26
|
The module folder can be defined using option "--src", a default is used otherwise.
|
|
27
27
|
|
|
28
28
|
*-s* | *--src* <folder>
|
package/bin/cds.js
CHANGED
|
@@ -8,6 +8,7 @@ const cli = { //NOSONAR
|
|
|
8
8
|
y: 'bind',
|
|
9
9
|
m: 'import',
|
|
10
10
|
c: 'compile',
|
|
11
|
+
p: 'parse',
|
|
11
12
|
s: 'serve',
|
|
12
13
|
w: 'watch',
|
|
13
14
|
e: 'env',
|
|
@@ -130,4 +131,3 @@ else { // TODO compat to cds 3 remove after a while.
|
|
|
130
131
|
if (!module.parent) module.exports()
|
|
131
132
|
|
|
132
133
|
/* eslint no-console:off */
|
|
133
|
-
|
package/bin/deploy/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module.exports = Object.assign(deploy, {
|
|
2
|
-
options: ['--to', '--tunnel-address', '--vcap-file'], flags: [ '--no-save', '--auto-undeploy', '--dry', '--with-mocks' ],
|
|
2
|
+
options: ['--to', '--tunnel-address', '--vcap-file'], flags: [ '--no-save', '--auto-undeploy', '--dry', '--with-mocks', '--bind' ],
|
|
3
3
|
shortcuts: ['-2'],
|
|
4
4
|
help: `
|
|
5
5
|
# SYNOPSIS
|
|
@@ -47,6 +47,12 @@ module.exports = Object.assign(deploy, {
|
|
|
47
47
|
creating new credentials. File must be in *default-env.json* format, with a root
|
|
48
48
|
node *VCAP_SERVICES*.
|
|
49
49
|
|
|
50
|
+
*--bind* (beta feature, only in combination with *--to hana*)
|
|
51
|
+
|
|
52
|
+
Use *cds bind* to connect the created service after deployment.
|
|
53
|
+
This will no longer create default-env.json files. Instead, cds bind is used to
|
|
54
|
+
create and store connection information in file *.cdsrc-private.json*.
|
|
55
|
+
|
|
50
56
|
# EXAMPLES
|
|
51
57
|
cds deploy --to sqlite:db
|
|
52
58
|
cds deploy --to hana:myService --auto-undeploy
|
package/bin/deploy/to-hana.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
const {join} = require('path')
|
|
1
|
+
const { join } = require('path');
|
|
2
2
|
|
|
3
3
|
exports.deploy = (_model, _db, options) => {
|
|
4
4
|
// locate deployer relative to already located sap/cds -> local cds takes precedence
|
|
5
|
-
const cdsHome = require('@sap/cds').home
|
|
6
|
-
const deployer = require(join(cdsHome, 'bin/deploy/to-hana'))
|
|
5
|
+
const cdsHome = require('@sap/cds').home;
|
|
6
|
+
const deployer = require(join(cdsHome, 'bin/deploy/to-hana'));
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const bind = require('../bind');
|
|
9
|
+
return deployer.deploy(_model, _db, options, options.bind ? bind : null);
|
|
9
10
|
}
|
package/bin/deploy/to-sqlite.js
CHANGED
|
@@ -2,7 +2,8 @@ exports.deploy = function deploy_to_sqlite (_model, _db, options) {
|
|
|
2
2
|
const cds = require('@sap/cds/lib')
|
|
3
3
|
const {to:_dbrl} = options
|
|
4
4
|
const conf = cds.env.requires.db || {}
|
|
5
|
-
const
|
|
5
|
+
const fts = cds.env.features.folders
|
|
6
|
+
const model = _model || conf.model || cds.resolve(!fts ? '*' : ['*',fts], false)
|
|
6
7
|
const file = _database4 (_db, _dbrl, conf)
|
|
7
8
|
const dialect = _dbrl && _dbrl.match(/^(\w+)/) && RegExp.$1
|
|
8
9
|
if (dialect) options.dialect = dialect === 'sql' ? 'plain' : dialect
|
package/bin/extend.js
CHANGED
|
@@ -7,8 +7,8 @@ module.exports = Object.assign(extend, {
|
|
|
7
7
|
|
|
8
8
|
*cds extend* <app-url>
|
|
9
9
|
|
|
10
|
-
Create an extension project from an app
|
|
11
|
-
Obtain the URL from the SaaS application
|
|
10
|
+
Create an extension project from an extensible SaaS app.
|
|
11
|
+
Obtain the app URL from the SaaS application provider.
|
|
12
12
|
|
|
13
13
|
To facilitate running this multiple times against the same app, refer to the *cds login* command.
|
|
14
14
|
|
|
@@ -16,15 +16,15 @@ module.exports = Object.assign(extend, {
|
|
|
16
16
|
|
|
17
17
|
*-d* | *--directory* <project-extension-directory>
|
|
18
18
|
|
|
19
|
-
Specify the target directory of your extension project.
|
|
19
|
+
Specify the target directory of your extension project. By default, the current working directory is used.
|
|
20
20
|
|
|
21
21
|
*-s* | *--subdomain* <tenant-subdomain>
|
|
22
22
|
|
|
23
|
-
Specify
|
|
23
|
+
Specify your tenant's subdomain. By default, it's determined from the app URL.
|
|
24
24
|
|
|
25
25
|
*-p* | *--passcode* <passcode>
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Tenant-specific passcode for authentication.
|
|
28
28
|
|
|
29
29
|
*-u* | *--username* <name>
|
|
30
30
|
|
package/bin/help.js
CHANGED
|
@@ -13,6 +13,7 @@ module.exports = exports = Object.assign (help, {help:`
|
|
|
13
13
|
*y* | *bind* [beta] bind a service to a hana instance
|
|
14
14
|
*m* | *import* add models from external sources
|
|
15
15
|
*c* | *compile* compile cds models to different outputs
|
|
16
|
+
*p* | *parse* parses given cds models
|
|
16
17
|
*s* | *serve* run your services in local server
|
|
17
18
|
*w* | *watch* run and restart on file changes
|
|
18
19
|
*r* | *repl* read-eval-event loop
|
package/bin/import.js
CHANGED
|
@@ -44,11 +44,11 @@ module.exports = Object.assign(_import, {
|
|
|
44
44
|
*-f | --force*
|
|
45
45
|
Forcefully overwrites the contents in the CDS file and updates the checksum
|
|
46
46
|
|
|
47
|
-
*-ns | --include-namespaces <string_of_namespaces> or*
|
|
47
|
+
*-ns | --include-namespaces <string_of_namespaces> or* "\x2A"
|
|
48
48
|
Imports only entities matching to the given list of namespaces.
|
|
49
|
+
For OData V2 attributes with the namespace "sap" & "m" are captured by default.
|
|
49
50
|
|
|
50
51
|
|
|
51
|
-
|
|
52
52
|
|
|
53
53
|
# EXAMPLES
|
|
54
54
|
|
|
@@ -56,7 +56,7 @@ module.exports = Object.assign(_import, {
|
|
|
56
56
|
cds import - ~/Downloads/API_BUSINESS_PARTNER.edmx
|
|
57
57
|
cds import ~/Downloads/API_BUSINESS_PARTNER.edmx --as cds
|
|
58
58
|
cds import ~/Downloads/API_BUSINESS_PARTNER.edmx --include-namespaces "sap,c4c"
|
|
59
|
-
cds import ~/Downloads/API_BUSINESS_PARTNER.edmx --include-namespaces "
|
|
59
|
+
cds import ~/Downloads/API_BUSINESS_PARTNER.edmx --include-namespaces "\x2A"
|
|
60
60
|
|
|
61
61
|
`})
|
|
62
62
|
const cds = require('@sap/cds/lib')
|
|
@@ -109,37 +109,51 @@ async function _import(file, { out, dry, into, as,
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
async function _generateChecksumValidate(dest, output, force) {
|
|
112
|
-
let
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
let fileExists = await exists(dest);
|
|
113
|
+
|
|
114
|
+
// force flag disabled and cds file already exists, then throw error
|
|
115
|
+
if (!force && fileExists) {
|
|
116
|
+
throw new Error(messages.FILE_MODIFIED);
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return output;
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
throw new Error(messages.FILE_MODIFIED);
|
|
140
|
-
}
|
|
118
|
+
|
|
119
|
+
const currentChecksum = md5(output);
|
|
120
|
+
let existingFileContent, existingFileContentWithoutChecksum;
|
|
121
|
+
let existingFileContentChecksum, existingChecksumValue;
|
|
122
|
+
|
|
123
|
+
if (fileExists) {
|
|
124
|
+
existingFileContent = await read(dest, "utf-8");
|
|
125
|
+
const checksumStartIndex = existingFileContent.indexOf(`/* checksum : `);
|
|
126
|
+
const checksumEndIndex = existingFileContent.indexOf(" */");
|
|
127
|
+
|
|
128
|
+
if (checksumStartIndex >= 0) {
|
|
129
|
+
existingFileContentWithoutChecksum = existingFileContent.substring(
|
|
130
|
+
checksumEndIndex + 4
|
|
131
|
+
);
|
|
132
|
+
existingChecksumValue = existingFileContent.substring(
|
|
133
|
+
checksumStartIndex + 14, checksumEndIndex
|
|
134
|
+
);
|
|
135
|
+
existingFileContentChecksum = md5(existingFileContentWithoutChecksum);
|
|
141
136
|
}
|
|
142
137
|
}
|
|
138
|
+
|
|
139
|
+
// if force flag enbabled
|
|
140
|
+
if (force) {
|
|
141
|
+
// current and existing file content are same, and the existing
|
|
142
|
+
// checksum is not modified, then return the existing file content
|
|
143
|
+
if (currentChecksum == existingFileContentChecksum &&
|
|
144
|
+
currentChecksum == existingChecksumValue) {
|
|
145
|
+
return existingFileContent;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/*
|
|
149
|
+
* 1. current and existing checksum are different.
|
|
150
|
+
* 2. checksum is missing in the existing file:
|
|
151
|
+
* a. existing and current file content are same.
|
|
152
|
+
* b. existing and current file content are different.
|
|
153
|
+
* 3. cds file doesn't exist.
|
|
154
|
+
* 4. checksum of the existing file is modified.
|
|
155
|
+
*/
|
|
156
|
+
return "/* checksum : " + currentChecksum + " */\n" + output;
|
|
143
157
|
}
|
|
144
158
|
|
|
145
159
|
async function _getResult(output, service, as, dest, force) {
|
package/bin/login.js
CHANGED
|
@@ -58,19 +58,18 @@ module.exports = Object.assign(login, {
|
|
|
58
58
|
|
|
59
59
|
*-s* | *--subdomain* <tenant-subdomain>
|
|
60
60
|
|
|
61
|
-
The subdomain to log in to.
|
|
62
|
-
|
|
63
|
-
interpreting its output by reference to the <app-url>.
|
|
61
|
+
The subdomain to log in to. By default, it's determined from project settings.
|
|
62
|
+
If no such setting is saved, the CF client is invoked to determine the respective subdomain.
|
|
64
63
|
|
|
65
64
|
*-d* | *--directory* <extension-project-directory>
|
|
66
65
|
|
|
67
66
|
The extension-project folder (relevant for loading and saving settings).
|
|
68
|
-
If omitted,
|
|
69
|
-
directory will be used.
|
|
67
|
+
If omitted, either an existing subdirectory named as the subdomain or the current
|
|
68
|
+
working directory will be used.
|
|
70
69
|
|
|
71
70
|
*-p* | *--passcode* <passcode>
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
Tenant-specific passcode for authentication.
|
|
74
73
|
|
|
75
74
|
*-c* | *--clientid* <clientid>
|
|
76
75
|
|
package/bin/logout.js
CHANGED
|
@@ -33,11 +33,11 @@ module.exports = Object.assign(logout, {
|
|
|
33
33
|
|
|
34
34
|
*-l* | *--url* <app-url>
|
|
35
35
|
|
|
36
|
-
The <app-url> to logout from.
|
|
36
|
+
The <app-url> to logout from. By default, it's determined from project settings.
|
|
37
37
|
|
|
38
38
|
*-s* | *--subdomain* <subdomain>
|
|
39
39
|
|
|
40
|
-
The subdomain to logout from.
|
|
40
|
+
The subdomain to logout from. By default, it's determined from project settings.
|
|
41
41
|
|
|
42
42
|
*--delete-settings*
|
|
43
43
|
|
package/bin/parse.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const compile = require('./compile')
|
|
2
|
+
module.exports = Object.assign (
|
|
3
|
+
cds_parse, compile, {help: `
|
|
4
|
+
# SYNOPSIS
|
|
5
|
+
|
|
6
|
+
*cds parse* ...
|
|
7
|
+
|
|
8
|
+
Convenient shortcut for 'cds compile --flavor parsed'.
|
|
9
|
+
|
|
10
|
+
# OPTIONS
|
|
11
|
+
|
|
12
|
+
- see _cds help compile_
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
`})
|
|
16
|
+
|
|
17
|
+
function cds_parse (projects, options) {
|
|
18
|
+
return compile (projects,{ flavor:'parsed', ...options })
|
|
19
|
+
}
|
package/lib/bind/bindingUtil.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const IS_WIN = os.platform() === 'win32';
|
|
4
|
+
|
|
1
5
|
const KindToRequiresNameMap = {
|
|
2
6
|
xsuaa: 'uaa',
|
|
7
|
+
'xsuaa-auth': 'uaa',
|
|
8
|
+
'hana-cloud': 'db',
|
|
3
9
|
hana: 'db',
|
|
4
10
|
destinations: 'destinations',
|
|
5
11
|
connectivity: 'connectivity',
|
|
@@ -10,6 +16,11 @@ const KindToRequiresNameMap = {
|
|
|
10
16
|
'enterprise-messaging-shared': 'messaging'
|
|
11
17
|
}
|
|
12
18
|
|
|
19
|
+
const PreferredKinds = [
|
|
20
|
+
'hana-cloud',
|
|
21
|
+
'xsuaa'
|
|
22
|
+
];
|
|
23
|
+
|
|
13
24
|
function getRequiresNameFromKind(service, kind) {
|
|
14
25
|
const requiresName = KindToRequiresNameMap[kind];
|
|
15
26
|
if (!requiresName) throw new Error(`Unknown CDS service name for service "${service}". Please specify as argument for "cds bind".`)
|
|
@@ -21,68 +32,54 @@ function getRequiresNameFromKind(service, kind) {
|
|
|
21
32
|
* information in the configuration.
|
|
22
33
|
*/
|
|
23
34
|
function determineKinds(services) {
|
|
24
|
-
|
|
35
|
+
const vcapServices = {}
|
|
25
36
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
37
|
+
// Build VCAP_SERVICES
|
|
38
|
+
for (const service of services) {
|
|
39
|
+
service.kindCandidates = [ ]
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const service = services[index];
|
|
34
|
-
service.kindCandidates = [ ]
|
|
35
|
-
service.nameCandidates = [ ]
|
|
41
|
+
const { label, name, tags } = service.binding && service.binding.vcap || {};
|
|
42
|
+
if (!label) continue;
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
if (!vcapServices[label]) vcapServices[label] = [];
|
|
45
|
+
vcapServices[label].push({ credentials: { dummy: 'dummy' }, label, name, tags, service });
|
|
46
|
+
}
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
vcapServices[label].push({ credentials: { binding: { index } }, label, name, tags });
|
|
42
|
-
}
|
|
48
|
+
// Auto configure services based on VCAP_SERVICES
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const VCAP_SERVICES = process.env.VCAP_SERVICES;
|
|
47
|
-
try {
|
|
48
|
-
process.env.VCAP_SERVICES = JSON.stringify(vcapServices);
|
|
49
|
-
const env = cds.env.for('cds', '.');
|
|
50
|
-
|
|
51
|
-
// Extract "kind" from auto configured services
|
|
52
|
-
for (const kind of Object.keys(env.requires)) {
|
|
53
|
-
const requireService = env.requires[kind];
|
|
54
|
-
const superKind = requireService.kind;
|
|
55
|
-
const index = getIndex(requireService);
|
|
56
|
-
if (!Number.isInteger(index)) continue;
|
|
57
|
-
|
|
58
|
-
const superRequireService = env.requires[superKind];
|
|
59
|
-
if (superRequireService) {
|
|
60
|
-
const superIndex = getIndex(superRequireService);
|
|
61
|
-
if (index === superIndex) continue;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
services[index].kindCandidates.push(kind);
|
|
65
|
-
}
|
|
50
|
+
const cds = require('@sap/cds/lib');
|
|
51
|
+
const env = cds.env.for('cds', process.cwd());
|
|
66
52
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
service.kind = service.kindCandidates[0];
|
|
71
|
-
}
|
|
53
|
+
if (!env._find_credentials_for_required_service) {
|
|
54
|
+
throwError `Please provide a service kind or update @sap/cds version to use the kind detection.`;
|
|
55
|
+
}
|
|
72
56
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
57
|
+
const requires = env.requires.kinds || {};
|
|
58
|
+
for (const kind of Object.keys(requires)) {
|
|
59
|
+
const requireService = requires[kind];
|
|
60
|
+
const vcapService = env._find_credentials_for_required_service(kind, requireService, vcapServices);
|
|
61
|
+
if (!vcapService) continue;
|
|
62
|
+
if (!Object.values(requires).find( require => require !== requireService && require.kind == kind ))
|
|
63
|
+
vcapService.service.kindCandidates.push(kind);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check if one "kind" per service was found
|
|
67
|
+
for (const service of services) {
|
|
68
|
+
const preferredKind = service.kindCandidates.find( kind => PreferredKinds.indexOf(kind) >= 0);
|
|
69
|
+
if (preferredKind) {
|
|
70
|
+
service.kind = preferredKind;
|
|
71
|
+
} if (service.kindCandidates.length === 1) {
|
|
72
|
+
service.kind = service.kindCandidates[0];
|
|
80
73
|
}
|
|
74
|
+
|
|
75
|
+
delete service.kindCandidates;
|
|
81
76
|
}
|
|
77
|
+
}
|
|
82
78
|
|
|
83
79
|
function execAndExit(command, ...args) {
|
|
84
80
|
const { spawnSync } = require('child_process');
|
|
85
|
-
|
|
81
|
+
// use shell with Windows only; without output is not visible and some commands cannot be run
|
|
82
|
+
const result = spawnSync(command, args, { stdio: 'inherit', shell: IS_WIN });
|
|
86
83
|
process.exit(result.status);
|
|
87
84
|
}
|
|
88
85
|
|