@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
|
@@ -89,10 +89,12 @@ module.exports = new class ProjectReader {
|
|
|
89
89
|
* @property {boolean} hasApprouter Indicates if the project uses the SAP Application Router.
|
|
90
90
|
* @property {boolean} hasHtml5Repo Indicates if the project uses the SAP BTP HTML5 Application Repository.
|
|
91
91
|
* @property {boolean} hasPortal Indicates if the project uses the SAP Cloud Portal service.
|
|
92
|
+
* @property {boolean} hasWorkzone Indicates if the project uses the SAP Build Work Zone service.
|
|
92
93
|
* @property {boolean} hasDestination Indicates if the project uses the SAP BTP Destination service.
|
|
93
94
|
* @property {boolean} hasMTXRoute Indicates if the approuter should have a multitenant route.
|
|
94
95
|
* @property {boolean} hasMTXRouteJava Indicates if the approuter should have a multitenant subscription route (java).
|
|
95
96
|
* @property {boolean} hasMalwareScanner Indicates if the project uses the SAP Malware Scanning service.
|
|
97
|
+
* @property {boolean} hasDynatrace Indicates if the project uses Dynatrace.
|
|
96
98
|
*
|
|
97
99
|
*/
|
|
98
100
|
|
|
@@ -3,6 +3,7 @@ const cds = require('../../../cds')
|
|
|
3
3
|
const { exists } = require('../../../cds').utils
|
|
4
4
|
const { readProject } = require('../../projectReader')
|
|
5
5
|
const { renderAndCopy } = require('../../template')
|
|
6
|
+
const mvn = require('../../mvn')
|
|
6
7
|
const MANIFEST_FILE = 'manifest.yml'
|
|
7
8
|
const SERVICES_MANIFEST_FILE = 'services-manifest.yml'
|
|
8
9
|
|
|
@@ -29,5 +30,6 @@ module.exports = class CfManifestTemplate extends require('../../plugin') {
|
|
|
29
30
|
async run() {
|
|
30
31
|
const project = readProject()
|
|
31
32
|
await renderAndCopy(join(__dirname, 'files'), cds.root, project)
|
|
33
|
+
if (project.isJava) await mvn.add('CF')
|
|
32
34
|
}
|
|
33
35
|
}
|
|
@@ -3,6 +3,17 @@ modules:
|
|
|
3
3
|
- name: {{appName}}-srv
|
|
4
4
|
type: {{language}}
|
|
5
5
|
path: {{& srvPath}}
|
|
6
|
+
{{#isJava}}
|
|
7
|
+
properties:
|
|
8
|
+
JBP_CONFIG_JAVA_OPTS:
|
|
9
|
+
from_environment: false
|
|
10
|
+
java_opts: >
|
|
11
|
+
-javaagent:META-INF/.sap_java_buildpack/otel_agent/opentelemetry-javaagent.jar
|
|
12
|
+
-Dotel.javaagent.extensions=META-INF/.sap_java_buildpack/otel_agent_extension/otel-agent-ext-java.jar
|
|
13
|
+
OTEL_METRICS_EXPORTER: cloud-logging
|
|
14
|
+
OTEL_TRACES_EXPORTER: cloud-logging
|
|
15
|
+
OTEL_LOGS_EXPORTER: none
|
|
16
|
+
{{/isJava}}
|
|
6
17
|
requires:
|
|
7
18
|
- name: {{appName}}-cloud-logging
|
|
8
19
|
- name: {{appName}}-mtx
|
|
@@ -21,5 +32,5 @@ resources:
|
|
|
21
32
|
service: cloud-logging
|
|
22
33
|
service-plan: {{cloudLoggingServicePlan}}
|
|
23
34
|
config:
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
ingest_otlp:
|
|
36
|
+
enabled: true
|
|
@@ -30,9 +30,10 @@ module.exports = class extends require('../../plugin') {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async run() {
|
|
33
|
-
const { hasTelemetry } =
|
|
34
|
-
if (cds.cli.options['with-telemetry'] || hasTelemetry) {
|
|
35
|
-
|
|
33
|
+
const project = readProject(), { hasTelemetry, isNodejs } = project
|
|
34
|
+
if (isNodejs && (cds.cli.options['with-telemetry'] || hasTelemetry)) {
|
|
35
|
+
project.profile ??= 'production'
|
|
36
|
+
await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: project })
|
|
36
37
|
await sort('package.json', 'dependencies')
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -39,6 +39,12 @@ module.exports = async (data={}, csn, { headerOnly=false, separator=',' }={}) =>
|
|
|
39
39
|
}
|
|
40
40
|
record.push(...Object.values(value))
|
|
41
41
|
}
|
|
42
|
+
else if (element.is_struct) {
|
|
43
|
+
if (i === 0) {
|
|
44
|
+
header.push(...Object.keys(value).map(structField => name + '_' + structField))
|
|
45
|
+
}
|
|
46
|
+
record.push(...Object.values(value))
|
|
47
|
+
}
|
|
42
48
|
else {
|
|
43
49
|
if (i === 0) header.push(name)
|
|
44
50
|
if (Array.isArray(value)) { // `array of` / `many`
|
|
@@ -121,9 +121,16 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
|
|
|
121
121
|
else if (element.items?.type) // `array of` / `many` with simple type
|
|
122
122
|
return [ dataForField(element.items, entity, csn, record, data, null, depth+1, referenceData) ]
|
|
123
123
|
|
|
124
|
+
if (element.is_struct) {
|
|
125
|
+
let struct = {}
|
|
126
|
+
for (const el of element.elements) {
|
|
127
|
+
struct[el.name] = dataForField(el, entity, csn, record, data, null, depth+1, referenceData)
|
|
128
|
+
}
|
|
129
|
+
return struct
|
|
130
|
+
}
|
|
131
|
+
|
|
124
132
|
const type = element._type || element.type
|
|
125
133
|
switch (type) {
|
|
126
|
-
case undefined: return
|
|
127
134
|
case 'cds.Time':
|
|
128
135
|
return '22:59:53'
|
|
129
136
|
|
|
@@ -67,7 +67,7 @@ module.exports = class DataTemplate extends require('../../plugin') {
|
|
|
67
67
|
: getDefaultTargetFolder(env)
|
|
68
68
|
dest = resolve(cds.root, dest)
|
|
69
69
|
|
|
70
|
-
let csn = await cds.load(cds.env.roots) // normal CSN
|
|
70
|
+
let csn = await cds.load([cds.env.roots, join(`${cds.env.folders.srv}`, `external`) ]) // normal CSN. Default paths and models imported with `cds import`
|
|
71
71
|
// Skip of unused reuse entities like Language, Country, Currency
|
|
72
72
|
csn = cds.minify(csn)
|
|
73
73
|
csn = cds.reflect(csn) // reflected model (adds additional helper functions)
|
|
@@ -31,14 +31,14 @@ resources:
|
|
|
31
31
|
destinations:
|
|
32
32
|
- Name: {{appName}}-srv-api
|
|
33
33
|
URL: ~{srv-api/srv-url}
|
|
34
|
-
Authentication:
|
|
34
|
+
Authentication: NoAuthentication
|
|
35
35
|
Type: HTTP
|
|
36
36
|
ProxyType: Internet
|
|
37
37
|
HTML5.ForwardAuthToken: true
|
|
38
38
|
HTML5.DynamicDestination: true
|
|
39
|
-
-
|
|
40
|
-
Name: ui5
|
|
41
|
-
ProxyType: Internet
|
|
42
|
-
Type: HTTP
|
|
39
|
+
- Name: ui5
|
|
43
40
|
URL: https://ui5.sap.com
|
|
41
|
+
Authentication: NoAuthentication
|
|
42
|
+
Type: HTTP
|
|
43
|
+
ProxyType: Internet
|
|
44
44
|
{{/hasHtml5Repo}}
|
|
@@ -3,8 +3,28 @@ modules:
|
|
|
3
3
|
- name: {{appName}}-srv
|
|
4
4
|
type: {{language}}
|
|
5
5
|
path: {{& srvPath}}
|
|
6
|
+
{{#isJava}}
|
|
7
|
+
properties:
|
|
8
|
+
JBP_CONFIG_JAVA_OPTS:
|
|
9
|
+
from_environment: false
|
|
10
|
+
java_opts: >
|
|
11
|
+
-javaagent:META-INF/.sap_java_buildpack/otel_agent/opentelemetry-javaagent.jar
|
|
12
|
+
-Dotel.javaagent.extensions=META-INF/.sap_java_buildpack/otel_agent_extension/otel-agent-ext-java.jar
|
|
13
|
+
-Dotel.javaagent.extension.sap.cf.binding.dynatrace.metrics.token-name=ingest_apitoken
|
|
14
|
+
OTEL_METRICS_EXPORTER: dynatrace
|
|
15
|
+
OTEL_TRACES_EXPORTER: none
|
|
16
|
+
OTEL_LOGS_EXPORTER: none
|
|
17
|
+
{{/isJava}}
|
|
6
18
|
requires:
|
|
7
19
|
- name: {{appName}}-dynatrace
|
|
20
|
+
parameters:
|
|
21
|
+
config:
|
|
22
|
+
tokens:
|
|
23
|
+
- name: ingest_apitoken
|
|
24
|
+
scopes:
|
|
25
|
+
- openTelemetryTrace.ingest
|
|
26
|
+
- metrics.ingest
|
|
27
|
+
|
|
8
28
|
- name: {{appName}}-mtx
|
|
9
29
|
type: nodejs
|
|
10
30
|
path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
|
|
@@ -15,10 +35,6 @@ resources:
|
|
|
15
35
|
type: org.cloudfoundry.managed-service
|
|
16
36
|
parameters:
|
|
17
37
|
service: dynatrace
|
|
18
|
-
service-plan:
|
|
38
|
+
service-plan: environment
|
|
19
39
|
config:
|
|
20
|
-
|
|
21
|
-
- name: ingest_apitoken
|
|
22
|
-
scopes:
|
|
23
|
-
- openTelemetryTrace.ingest
|
|
24
|
-
- metrics.ingest
|
|
40
|
+
environment_name: {{appName}}
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@cap-js/telemetry": ">=0",
|
|
4
4
|
"@opentelemetry/exporter-metrics-otlp-proto": "^0"{{#hasHelm}},
|
|
5
|
-
"@opentelemetry/exporter-trace-otlp-proto": "^0",
|
|
6
5
|
"@opentelemetry/host-metrics": "^0"
|
|
7
6
|
{{/hasHelm}}
|
|
8
7
|
},
|
|
9
8
|
"cds": {
|
|
10
9
|
"requires": {
|
|
11
|
-
"
|
|
10
|
+
"[{{profile}}]": {
|
|
11
|
+
"telemetry": {
|
|
12
|
+
"kind": "to-dynatrace"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
12
15
|
}
|
|
13
16
|
}
|
|
14
17
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
srv:
|
|
2
|
+
bindings:
|
|
3
|
+
dynatrace:
|
|
4
|
+
serviceInstanceName: dynatrace
|
|
5
|
+
parameters:
|
|
6
|
+
tokens:
|
|
7
|
+
- name: ingest_apitoken
|
|
8
|
+
scopes:
|
|
9
|
+
- openTelemetryTrace.ingest
|
|
10
|
+
- metrics.ingest
|
|
11
|
+
dynatrace:
|
|
12
|
+
serviceOfferingName: dynatrace
|
|
13
|
+
servicePlanName: environment
|
|
14
|
+
parameters:
|
|
15
|
+
environment_name: DYNATRACE # (Mandatory) maximum of 16 characters and can only comprise of uppercase letters and digits.
|
|
@@ -10,20 +10,21 @@ module.exports = class extends require('../../plugin') {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
async canRun() {
|
|
13
|
-
const { hasMta, hasHelm, hasHelmUnifiedRuntime } = readProject()
|
|
14
|
-
if ((hasHelmUnifiedRuntime || hasHelm) && !hasMta) throw `'cds add dynatrace' is not available for Kyma yet`
|
|
15
13
|
return true
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
async run() {
|
|
19
17
|
const project = readProject()
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
if (project.isNodejs) {
|
|
19
|
+
project.profile ??= 'production'
|
|
20
|
+
await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: project })
|
|
21
|
+
await sort('package.json', 'dependencies')
|
|
22
|
+
}
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
async combine() {
|
|
25
26
|
const project = readProject()
|
|
26
|
-
const { hasMta, isJava, hasMultitenancy, srvPath } = project
|
|
27
|
+
const { hasMta, hasHelm, hasHelmUnifiedRuntime, isJava, hasMultitenancy, srvPath } = project
|
|
27
28
|
|
|
28
29
|
if (hasMta) {
|
|
29
30
|
const dynatrace = {
|
|
@@ -51,5 +52,9 @@ module.exports = class extends require('../../plugin') {
|
|
|
51
52
|
with: project, additions, relationships
|
|
52
53
|
})
|
|
53
54
|
}
|
|
55
|
+
|
|
56
|
+
if (hasHelm || hasHelmUnifiedRuntime) {
|
|
57
|
+
await merge(__dirname, 'files', 'values.yaml').into('chart/values.yaml')
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
}
|
|
@@ -5,7 +5,22 @@ const mvn = require('../../mvn')
|
|
|
5
5
|
module.exports = class Handler extends require('../../plugin') {
|
|
6
6
|
|
|
7
7
|
static help() {
|
|
8
|
-
return 'add handler stubs'
|
|
8
|
+
return 'add handler stubs for actions and functions (Java)'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
options() {
|
|
12
|
+
return {
|
|
13
|
+
'filter': {
|
|
14
|
+
type: 'string',
|
|
15
|
+
short: 'f',
|
|
16
|
+
help: `Filter actions or functions by name prefix. Regular expressions are not supported.`
|
|
17
|
+
},
|
|
18
|
+
'out': {
|
|
19
|
+
type: 'string',
|
|
20
|
+
short: 'o',
|
|
21
|
+
help: 'Specify a custom output directory inside the `handlers` directory. The default is `handlers`.'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
9
24
|
}
|
|
10
25
|
|
|
11
26
|
canRun() {
|
|
@@ -26,6 +26,6 @@ srv:
|
|
|
26
26
|
memory: {{#isJava}}1G{{/isJava}}{{^isJava}}500M{{/isJava}}
|
|
27
27
|
health:
|
|
28
28
|
liveness:
|
|
29
|
-
path: {{#isJava}}/actuator/health{{/isJava}}{{^isJava}}/health{{/isJava}}
|
|
29
|
+
path: {{#isJava}}/actuator/health/liveness{{/isJava}}{{^isJava}}/health{{/isJava}}
|
|
30
30
|
readiness:
|
|
31
|
-
path: {{#isJava}}/actuator/health{{/isJava}}{{^isJava}}/health{{/isJava}}
|
|
31
|
+
path: {{#isJava}}/actuator/health/readiness{{/isJava}}{{^isJava}}/health{{/isJava}}
|
|
@@ -5,6 +5,7 @@ const { readProject } = require('../../projectReader')
|
|
|
5
5
|
const { merge } = require('../../merge')
|
|
6
6
|
const { ask4 } = require('../../../util/question')
|
|
7
7
|
const { execSync } = require('child_process')
|
|
8
|
+
const { mvn } = require('../../add')
|
|
8
9
|
|
|
9
10
|
module.exports = class HelmTemplate extends require('../../plugin') {
|
|
10
11
|
|
|
@@ -90,10 +91,11 @@ module.exports = class HelmTemplate extends require('../../plugin') {
|
|
|
90
91
|
await merge(__dirname, 'files/Chart.yaml.hbs').into('chart/Chart.yaml', { with: project })
|
|
91
92
|
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
|
|
92
93
|
await this._mergeDependency('web-application', 'srv')
|
|
94
|
+
if (project.isJava) await mvn.add('k8s')
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
async combine() {
|
|
96
|
-
const { hasDestination, hasEnterpriseMessaging, hasEnterpriseMessagingShared, hasHana, hasMultitenancy, hasXsuaa, hasHtml5Repo, hasApprouter, hasKafka, hasAttachments, hasPortal, hasMalwareScanner } = readProject()
|
|
98
|
+
const { hasDestination, hasEnterpriseMessaging, hasEnterpriseMessagingShared, hasHana, hasMultitenancy, hasXsuaa, hasHtml5Repo, hasApprouter, hasKafka, hasAttachments, hasPortal, hasMalwareScanner, hasDynatrace } = readProject()
|
|
97
99
|
|
|
98
100
|
if (hasApprouter) {
|
|
99
101
|
await this._mergeDependency('web-application', 'approuter')
|
|
@@ -140,6 +142,9 @@ module.exports = class HelmTemplate extends require('../../plugin') {
|
|
|
140
142
|
if (hasMalwareScanner) {
|
|
141
143
|
await this._mergeDependency('service-instance', 'malware-scanner')
|
|
142
144
|
}
|
|
145
|
+
if (hasDynatrace) {
|
|
146
|
+
await this._mergeDependency('service-instance', 'dynatrace')
|
|
147
|
+
}
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
async _mergeDependency(name, alias) {
|
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
"start": "ui5 serve"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@ui5
|
|
11
|
+
{{#hasWorkzone}}"@sap/ui5-builder-webide-extension": "^1.1.9",{{/hasWorkzone}}
|
|
12
|
+
"@ui5/cli": "^4",
|
|
12
13
|
"ui5-task-zipper": "^3"
|
|
13
14
|
},
|
|
14
15
|
"ui5": {
|
|
15
16
|
"dependencies": [
|
|
17
|
+
{{#hasWorkzone}}"@sap/ui5-builder-webide-extension",{{/hasWorkzone}}
|
|
16
18
|
"ui5-task-zipper"
|
|
17
19
|
]
|
|
18
20
|
}
|
|
@@ -13,6 +13,13 @@ builder:
|
|
|
13
13
|
- "/test/**"
|
|
14
14
|
- "/localService/**"
|
|
15
15
|
customTasks:
|
|
16
|
+
{{#hasWorkzone}}
|
|
17
|
+
- name: webide-extension-task-updateManifestJson
|
|
18
|
+
afterTask: replaceVersion
|
|
19
|
+
configuration:
|
|
20
|
+
appFolder: webapp
|
|
21
|
+
destDir: dist
|
|
22
|
+
{{/hasWorkzone}}
|
|
16
23
|
- name: ui5-task-zipper
|
|
17
24
|
afterTask: generateVersionInfo
|
|
18
25
|
configuration:
|
|
@@ -2,6 +2,7 @@ const { join } = require('path')
|
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
3
|
const { merge } = require('../../merge')
|
|
4
4
|
const { srv4, html5RepoHost, html5Runtime, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
|
|
5
|
+
const { odataApi } = require('../../registries/xs-app')
|
|
5
6
|
|
|
6
7
|
module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
7
8
|
|
|
@@ -52,7 +53,8 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
52
53
|
|
|
53
54
|
await Promise.all(apps.map(async ({app}) => {
|
|
54
55
|
project.app = app
|
|
55
|
-
|
|
56
|
+
const additions = [odataApi]
|
|
57
|
+
await merge(__dirname, 'files/xs-app.json.hbs').into(join(appPath, app, 'xs-app.json'), { with: project, additions })
|
|
56
58
|
}))
|
|
57
59
|
|
|
58
60
|
if (hasMultitenancy) {
|
|
@@ -29,7 +29,7 @@ modules:
|
|
|
29
29
|
parameters:
|
|
30
30
|
buildpack: sap_java_buildpack_jakarta
|
|
31
31
|
readiness-health-check-type: http
|
|
32
|
-
readiness-health-check-http-endpoint: /actuator/health
|
|
32
|
+
readiness-health-check-http-endpoint: /actuator/health/readiness
|
|
33
33
|
properties:
|
|
34
34
|
SPRING_PROFILES_ACTIVE: cloud,sandbox
|
|
35
35
|
JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jre.SAPMachineJRE']"
|
|
@@ -5,6 +5,7 @@ const { bold } = require('../../../util/term')
|
|
|
5
5
|
const { copyRenderedYAML } = require('../../../util/fs')
|
|
6
6
|
const { readProject } = require('../../projectReader')
|
|
7
7
|
const { merge, sort } = require('../../merge')
|
|
8
|
+
const { mvn } = require('../../add')
|
|
8
9
|
|
|
9
10
|
module.exports = class MtaTemplate extends require('../../plugin') {
|
|
10
11
|
|
|
@@ -23,6 +24,7 @@ module.exports = class MtaTemplate extends require('../../plugin') {
|
|
|
23
24
|
}
|
|
24
25
|
await merge(__dirname, 'files/package.json').into('package.json')
|
|
25
26
|
await sort('package.json', 'devDependencies')
|
|
27
|
+
if (project.isJava) await mvn.add('cf')
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
async finalize() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
3
|
const { merge, mergeGitignore } = require('../../merge')
|
|
4
|
-
const { warn, dim } = require('../../../util/term')
|
|
4
|
+
const { warn, dim, bold } = require('../../../util/term')
|
|
5
5
|
const { TYPER } = require('../../constants').OPTIONS
|
|
6
6
|
const { exists, read } = require('../../../cds').utils
|
|
7
7
|
|
|
@@ -30,6 +30,7 @@ module.exports = class TyperTemplate extends require('../../plugin') {
|
|
|
30
30
|
await merge(template('package.json')).into('package.json')
|
|
31
31
|
await mergeGitignore('.gitignore', template('gitignore'))
|
|
32
32
|
console.log(dim(` Adding '@cds-models' to .gitignore to ignore generated types`)) // REVISIT: other facets are silent wrt. what they change
|
|
33
|
+
console.log(dim(' Added new dependencies to the project. Run ') + bold('npm i') + dim(' to install.'))
|
|
33
34
|
try {
|
|
34
35
|
await merge(source).into(target)
|
|
35
36
|
} catch (e) {
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
+
"sap.app": {
|
|
3
|
+
"crossNavigation": {
|
|
4
|
+
"inbounds": {
|
|
5
|
+
"{{uiApp}}-display": {
|
|
6
|
+
"semanticObject": "{{uiApp}}",
|
|
7
|
+
"action": "display",
|
|
8
|
+
"signature": {
|
|
9
|
+
"parameters": {},
|
|
10
|
+
"additionalParameters": "allowed"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
2
16
|
"sap.cloud": {
|
|
3
17
|
"public": true,
|
|
4
|
-
"service": "{{
|
|
18
|
+
"service": "{{strippedAppName}}.service"
|
|
5
19
|
}
|
|
6
20
|
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
modules:
|
|
3
|
+
- name: {{appName}}-srv
|
|
4
|
+
type: {{language}}
|
|
5
|
+
path: {{& srvPath}}
|
|
6
|
+
provides:
|
|
7
|
+
- name: srv-api # required by consumers of CAP services (e.g. approuter)
|
|
8
|
+
properties:
|
|
9
|
+
srv-url: ${default-url}
|
|
10
|
+
|
|
3
11
|
- name: {{appName}}-destinations
|
|
4
12
|
type: com.sap.application.content
|
|
5
13
|
requires:
|
|
@@ -25,13 +33,14 @@ modules:
|
|
|
25
33
|
- Name: {{appName}}-html5-repository
|
|
26
34
|
ServiceInstanceName: {{appName}}-html5-repo-host
|
|
27
35
|
ServiceKeyName: {{appName}}-html5-repo-host-key
|
|
28
|
-
sap.cloud.service: {{
|
|
36
|
+
sap.cloud.service: {{strippedAppName}}.service
|
|
29
37
|
- Name: {{appName}}-auth
|
|
30
38
|
Authentication: OAuth2UserTokenExchange
|
|
31
39
|
ServiceInstanceName: {{appName}}-auth
|
|
32
40
|
ServiceKeyName: {{appName}}-auth-key
|
|
33
|
-
sap.cloud.service: {{
|
|
41
|
+
sap.cloud.service: {{strippedAppName}}.service
|
|
34
42
|
|
|
43
|
+
resources:
|
|
35
44
|
- name: {{appName}}-destination
|
|
36
45
|
type: org.cloudfoundry.managed-service
|
|
37
46
|
parameters:
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"authenticationMethod": "route",
|
|
3
|
+
"routes": [
|
|
4
|
+
{
|
|
5
|
+
"source": "^/?odata/(.*)$",
|
|
6
|
+
"target": "/odata/$1",
|
|
7
|
+
"destination": "{{appName}}-srv-api",
|
|
8
|
+
{{#hasXsuaa}}"authenticationType": "xsuaa",{{/hasXsuaa}}
|
|
9
|
+
"csrfProtection": true
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"source": "^(.*)$",
|
|
13
|
+
"target": "$1",
|
|
14
|
+
"service": "html5-apps-repo-rt"{{#hasXsuaa}},
|
|
15
|
+
"authenticationType": "xsuaa"{{/hasXsuaa}}
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -2,7 +2,8 @@ const cds = require('../../../cds')
|
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
3
|
const { merge } = require('../../merge')
|
|
4
4
|
const { join } = require('path')
|
|
5
|
-
const { destination, destinations } = require('../../registries/mta')
|
|
5
|
+
const { destination, destinations, srv4 } = require('../../registries/mta')
|
|
6
|
+
const { odataApi } = require('../../registries/xs-app')
|
|
6
7
|
|
|
7
8
|
module.exports = class extends require('../../plugin') {
|
|
8
9
|
|
|
@@ -28,19 +29,36 @@ module.exports = class extends require('../../plugin') {
|
|
|
28
29
|
async run() {
|
|
29
30
|
const project = readProject()
|
|
30
31
|
const { appUIPaths, appPath } = project
|
|
31
|
-
await Promise.all(appUIPaths.map(p =>
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
await Promise.all(appUIPaths.map(p => {
|
|
33
|
+
project.uiApp = p
|
|
34
|
+
return merge(__dirname, 'files/manifest.json.hbs').into(join(appPath, p, 'webapp/manifest.json'), { project })
|
|
35
|
+
}))
|
|
34
36
|
await merge({ cds: { requires: { workzone: true } } }).into('package.json')
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
async combine() {
|
|
38
40
|
const project = readProject()
|
|
39
|
-
const { hasMta } = project
|
|
41
|
+
const { hasMta, srvPath, apps, appPath } = project
|
|
42
|
+
|
|
43
|
+
await Promise.all(apps.map(async ({app}) => {
|
|
44
|
+
const additions = [odataApi]
|
|
45
|
+
const overwrites = [{
|
|
46
|
+
item: [odataApi, 'destination'],
|
|
47
|
+
withValue: `${project.appName}-srv-api`
|
|
48
|
+
}]
|
|
49
|
+
project.app = app
|
|
50
|
+
await merge(__dirname, 'files/xs-app.json.hbs').into(join(appPath, app, 'xs-app.json'), { with: project, additions, overwrites })
|
|
51
|
+
}))
|
|
40
52
|
|
|
41
53
|
if (hasMta) {
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
const srv = srv4(srvPath)
|
|
55
|
+
const additions = [srv, destinations, destination,
|
|
56
|
+
{
|
|
57
|
+
in: [destination, 'requires'],
|
|
58
|
+
where: { name: 'srv-api' }
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project, additions })
|
|
44
62
|
}
|
|
45
63
|
}
|
|
46
64
|
}
|
package/lib/mtx/auth_manager.js
CHANGED
|
@@ -67,7 +67,7 @@ function reqParams(method, params) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
async function fetchToken(params) {
|
|
70
|
-
if (params.has('token') || !(params.has('refreshToken') || params.has('passcode') || !params.has('passcodeUrl'))) {
|
|
70
|
+
if (params.has('token') || !(params.has('refreshToken') || params.has('passcode') || params.has('clientid') || !params.has('passcodeUrl'))) {
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -99,18 +99,20 @@ async function fetchToken(params) {
|
|
|
99
99
|
if (error) {
|
|
100
100
|
let message;
|
|
101
101
|
if (REASONS.invalid_scope.test(error.message)) {
|
|
102
|
-
message = 'token has invalid scope.
|
|
102
|
+
message = 'token has invalid scope. Ensure your user has the required roles';
|
|
103
103
|
} else if (error.status === 404) {
|
|
104
|
-
message = 'token endpoint not found.
|
|
104
|
+
message = 'token endpoint not found. Ensure that MTX is running with extensibility enabled';
|
|
105
105
|
} else if (error.message.includes('<html')) { // should already be caught when fetching passcode URL
|
|
106
|
-
message = 'HTML response received.
|
|
106
|
+
message = 'HTML response received. Ensure the route to MTX is configured correctly in App Router';
|
|
107
107
|
} else if (error.status === 401) {
|
|
108
108
|
message = `invalid credentials`;
|
|
109
109
|
if (params.has('passcode')) {
|
|
110
|
-
message += `.
|
|
110
|
+
message += `. Ensure the passcode is correct`;
|
|
111
111
|
if (params.has('passcodeUrl')) {
|
|
112
112
|
message += `. Passcode URL: ${params.get('passcodeUrl')}`;
|
|
113
113
|
}
|
|
114
|
+
} else if (params.has('clientid')) {
|
|
115
|
+
message += `. Ensure the client credentials are correct`;
|
|
114
116
|
}
|
|
115
117
|
} else {
|
|
116
118
|
message = 'error on token request';
|
package/lib/mtx/util/errors.js
CHANGED
|
@@ -5,11 +5,11 @@ function handleHttpError(error, params, { url, command } = {}) {
|
|
|
5
5
|
const prefix = `Request to ${url} failed`;
|
|
6
6
|
switch (error.status) {
|
|
7
7
|
case 401:
|
|
8
|
-
throw getMessage(`${prefix}: invalid authentication
|
|
9
|
-
params.has('
|
|
10
|
-
|
|
8
|
+
throw getMessage(`${prefix}: invalid authentication` + (
|
|
9
|
+
params.has('username') ? `. Ensure that username and password are correct` : ''
|
|
10
|
+
), { error, command });
|
|
11
11
|
case 403:
|
|
12
|
-
throw getMessage(prefix + ': insufficient authorization. Ensure
|
|
12
|
+
throw getMessage(prefix + ': insufficient authorization. Ensure the user has all necessary roles.', { error, command });
|
|
13
13
|
case 404:
|
|
14
14
|
throw getMessage(prefix + ': resource not found.', { error, command });
|
|
15
15
|
case 422:
|