@sap/cds-dk 9.4.1 → 9.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/bin/data-products/index.js +10 -2
- package/bin/data-products/prepare-csn.js +63 -26
- package/bin/help.js +2 -2
- package/bin/import.js +7 -2
- package/bin/up.js +25 -4
- package/bin/util/containerize.js +142 -0
- package/lib/build/buildTaskEngine.js +5 -2
- package/lib/build/plugin.js +1 -1
- package/lib/build/plugins/helm/index.js +6 -7
- package/lib/build/provider/hana/index.js +10 -2
- package/lib/import/common.js +3 -3
- package/lib/import/message.js +1 -1
- package/lib/init/constants.js +3 -1
- package/lib/init/index.js +4 -5
- package/lib/init/projectReader.js +101 -77
- package/lib/init/registries/mta.js +3 -0
- package/lib/init/registries/xs-app.js +7 -1
- package/lib/init/template/ams/index.js +7 -6
- package/lib/init/template/app-frontend/files/mta.yaml.hbs +0 -7
- package/lib/init/template/app-frontend/index.js +2 -2
- package/lib/init/template/application-logging/index.js +13 -10
- package/lib/init/template/approuter/files/mta.yaml.hbs +7 -0
- package/lib/init/template/approuter/index.js +30 -18
- package/lib/init/template/attachments/index.js +3 -3
- package/lib/init/template/audit-logging/index.js +4 -4
- package/lib/init/template/cloud-logging/index.js +13 -10
- package/lib/init/template/connectivity/index.js +3 -3
- package/lib/init/template/containerize/files/containerize.yaml.hbs +1 -2
- package/lib/init/template/destination/index.js +5 -9
- package/lib/init/template/dynatrace/index.js +13 -10
- package/lib/init/template/enterprise-messaging/index.js +5 -5
- package/lib/init/template/enterprise-messaging-shared/index.js +4 -4
- package/lib/init/template/extensibility/index.js +2 -2
- package/lib/init/template/file-based-messaging/index.js +2 -2
- package/lib/init/template/github-actions/files/kyma-setup/action.yaml +0 -2
- package/lib/init/template/github-actions/index.js +3 -3
- package/lib/init/template/hana/index.js +19 -22
- package/lib/init/template/helm/index.js +47 -50
- package/lib/init/template/html5-repo/files/containerize.yaml.hbs +0 -10
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +3 -7
- package/lib/init/template/html5-repo/files/values.yaml.hbs +6 -0
- package/lib/init/template/html5-repo/files/xs-app.json.hbs +5 -3
- package/lib/init/template/html5-repo/index.js +10 -8
- package/lib/init/template/http/index.js +31 -10
- package/lib/init/template/ias/files/mta.yaml.hbs +3 -0
- package/lib/init/template/ias/files/values.yaml.hbs +4 -1
- package/lib/init/template/ias/index.js +10 -11
- package/lib/init/template/kafka/index.js +3 -3
- package/lib/init/template/local-messaging/index.js +2 -2
- package/lib/init/template/malware-scanner/index.js +3 -7
- package/lib/init/template/mta/files/mta.yaml.hbs +10 -0
- package/lib/init/template/multitenancy/index.js +8 -10
- package/lib/init/template/notifications/index.js +2 -2
- package/lib/init/template/pipeline/index.js +5 -1
- package/lib/init/template/portal/files/mta.yaml.hbs +6 -0
- package/lib/init/template/portal/index.js +7 -7
- package/lib/init/template/postgres/index.js +4 -4
- package/lib/init/template/redis/index.js +2 -2
- package/lib/init/template/redis-messaging/index.js +2 -2
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +2 -2
- package/lib/init/template/sample/files/javascript/admin-service.js.hbs +24 -0
- package/lib/init/template/sample/files/javascript/cat-service.js.hbs +43 -0
- package/lib/init/template/sample/files/typescript/admin-service.ts.hbs +16 -0
- package/lib/init/template/sample/files/typescript/cat-service.ts.hbs +31 -0
- package/lib/init/template/test/files/test/test.xs.hbs +1 -1
- package/lib/init/template/test/index.js +2 -2
- package/lib/init/template/tiny-sample/index.js +1 -1
- package/lib/init/template/workzone-standard/index.js +5 -6
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +0 -2
- package/lib/init/template/xsuaa/index.js +24 -19
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/util/question.js +1 -1
- package/npm-shrinkwrap.json +22 -22
- package/package.json +1 -1
|
@@ -44,13 +44,16 @@ identity:
|
|
|
44
44
|
{{#hasXsuaa}}
|
|
45
45
|
xsuaa-cross-consumption: true
|
|
46
46
|
{{/hasXsuaa}}
|
|
47
|
+
provided-apis:
|
|
48
|
+
- name: {{appName}}-ias-api
|
|
49
|
+
description: API exposed by the application
|
|
47
50
|
oauth2-configuration:
|
|
48
51
|
token-policy:
|
|
49
52
|
access-token-format: "jwt"
|
|
50
53
|
{{#hasApprouter}}
|
|
51
54
|
redirect-uris:
|
|
52
55
|
{{=<% %>=}}
|
|
53
|
-
- https://*.{{ tpl .Values.global.domain . }}
|
|
56
|
+
- https://*.{{ tpl .Values.global.domain . }}/**
|
|
54
57
|
<%={{ }}=%>
|
|
55
58
|
post-logout-redirect-uris:
|
|
56
59
|
{{=<% %>=}}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { readProject } = require('../../projectReader')
|
|
2
2
|
const { merge, sort } = require('../../merge')
|
|
3
|
-
const { srv4, approuter, mtxSidecar4 } = require('../../registries/mta')
|
|
3
|
+
const { srv4, approuter, ias, mtxSidecar4 } = require('../../registries/mta')
|
|
4
4
|
const cds = require('../../../cds')
|
|
5
5
|
const { exists, read } = cds.utils
|
|
6
6
|
|
|
@@ -21,16 +21,16 @@ module.exports = class IasTemplate extends require('../../plugin') {
|
|
|
21
21
|
const project = readProject()
|
|
22
22
|
const { configFile, isNodejs } = project
|
|
23
23
|
project.profile ??= 'production'
|
|
24
|
-
project.shortcut = typeof (await read(configFile)).cds?.requires?.
|
|
24
|
+
project.shortcut = exists(configFile) ? typeof (await read(configFile)).cds?.requires?.db !== 'object' : true
|
|
25
25
|
await merge(__dirname, 'files/package.json.hbs').into(configFile, { project, forceOverwrite: true })
|
|
26
26
|
if (isNodejs) await sort('package.json', 'dependencies')
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async combine() {
|
|
30
30
|
const project = readProject()
|
|
31
|
-
const { isJava, hasMta,
|
|
31
|
+
const { isJava, addMta, hasMta, addCfManifest, addHelm, addHelmUnifiedRuntime, addApprouter, addMultitenancy, srvPath } = project
|
|
32
32
|
|
|
33
|
-
if (
|
|
33
|
+
if (addMultitenancy) {
|
|
34
34
|
const conf = exists('mtx/sidecar/package.json') ? await read('mtx/sidecar/package.json') : {}
|
|
35
35
|
conf.cds ??= {}
|
|
36
36
|
const profile = conf.cds.profile
|
|
@@ -43,15 +43,14 @@ module.exports = class IasTemplate extends require('../../plugin') {
|
|
|
43
43
|
await merge(__dirname, 'files/sidecar.package.json.hbs').into('mtx/sidecar/package.json')
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
if (hasMta) {
|
|
46
|
+
if (addMta || (addApprouter || addMultitenancy) && hasMta) {
|
|
47
47
|
const srv = srv4(srvPath)
|
|
48
|
-
const identity = { in: 'resources', where: { 'parameters.service': 'identity' } }
|
|
49
48
|
const srvIdentityBinding = { in: [srv, 'requires'], where: { 'parameters.config.app-identifier': 'srv' } }
|
|
50
49
|
const srvCertUrlApi = { in: [srv, 'provides'], where: { 'name': 'srv-api' } }
|
|
51
|
-
const additions = [srv,
|
|
50
|
+
const additions = [srv, ias, srvIdentityBinding, srvCertUrlApi]
|
|
52
51
|
const overwrites = []
|
|
53
52
|
|
|
54
|
-
if (
|
|
53
|
+
if (addApprouter) {
|
|
55
54
|
additions.push(approuter)
|
|
56
55
|
additions.push({ in: [approuter, 'requires'], where: { 'parameters.config.app-identifier': 'approuter' }})
|
|
57
56
|
const approuterSrvApi = { in: [approuter, 'requires'], where: { 'name': 'srv-api' } }
|
|
@@ -60,7 +59,7 @@ module.exports = class IasTemplate extends require('../../plugin') {
|
|
|
60
59
|
overwrites.push({ item: [approuterSrvApi, 'properties.forwardAuthCertificates'], withValue: true })
|
|
61
60
|
overwrites.push({ item: [approuterSrvApi, 'properties.strictSSL'], withValue: true })
|
|
62
61
|
}
|
|
63
|
-
if (
|
|
62
|
+
if (addMultitenancy) {
|
|
64
63
|
const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
|
|
65
64
|
const mtxIdentityBinding = { in: [mtxSidecar, 'requires'], where: { 'parameters.config.app-identifier': 'mtx' } }
|
|
66
65
|
additions.push(mtxSidecar, mtxIdentityBinding)
|
|
@@ -68,13 +67,13 @@ module.exports = class IasTemplate extends require('../../plugin') {
|
|
|
68
67
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { project, additions, overwrites })
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
if (
|
|
70
|
+
if (addHelm || addHelmUnifiedRuntime) {
|
|
72
71
|
const identity = { in: 'dependencies', where: { 'alias': 'identity' } }
|
|
73
72
|
await merge(__dirname, 'files/Chart.yaml.hbs').into('chart/Chart.yaml', { project, additions: [identity] })
|
|
74
73
|
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { project })
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
if (
|
|
76
|
+
if (addCfManifest) {
|
|
78
77
|
await this.#combineWithCfManifest(project) // REVISIT: we shouldn't overly promote cf-manifest
|
|
79
78
|
}
|
|
80
79
|
}
|
|
@@ -28,9 +28,9 @@ module.exports = class KafkaTemplate extends require('../../plugin') {
|
|
|
28
28
|
|
|
29
29
|
async combine() {
|
|
30
30
|
const project = readProject()
|
|
31
|
-
const {
|
|
31
|
+
const { addMta, srvPath, addHelm, addHelmUnifiedRuntime } = project
|
|
32
32
|
|
|
33
|
-
if (
|
|
33
|
+
if (addMta) {
|
|
34
34
|
const srv = srv4(srvPath)
|
|
35
35
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
36
36
|
project,
|
|
@@ -42,7 +42,7 @@ module.exports = class KafkaTemplate extends require('../../plugin') {
|
|
|
42
42
|
})
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
if (
|
|
45
|
+
if (addHelm || addHelmUnifiedRuntime) {
|
|
46
46
|
await merge(__dirname, 'files/values.yaml').into('chart/values.yaml')
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
|
-
const { read } = cds.utils
|
|
2
|
+
const { read, exists } = cds.utils
|
|
3
3
|
const { readProject } = require('../../projectReader')
|
|
4
4
|
const { merge } = require('../../merge')
|
|
5
5
|
|
|
@@ -22,7 +22,7 @@ module.exports = class LocalMessagingTemplate extends require('../../plugin') {
|
|
|
22
22
|
async run() {
|
|
23
23
|
const project = readProject()
|
|
24
24
|
const { configFile } = project
|
|
25
|
-
project.shortcut = typeof (await read(configFile)).cds?.requires?.messaging !== 'object'
|
|
25
|
+
project.shortcut = !exists(configFile) || typeof (await read(configFile)).cds?.requires?.messaging !== 'object'
|
|
26
26
|
await merge(__dirname, 'files/package.json.hbs').into(configFile, { with: project })
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -12,10 +12,6 @@ module.exports = class MalwareScannerTemplate extends require('../../plugin') {
|
|
|
12
12
|
return !!env.requires['malware-scanner']
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
async canRun() {
|
|
16
|
-
return true
|
|
17
|
-
}
|
|
18
|
-
|
|
19
15
|
async run() {
|
|
20
16
|
const project = readProject()
|
|
21
17
|
const { isNodejs } = project
|
|
@@ -26,9 +22,9 @@ module.exports = class MalwareScannerTemplate extends require('../../plugin') {
|
|
|
26
22
|
|
|
27
23
|
async combine() {
|
|
28
24
|
const project = readProject()
|
|
29
|
-
const {
|
|
25
|
+
const { addMta, addHelm, addHelmUnifiedRuntime, srvPath } = project
|
|
30
26
|
|
|
31
|
-
if (
|
|
27
|
+
if (addMta) {
|
|
32
28
|
const srv = srv4(srvPath)
|
|
33
29
|
const additions = [srv, malwareScanner ]
|
|
34
30
|
const relationships = [{
|
|
@@ -40,7 +36,7 @@ module.exports = class MalwareScannerTemplate extends require('../../plugin') {
|
|
|
40
36
|
})
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
if (
|
|
39
|
+
if (addHelm || addHelmUnifiedRuntime) {
|
|
44
40
|
await merge(__dirname, 'files', 'values.yaml').into('chart/values.yaml')
|
|
45
41
|
}
|
|
46
42
|
}
|
|
@@ -43,6 +43,16 @@ modules:
|
|
|
43
43
|
properties:
|
|
44
44
|
srv-url: ${default-url}
|
|
45
45
|
requires: []
|
|
46
|
+
{{#externalServices}}
|
|
47
|
+
- name: {{name}}
|
|
48
|
+
type: nodejs
|
|
49
|
+
path: {{& path }}
|
|
50
|
+
parameters:
|
|
51
|
+
instances: 1
|
|
52
|
+
buildpack: nodejs_buildpack
|
|
53
|
+
build-parameters:
|
|
54
|
+
builder: npm-ci
|
|
55
|
+
{{/externalServices}}
|
|
46
56
|
|
|
47
57
|
resources:
|
|
48
58
|
[]
|
|
@@ -19,9 +19,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
static hasInProduction(env) {
|
|
22
|
-
|
|
23
|
-
// REVISIT: Check if this can be simplified
|
|
24
|
-
return options?.add?.has('mtx') || options?.add?.has('multitenancy') || !!env.requires?.multitenancy || false
|
|
22
|
+
return env.requires?.multitenancy
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
async run() {
|
|
@@ -44,12 +42,12 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
44
42
|
async combine() {
|
|
45
43
|
const project = readProject()
|
|
46
44
|
const {
|
|
47
|
-
isNodejs, isJava, hasMta,
|
|
48
|
-
hasXsuaa, hasIas, hasHana,
|
|
45
|
+
isNodejs, isJava, addMta, hasMta, addHelm, addHelmUnifiedRuntime,
|
|
46
|
+
addXsuaa, hasXsuaa, addIas, hasIas, hasHana, addContainerize, hasApprouter,
|
|
49
47
|
srvPath, appName
|
|
50
48
|
} = project
|
|
51
49
|
|
|
52
|
-
if (hasMta) {
|
|
50
|
+
if (addMta || (addIas || addXsuaa) && hasMta) {
|
|
53
51
|
const srv = srv4(srvPath)
|
|
54
52
|
const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
|
|
55
53
|
const modules = [srv, mtxSidecar]
|
|
@@ -60,7 +58,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
60
58
|
if (isJava) apis.push(requiredMtxSidecarApi4(srv))
|
|
61
59
|
const additions = [...modules, ...services, ...apis]
|
|
62
60
|
const relationships = []
|
|
63
|
-
if (
|
|
61
|
+
if (addXsuaa) {
|
|
64
62
|
relationships.push({
|
|
65
63
|
insert: [saasRegistry, 'name'],
|
|
66
64
|
into: [isJava ? srv : mtxSidecar, 'requires', 'name']
|
|
@@ -82,7 +80,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
82
80
|
await merge(templateMtaPath).into('mta.yaml', { with: project, additions, relationships })
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
if (
|
|
83
|
+
if (addHelm || addHelmUnifiedRuntime) {
|
|
86
84
|
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
|
|
87
85
|
const applicationWorkload = hasApprouter ? 'approuter' : 'srv'
|
|
88
86
|
await merge({
|
|
@@ -96,7 +94,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
96
94
|
}).into('chart/values.yaml',{ forceOverwrite: true })
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
if (
|
|
97
|
+
if (addContainerize) {
|
|
100
98
|
const deletions = []
|
|
101
99
|
if (hasHana) {
|
|
102
100
|
deletions.push({
|
|
@@ -113,7 +111,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
113
111
|
await merge(__dirname, '/files/containerize.yaml.hbs').into('containerize.yaml', { with: project, additions, deletions })
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
if (
|
|
114
|
+
if (addXsuaa) {
|
|
117
115
|
await merge(__dirname, 'files/xs-security.json.hbs').into('xs-security.json', {
|
|
118
116
|
project,
|
|
119
117
|
additions: [{
|
|
@@ -35,9 +35,9 @@ module.exports = class NotificationsTemplate extends require('../../plugin') {
|
|
|
35
35
|
|
|
36
36
|
async combine() {
|
|
37
37
|
const project = readProject()
|
|
38
|
-
const {
|
|
38
|
+
const { addMta } = project
|
|
39
39
|
|
|
40
|
-
if (
|
|
40
|
+
if (addMta) {
|
|
41
41
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { project, additions: [notificationTypesDeployer] })
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -24,12 +24,16 @@ module.exports = class PipelineTemplate extends require('../../plugin') {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
async run() {
|
|
27
|
-
await
|
|
27
|
+
await Promise.all([
|
|
28
|
+
copy(join(__dirname, 'files', '.pipeline')).to(join(cds.root, '.pipeline')),
|
|
29
|
+
copy(join(__dirname, 'files', 'Jenkinsfile')).to(join(cds.root, 'Jenkinsfile'))
|
|
30
|
+
])
|
|
28
31
|
|
|
29
32
|
const project = readProject()
|
|
30
33
|
const { apps, appPath, hasUI5 } = project
|
|
31
34
|
|
|
32
35
|
if (hasUI5) { // UI5 integration might be needed even without HTML5 repo
|
|
36
|
+
console.log('Adding UI5 integration to the pipeline for the detected UI5 apps...')
|
|
33
37
|
for (const { app } of apps) {
|
|
34
38
|
project.app = app
|
|
35
39
|
await Promise.all([
|
|
@@ -28,13 +28,13 @@ module.exports = class PortalTemplate extends require('../../plugin') {
|
|
|
28
28
|
|
|
29
29
|
async combine() {
|
|
30
30
|
const project = readProject()
|
|
31
|
-
const { appName, isJava, hasMta, srvPath,
|
|
31
|
+
const { appName, isJava, addMta, hasMta, srvPath, addHtml5Repo, addXsuaa, addApprouter, addMultitenancy, addHelm, addHelmUnifiedRuntime, addContainerize, hasApprouter, hasHtml5Repo } = project
|
|
32
32
|
|
|
33
|
-
if (
|
|
33
|
+
if (addMultitenancy) {
|
|
34
34
|
await merge(__dirname, 'files/package.sidecar.json').into('mtx/sidecar/package.json')
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
if (hasMta) {
|
|
37
|
+
if (addMta || (addXsuaa || addHtml5Repo || addApprouter || addMultitenancy) && hasMta) {
|
|
38
38
|
const srv = srv4(srvPath)
|
|
39
39
|
const additions = [srv, portal, appDeployer, portalDeployer]
|
|
40
40
|
const relationships = [{
|
|
@@ -45,7 +45,7 @@ module.exports = class PortalTemplate extends require('../../plugin') {
|
|
|
45
45
|
into: [portalDeployer, 'requires', 'name']
|
|
46
46
|
}]
|
|
47
47
|
|
|
48
|
-
if (
|
|
48
|
+
if (addXsuaa) {
|
|
49
49
|
additions.push(xsuaa)
|
|
50
50
|
relationships.push({
|
|
51
51
|
insert: [xsuaa, 'name'],
|
|
@@ -68,7 +68,7 @@ module.exports = class PortalTemplate extends require('../../plugin') {
|
|
|
68
68
|
})
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
if (
|
|
71
|
+
if (addMultitenancy) {
|
|
72
72
|
relationships.push({
|
|
73
73
|
insert: [portal, 'name'],
|
|
74
74
|
into: [isJava ? srv : mtxSidecar4('gen/mtx/sidecar'), 'requires', 'name']
|
|
@@ -80,7 +80,7 @@ module.exports = class PortalTemplate extends require('../../plugin') {
|
|
|
80
80
|
})
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
if (
|
|
83
|
+
if (addContainerize) {
|
|
84
84
|
const additions = [{
|
|
85
85
|
in: 'modules',
|
|
86
86
|
where: { name: `${appName}-portal-deployer` }
|
|
@@ -88,7 +88,7 @@ module.exports = class PortalTemplate extends require('../../plugin') {
|
|
|
88
88
|
await merge(__dirname, '/files/containerize.yaml.hbs').into('containerize.yaml', { with: project, additions })
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
if (
|
|
91
|
+
if (addHelm || addHelmUnifiedRuntime) {
|
|
92
92
|
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
|
-
const { read } = cds.utils
|
|
2
|
+
const { read, exists } = cds.utils
|
|
3
3
|
const { readProject } = require('../../projectReader')
|
|
4
4
|
const { merge } = require('../../merge')
|
|
5
5
|
const mvn = require('../../mvn')
|
|
@@ -24,16 +24,16 @@ module.exports = class PostgresTemplate extends require('../../plugin') {
|
|
|
24
24
|
async run() {
|
|
25
25
|
const project = readProject()
|
|
26
26
|
const { configFile, isJava } = project
|
|
27
|
-
project.shortcut = typeof (await read(configFile)).cds?.requires?.db !== 'object'
|
|
27
|
+
project.shortcut = !exists(configFile) || typeof (await read(configFile)).cds?.requires?.db !== 'object'
|
|
28
28
|
await merge(__dirname, 'files/package.json.hbs').into('package.json', { project })
|
|
29
29
|
if (isJava) await mvn.add('postgresql')
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async combine() {
|
|
33
33
|
const project = readProject()
|
|
34
|
-
const {
|
|
34
|
+
const { addMta, srvPath } = project
|
|
35
35
|
|
|
36
|
-
if (
|
|
36
|
+
if (addMta) {
|
|
37
37
|
const srv = srv4(srvPath)
|
|
38
38
|
await merge(__dirname, 'files/mta.yml.hbs').into('mta.yaml', {
|
|
39
39
|
project,
|
|
@@ -27,9 +27,9 @@ module.exports = class extends require('../../plugin') {
|
|
|
27
27
|
|
|
28
28
|
async combine() {
|
|
29
29
|
const project = readProject()
|
|
30
|
-
const {
|
|
30
|
+
const { addMta, srvPath } = project
|
|
31
31
|
|
|
32
|
-
if (
|
|
32
|
+
if (addMta) {
|
|
33
33
|
const srv = srv4(srvPath)
|
|
34
34
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
35
35
|
project,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
|
-
const { read } = cds.utils
|
|
2
|
+
const { read, exists } = cds.utils
|
|
3
3
|
const { readProject } = require('../../projectReader')
|
|
4
4
|
const { merge } = require('../../merge')
|
|
5
5
|
|
|
@@ -28,7 +28,7 @@ module.exports = class RedisMessagingTemplate extends require('../../plugin') {
|
|
|
28
28
|
async run() {
|
|
29
29
|
const project = readProject()
|
|
30
30
|
const { configFile } = project
|
|
31
|
-
project.shortcut = typeof (await read(configFile)).cds?.requires?.messaging !== 'object'
|
|
31
|
+
project.shortcut = !exists(configFile) || typeof (await read(configFile)).cds?.requires?.messaging !== 'object'
|
|
32
32
|
await merge(__dirname, 'files/package.json.hbs').into(configFile, { project })
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -109,8 +109,8 @@ extend service AdminService {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// Workaround for Fiori popups for asking user to enter a valid UUID on Create
|
|
112
|
-
annotate AdminService.Authors : ID with @Core.Computed
|
|
113
|
-
annotate AdminService.Books : ID with @Core.Computed
|
|
112
|
+
annotate AdminService.Authors : ID with @Core.Computed;
|
|
113
|
+
annotate AdminService.Books : ID with @Core.Computed;
|
|
114
114
|
|
|
115
115
|
// Show Genre as drop down, not a dialog
|
|
116
116
|
annotate AdminService.Books with {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{{#isESM}}
|
|
2
|
+
import cds from '@sap/cds'
|
|
3
|
+
|
|
4
|
+
export class AdminService extends cds.ApplicationService { init() {
|
|
5
|
+
{{/isESM}}
|
|
6
|
+
{{^isESM}}
|
|
7
|
+
const cds = require('@sap/cds')
|
|
8
|
+
|
|
9
|
+
module.exports = class AdminService extends cds.ApplicationService { init() {
|
|
10
|
+
{{/isESM}}
|
|
11
|
+
|
|
12
|
+
const { Books } = this.entities
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generate IDs for new Books drafts
|
|
16
|
+
*/
|
|
17
|
+
this.before ('NEW', Books.drafts, async (req) => {
|
|
18
|
+
if (req.data.ID) return
|
|
19
|
+
const { ID:id1 } = await SELECT.one.from(Books).columns('max(ID) as ID')
|
|
20
|
+
const { ID:id2 } = await SELECT.one.from(Books.drafts).columns('max(ID) as ID')
|
|
21
|
+
req.data.ID = Math.max(id1||0, id2||0) + 1
|
|
22
|
+
})
|
|
23
|
+
return super.init()
|
|
24
|
+
}}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{{#isESM}}
|
|
2
|
+
import cds from '@sap/cds'
|
|
3
|
+
|
|
4
|
+
export class CatalogService extends cds.ApplicationService { init() {
|
|
5
|
+
{{/isESM}}
|
|
6
|
+
{{^isESM}}
|
|
7
|
+
const cds = require('@sap/cds')
|
|
8
|
+
|
|
9
|
+
module.exports = class CatalogService extends cds.ApplicationService { init() {
|
|
10
|
+
{{/isESM}}
|
|
11
|
+
|
|
12
|
+
const { Books } = cds.entities('sap.capire.bookshop')
|
|
13
|
+
const { ListOfBooks } = this.entities
|
|
14
|
+
|
|
15
|
+
// Add some discount for overstocked books
|
|
16
|
+
this.after('each', ListOfBooks, book => {
|
|
17
|
+
if (book.stock > 111) book.title += ` -- 11% discount!`
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// Reduce stock of ordered books if available stock suffices
|
|
21
|
+
this.on('submitOrder', async req => {
|
|
22
|
+
let { book:id, quantity } = req.data
|
|
23
|
+
let book = await SELECT.one.from (Books, id, b => b.stock)
|
|
24
|
+
|
|
25
|
+
// Validate input data
|
|
26
|
+
if (!book) return req.error (404, `Book #${id} doesn't exist`)
|
|
27
|
+
if (quantity < 1) return req.error (400, `quantity has to be 1 or more`)
|
|
28
|
+
if (!book.stock || quantity > book.stock) return req.error (409, `${quantity} exceeds stock for book #${id}`)
|
|
29
|
+
|
|
30
|
+
// Reduce stock in database and return updated stock value
|
|
31
|
+
await UPDATE (Books, id) .with ({ stock: book.stock -= quantity })
|
|
32
|
+
return book
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// Emit event when an order has been submitted
|
|
36
|
+
this.after('submitOrder', async (_,req) => {
|
|
37
|
+
let { book, quantity } = req.data
|
|
38
|
+
await this.emit('OrderedBook', { book, quantity, buyer: req.user.id })
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// Delegate requests to the underlying generic service
|
|
42
|
+
return super.init()
|
|
43
|
+
}}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import cds from '@sap/cds'
|
|
2
|
+
|
|
3
|
+
import { Authors, Books } from '#cds-models/AdminService'
|
|
4
|
+
|
|
5
|
+
export class AdminService extends cds.ApplicationService { init(){
|
|
6
|
+
this.before (['NEW','CREATE'], Authors, genid)
|
|
7
|
+
this.before (['NEW','CREATE'], Books, genid)
|
|
8
|
+
return super.init()
|
|
9
|
+
}}
|
|
10
|
+
|
|
11
|
+
/** Generate primary keys for target entity in request */
|
|
12
|
+
async function genid (req:any) {
|
|
13
|
+
if (req.data.ID) return
|
|
14
|
+
const {id} = await SELECT.one.from(req.target).columns('max(ID) as id')
|
|
15
|
+
req.data.ID = id + 4 // Note: that is not safe! ok for this sample only.
|
|
16
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import cds from '@sap/cds'
|
|
2
|
+
|
|
3
|
+
import { Books } from '#cds-models/sap/capire/bookshop'
|
|
4
|
+
import { submitOrder, ListOfBooks } from '#cds-models/CatalogService'
|
|
5
|
+
|
|
6
|
+
export class CatalogService extends cds.ApplicationService { async init() {
|
|
7
|
+
|
|
8
|
+
// Add some discount for overstocked books
|
|
9
|
+
this.after('each', ListOfBooks, book => {
|
|
10
|
+
if (book?.stock === undefined || book.stock === null) return
|
|
11
|
+
if (book?.stock > 111) book.title += ` -- 11% discount!`
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
// Reduce stock of ordered books if available stock suffices
|
|
15
|
+
this.on(submitOrder, async req => {
|
|
16
|
+
let { book:id, quantity } = req.data
|
|
17
|
+
let book = await SELECT.from (Books, id!, b => b.stock)
|
|
18
|
+
|
|
19
|
+
// Validate input data
|
|
20
|
+
if (!book) return req.error (404, `Book #${id} doesn't exist`)
|
|
21
|
+
if (!quantity || quantity < 1) return req.error (400, `quantity has to be 1 or more`)
|
|
22
|
+
if (quantity > book.stock!) return req.error (409, `${quantity} exceeds stock for book #${id}`)
|
|
23
|
+
|
|
24
|
+
// Reduce stock in database and return updated stock value
|
|
25
|
+
await UPDATE (Books, id) .with ({ stock: book.stock! -= quantity })
|
|
26
|
+
return book
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// Delegate requests to the underlying generic service
|
|
30
|
+
return super.init()
|
|
31
|
+
}}
|
|
@@ -13,7 +13,7 @@ const { GET, POST, expect, axios } = cds.test (__dirname+'/..')
|
|
|
13
13
|
axios.defaults.auth = { username: '{{user}}', password: '{{password}}' }
|
|
14
14
|
{{/user}}
|
|
15
15
|
|
|
16
|
-
describe('OData APIs', () => {
|
|
16
|
+
describe('{{serviceName}} OData APIs', () => {
|
|
17
17
|
|
|
18
18
|
{{#entities}}{{=<% %>=}}
|
|
19
19
|
it('serves <%name%>', async () => {
|
|
@@ -69,7 +69,7 @@ async function createNodeTest(proj) {
|
|
|
69
69
|
.filter(([name]) => name.match(nameFilter))
|
|
70
70
|
.filter(([name]) => !name.match(/[._]texts$/))
|
|
71
71
|
.filter(([, e]) => !e['@cds.autoexposed']) // only consider non-autoexposed entities to reduce clutter
|
|
72
|
-
.map(([, e]) => e)
|
|
72
|
+
.map(([name, e]) => {e._nameUnqualified = name; return e})
|
|
73
73
|
|
|
74
74
|
let entity // use one entity only (don't want to make users test all entities)
|
|
75
75
|
if (entities.length) entity = entities[0]
|
|
@@ -99,7 +99,7 @@ async function createNodeTest(proj) {
|
|
|
99
99
|
|
|
100
100
|
proj.entities = [{
|
|
101
101
|
name: entity.name,
|
|
102
|
-
urlPath: `/${sInfo.endpoints[0].path}${entity.
|
|
102
|
+
urlPath: `/${sInfo.endpoints[0].path}${entity._nameUnqualified}`,
|
|
103
103
|
selectString: selectElements.join(','),
|
|
104
104
|
elementsString: JSON.stringify(
|
|
105
105
|
Object.entries(sampleData[entity.name][0])
|
|
@@ -14,7 +14,7 @@ module.exports = class TinySampleTemplate extends require('../../plugin') {
|
|
|
14
14
|
async run() {
|
|
15
15
|
const { isJava } = readProject()
|
|
16
16
|
if (isJava) {
|
|
17
|
-
if (!cds.cli.options.add
|
|
17
|
+
if (!cds.cli.options.add?.has(JAVA)) {
|
|
18
18
|
await mvn.add('tiny_sample')
|
|
19
19
|
}
|
|
20
20
|
} else {
|
|
@@ -26,7 +26,7 @@ module.exports = class extends require('../../plugin') {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
static hasInProduction(env) {
|
|
29
|
-
return !!env.requires?.workzone || cds.cli.options.add
|
|
29
|
+
return !!env.requires?.workzone || cds.cli.options.add?.has('workzone-standard')
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async run() {
|
|
@@ -41,7 +41,7 @@ module.exports = class extends require('../../plugin') {
|
|
|
41
41
|
|
|
42
42
|
async combine() {
|
|
43
43
|
const project = readProject()
|
|
44
|
-
const { isJava, hasMta, srvPath, apps, appPath, appUIPaths,
|
|
44
|
+
const { isJava, addMta, hasMta, srvPath, apps, appPath, appUIPaths, addMultitenancy, strippedAppName } = project
|
|
45
45
|
|
|
46
46
|
await Promise.all(appUIPaths.map(async p => {
|
|
47
47
|
project.uiApp = p
|
|
@@ -67,7 +67,7 @@ module.exports = class extends require('../../plugin') {
|
|
|
67
67
|
await merge(__dirname, 'files/xs-app.json.hbs').into(join(appPath, app, 'xs-app.json'), { with: project, additions, overwrites })
|
|
68
68
|
}))
|
|
69
69
|
|
|
70
|
-
if (
|
|
70
|
+
if (addMultitenancy) {
|
|
71
71
|
const mtxPackageJson = await read('mtx/sidecar/package.json')
|
|
72
72
|
mtxPackageJson.cds ??= {}
|
|
73
73
|
mtxPackageJson.cds.requires ??= {}
|
|
@@ -78,14 +78,14 @@ module.exports = class extends require('../../plugin') {
|
|
|
78
78
|
await write('mtx/sidecar/package.json', mtxPackageJson, { spaces: 2 })
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
if (hasMta) {
|
|
81
|
+
if (addMta || addMultitenancy && hasMta) {
|
|
82
82
|
const srv = srv4(srvPath)
|
|
83
83
|
const additions = [srv, destinations, destination, {
|
|
84
84
|
in: [destination, 'requires'],
|
|
85
85
|
where: { name: 'srv-api' }
|
|
86
86
|
}]
|
|
87
87
|
const relationships = []
|
|
88
|
-
if (
|
|
88
|
+
if (addMultitenancy) {
|
|
89
89
|
additions.push(html5RepoHost)
|
|
90
90
|
relationships.push({
|
|
91
91
|
insert: [html5RepoHost, 'name'],
|
|
@@ -93,7 +93,6 @@ module.exports = class extends require('../../plugin') {
|
|
|
93
93
|
})
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
97
96
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project, additions, relationships })
|
|
98
97
|
}
|
|
99
98
|
}
|
|
@@ -6,13 +6,11 @@ modules:
|
|
|
6
6
|
requires:
|
|
7
7
|
- name: {{appName}}-auth
|
|
8
8
|
|
|
9
|
-
{{#hasMultitenancy}}
|
|
10
9
|
- name: {{appName}}-mtx
|
|
11
10
|
type: nodejs
|
|
12
11
|
path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
|
|
13
12
|
requires:
|
|
14
13
|
- name: {{appName}}-auth
|
|
15
|
-
{{/hasMultitenancy}}
|
|
16
14
|
|
|
17
15
|
resources:
|
|
18
16
|
- name: {{appName}}-auth{{#servicePlan}}-{{servicePlan}}{{/servicePlan}}
|