@sap/cds-dk 9.1.2 → 9.2.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/bin/cds.js +2 -0
  3. package/bin/repl.js +4 -2
  4. package/bin/up.js +11 -1
  5. package/bin/util/log.js +8 -1
  6. package/bin/version.js +20 -15
  7. package/lib/bind/shared.js +3 -1
  8. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
  9. package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +1 -1
  10. package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +8 -0
  11. package/lib/build/plugins/helm/files/subcharts/web-application/templates/virtual-service.yaml +38 -0
  12. package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +15 -0
  13. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +12 -9
  14. package/lib/build/plugins/helm/index.js +1 -1
  15. package/lib/build/provider/hana/index.js +5 -4
  16. package/lib/build/provider/hana/template/.hdiconfig-all +6 -0
  17. package/lib/compile/to-xsuaa.js +3 -2
  18. package/lib/init/constants.js +5 -3
  19. package/lib/init/index.js +6 -1
  20. package/lib/init/merge.js +7 -3
  21. package/lib/init/projectReader.js +4 -1
  22. package/lib/init/registries/mta.js +6 -0
  23. package/lib/init/template/ams/files/values.yaml.hbs +5 -0
  24. package/lib/init/template/approuter/files/containerize.yaml.hbs +1 -1
  25. package/lib/init/template/approuter/files/values.yaml.hbs +1 -5
  26. package/lib/init/template/data/as-json.js +4 -3
  27. package/lib/init/template/data/index.js +1 -0
  28. package/lib/init/template/destination/files/mta.yaml.hbs +1 -20
  29. package/lib/init/template/extension/index.js +1 -1
  30. package/lib/init/template/github-actions/files/cf-github-deploy/action.yaml +48 -0
  31. package/lib/init/template/github-actions/files/cf-setup/action.yaml +53 -0
  32. package/lib/init/template/github-actions/files/kyma-info/action.yaml +37 -0
  33. package/lib/init/template/github-actions/files/kyma-setup/action.yaml +64 -0
  34. package/lib/init/template/github-actions/files/workflows/cf.yaml.hbs +48 -0
  35. package/lib/init/template/github-actions/files/workflows/kyma.yaml.hbs +39 -0
  36. package/lib/init/template/github-actions/files/workflows/test.yaml.hbs +21 -0
  37. package/lib/init/template/github-actions/index.js +73 -0
  38. package/lib/init/template/helm/index.js +5 -1
  39. package/lib/init/template/html5-repo/files/containerize.yaml.hbs +4 -4
  40. package/lib/init/template/html5-repo/files/mta.yaml.hbs +24 -0
  41. package/lib/init/template/html5-repo/files/values.yaml.hbs +2 -1
  42. package/lib/init/template/html5-repo/index.js +9 -3
  43. package/lib/init/template/http/index.js +4 -4
  44. package/lib/init/template/ias/files/package.json.hbs +7 -0
  45. package/lib/init/template/ias/files/values.yaml.hbs +1 -4
  46. package/lib/init/template/ias/index.js +2 -1
  47. package/lib/init/template/kyma/index.js +10 -0
  48. package/lib/init/template/malware-scanner/index.js +1 -1
  49. package/lib/init/template/multitenancy/files/values.yaml.hbs +53 -1
  50. package/lib/init/template/multitenancy/index.js +0 -13
  51. package/lib/init/template/pipeline/files/Jenkinsfile +2 -2
  52. package/lib/init/template/pipeline/index.js +1 -1
  53. package/lib/init/template/portal/files/containerize.yaml.hbs +15 -0
  54. package/lib/init/template/portal/files/values.yaml.hbs +1 -1
  55. package/lib/init/template/portal/index.js +9 -1
  56. package/lib/init/template/sample/index.js +1 -1
  57. package/lib/init/template/test/index.js +1 -1
  58. package/lib/init/template/tiny-sample/index.js +1 -1
  59. package/lib/init/template/typescript/index.js +1 -1
  60. package/lib/init/template/workzone-standard/index.js +13 -4
  61. package/lib/init/template/xsuaa/files/mta.yaml.hbs +8 -0
  62. package/lib/init/template/xsuaa/index.js +11 -0
  63. package/lib/init/template.js +38 -26
  64. package/lib/lint/eslintHelp.json +1 -1
  65. package/lib/watch/watched.js +1 -1
  66. package/npm-shrinkwrap.json +15 -15
  67. package/package.json +1 -1
  68. /package/lib/init/template/html5-repo/files/{ui-resources/package.json.hbs → html5-deployer.package.json.hbs} +0 -0
