@sap/cds-dk 8.2.3 → 8.3.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 +28 -0
- package/bin/cds.js +5 -4
- package/bin/compile/index.js +6 -2
- package/bin/deploy/index.js +22 -3
- package/bin/import.js +24 -14
- package/bin/repl.js +21 -8
- package/bin/util/fuzzySearch.js +8 -5
- package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.schema.json +1 -1
- package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/virtual-service.yaml +23 -12
- package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +2 -2
- package/lib/compile/to-mermaid.js +87 -0
- package/lib/import/common.js +2 -2
- package/lib/import/importapi.js +3 -3
- package/lib/import/openapi/importOpenAPI.js +42 -4
- package/lib/init/merge.js +2 -2
- package/lib/init/mvn.js +2 -2
- package/lib/init/projectReader.js +2 -0
- package/lib/init/registries/xs-app.js +10 -0
- package/lib/init/template/cf-manifest/index.js +2 -0
- package/lib/init/template/cloud-logging/files/mta.yaml.hbs +13 -2
- package/lib/init/template/cloud-logging/files/{package.json → package.json.hbs} +5 -1
- package/lib/init/template/cloud-logging/index.js +4 -3
- package/lib/init/template/data/as-csv.js +6 -0
- package/lib/init/template/data/as-json.js +8 -1
- package/lib/init/template/data/index.js +1 -1
- package/lib/init/template/destination/files/mta.yaml.hbs +5 -5
- package/lib/init/template/dynatrace/files/mta.yaml.hbs +22 -6
- package/lib/init/template/dynatrace/files/package.json.hbs +5 -2
- package/lib/init/template/dynatrace/files/values.yaml +15 -0
- package/lib/init/template/dynatrace/index.js +10 -5
- package/lib/init/template/handler/index.js +16 -1
- package/lib/init/template/helm/files/values.yaml.hbs +2 -2
- package/lib/init/template/helm/index.js +6 -1
- package/lib/init/template/html5-repo/files/app-package.json.hbs +3 -1
- package/lib/init/template/html5-repo/files/ui5-deploy.yaml.hbs +7 -0
- package/lib/init/template/html5-repo/index.js +3 -1
- package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
- package/lib/init/template/mta/index.js +2 -0
- package/lib/init/template/typer/index.js +2 -1
- package/lib/init/template/workzone-standard/files/manifest.json.hbs +15 -1
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +11 -2
- package/lib/init/template/workzone-standard/files/xs-app.json.hbs +18 -0
- package/lib/init/template/workzone-standard/index.js +25 -7
- package/lib/mtx/auth_manager.js +7 -5
- package/lib/mtx/util/errors.js +4 -4
- package/npm-shrinkwrap.json +36 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
9
9
|
|
|
10
|
+
## Version 8.3.0 - 2024-09-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `cds add mta`, `cds add helm` and `cds add cf-manifest` execute the `mvn cds:add -Dfeature CF/K8S` under the hood for Java projects.
|
|
15
|
+
- `cds compile --to mermaid` now supports `mta.yaml` to generate a visualization of your deployment descriptor.
|
|
16
|
+
- `cds add data` now also generates data for models imported with `cds import`.
|
|
17
|
+
- `cds add data` now also supports structured types.
|
|
18
|
+
- `cds deploy` now can also write its DDL statements to a separate log file with the `--out <file>` parameter.
|
|
19
|
+
- `cds add dynatrace` is now supported for Kyma.
|
|
20
|
+
- `cds import --name ...` to be used in RFC importer (`@sap/cds-rfc`).
|
|
21
|
+
- `cds add cloud-logging --with-telemetry` and `cds add dynatrace` are added to the `production` profile by default and respect the `for` option.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- `cds add sample` now uses `@ui5/cli` version 4.
|
|
26
|
+
- `cds import` now throws a warning for OpenAPI files containing recursive data types.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- With `cds add workzone`, apps can now directly be added via Content Manager in SAP Build Work Zone.
|
|
31
|
+
- Less obstrusive warning about `cds` instead of `cds-ts` in Typescript projects.
|
|
32
|
+
|
|
10
33
|
## Version 8.2.3 - 2024-09-25
|
|
11
34
|
|
|
12
35
|
### Fixed
|
|
@@ -265,6 +288,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
|
265
288
|
|
|
266
289
|
- `cds add notebook` is removed. CAP Jupyter Notebooks have been replaced by custom CAP Notebooks for VS Code which are now part of the CDS Editor. See https://cap.cloud.sap/docs/tools/#add-cds-editor for more.
|
|
267
290
|
|
|
291
|
+
## Version 7.9.8 - 2024-09-17
|
|
292
|
+
|
|
293
|
+
### Fixed
|
|
294
|
+
|
|
295
|
+
- BDSA-2024-6188: vulnerability with express.js 4.19.2
|
|
268
296
|
|
|
269
297
|
## Version 7.9.7 - 2024-08-22
|
|
270
298
|
|
package/bin/cds.js
CHANGED
|
@@ -77,11 +77,12 @@ const cli = {
|
|
|
77
77
|
|
|
78
78
|
if (args[1]?.['resolve-bindings']) await _resolveBindings({ silent: cmd === 'env' })
|
|
79
79
|
|
|
80
|
-
//
|
|
81
|
-
// showing the full detected path should give the user an idea whether this info is relevant for them
|
|
80
|
+
// warn users if they are using cds instead of cds-ts in a TypeScript project
|
|
82
81
|
const tsconfig = path.join(cds.root ?? '.', 'tsconfig.json')
|
|
83
|
-
if (!process.env.CDS_TYPESCRIPT && fs.existsSync(tsconfig)) {
|
|
84
|
-
|
|
82
|
+
if (!process.env.CDS_TYPESCRIPT && cds.cli?.command === 'serve' && fs.existsSync(tsconfig)) {
|
|
83
|
+
// cds.root may for some subcommands not point to the correct directory (e.g. cds w where users can pass a project directory)
|
|
84
|
+
// showing the full detected path should give the user an idea whether this info is relevant for them
|
|
85
|
+
console.error(`Detected ${tsconfig}. If this is a TypeScript project, consider running commands using 'cds-ts' instead of 'cds'.\n`)
|
|
85
86
|
}
|
|
86
87
|
return await task.apply(this, args)
|
|
87
88
|
}
|
package/bin/compile/index.js
CHANGED
|
@@ -230,8 +230,12 @@ async function compile (models, options={}) {
|
|
|
230
230
|
const messages = options.messages = []
|
|
231
231
|
|
|
232
232
|
if (Array.isArray(models) && models.length > 0) { // any arguments?
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
if (/mta.*\.ya?ml/.test(models[0])) {
|
|
234
|
+
model = Promise.resolve(models[0])
|
|
235
|
+
} else {
|
|
236
|
+
model = cds.load (models, options)
|
|
237
|
+
src = models[0] .replace (/\.[^.]+$/,'') //> excluding source file extension, e.g. .cds
|
|
238
|
+
}
|
|
235
239
|
} else if (!process.stdin.isTTY && process.argv[1].endsWith('cds')) { // else check for stdin
|
|
236
240
|
model = readModelFromStdin()
|
|
237
241
|
src = 'stdin'
|
package/bin/deploy/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = Object.assign(deploy, {
|
|
2
|
-
options: ['--to', '--for', '--tunnel-address', '--vcap-file', '--delta-from' ],
|
|
2
|
+
options: ['--to', '--for', '--out', '--tunnel-address', '--vcap-file', '--delta-from' ],
|
|
3
3
|
flags: ['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--model-only', '--script', '--with-auto-schema-evolution' ],
|
|
4
|
-
shortcuts: ['-2', '-4'],
|
|
4
|
+
shortcuts: ['-2', '-4', '-o'],
|
|
5
5
|
help: `
|
|
6
6
|
# SYNOPSIS
|
|
7
7
|
|
|
@@ -37,6 +37,11 @@ module.exports = Object.assign(deploy, {
|
|
|
37
37
|
|
|
38
38
|
Just print the SQL statements without executing them.
|
|
39
39
|
|
|
40
|
+
*--out* | *-o* <file>
|
|
41
|
+
|
|
42
|
+
Write the DDL statements to the given file.
|
|
43
|
+
Not available in combination with '--to hana'.
|
|
44
|
+
|
|
40
45
|
*--with-mocks*
|
|
41
46
|
|
|
42
47
|
Also create tables for all entities from imported models.
|
|
@@ -134,10 +139,19 @@ async function deploy(_model, options) { // NOSONAR
|
|
|
134
139
|
}
|
|
135
140
|
try {
|
|
136
141
|
options.messages = []
|
|
137
|
-
if(options.script) options.dry = true // to ensure that we don't accidentally execute any SQLs
|
|
142
|
+
if (options.script) options.dry = true // to ensure that we don't accidentally execute any SQLs
|
|
143
|
+
if (options.out) {
|
|
144
|
+
ensureVersion(cds.version, 8, 3, `Option --out is available with @sap/cds >= 8.3.0, current version is ${cds.version}`)
|
|
145
|
+
options.schema_log = []
|
|
146
|
+
}
|
|
147
|
+
|
|
138
148
|
await deployer.deploy(_model, _db, options)
|
|
139
149
|
const log = this.log || _log
|
|
140
150
|
if (options.messages.length) log (options.messages, options)
|
|
151
|
+
|
|
152
|
+
if (options.out) {
|
|
153
|
+
await cds.utils.write (options.out, options.schema_log.join('\n'))
|
|
154
|
+
}
|
|
141
155
|
} catch (e) {
|
|
142
156
|
if (e.code === 'MODEL_NOT_FOUND') {
|
|
143
157
|
if (!_model) throw new Error('No .cds models found, please specify one as an argument')
|
|
@@ -153,3 +167,8 @@ function _log (messages, options) {
|
|
|
153
167
|
messages = sortMessagesSeverityAware (messages)
|
|
154
168
|
cds._log (messages, options)
|
|
155
169
|
}
|
|
170
|
+
|
|
171
|
+
function ensureVersion(version, reqMajor, reqMinor, message) {
|
|
172
|
+
const [major, minor] = version.split('.').map(Number)
|
|
173
|
+
if (major < reqMajor || (major === reqMajor && minor < reqMinor)) throw message
|
|
174
|
+
}
|
package/bin/import.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module.exports = Object.assign(_import, {
|
|
2
2
|
_name: 'import',
|
|
3
|
-
options: ['--out', '--as', '--include-namespaces', '--from', '--config', '--destination'],
|
|
3
|
+
options: ['--out', '--as', '--name', '--include-namespaces', '--from', '--config', '--destination'],
|
|
4
4
|
flags: ['--dry', '--force', '--no-copy', '--no-save', '--keep-namespace', '--beta'],
|
|
5
|
-
shortcuts: ['-o', '-as', '-ns', undefined, '-c', undefined, '-', '-f'],
|
|
5
|
+
shortcuts: ['-o', '-as', '-n', '-ns', undefined, '-c', undefined, '-', '-f'],
|
|
6
6
|
help: `
|
|
7
7
|
# SYNOPSIS
|
|
8
8
|
|
|
@@ -43,7 +43,7 @@ module.exports = Object.assign(_import, {
|
|
|
43
43
|
*--from*
|
|
44
44
|
Imports the model from the one of the given options "edmx", "openapi" or
|
|
45
45
|
"asyncapi".
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
*-c | --config* <JSON Object>
|
|
48
48
|
Adds the provided JSON Object as custom configuration data to the package.json.
|
|
49
49
|
|
|
@@ -51,6 +51,10 @@ module.exports = Object.assign(_import, {
|
|
|
51
51
|
Enables beta mode in cds import.
|
|
52
52
|
- Populates default value for optional action and function parameters in the CSN or CDS.
|
|
53
53
|
|
|
54
|
+
*--destination*
|
|
55
|
+
Destination name under which the remote service can be reached.
|
|
56
|
+
Not supported by import types "edmx", "openapi" or "asyncapi".
|
|
57
|
+
|
|
54
58
|
*Below options are valid for OData only*
|
|
55
59
|
|
|
56
60
|
*--keep-namespace*
|
|
@@ -62,10 +66,11 @@ module.exports = Object.assign(_import, {
|
|
|
62
66
|
For OData V2 attributes with the namespace "sap" & "m" are captured by
|
|
63
67
|
default.
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
Destination name under which the remote service can be reached.
|
|
67
|
-
Not supported by import types "edmx", "openapi" or "asyncapi".
|
|
69
|
+
*Below options are valid for RFC only*
|
|
68
70
|
|
|
71
|
+
*-n | --name*
|
|
72
|
+
The name of the module to be imported
|
|
73
|
+
Requires valid system credentials as the import connects to the system to fetch the metadata.
|
|
69
74
|
|
|
70
75
|
# EXAMPLES
|
|
71
76
|
|
|
@@ -85,20 +90,25 @@ const messages = require('../lib/import/message').getMessages();
|
|
|
85
90
|
const common = require('../lib/import/common');
|
|
86
91
|
const cdsImport = require('../lib/index');
|
|
87
92
|
|
|
88
|
-
async function _import(
|
|
89
|
-
let csn =
|
|
93
|
+
async function _import(args, options = {}) {
|
|
94
|
+
let csn = '';
|
|
90
95
|
let apiOptions = {};
|
|
91
96
|
// preprocess
|
|
92
97
|
let cwd = process.cwd();
|
|
93
|
-
if (Array.isArray(file)) file = file[0];
|
|
94
|
-
if (!file) return this.help('import');
|
|
95
98
|
// process options
|
|
96
99
|
await common.processOptions(options, apiOptions);
|
|
97
|
-
const srcFilePath = await common.preProcess(file, options, cwd);
|
|
98
100
|
|
|
99
101
|
const cds = require('../lib/cds')
|
|
100
102
|
await cds.plugins
|
|
101
103
|
|
|
104
|
+
let file
|
|
105
|
+
let input
|
|
106
|
+
if (!options.name) {
|
|
107
|
+
file = Array.isArray(args) ? args[0] : args
|
|
108
|
+
if (!file) return this.help('import')
|
|
109
|
+
input = await common.preProcess(file, options, cwd);
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
// process - csn generation
|
|
103
113
|
// if --from option is given, call api directly accordingly
|
|
104
114
|
if (options.from) {
|
|
@@ -106,14 +116,14 @@ async function _import(file, options = {}) {
|
|
|
106
116
|
// the required plugin might not be installed, e.g. rfc importer
|
|
107
117
|
throw messages.UNSUPPORTED_FROM_OPTION;
|
|
108
118
|
}
|
|
109
|
-
csn = await cdsImport.import.from[options.from](
|
|
119
|
+
csn = await cdsImport.import.from[options.from](input, apiOptions);
|
|
110
120
|
} else {
|
|
111
|
-
csn = await cdsImport.import(
|
|
121
|
+
csn = await cdsImport.import(input, apiOptions);
|
|
112
122
|
}
|
|
113
123
|
|
|
114
124
|
// reads the file version
|
|
115
125
|
options.inputFileKind = apiOptions.odataVersion ? apiOptions.odataVersion : apiOptions.inputFileKind;
|
|
116
126
|
|
|
117
127
|
// postprocess
|
|
118
|
-
return await common.postProcess(file, options, csn, cwd);
|
|
128
|
+
return await common.postProcess(apiOptions.file ?? file, options, csn, cwd);
|
|
119
129
|
}
|
package/bin/repl.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
module.exports = Object.assign (repl, { options: [], help: `
|
|
3
3
|
# SYNOPSIS
|
|
4
4
|
|
|
@@ -24,7 +24,9 @@ async function repl (_, options={}) {
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
const repl = require('repl').start ({
|
|
27
|
-
...options,
|
|
27
|
+
...options,
|
|
28
|
+
ignoreUndefined: true,
|
|
29
|
+
useGlobal: true,
|
|
28
30
|
writer: o => {
|
|
29
31
|
if (!o || typeof o !== 'object') return o
|
|
30
32
|
return inspect(o).replace(/\[Object: null prototype\] /g, '')
|
|
@@ -32,12 +34,23 @@ async function repl (_, options={}) {
|
|
|
32
34
|
})
|
|
33
35
|
|
|
34
36
|
Object.defineProperty (cds,'repl',{value:repl})
|
|
35
|
-
cds.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
37
|
+
cds.extend (repl.context) .with ( class {
|
|
38
|
+
get Foo() { return ctx.Foo ??= new cds.entity({ name: 'Foo' }) }
|
|
39
|
+
get Bar() { return ctx.Bar ??= new cds.entity({ name: 'Bar' }) }
|
|
40
|
+
get expect() { return cds.test.expect }
|
|
41
|
+
} .prototype )
|
|
42
|
+
const ctx={}
|
|
43
|
+
|
|
44
|
+
repl.defineCommand ('run', {
|
|
45
|
+
help: 'Runs a cds server in the given CAP project folder, which can be a module name like @capire/bookshop.',
|
|
46
|
+
async action (project) {
|
|
47
|
+
// await cds.exec ('--project', project, '--port', '0')
|
|
48
|
+
await cds.test (project)
|
|
49
|
+
console.log ('Following are made avaliable as global variables:')
|
|
50
|
+
console.log ('- cds.services:', Object.keys(cds.services)); Object.assign (repl.context, cds.services)
|
|
51
|
+
console.log ('- cds.entities:', Object.keys(cds.entities)); Object.assign (repl.context, cds.entities)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
41
54
|
|
|
42
55
|
repl.history = new Array(222)
|
|
43
56
|
const home = process.env.HOME || process.env.USERPROFILE
|
package/bin/util/fuzzySearch.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
const cache =
|
|
11
|
+
const cache = new Map();
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
module.exports = (input, list, log) => {
|
|
@@ -52,8 +52,9 @@ module.exports = (input, list, log) => {
|
|
|
52
52
|
|
|
53
53
|
const levDistance = (a, b) => {
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const cachedObj = cache.get(a)?.get(b);
|
|
56
|
+
if (cachedObj) {
|
|
57
|
+
return cachedObj;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
if (a.length === 0) {
|
|
@@ -81,7 +82,9 @@ const levDistance = (a, b) => {
|
|
|
81
82
|
|
|
82
83
|
|
|
83
84
|
const addToCache = (a, b, value) => {
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
if (!cache.has(a)) {
|
|
86
|
+
cache.set(a, new Map());
|
|
87
|
+
}
|
|
88
|
+
cache.get(a).set(b, value);
|
|
86
89
|
return value;
|
|
87
90
|
}
|
|
@@ -528,7 +528,7 @@
|
|
|
528
528
|
"title": "Image tag",
|
|
529
529
|
"type": "string",
|
|
530
530
|
"$comment": "Copied from https://github.com/containers/image/blob/18d58d29fdc4fc32fb8a8a6d186b829b217f1bf5/docker/reference/regexp.go#L68-L70",
|
|
531
|
-
"pattern": "^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?/)?[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-
|
|
531
|
+
"pattern": "^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?/)?[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-zA-Z0-9]+)+)?(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?)(?::([\\w][\\w.-]{0,127}))?(?:@([A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}))?$"
|
|
532
532
|
},
|
|
533
533
|
"ImagePullPolicy": {
|
|
534
534
|
"title": "ImagePullPolicy",
|
package/lib/build/plugins/helm/files/subcharts/web-application/templates/virtual-service.yaml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{{- if include "web-application.internal.TENANT_HOST_PATTERN" . -}}
|
|
1
|
+
{{- if and .Values.expose.enabled (include "web-application.internal.TENANT_HOST_PATTERN" .) -}}
|
|
2
2
|
apiVersion: networking.istio.io/v1beta1
|
|
3
3
|
kind: VirtualService
|
|
4
4
|
metadata:
|
|
@@ -10,7 +10,26 @@ spec:
|
|
|
10
10
|
hosts:
|
|
11
11
|
- "*"
|
|
12
12
|
http:
|
|
13
|
-
|
|
13
|
+
{{- range $httpRule := .Values.expose.rules }}
|
|
14
|
+
- match:
|
|
15
|
+
- uri:
|
|
16
|
+
regex: {{ $httpRule.path }}
|
|
17
|
+
{{- if $httpRule.methods }}
|
|
18
|
+
method:
|
|
19
|
+
regex: ^({{ join "|" $httpRule.methods }})$
|
|
20
|
+
{{- end }}
|
|
21
|
+
headers:
|
|
22
|
+
Host:
|
|
23
|
+
regex: {{ tpl (include "web-application.internal.TENANT_HOST_PATTERN" $) $ }}
|
|
24
|
+
route:
|
|
25
|
+
- weight: 100
|
|
26
|
+
destination:
|
|
27
|
+
host: "{{ include "web-application.fullname" $ }}.{{ $.Release.Namespace }}.svc.cluster.local"
|
|
28
|
+
{{- if $httpRule.corsPolicy }}
|
|
29
|
+
corsPolicy:
|
|
30
|
+
{{ $httpRule.corsPolicy | toYaml | nindent 8 }}
|
|
31
|
+
{{- else }}
|
|
32
|
+
corsPolicy:
|
|
14
33
|
allowHeaders:
|
|
15
34
|
- Authorization
|
|
16
35
|
- Content-Type
|
|
@@ -23,14 +42,6 @@ spec:
|
|
|
23
42
|
- PATCH
|
|
24
43
|
allowOrigins:
|
|
25
44
|
- regex: .*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
regex: /.*
|
|
29
|
-
headers:
|
|
30
|
-
Host:
|
|
31
|
-
regex: {{ tpl (include "web-application.internal.TENANT_HOST_PATTERN" .) . }}
|
|
32
|
-
route:
|
|
33
|
-
- weight: 100
|
|
34
|
-
destination:
|
|
35
|
-
host: "{{ include "web-application.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local"
|
|
45
|
+
{{- end }}
|
|
46
|
+
{{- end }}
|
|
36
47
|
{{- end }}
|
|
@@ -1326,7 +1326,7 @@
|
|
|
1326
1326
|
"title": "Image tag",
|
|
1327
1327
|
"type": "string",
|
|
1328
1328
|
"$comment": "Copied from https://github.com/containers/image/blob/18d58d29fdc4fc32fb8a8a6d186b829b217f1bf5/docker/reference/regexp.go#L68-L70",
|
|
1329
|
-
"pattern": "^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?/)?[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-
|
|
1329
|
+
"pattern": "^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?/)?[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-zA-Z0-9]+)+)?(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?)(?::([\\w][\\w.-]{0,127}))?(?:@([A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}))?$"
|
|
1330
1330
|
},
|
|
1331
1331
|
"ImagePullPolicy": {
|
|
1332
1332
|
"title": "ImagePullPolicy",
|
|
@@ -15,7 +15,7 @@ global:
|
|
|
15
15
|
_internal:
|
|
16
16
|
web-application:
|
|
17
17
|
versions:
|
|
18
|
-
1.17.
|
|
18
|
+
1.17.2: true
|
|
19
19
|
## Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
|
|
20
20
|
# nameOverride: name
|
|
21
21
|
|
|
@@ -159,7 +159,7 @@ expose:
|
|
|
159
159
|
# Rules represents collection of Rule to apply.
|
|
160
160
|
rules:
|
|
161
161
|
- accessStrategies:
|
|
162
|
-
- handler:
|
|
162
|
+
- handler: no_auth
|
|
163
163
|
methods:
|
|
164
164
|
- GET
|
|
165
165
|
- POST
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const cds = require('../cds')
|
|
2
2
|
|
|
3
3
|
module.exports = function to_mermaid (model, options={}) {
|
|
4
|
+
if (typeof model === 'string' && /mta.*\.ya?ml/.test(model)) return to_mta_mermaid(model)
|
|
5
|
+
|
|
4
6
|
options = Object.assign({
|
|
5
7
|
assocnames: false, // include association names
|
|
6
8
|
elements : false, // include all elements { falsy | 'all'|true | 'keys' }
|
|
@@ -119,3 +121,88 @@ function resolveTargets (query) {
|
|
|
119
121
|
|
|
120
122
|
return targets
|
|
121
123
|
}
|
|
124
|
+
|
|
125
|
+
function to_mta_mermaid (file) {
|
|
126
|
+
const content = cds.utils.fs.readFileSync(file, 'utf8')
|
|
127
|
+
const mta = cds.utils.yaml.parse(content)
|
|
128
|
+
const { modules = [], resources = [] } = mta
|
|
129
|
+
|
|
130
|
+
const all = new Set([...modules.map(m => m.name), ...resources.map(r => r.name)])
|
|
131
|
+
const provided = new Set()
|
|
132
|
+
const required = new Set()
|
|
133
|
+
|
|
134
|
+
let diag = 'graph LR\n'
|
|
135
|
+
|
|
136
|
+
const appModules = modules.filter(module => module.provides && module.provides.length > 0)
|
|
137
|
+
const utilityModules = modules.filter(module => !module.provides || module.provides.length === 0)
|
|
138
|
+
|
|
139
|
+
diag += ' subgraph Modules\n'
|
|
140
|
+
appModules.forEach(module => {
|
|
141
|
+
diag += ` subgraph ${module.name}\n`
|
|
142
|
+
module.provides.forEach(provide => {
|
|
143
|
+
provided.add(provide.name)
|
|
144
|
+
diag += ` ${provide.name}["${provide.name}"]\n`
|
|
145
|
+
})
|
|
146
|
+
diag += ` end\n`
|
|
147
|
+
})
|
|
148
|
+
utilityModules.forEach(module => {
|
|
149
|
+
diag += ` ${module.name}["${module.name}"]:::module\n`
|
|
150
|
+
})
|
|
151
|
+
diag += ' end\n'
|
|
152
|
+
|
|
153
|
+
diag += ' subgraph Resources\n'
|
|
154
|
+
resources.forEach(resource => {
|
|
155
|
+
diag += ` ${resource.name}["${resource.name}"]:::resource\n`
|
|
156
|
+
})
|
|
157
|
+
diag += ' end\n'
|
|
158
|
+
|
|
159
|
+
modules.forEach(module => {
|
|
160
|
+
if (module.requires) {
|
|
161
|
+
module.requires.forEach(require => {
|
|
162
|
+
required.add(require.name)
|
|
163
|
+
if (!all.has(require.name) && !provided.has(require.name)) {
|
|
164
|
+
diag += ` ${module.name} -->|requires| ${require.name}:::missing\n`
|
|
165
|
+
} else {
|
|
166
|
+
diag += ` ${module.name} -->|requires| ${require.name}\n`
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
resources.forEach(resource => {
|
|
172
|
+
if (resource.requires) {
|
|
173
|
+
resource.requires.forEach(require => {
|
|
174
|
+
required.add(require.name)
|
|
175
|
+
if (!all.has(require.name) && !provided.has(require.name)) {
|
|
176
|
+
diag += ` ${resource.name} -->|requires| ${require.name}:::missing\n`
|
|
177
|
+
} else {
|
|
178
|
+
diag += ` ${resource.name} -->|requires| ${require.name}\n`
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
provided.forEach(api => {
|
|
185
|
+
if (!required.has(api)) {
|
|
186
|
+
diag += ` class ${api} unused\n`
|
|
187
|
+
} else {
|
|
188
|
+
diag += ` class ${api} api\n`
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
modules.forEach(module => {
|
|
192
|
+
diag += ` class ${module.name} module\n`
|
|
193
|
+
})
|
|
194
|
+
resources.forEach(resource => {
|
|
195
|
+
diag += ` class ${resource.name} resource\n`
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
diag += `
|
|
199
|
+
classDef module fill:#36aeff,stroke:#333,stroke-width:2px;
|
|
200
|
+
classDef resource fill:#2bab43,stroke:#333,stroke-width:2px;
|
|
201
|
+
classDef api fill:#e03da4,stroke:#333,stroke-width:2px;
|
|
202
|
+
classDef missing fill:#ffcccc,stroke:#ff0000,stroke-width:2px,color:#ff0000;
|
|
203
|
+
classDef unused fill:#ffcccc,stroke:#ff0000,stroke-width:2px,color:#ff0000;
|
|
204
|
+
`
|
|
205
|
+
|
|
206
|
+
return diag
|
|
207
|
+
}
|
|
208
|
+
|
package/lib/import/common.js
CHANGED
|
@@ -17,7 +17,7 @@ let optionsMapping = {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
let apiOptions = ['includeNamespaces', 'keepNamespace', 'beta'];
|
|
20
|
-
let commonOptions = ['no_copy', 'no_save', 'out', 'dry', 'as', 'from', 'force', 'config', 'destination'];
|
|
20
|
+
let commonOptions = ['no_copy', 'no_save', 'out', 'dry', 'as', 'from', 'force', 'config', 'destination', 'name'];
|
|
21
21
|
|
|
22
22
|
async function generateEDMX2JSON(edmx) {
|
|
23
23
|
let cjson = convert.xml2json(edmx, {
|
|
@@ -344,7 +344,7 @@ async function _updatePackageJson(dest, services, kind, cwd, config, destination
|
|
|
344
344
|
if (!config && destination) {
|
|
345
345
|
config = { "[production]": { credentials: { destination } } };
|
|
346
346
|
}
|
|
347
|
-
|
|
347
|
+
|
|
348
348
|
let package_json_updated = false;
|
|
349
349
|
for (let service of services) {
|
|
350
350
|
// existing service configuration data can be updated, e.g. in case of delta imports
|
package/lib/import/importapi.js
CHANGED
|
@@ -7,11 +7,11 @@ let asyncapi = require('./asyncapi');
|
|
|
7
7
|
let messages = require('./message').getMessages();
|
|
8
8
|
|
|
9
9
|
module.exports = Object.assign(cds_import, {
|
|
10
|
-
from:
|
|
10
|
+
from: {
|
|
11
11
|
edmx: cds_import_from_edmx,
|
|
12
12
|
openapi: cds_import_from_openapi,
|
|
13
13
|
asyncapi: cds_import_from_asyncapi
|
|
14
|
-
}
|
|
14
|
+
}
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -95,7 +95,7 @@ async function cds_import_from_openapi(filepath, options = {}) {
|
|
|
95
95
|
return csn;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
/**
|
|
98
|
+
/**
|
|
99
99
|
* This is the import API function to generate CSN from asyncapi files.
|
|
100
100
|
* @param {string} filepath
|
|
101
101
|
* - a single valid filepath
|
|
@@ -552,14 +552,13 @@ function indirectlyReferencedType(context, subSchema) {
|
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
function referencedType(context, ref) {
|
|
555
|
-
const expectedPrefix = context.v3
|
|
556
|
-
? "#/components/schemas/"
|
|
557
|
-
: "#/definitions/";
|
|
555
|
+
const expectedPrefix = context.v3 ? "#/components/schemas/" : "#/definitions/";
|
|
558
556
|
if (!ref.startsWith(expectedPrefix)) {
|
|
559
557
|
throw new Error(`TODO: unexpected reference ${ref} in schema.`);
|
|
560
558
|
}
|
|
561
559
|
const schemaName = ref.substring(expectedPrefix.length);
|
|
562
560
|
const schema = context.schemas[schemaName];
|
|
561
|
+
|
|
563
562
|
return {
|
|
564
563
|
name: `${context.serviceName}_types.${cdsName(schemaName)}`,
|
|
565
564
|
schema,
|
|
@@ -633,11 +632,50 @@ function betterType(currentType, schema) {
|
|
|
633
632
|
// }
|
|
634
633
|
|
|
635
634
|
function structElements(context, type, schema) {
|
|
635
|
+
checkCircularReference(schema);
|
|
636
|
+
const schemaName = Object.keys(context.schemas).find(key => context.schemas[key] === schema);
|
|
637
|
+
const refPath = `#/components/schemas/${schemaName}`;
|
|
636
638
|
//TODO: interpret "required"
|
|
637
639
|
for (const [prop, propSchema] of Object.entries(schema.properties || {})) {
|
|
638
640
|
const name = cdsName(prop);
|
|
641
|
+
//to detect recursive data types
|
|
642
|
+
if ((propSchema?.$ref === refPath) || (propSchema?.items?.$ref === refPath)) {
|
|
643
|
+
console.warn(`Recursive data type detected: ${schemaName} for the property ${name}`);
|
|
644
|
+
}
|
|
639
645
|
//TODO: check if property "name" already exists and has identical cdsType, warn otherwise
|
|
640
646
|
type.elements[name] = cdsType(context, propSchema);
|
|
641
647
|
if (name !== prop) type.elements[name]["@openapi.name"] = prop;
|
|
642
648
|
}
|
|
643
|
-
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// function to check circular references and throw error if found
|
|
652
|
+
function checkCircularReference(schema, visited = new Set()) {
|
|
653
|
+
if (schema.$ref) {
|
|
654
|
+
const ref = schema.$ref;
|
|
655
|
+
if (visited.has(ref)) {
|
|
656
|
+
console.warn(`Circular reference detected: ${ref}`);
|
|
657
|
+
}
|
|
658
|
+
visited.add(ref);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (schema.allOf) {
|
|
662
|
+
schema.allOf.forEach(subSchema => checkCircularReference(subSchema, visited));
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (schema.anyOf) {
|
|
666
|
+
schema.anyOf.forEach(subSchema => checkCircularReference(subSchema, visited));
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if (schema.oneOf) {
|
|
670
|
+
schema.oneOf.forEach(subSchema => checkCircularReference(subSchema, visited));
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
if (schema.properties) {
|
|
674
|
+
Object.values(schema.properties).forEach(subSchema => checkCircularReference(subSchema, visited));
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (schema.items) {
|
|
678
|
+
checkCircularReference(schema.items, visited);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
package/lib/init/merge.js
CHANGED
|
@@ -162,8 +162,8 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
162
162
|
|
|
163
163
|
let collectionStack = [target.contents]
|
|
164
164
|
|
|
165
|
-
const _getProperty = (object, keyPath) => keyPath.split('.').reduce((p, k) => p && p[k], object)
|
|
166
|
-
const _getYAMLProperty = (object, keyPath) => keyPath.split('.').reduce((p, k) => p && p.get(k), object)
|
|
165
|
+
const _getProperty = (object, keyPath) => keyPath.split('.').filter(k => k).reduce((p, k) => p && p[k], object)
|
|
166
|
+
const _getYAMLProperty = (object, keyPath) => keyPath.split('.').filter(k => k).reduce((p, k) => p && p.get(k), object)
|
|
167
167
|
|
|
168
168
|
const _validateWhere = (node, dict, index) => {
|
|
169
169
|
const _addToMap = entries => entries?.filter(entry => {
|
package/lib/init/mvn.js
CHANGED
|
@@ -17,8 +17,8 @@ module.exports.add = async function (feature) {
|
|
|
17
17
|
if (javaMvn) _scan(javaMvn).forEach(([k,v]) => params.set(k,v))
|
|
18
18
|
const archetypeVersion = params.get('-DarchetypeVersion') ?? MAVEN_ARCHETYPE_VERSION
|
|
19
19
|
if (feature === HANA) { // REVISIT: compat for HANA until -Dfeature HANA is provided by Java
|
|
20
|
-
params.set(`com.sap.cds:cds-maven-plugin:${archetypeVersion}:
|
|
21
|
-
params.set(`-
|
|
20
|
+
params.set(`com.sap.cds:cds-maven-plugin:${archetypeVersion}:add`)
|
|
21
|
+
params.set(`-Dfeature`, `CF`) // REVISIT: Should get rid of CF dependency for Kyma scenarios
|
|
22
22
|
} else {
|
|
23
23
|
params.set(`com.sap.cds:cds-maven-plugin:${archetypeVersion}:add`)
|
|
24
24
|
params.set(`-Dfeature`, feature)
|