@@ -228,9 +228,10 @@ function dataForField(element, artifact, csn, record, data, parent, depth, refer
228
228
  return randomIntInRange(range)
229
229
  }
230
230
  case 'cds.hana.REAL':
231
- case 'cds.Decimal': { // Decimal(9,5), Decimal(9), Decimal(precision:5)
231
+ case 'cds.Decimal': { // Decimal(9,5), Decimal(9), Decimal(precision:5), Decimal(2,2)
232
232
  const scale = element.scale ?? (element.precision ? 0 : 2) // scale is 0 if only precision is given
233
- const prec = element.precision ? Math.min(Math.pow(10, element.precision-scale), Number.MAX_SAFE_INTEGER) : 100
233
+ //10^x would allow one digit more than allowed, that's why -1
234
+ const prec = element.precision ? Math.min(Math.pow(10, element.precision - scale) - 1, Number.MAX_SAFE_INTEGER) : 100
234
235
  const range = { from: 0, to: prec }
235
236
  annotatedIntRange(element, range)
236
237
  return +(randomDecimalInRange(range).toFixed(scale))
@@ -550,7 +551,7 @@ function randomDateInRange(dateRange) {
550
551
  function randomDecimalInRange(decimalRange) {
551
552
  const max = decimalRange.to
552
553
  const min = decimalRange.from
553
- const num = min + (randomNumber() % (max - min))
554
+ const num = max === 0 ? 0 : min + (randomNumber() % (max - min))
554
555
  let dec = randomNumber()
555
556
  const divider = Math.pow(10, dec.toString().length)
556
557
  dec = dec / divider
@@ -82,6 +82,7 @@ module.exports = class DataTemplate extends require('../../plugin') {
82
82
 
83
83
  if (contentType === 'csv') {
84
84
  const headerOnly = !cds.cli.options['records'] // compat to old behavior which only creates headers
85
+ if (headerOnly) console.log(`${dim('adding headers only, use --records to create random entries')}`)
85
86
  await asCsv(data, csn, Object.assign({ headerOnly }, dataForParams))
86
87
  }
87
88
 
@@ -22,23 +22,4 @@ resources:
22
22
  type: org.cloudfoundry.managed-service
23
23
  parameters:
24
24
  service: destination
25
- service-plan: lite{{#hasHtml5Repo}}
26
- config:
27
- HTML5Runtime_enabled: true
28
- init_data:
29
- instance:
30
- existing_destinations_policy: update
31
- destinations:
32
- - Name: srv-api
33
- URL: ~{srv-api/srv-url}
34
- Authentication: NoAuthentication
35
- Type: HTTP
36
- ProxyType: Internet
37
- HTML5.ForwardAuthToken: true
38
- HTML5.DynamicDestination: true
39
- - Name: ui5
40
- URL: https://ui5.sap.com
41
- Authentication: NoAuthentication
42
- Type: HTTP
43
- ProxyType: Internet
44
- {{/hasHtml5Repo}}
25
+ service-plan: lite
@@ -8,7 +8,7 @@ const npmPackageRegex = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/
8
8
  module.exports = class ExtensionProjectTemplate extends require('../../plugin') {
9
9
 
10
10
  static help() {
11
- return 'Extension project'
11
+ return 'extension project'
12
12
  }
13
13
 
14
14
  options() {
@@ -0,0 +1,48 @@
1
+ name: GitHub Deployment for Cloud Foundry
2
+ description: "Creates a GitHub deployment for your Cloud Foundry app"
3
+
4
+ inputs:
5
+ app-name:
6
+ description: "Base name of the deployed CAP app"
7
+ required: true
8
+
9
+ runs:
10
+ using: "composite"
11
+ steps:
12
+ - name: Get deployed server URL
13
+ id: get-url
14
+ shell: bash
15
+ run: |
16
+ raw=$(cf app "${{ inputs.app-name }}" | awk '/routes:/ {print $2}')
17
+ raw=$(echo "$raw" | sed -E 's#^https?://##')
18
+ echo "url=https://$raw" >> "$GITHUB_OUTPUT"
19
+
20
+ - name: Create GitHub Deployment
21
+ uses: actions/github-script@v7
22
+ env:
23
+ URL: ${{ steps.get-url.outputs.url }}
24
+ with:
25
+ script: |
26
+ const { owner, repo } = context.repo
27
+ const ref = context.ref
28
+ const url = process.env.URL
29
+
30
+ const deployment = await github.rest.repos.createDeployment({
31
+ owner,
32
+ repo,
33
+ ref,
34
+ required_contexts: [],
35
+ environment: 'Production',
36
+ auto_merge: false,
37
+ description: 'Deployed to Cloud Foundry',
38
+ })
39
+
40
+ await github.rest.repos.createDeploymentStatus({
41
+ owner,
42
+ repo,
43
+ deployment_id: deployment.data.id,
44
+ state: 'success',
45
+ environment_url: url,
46
+ log_url: `https://github.com/${owner}/${repo}/actions/runs/${context.runId}`,
47
+ description: 'CAP app is live',
48
+ })
@@ -0,0 +1,53 @@
1
+ name: Cloud Foundry Setup
2
+ description: "Installs dependencies for Cloud Foundry deployment"
3
+
4
+ inputs:
5
+ cf-version:
6
+ description: "The version of the Cloud Foundry CLI to install"
7
+ required: false
8
+ default: "8.8.3"
9
+ cf-api:
10
+ description: "The Cloud Foundry API endpoint to connect to"
11
+ required: true
12
+ cf-org:
13
+ description: "The Cloud Foundry organization to target"
14
+ required: true
15
+ cf-space:
16
+ description: "The Cloud Foundry space to target"
17
+ required: true
18
+ cf-username:
19
+ description: "The Cloud Foundry username to authenticate with"
20
+ required: true
21
+ cf-password:
22
+ description: "The Cloud Foundry password to authenticate with"
23
+ required: true
24
+
25
+ runs:
26
+ using: composite
27
+ steps:
28
+ - shell: bash
29
+ run: |
30
+ set -e
31
+ echo "Using CF_VERSION=${{ inputs.cf-version }}"
32
+ echo "Using CF_API=${{ inputs.cf-api }}"
33
+ curl -L "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=${{ inputs.cf-version }}&source=github" -o cf-cli.tgz
34
+ mkdir cf-cli && tar -xzf cf-cli.tgz -C cf-cli
35
+ chmod +x cf-cli/cf
36
+ echo "${PWD}/cf-cli" >> $GITHUB_PATH
37
+
38
+ - shell: bash
39
+ run: |
40
+ echo "Installing MBT..."
41
+ npm install -g mbt
42
+
43
+ - shell: bash
44
+ run: |
45
+ echo "Installing CF CLI multiapps plugin..."
46
+ cf install-plugin multiapps -f
47
+
48
+ - shell: bash
49
+ run: |
50
+ echo "Authenticating to Cloud Foundry..."
51
+ cf api "${{ inputs.cf-api }}"
52
+ cf auth "${{ inputs.cf-username }}" "${{ inputs.cf-password }}"
53
+ cf target -o "${{ inputs.cf-org }}" -s "${{ inputs.cf-space }}"
@@ -0,0 +1,37 @@
1
+ name: Kyma Info
2
+
3
+ description: "Prints post-deployment information for Kyma applications"
4
+
5
+ inputs:
6
+ app:
7
+ description: App Name
8
+ required: true
9
+
10
+ runs:
11
+ using: "composite"
12
+ steps:
13
+ - name: Get Events
14
+ shell: bash
15
+ run: kubectl get events --sort-by='.lastTimestamp' | tail -n 10
16
+ - name: Get Pods
17
+ shell: bash
18
+ run: kubectl get pods
19
+ - name: Get Secrets
20
+ shell: bash
21
+ run: kubectl get secrets
22
+ - name: Get Service Instances
23
+ shell: bash
24
+ run: kubectl get serviceinstances
25
+ - name: Get Service Bindings
26
+ shell: bash
27
+ run: kubectl get servicebindings
28
+ - shell: bash
29
+ run: |
30
+ echo "::group::Kyma Logs for ${{ inputs.app }}-srv"
31
+ kubectl get pods --no-headers | awk '{print $1}' | grep "${{ inputs.app }}.*-srv" | xargs -r -I % kubectl logs % --since=10m
32
+ echo "::endgroup::"
33
+ - shell: bash
34
+ run: |
35
+ echo "::group::Kyma Logs for ${{ inputs.app }}-approuter"
36
+ kubectl get pods --no-headers | awk '{print $1}' | grep "${{ inputs.app }}.*-approuter" | xargs -r -I % kubectl logs % --since=10m
37
+ echo "::endgroup::"
@@ -0,0 +1,64 @@
1
+ name: Kyma Setup
2
+
3
+ description: "Installs dependencies for Kyma deployment"
4
+
5
+ inputs:
6
+ registry:
7
+ description: Image Registry
8
+ required: true
9
+ user:
10
+ description: Registry User
11
+ required: true
12
+ password:
13
+ description: Registry Password
14
+ required: true
15
+ kube-config:
16
+ description: Base64-encoded Kubernetes Config
17
+ required: true
18
+
19
+ runs:
20
+ using: "composite"
21
+ steps:
22
+ - run: apt-get update -y
23
+ shell: bash
24
+ - run: apt-get install software-properties-common -y
25
+ shell: bash
26
+ - run: apt-get install curl ca-certificates -y
27
+ shell: bash
28
+ - run: apt install sudo
29
+ shell: bash
30
+ - run: curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
31
+ shell: bash
32
+ - run: echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
33
+ shell: bash
34
+ - run: apt-get update -y
35
+ shell: bash
36
+ - run: apt-get install make -y
37
+ shell: bash
38
+ - run: apt-get install maven -y
39
+ shell: bash
40
+ - run: apt-get install docker.io -y
41
+ shell: bash
42
+ - run: (curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.31.0/pack-v0.31.0-linux.tgz" | sudo tar -C /usr/local/bin/ --no-same-owner -xzv pack)
43
+ shell: bash
44
+ - run: apt-get install kubectl -y
45
+ shell: bash
46
+ - run: curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
47
+ shell: bash
48
+ - run: sudo apt-get install apt-transport-https --yes
49
+ shell: bash
50
+ - run: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
51
+ shell: bash
52
+ - run: sudo apt-get update
53
+ shell: bash
54
+ - run: sudo apt-get install helm
55
+ shell: bash
56
+ - run: npm install -g ctz
57
+ shell: bash
58
+ - shell: bash
59
+ run: |
60
+ mkdir ${HOME}/kyma-binaries
61
+ export PATH=${HOME}/kyma-binaries/:$PATH
62
+ echo "${{ inputs.password }}" | docker login "${{ inputs.registry }}" -u "${{ inputs.user }}" --password-stdin
63
+ mkdir ${HOME}/.kube
64
+ echo "${{ inputs.kube-config }}" | base64 --decode > ${HOME}/.kube/config
@@ -0,0 +1,48 @@
1
+ name: Cloud Foundry
2
+
3
+ on:
4
+ workflow_call:
5
+ workflow_dispatch:
6
+ merge_group:
7
+ push:
8
+ branches:
9
+ - main
10
+
11
+ concurrency:
12
+ group: {{#literal}}cf-${{ github.workflow }}-${{ github.head_ref || github.run_id }}{{/literal}}
13
+ cancel-in-progress: true
14
+
15
+ env:
16
+ APP_NAME: {{ appName }}
17
+ jobs:
18
+ deploy:
19
+ runs-on: {{#sap}}[self-hosted, solinas]{{/sap}}{{^sap}}ubuntu-latest{{/sap}}
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: actions/setup-node@v4
23
+ with:
24
+ node-version: 22
25
+ - uses: ./.github/actions/cf-setup # cap-js/cf-setup@v1
26
+ with:
27
+ cf-api: {{#literal}}${{ vars.CF_API }}{{/literal}}
28
+ cf-org: {{#literal}}${{ vars.CF_ORG }}{{/literal}}
29
+ cf-space: {{#literal}}${{ vars.CF_SPACE }}{{/literal}}
30
+ cf-username: {{#literal}}${{ vars.CF_USERNAME }}{{/literal}}
31
+ cf-password: {{#literal}}${{ secrets.CF_PASSWORD }}{{/literal}}
32
+ - run: npm install
33
+ - run: npx cds up
34
+
35
+ - uses: ./.github/actions/cf-github-deploy
36
+ with:
37
+ app-name: {{#literal}}${{ env.APP_NAME }}{{/literal}}
38
+
39
+ {{#hasApprouter}}
40
+ - run: cf logs "${{ env.APP_NAME }}" --recent
41
+ {{/hasApprouter}}
42
+ - run: cf logs "${{ env.APP_NAME }}-srv" --recent
43
+ {{^hasMultitenancy}}
44
+ - run: cf logs "${{ env.APP_NAME }}-db-deployer" --recent
45
+ {{/hasMultitenancy}}
46
+ {{#hasMultitenancy}}
47
+ - run: cf logs "${{ env.APP_NAME }}-mtx" --recent
48
+ {{/hasMultitenancy}}
@@ -0,0 +1,39 @@
1
+ name: Kyma
2
+
3
+ on:
4
+ workflow_call:
5
+ workflow_dispatch:
6
+ merge_group:
7
+ push:
8
+ branches:
9
+ - main
10
+
11
+ concurrency:
12
+ group: {{#literal}}deploy-${{ github.workflow }}-${{ github.head_ref || github.run_id }}{{/literal}}
13
+ cancel-in-progress: true
14
+
15
+ env:
16
+ APP_NAME: {{ appName }}
17
+ jobs:
18
+ deploy:
19
+ runs-on: [self-hosted, {{#sap}}solinas{{/sap}}{{^sap}}ubuntu-latest{{/sap}}]
20
+ container:
21
+ image: public.int.repositories.cloud.sap/ubuntu:24.04
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: actions/setup-node@v4
25
+ with:
26
+ node-version: 22
27
+ - uses: ./.github/actions/kyma-setup
28
+ with:
29
+ registry: {{#literal}}${{ vars.DOCKER_REGISTRY }}{{/literal}}
30
+ user: {{#literal}}${{ vars.DOCKER_USERNAME }}{{/literal}}
31
+ password: {{#literal}}${{ secrets.DOCKER_PASSWORD }}{{/literal}}
32
+ kube-config: {{#literal}}${{ secrets.KUBE_CONFIG }}{{/literal}}
33
+ - run: npm clean-install
34
+ - run: npx cds up --to k8s
35
+
36
+ - uses: ./.github/actions/kyma-info
37
+ if: always()
38
+ with:
39
+ app: {{#literal}}${{ env.APP_NAME }}{{/literal}}
@@ -0,0 +1,21 @@
1
+ name: Tests
2
+
3
+ on:
4
+ workflow_call:
5
+ workflow_dispatch:
6
+ pull_request:
7
+ merge_group:
8
+ push:
9
+ branches:
10
+ - main
11
+
12
+ jobs:
13
+ tests:
14
+ runs-on: [self-hosted, {{#sap}}solinas{{/sap}}{{^sap}}ubuntu-latest{{/sap}}]
15
+ steps:
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 22
19
+ - uses: actions/checkout@v4
20
+ - run: npm install
21
+ - run: npm test
@@ -0,0 +1,73 @@
1
+ const path = require('node:path')
2
+ const { readProject } = require('../../projectReader')
3
+ const { renderAndCopy } = require('../../template')
4
+ const cds = require('../../../cds')
5
+ const { exists, copy } = cds.utils
6
+
7
+ module.exports = class GitHubActionTemplate extends require('../../plugin') {
8
+
9
+ static hasInProduction() {
10
+ return exists('.github/workflows/test.yaml')
11
+ }
12
+
13
+ options() {
14
+ return {
15
+ 'sap': {
16
+ type: 'boolean'
17
+ }
18
+ }
19
+ }
20
+
21
+ static help() {
22
+ return 'CI/CD pipeline via GitHub Actions'
23
+ }
24
+
25
+ async run() {
26
+ const out = '.github/workflows/test.yaml'
27
+ if (!exists(out) || cds.cli.options.force) {
28
+ await renderAndCopy(path.join(__dirname, 'files/workflows/test.yaml.hbs'), out, { sap: cds.cli.options.sap })
29
+ } else {
30
+ console.log('> skipping ' + out)
31
+ }
32
+ }
33
+
34
+ async combine() {
35
+ const project = readProject()
36
+ const { hasMta, hasHelm } = project, { force } = cds.cli.options
37
+ project.literal = () => text => text
38
+ project.sap = cds.cli.options.sap
39
+ if (hasMta) {
40
+ const cf = '.github/workflows/cf.yaml'
41
+ if (!exists(cf) || force) {
42
+ await renderAndCopy(path.join(__dirname, 'files/workflows/cf.yaml.hbs'), cf, project)
43
+ }
44
+ const cfSetup = '.github/actions/cf-setup'
45
+ if (!exists(cfSetup) || force) {
46
+ await copy(path.join(__dirname, 'files/cf-setup'), cfSetup)
47
+ }
48
+ const cfGithub = '.github/actions/cf-github-deploy'
49
+ if (!exists(cfGithub) || force) {
50
+ await copy(path.join(__dirname, 'files/cf-github-deploy'), cfGithub)
51
+ }
52
+ const cfInfo = '.github/actions/cf-info'
53
+ if (!exists(cfInfo) || force) {
54
+ await copy(path.join(__dirname, 'files/cf-info'), cfInfo)
55
+ }
56
+ }
57
+ if (hasHelm) {
58
+ const kyma = '.github/workflows/kyma.yaml'
59
+ if (!exists(kyma) || force) {
60
+ await renderAndCopy(path.join(__dirname, 'files/workflows/kyma.yaml.hbs'), kyma, project)
61
+ }
62
+ const kymaSetup = '.github/actions/kyma-setup'
63
+ if (!exists(kymaSetup) || force) {
64
+ await copy(path.join(__dirname, 'files/kyma-setup'), kymaSetup)
65
+ }
66
+
67
+ const kymaInfo = '.github/actions/kyma-info'
68
+ if (!exists(kymaInfo) || force) {
69
+ await copy(path.join(__dirname, 'files/kyma-info'), kymaInfo)
70
+ }
71
+ }
72
+ }
73
+ }
@@ -101,7 +101,11 @@ module.exports = class HelmTemplate extends require('../../plugin') {
101
101
  }
102
102
  if (hasMultitenancy) {
103
103
  await this._mergeDependency('web-application', 'sidecar')
104
- await this._mergeDependency('service-instance', 'saas-registry')
104
+ if (hasXsuaa) {
105
+ await this._mergeDependency('service-instance', 'saas-registry')
106
+ } else {
107
+ await this._mergeDependency('service-instance', 'subscription-manager')
108
+ }
105
109
  }
106
110
  if (hasDestination) {
107
111
  await this._mergeDependency('service-instance', 'destination')
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  before-all:
3
3
  {{#hasUI5}}
4
- - mkdir -p ui-resources/resources
4
+ - mkdir -p app/html5-deployer/resources
5
5
  {{#apps}}
6
6
  - npm i --prefix app/{{app}}
7
7
  - npm run build --prefix app/{{app}}
8
8
  # zip filename should match the archiveName specified in ui5-deploy.yaml
9
- - cp -f app/{{app}}/dist/{{app}}.zip ui-resources/resources/{{app}}.zip
9
+ - cp -f app/{{app}}/dist/{{app}}.zip app/html5-deployer/resources/{{app}}.zip
10
10
  {{/apps}}
11
11
  {{/hasUI5}}
12
12
  modules:
@@ -20,6 +20,6 @@ modules:
20
20
  type: nodejs
21
21
  builder: builder-jammy-base
22
22
  {{/hasHelmUnifiedRuntime}}
23
- path: ui-resources
23
+ path: app/html5-deployer
24
24
  env:
25
- BP_NODE_RUN_SCRIPTS: ""
25
+ BP_NODE_RUN_SCRIPTS: ""
@@ -25,9 +25,14 @@ modules:
25
25
  type: com.sap.application.content
26
26
  path: {{#isNodejs}}gen{{/isNodejs}}{{#isJava}}.{{/isJava}}
27
27
  requires:
28
+ - name: {{appName}}-auth
29
+ - name: srv-api
28
30
  - name: {{appName}}-html5-repo-host
29
31
  parameters:
30
32
  content-target: true
33
+ config:
34
+ HTML5Runtime_enabled: true{{#hasIas}}
35
+ IASDependencyName: {{appName}}-api{{/hasIas}}
31
36
  build-parameters:
32
37
  build-result: {{#isNodejs}}{{& appPath }}{{/isNodejs}}{{#isJava}}resources{{/isJava}}
33
38
  requires:
@@ -37,6 +42,25 @@ modules:
37
42
  - {{app}}.zip
38
43
  target-path: {{#isNodejs}}{{& appPath }}{{/isNodejs}}{{#isJava}}resources{{/isJava}}
39
44
  {{/apps}}
45
+ parameters:
46
+ config:
47
+ HTML5Runtime_enabled: true
48
+ init_data:
49
+ instance:
50
+ existing_destinations_policy: update
51
+ destinations:
52
+ - Name: srv-api
53
+ URL: ~{srv-api/srv-url}
54
+ Authentication: NoAuthentication
55
+ Type: HTTP
56
+ ProxyType: Internet
57
+ HTML5.ForwardAuthToken: true
58
+ HTML5.DynamicDestination: true
59
+ - Name: ui5
60
+ URL: https://ui5.sap.com
61
+ Authentication: NoAuthentication
62
+ Type: HTTP
63
+ ProxyType: Internet
40
64
 
41
65
  {{#apps}}
42
66
  - name: {{strippedAppName}}{{strippedApp}}
@@ -16,10 +16,11 @@ html5-apps-deployer:
16
16
  serviceInstanceName: xsuaa
17
17
  {{/hasXsuaa}}
18
18
  {{#hasIas}}
19
- ias:
19
+ identity:
20
20
  serviceInstanceName: identity
21
21
  parameters:
22
22
  credential-type: X509_GENERATED
23
+ app-identifier: html5-deployer
23
24
  {{/hasIas}}
24
25
  destination:
25
26
  serviceInstanceName: destination
@@ -1,7 +1,7 @@
1
1
  const { join } = require('path')
2
2
  const { readProject } = require('../../projectReader')
3
3
  const { merge } = require('../../merge')
4
- const { srv4, html5RepoHost, html5Runtime, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
4
+ const { srv4, html5RepoHost, html5Runtime, xsuaa, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
5
5
  const { odataApi } = require('../../registries/xs-app')
6
6
  const { exists } = require('../../../cds').utils
7
7
  const { renderAndCopy } = require('../../template')
@@ -51,7 +51,7 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
51
51
 
52
52
  async combine() {
53
53
  const project = readProject()
54
- const { isJava, srvPath, appPath, hasMta, hasMultitenancy, hasWorkzoneStandard, hasHelm, hasHelmUnifiedRuntime, hasApprouter, hasContainerize, apps } = project
54
+ const { isJava, srvPath, appPath, hasMta, hasXsuaa, hasMultitenancy, hasWorkzoneStandard, hasHelm, hasHelmUnifiedRuntime, hasApprouter, hasContainerize, apps } = project
55
55
 
56
56
  await Promise.all(apps.map(async ({ app }) => {
57
57
  project.app = app
@@ -97,6 +97,12 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
97
97
  into: [isJava ? srv : mtxSidecar4('gen/mtx/sidecar'), 'requires', 'name']
98
98
  })
99
99
  }
100
+ if (hasXsuaa) {
101
+ relationships.push({
102
+ insert: [xsuaa, 'name'],
103
+ into: [appDeployer, 'requires']
104
+ })
105
+ }
100
106
  await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
101
107
  with: project,
102
108
  additions,
@@ -111,7 +117,7 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
111
117
  await merge(__dirname, '/files/containerize.yaml.hbs').into('containerize.yaml', { with: project, additions })
112
118
  }
113
119
  if (hasHelm || hasHelmUnifiedRuntime) {
114
- await renderAndCopy(join(__dirname, 'files/ui-resources'), 'ui-resources', project)
120
+ await renderAndCopy(join(__dirname, 'files/html5-deployer.package.json.hbs'), 'app/html5-deployer/package.json', project)
115
121
  await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
116
122
  }
117
123
  }
@@ -163,7 +163,7 @@ module.exports = class HttpTemplate extends require('../../plugin') {
163
163
  const key = Object.keys(e.keys)[0] // draft keys are always single
164
164
  delete entityData[key] // draft keys should always by auto generated (either UUID or through custom logic), so remove them from the payload
165
165
  const postBody = JSON.stringify(entityData, null, 2)
166
- generateDraftRequests(requests, requestTitle, url, headers, headerAuth, postBody, key)
166
+ generateDraftRequests(requests, requestTitle, url, headers, headerAuth, postBody, key, service)
167
167
  }
168
168
  else {
169
169
  const postBody = JSON.stringify(entityData, null, 2)
@@ -198,14 +198,14 @@ module.exports = class HttpTemplate extends require('../../plugin') {
198
198
  this.#write(requests, serviceName)
199
199
  }
200
200
 
201
- function generateDraftRequests(requests, title, url, headers, headerAuth, postBody, key) {
201
+ function generateDraftRequests(requests, title, url, headers, headerAuth, postBody, key, service) {
202
202
  const nameDraftsCreate = slug(title+'_Draft_POST')
203
203
  requests.push(`${title} Drafts GET\n# @name ${slug(title+'_Drafts_GET')}\nGET ${url}?$filter=(IsActiveEntity eq false)\n${headerAuth}\n`) // unencoded URL for better readability (client can handle this)
204
204
  requests.push(`${title} Draft POST\n# @name ${nameDraftsCreate}\nPOST ${url}\n${headers}\n\n${postBody}\n`)
205
205
  requests.push(`\n### Result from POST request above\n@draftID={{${nameDraftsCreate}.response.body.$.${key}}}\n`)
206
206
  requests.push(`${title} Draft PATCH\n# @name ${slug(title+'_Draft_Patch')}\nPATCH ${url}(${key}={{draftID}},IsActiveEntity=false)\n${headers}\n\n${postBody}\n`)
207
- requests.push(`${title} Draft Prepare\n# @name ${slug(title+'_Draft_Prepare')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)/AdminService.draftPrepare\n${headers}\n\n{}\n`)
208
- requests.push(`${title} Draft Activate\n# @name ${slug(title+'_Draft_Activate')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)/AdminService.draftActivate\n${headers}\n\n{}\n`)
207
+ requests.push(`${title} Draft Prepare\n# @name ${slug(title+'_Draft_Prepare')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)/${service.name}.draftPrepare\n${headers}\n\n{}\n`)
208
+ requests.push(`${title} Draft Activate\n# @name ${slug(title+'_Draft_Activate')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)/${service.name}.draftActivate\n${headers}\n\n{}\n`)
209
209
  }
210
210
 
211
211
  function slug(str) {
@@ -9,13 +9,20 @@
9
9
  {{#profile}}
10
10
  "[{{profile}}]": {
11
11
  {{/profile}}
12
+ {{#shortcut}}
13
+ "auth": "ias"
14
+ {{/shortcut}}
15
+ {{^shortcut}}
12
16
  "auth": {
13
17
  "kind": "ias"
14
18
  }
19
+ {{/shortcut}}
20
+
15
21
  {{#profile}}
16
22
  }
17
23
  {{/profile}}
18
24
  }
25
+
19
26
  {{#isNodejs}}
20
27
  }
21
28
  {{/isNodejs}}
@@ -29,10 +29,6 @@ identity:
29
29
  servicePlanName: application
30
30
  parameters:
31
31
  display-name: {{appName}}
32
- {{#hasAms}}
33
- authorization:
34
- enabled: true
35
- {{/hasAms}}
36
32
  {{#hasMultitenancy}}
37
33
  multi-tenant: true
38
34
  {{/hasMultitenancy}}
@@ -50,3 +46,4 @@ identity:
50
46
  - https://*.{{ tpl .Values.global.domain . }}/*/logout.html
51
47
  <%={{ }}=%>
52
48
  {{/hasApprouter}}
49
+