@sap/cds-dk 7.6.1 → 7.7.1

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 (49) hide show
  1. package/bin/cds.js +1 -1
  2. package/bin/version.js +21 -20
  3. package/bin/watch.js +6 -0
  4. package/lib/build/buildTaskEngine.js +6 -4
  5. package/lib/build/buildTaskProviderFactory.js +5 -0
  6. package/lib/build/provider/edmxBuildPlugin.js +1 -1
  7. package/lib/build/provider/internalBuildTaskProvider.js +12 -10
  8. package/lib/build/provider/mtx/index.js +2 -2
  9. package/lib/build/provider/mtx/resourcesTarBuilder.js +1 -1
  10. package/lib/build/provider/mtx-extension/extensionCompilation.js +50 -0
  11. package/lib/build/provider/mtx-extension/index.js +70 -50
  12. package/lib/build/provider/mtx-sidecar/index.js +3 -3
  13. package/lib/build/util.js +9 -4
  14. package/lib/env/schema.js +1 -0
  15. package/lib/env/schemas/cds-rc.js +54 -1
  16. package/lib/import/asyncapi/parserContext.js +6 -0
  17. package/lib/init/add.js +2 -0
  18. package/lib/init/constants.js +2 -2
  19. package/lib/init/index.js +4 -8
  20. package/lib/init/merge.js +31 -13
  21. package/lib/init/projectReader.js +9 -1
  22. package/lib/init/registries/mta.js +19 -1
  23. package/lib/init/template/approuter/files/mta.yaml.hbs +1 -1
  24. package/lib/init/template/approuter/index.js +5 -5
  25. package/lib/init/template/connectivity/index.js +3 -4
  26. package/lib/init/template/helm/files/content-deployment/Chart.yaml +1 -1
  27. package/lib/init/template/helm/files/content-deployment/templates/job.yaml +3 -0
  28. package/lib/init/template/helm/files/content-deployment/values.schema.json +13 -1
  29. package/lib/init/template/helm/files/content-deployment/values.yaml +1 -1
  30. package/lib/init/template/helm/files/web-application/Chart.yaml +1 -1
  31. package/lib/init/template/helm/files/web-application/templates/deployment.yaml +1 -0
  32. package/lib/init/template/helm/files/web-application/templates/service.yaml +4 -0
  33. package/lib/init/template/helm/files/web-application/values.schema.json +16 -0
  34. package/lib/init/template/helm/files/web-application/values.yaml +7 -1
  35. package/lib/init/template/html5-repo/files/app-package.json.hbs +16 -0
  36. package/lib/init/template/html5-repo/files/mta.yaml.hbs +83 -0
  37. package/lib/init/template/html5-repo/files/package.json.hbs +17 -0
  38. package/lib/init/template/html5-repo/files/ui5.yaml.hbs +33 -0
  39. package/lib/init/template/html5-repo/files/xs-app.json.hbs +19 -0
  40. package/lib/init/template/html5-repo/index.js +56 -12
  41. package/lib/init/template/mta/files/mta.yaml.hbs +1 -0
  42. package/lib/init/template/mta/index.js +5 -0
  43. package/lib/init/template/nodejs/files/.vscode/extensions.json +1 -2
  44. package/lib/init/template/nodejs/files/README.md +1 -1
  45. package/lib/init/template/sample/files/app/index.html +8 -6
  46. package/lib/init/template/sample/index.js +12 -2
  47. package/lib/util/cf.js +1 -0
  48. package/npm-shrinkwrap.json +31 -29
  49. package/package.json +1 -1
package/lib/init/index.js CHANGED
@@ -8,7 +8,7 @@ const {
8
8
  HANA, APPROUTER, XSUAA, APPLICATION_LOGGING, ENTERPRISE_MESSAGING,
9
9
  MTA, MULTITENANCY, PIPELINE,
10
10
  TINY_SAMPLE, SAMPLE
11
- } = OPTIONS
11
+ } = OPTIONS
12
12
 
13
13
  const cds = require('..'), { exists, readdir } = cds.utils
14
14
  const DEBUG = /\b(y|all|cli)\b/.test(process.env.DEBUG) ? console.debug : undefined
@@ -334,13 +334,9 @@ module.exports = class CDSGenerator {
334
334
 
335
335
  // remove duplicates by using a set
336
336
  const invalidChars = new Set(projectName.match(REGEX_PROJECT_NAME));
337
- switch (invalidChars.size) {
338
- case 0:
339
- break;
340
- case 1:
341
- throw `Project name ${projectName} contains an invalid character (${[...invalidChars].join(', ')}). Specify a different project name.`
342
- default:
343
- throw `Project name ${projectName} contains invalid characters (${[...invalidChars].join(', ')}). Specify a different project name.`
337
+ if (invalidChars.size > 0) {
338
+ throw `Project name '${projectName}' contains at least one character ('${[...invalidChars]}') which is not supported in npm package names.
339
+ Specify a different project name by replacing characters with '_' or '-', for example '${projectName.replace(REGEX_PROJECT_NAME, '_')}' or '${projectName.replace(REGEX_PROJECT_NAME, '-')}'.`
344
340
  }
345
341
  }
346
342
 
package/lib/init/merge.js CHANGED
@@ -141,7 +141,7 @@ async function _mergeYAML(into, from, project, semantics = {}) {
141
141
  throw new Error(`Target YAML doesn't exist`)
142
142
  }
143
143
 
144
- const entryMap = new Map, templateEntryMap = new Map()
144
+ const entryMap = new Map, templateEntryMap = new Map
145
145
 
146
146
  const { additions, overwrites, deletions, relationships } = semantics
147
147
  additions?.forEach(entry => {
@@ -236,7 +236,7 @@ async function _mergeYAML(into, from, project, semantics = {}) {
236
236
 
237
237
  if (!templateCollection?.items) return
238
238
 
239
- templateCollection.items.forEach((templateNode, templateIndex) => {
239
+ templateCollection.items?.forEach((templateNode, templateIndex) => {
240
240
  if (YAML.isScalar(templateNode)) {
241
241
  if (!collection.items.map(item => item.value).includes(templateNode.value)) {
242
242
  collection.add(templateNode)
@@ -413,20 +413,38 @@ async function removeFromYAMLArray(name, keyPath, aliasToRemove) {
413
413
  await writeYAML(name, yaml)
414
414
  }
415
415
 
416
+
416
417
  const path = require('path')
418
+
419
+ /**
420
+ * @param {...(string | Object | YAML.Document)} src The source to merge from.
421
+ * @returns {{
422
+ * into: (dst: (string | Object | YAML.Document), options?: {project?: Object, semantics?: MergingSemantics}) => Promise<any>
423
+ * }} An object with an 'into' method to merge the sources into the specified destination.
424
+ */
417
425
  const merge = (...src) => {
418
- return { into: (dst, { with: withProject, project, ...semantics } = {}) => {
419
- if (Object.keys(semantics).length === 0) semantics = undefined
420
- project ??= withProject // to allow { with: project } for a more fluent API
421
- const isYAML = typeof dst === 'string' && ['.yaml', '.yml', '.yaml.hbs', '.yml.hbs'].some(ext => dst.endsWith(ext))
422
- const _merge = isYAML ? _mergeYAML : _mergeJSON
423
- const target = typeof dst === 'string' ? path.resolve(cds.root, dst) : dst
424
- if (typeof src[src.length-1] === 'string') {
425
- return _merge(target, path.join(...src), project, semantics)
426
- } else {
427
- return _merge(target, ...src, project, semantics)
426
+ return {
427
+ /**
428
+ * Merges sources into the specified destination.
429
+ * @param {(string | Object | YAML.Document)} dst File path or object to merge into.
430
+ * @param {Object} [options] Merging options.
431
+ * @param {Object} [options.project] Project descriptor used for Mustache replacements.
432
+ * @param {MergingSemantics} [options.semantics] Merging algorithm semantics.
433
+ * @returns {Promise} A promise resolving to the merged object.
434
+ */
435
+ into: (dst, { with: withProject, project, ...semantics } = {}) => {
436
+ if (Object.keys(semantics).length === 0) semantics = undefined
437
+ project ??= withProject // to allow { with: project } for a more fluent API
438
+ const isYAML = typeof dst === 'string' && ['.yaml', '.yml', '.yaml.hbs', '.yml.hbs'].some(ext => dst.endsWith(ext))
439
+ const _merge = isYAML ? _mergeYAML : _mergeJSON
440
+ const target = typeof dst === 'string' ? path.resolve(cds.root, dst) : dst
441
+ if (typeof src[src.length-1] === 'string') {
442
+ return _merge(target, path.join(...src), project, semantics)
443
+ } else {
444
+ return _merge(target, ...src, project, semantics)
445
+ }
428
446
  }
429
- }}
447
+ }
430
448
  }
431
449
 
432
450
  module.exports = {
@@ -1,6 +1,6 @@
1
1
  const cds = require('../cds')
2
2
  const { join, resolve, basename } = require('path')
3
- const { fs, exists, isdir } = cds.utils
3
+ const { fs, exists, isdir, path } = cds.utils
4
4
  const { parseXml } = require('./xml')
5
5
  const { REGEX_JAVA_VERSION } = require('./constants')
6
6
  const DEBUG = cds.debug('cli')
@@ -59,6 +59,7 @@ module.exports = new class ProjectReader {
59
59
  * @property {Object} db Database configuration.
60
60
  * @property {string} configFile The name of the configuration file. This is typically the `package.json` for Node.js and `.cdsrc.json` for Java.
61
61
  * @property {string} appPath The path to the app folder.
62
+ * @property {string} approuterPath The path to the approuter folder.
62
63
  * @property {boolean} hasUIEmbedded Indicates if the project uses an embedded UI.
63
64
  * @property {boolean} hasUIModule Indicates if the project is using a modular UI.
64
65
  * @property {boolean} hasUI Indicates if the project has a UI.
@@ -112,8 +113,15 @@ module.exports = new class ProjectReader {
112
113
  return { folder, name, path }
113
114
  },
114
115
  configFile: () => exists('pom.xml') ? '.cdsrc.json' : 'package.json',
116
+ apps: () => (fs.readdirSync(path.resolve(cds.root, cds.env.folders.app))).filter(e =>
117
+ isdir(join(cds.root, cds.env.folders.app, e)) && e !== 'appconfig' && e !== '_i18n' && e !== 'router'
118
+ ).map(app => ({ app })),
119
+ appUIPaths: () => (fs.readdirSync(path.resolve(cds.root, cds.env.folders.app))).filter(e =>
120
+ isdir(join(cds.root, cds.env.folders.app, e)) && e !== 'appconfig' && e !== '_i18n' && e !== 'router'
121
+ ),
115
122
  appPath: () => env.folders.app,
116
123
  appVersion: () => appVersion,
124
+ approuterPath: () => join(env.folders.app, 'router'),
117
125
  appName: () => appName,
118
126
  cleanedAppName: () => appName.replaceAll('_', '-'),
119
127
  appId: () => appId,
@@ -122,6 +122,21 @@ const approuterExtensibility = {
122
122
  where: { source: '^/-/cds/.*', destination: 'mtx-api', authenticationType: 'none' }
123
123
  }
124
124
 
125
+ const html5RepoHost = {
126
+ in: 'resources',
127
+ where: { 'parameters.service': 'html5-apps-repo', 'parameters.service-plan': 'app-host' }
128
+ }
129
+
130
+ const html5Runtime = {
131
+ in: 'resources',
132
+ where: { 'parameters.service': 'html5-apps-repo', 'parameters.service-plan': 'app-runtime' }
133
+ }
134
+
135
+ const appContent = {
136
+ in: 'modules',
137
+ where: { type: 'com.sap.application.content' }
138
+ }
139
+
125
140
  module.exports = {
126
141
  srv4,
127
142
  approuter,
@@ -147,5 +162,8 @@ module.exports = {
147
162
  providedJavaApprouterApi4,
148
163
  providedJavaApprouterApi,
149
164
  applicationLogging,
150
- approuterExtensibility
165
+ approuterExtensibility,
166
+ html5RepoHost,
167
+ html5Runtime,
168
+ appContent
151
169
  }
@@ -19,7 +19,7 @@ modules:
19
19
 
20
20
  - name: {{appName}}
21
21
  type: approuter.nodejs
22
- path: {{& appPath}}
22
+ path: {{& approuterPath}}
23
23
  parameters:
24
24
  keep-existing-routes: true
25
25
  disk-quota: 256M
@@ -22,16 +22,16 @@ module.exports = class ApprouterTemplate extends require('../../plugin') {
22
22
  }
23
23
 
24
24
  async run() {
25
- const { appPath } = readProject()
26
- const appPackageJSONPath = join(appPath, 'package.json')
25
+ const { approuterPath } = readProject()
26
+ const appPackageJSONPath = join(approuterPath, 'package.json')
27
27
  await merge(__dirname, 'files/package.json').into(appPackageJSONPath)
28
28
  await sort(appPackageJSONPath, 'dependencies')
29
- await merge(__dirname, 'files/default-env.json').into(appPath + '/default-env.json')
29
+ await merge(__dirname, 'files/default-env.json').into(approuterPath + '/default-env.json')
30
30
  }
31
31
 
32
32
  async combine() {
33
33
  const project = readProject(this.options)
34
- const { isNodejs, isJava, hasExtensibility, hasMultitenancy, hasMta, hasHelm, hasHelmUnifiedRuntime, srvPath, appPath } = project
34
+ const { isNodejs, isJava, hasExtensibility, hasMultitenancy, hasMta, hasHelm, hasHelmUnifiedRuntime, srvPath, approuterPath } = project
35
35
 
36
36
  if (hasMta) {
37
37
  const srv = srv4(srvPath)
@@ -72,7 +72,7 @@ module.exports = class ApprouterTemplate extends require('../../plugin') {
72
72
  }
73
73
  }
74
74
 
75
- const xsAppPath = join(appPath, 'xs-app.json')
75
+ const xsAppPath = join(approuterPath, 'xs-app.json')
76
76
  const additions = hasExtensibility ? [{ ...approuterExtensibility, at: 0 }] : []
77
77
  await merge(__dirname, 'files/xs-app.json.hbs').into(xsAppPath, { project, additions })
78
78
  }
@@ -12,10 +12,9 @@ module.exports = class ConnectivityTemplate extends require('../../plugin') {
12
12
  }
13
13
 
14
14
  async run() {
15
- // Disable setting cds.requires.connectivity for now.
16
- // const project = readProject()
17
- // const { configFile } = project
18
- // await merge(__dirname, 'files', 'package.json.hbs').into(configFile, { with: project })
15
+ const project = readProject()
16
+ const { configFile } = project
17
+ await merge(__dirname, 'files', 'package.json.hbs').into(configFile, { with: project })
19
18
  }
20
19
 
21
20
  async combine() {
@@ -4,4 +4,4 @@ name: content-deployment
4
4
  sources:
5
5
  - https://github.tools.sap/unified-runtime/content-deployment
6
6
  type: application
7
- version: 1.4.0
7
+ version: 1.5.0
@@ -23,6 +23,9 @@ spec:
23
23
  serviceAccountName: {{ tpl (.Values.serviceAccountName | default (include "content-deployment.internal.fullname" .)) $ }}
24
24
  containers:
25
25
  - image: {{ include "content-deployment.internal.imageName" . }}
26
+ {{- if ( or .Values.global.imagePullPolicy .Values.imagePullPolicy ) }}
27
+ imagePullPolicy: {{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}
28
+ {{- end }}
26
29
  name: {{ include "content-deployment.internal.name" . }}
27
30
  env:
28
31
  - name: EXIT
@@ -58,6 +58,9 @@
58
58
  "$ref": "#/definitions/ImageRegistry"
59
59
  }
60
60
  }
61
+ },
62
+ "imagePullPolicy": {
63
+ "$ref": "#/definitions/ImagePullPolicy"
61
64
  }
62
65
  }
63
66
  },
@@ -133,6 +136,9 @@
133
136
  }
134
137
  }
135
138
  },
139
+ "imagePullPolicy": {
140
+ "$ref": "#/definitions/ImagePullPolicy"
141
+ },
136
142
  "resources": {
137
143
  "$id": "#/properties/resources",
138
144
  "type": "object",
@@ -506,6 +512,12 @@
506
512
  "title": "Image tag",
507
513
  "type": "string",
508
514
  "$comment": "Copied from https://github.com/containers/image/blob/18d58d29fdc4fc32fb8a8a6d186b829b217f1bf5/docker/reference/regexp.go#L68-L70",
509
- "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-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,}))?$" }
515
+ "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-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,}))?$"
516
+ },
517
+ "ImagePullPolicy": {
518
+ "title": "ImagePullPolicy",
519
+ "type": "string",
520
+ "enum": ["Always", "IfNotPresent", "Never"]
521
+ }
510
522
  }
511
523
  }
@@ -15,7 +15,7 @@ global:
15
15
  _internal:
16
16
  content-deployment:
17
17
  versions:
18
- 1.4.0: true
18
+ 1.5.0: true
19
19
  # Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
20
20
  # nameOverride: name
21
21
 
@@ -5,4 +5,4 @@ name: web-application
5
5
  sources:
6
6
  - https://github.tools.sap/unified-runtime/web-application
7
7
  type: application
8
- version: 1.10.0
8
+ version: 1.11.0
@@ -190,6 +190,7 @@ spec:
190
190
  maxSkew: {{ $constraint.maxSkew }}
191
191
  topologyKey: {{ $constraint.topologyKey }}
192
192
  whenUnsatisfiable: {{ $constraint.whenUnsatisfiable }}
193
+ matchLabelKeys: {{ $constraint.matchLabelKeys | default (list "pod-template-hash") | toYaml | nindent 10 }}
193
194
  {{- end }}
194
195
  volumes:
195
196
  - emptyDir: {}
@@ -3,6 +3,10 @@ kind: Service
3
3
  metadata:
4
4
  name: {{ include "web-application.fullname" . }}
5
5
  labels: {{- include "web-application.labels" . | nindent 4 }}
6
+ {{- if .Values.annotations.service }}
7
+ annotations:
8
+ {{- tpl (toYaml .Values.annotations.service) $ | nindent 4 }}
9
+ {{- end }}
6
10
  spec:
7
11
  ports:
8
12
  - port: {{ .Values.port }}
@@ -317,6 +317,12 @@
317
317
  "ScheduleAnyway",
318
318
  "DoNotSchedule"
319
319
  ]
320
+ },
321
+ "matchLabelKeys": {
322
+ "type": "array",
323
+ "items": {
324
+ "type": "string"
325
+ }
320
326
  }
321
327
  }
322
328
  },
@@ -824,7 +830,17 @@
824
830
  "type": "string"
825
831
  }
826
832
  }
833
+ },
834
+ "service": {
835
+ "type": "object",
836
+ "title": "Annotations to add to the Service",
837
+ "patternProperties": {
838
+ ".*": {
839
+ "type": "string"
840
+ }
841
+ }
827
842
  }
843
+
828
844
  }
829
845
  },
830
846
  "sidecars": {
@@ -15,7 +15,7 @@ global:
15
15
  _internal:
16
16
  web-application:
17
17
  versions:
18
- 1.10.0: true
18
+ 1.11.0: true
19
19
  ## Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
20
20
  # nameOverride: name
21
21
 
@@ -84,9 +84,13 @@ availability:
84
84
  - topologyKey: topology.kubernetes.io/zone
85
85
  maxSkew: 1
86
86
  whenUnsatisfiable: ScheduleAnyway
87
+ matchLabelKeys:
88
+ - pod-template-hash
87
89
  - topologyKey: kubernetes.io/hostname
88
90
  maxSkew: 1
89
91
  whenUnsatisfiable: ScheduleAnyway
92
+ matchLabelKeys:
93
+ - pod-template-hash
90
94
  # Health-check configuration
91
95
  health:
92
96
  # Liveness-probe configuration.
@@ -219,6 +223,8 @@ bindings:
219
223
  annotations:
220
224
  ## Annotations to add to the Deployment and underlying Pods
221
225
  deployment: {}
226
+ ## Annotations to add to the Service
227
+ service: {}
222
228
  # sidecars:
223
229
  # sidecar-1:
224
230
  # image:
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "{{app}}",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "<description>",
6
+ "main": "webapp/index.html",
7
+ "scripts": {
8
+ "build": "ui5 build preload --clean-dest --include-task=generateCachebusterInfo",
9
+ "start": "ui5 serve"
10
+ },
11
+ "devDependencies": {
12
+ "@ui5/cli": "^3.8.0",
13
+ "ui5-middleware-simpleproxy": "^3.2.10",
14
+ "ui5-task-zipper": "^3.1.1"
15
+ }
16
+ }
@@ -0,0 +1,83 @@
1
+ ---
2
+ modules:
3
+ - name: {{appName}}-srv
4
+ type: {{language}}
5
+ path: {{& srvPath}}
6
+
7
+ - name: {{appName}}
8
+ type: approuter.nodejs
9
+ path: {{& approuterPath}}
10
+ requires:
11
+ - name: {{appName}}-html5-runtime
12
+
13
+ - name: {{appName}}-app-content
14
+ type: com.sap.application.content
15
+ path: {{& appPath}}
16
+ requires:
17
+ - name: {{appName}}-destination
18
+ - name: {{appName}}-html5-repo-host
19
+ parameters:
20
+ content-target: true
21
+ build-parameters:
22
+ build-result: resources
23
+ requires:
24
+ {{#apps}}
25
+ - name: {{appName}}-app-{{app}}
26
+ artifacts:
27
+ - {{app}}.zip
28
+ target-path: resources/
29
+ {{/apps}}
30
+
31
+ {{#apps}}
32
+ - name: {{appName}}-app-{{app}}
33
+ type: html5
34
+ path: {{& appPath}}{{app}}
35
+ build-parameters:
36
+ build-result: dist
37
+ builder: custom
38
+ commands:
39
+ - npm ci
40
+ - npm run build
41
+ supported-platforms: []
42
+ {{/apps}}
43
+
44
+ resources:
45
+ {{#hasApprouter}}
46
+ - name: {{appName}}-html5-runtime
47
+ type: org.cloudfoundry.managed-service
48
+ parameters:
49
+ service: html5-apps-repo
50
+ service-plan: app-runtime
51
+ {{/hasApprouter}}
52
+
53
+ - name: {{appName}}-html5-repo-host
54
+ type: org.cloudfoundry.managed-service
55
+ parameters:
56
+ service: html5-apps-repo
57
+ service-plan: app-host
58
+
59
+ - name: {{appName}}-destination
60
+ type: org.cloudfoundry.managed-service
61
+ parameters:
62
+ service: destination
63
+ service-plan: lite
64
+ config:
65
+ HTML5Runtime_enabled: true
66
+ init_data:
67
+ instance:
68
+ existing_destinations_policy: update
69
+ destinations:
70
+ - Name: {{appName}}-srv
71
+ URL: ~{srv-api/srv-url}
72
+ Authentication: NoAuthentication
73
+ Type: HTTP
74
+ ProxyType: Internet
75
+ HTML5.ForwardAuthToken: true
76
+ HTML5.DynamicDestination: true
77
+ requires:
78
+ - name: srv-api
79
+ group: destinations
80
+ properties:
81
+ name: srv-api # must be used in xs-app.json as well
82
+ url: ~{srv-url}
83
+ forwardAuthToken: true
@@ -0,0 +1,17 @@
1
+ {
2
+ {{#isNodejs}}
3
+ "cds": {
4
+ {{/isNodejs}}
5
+ "requires": {
6
+ {{#profile}}
7
+ "[{{profile}}]": {
8
+ {{/profile}}
9
+ "html5-repo": true
10
+ {{#profile}}
11
+ }
12
+ {{/profile}}
13
+ }
14
+ {{#isNodejs}}
15
+ }
16
+ {{/isNodejs}}
17
+ }
@@ -0,0 +1,33 @@
1
+ ---
2
+ # yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json
3
+ specVersion: "3.0"
4
+ metadata:
5
+ name: sap.fe.cap.{{app}}
6
+ type: application
7
+
8
+ resources:
9
+ configuration:
10
+ propertiesFileSourceEncoding: UTF-8
11
+
12
+ builder:
13
+ resources:
14
+ excludes:
15
+ - "/test/**"
16
+ - "/localService/**"
17
+ customTasks:
18
+ - name: ui5-task-zipper
19
+ afterTask: generateCachebusterInfo
20
+ configuration:
21
+ archiveName: {{app}}
22
+ additionalFiles:
23
+ - xs-app.json
24
+
25
+ server:
26
+ customMiddleware:
27
+ - name: ui5-middleware-simpleproxy
28
+ mountPath: /{{app}}
29
+ afterMiddleware: compression
30
+ configuration:
31
+ baseUri: http://localhost:4004/{{app}}
32
+ username: admin # dummy credentials for local testing
33
+ password: admin # dummy credentials for local testing
@@ -0,0 +1,19 @@
1
+ {
2
+ "welcomeFile": "/index.html",
3
+ "authenticationMethod": "route",
4
+ "routes": [
5
+ {
6
+ "source": "^/{{app}}/(.*)$",
7
+ "target": "/{{app}}/$1",
8
+ "destination": "srv-api",
9
+ "authenticationType": "xsuaa",
10
+ "csrfProtection": false
11
+ },
12
+ {
13
+ "source": "^(.*)$",
14
+ "target": "$1",
15
+ "service": "html5-apps-repo-rt",
16
+ "authenticationType": "xsuaa"
17
+ }
18
+ ]
19
+ }
@@ -1,7 +1,9 @@
1
1
  const { join } = require('path')
2
- const { exists, copy } = require('../../../cds').utils
2
+ const cds = require('../../../cds')
3
+ const { copy } = cds.utils
3
4
  const { readProject } = require('../../projectReader')
4
5
  const { merge } = require('../../merge')
6
+ const { srv4, destination, html5RepoHost, html5Runtime, appContent, approuter } = require('../../registries/mta')
5
7
 
6
8
  module.exports = class Html5RepoTemplate extends require('../../plugin') {
7
9
 
@@ -9,23 +11,65 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
9
11
  return ['destination']
10
12
  }
11
13
 
12
- async canRun() {
13
- const project = readProject()
14
- const { hasMta, hasHelm, hasHelmUnifiedRuntime } = project
15
- if (!(hasHelm || hasHelmUnifiedRuntime) && hasMta) {
16
- throw `'cds add html5-repo' is not available for Cloud Foundry yet`
17
- }
18
- return true
14
+ static hasInProduction(env) {
15
+ return !!env.requires['html5-repo']
19
16
  }
20
17
 
21
- static hasInProduction() {
22
- // REVISIT: Should be detectable without helm charts
23
- return exists(join('chart', 'templates', 'html5-apps-deployer-configmap.yaml'))
18
+ async run() {
19
+ const project = readProject()
20
+ const { apps, appPath, configFile } = project
21
+ await merge(__dirname, 'files', 'package.json.hbs').into(configFile, { with: project })
22
+
23
+ await Promise.all(apps.map(async ({app}) => {
24
+ project.app = app
25
+ await merge(__dirname, 'files/ui5.yaml.hbs').into(join(appPath, app, 'ui5.yaml'), { project })
26
+ }))
27
+ await Promise.all(apps.map(async ({app}) => {
28
+ project.app = app
29
+ await merge(__dirname, 'files/app-package.json.hbs').into(join(appPath, app, 'package.json'), { project })
30
+ }))
24
31
  }
25
32
 
26
33
  async combine() {
27
34
  const project = readProject()
28
- const { hasHelm, hasHelmUnifiedRuntime } = project
35
+ const { srvPath, appPath, hasMta, hasHelm, hasHelmUnifiedRuntime, hasApprouter, apps } = project
36
+
37
+ if (hasApprouter) {
38
+ await Promise.all(apps.map(async ({app}) => {
39
+ project.app = app
40
+ await merge(__dirname, 'files/xs-app.json.hbs').into(join(appPath, app, 'xs-app.json'), { project })
41
+ }))
42
+ }
43
+
44
+ if (hasMta) {
45
+ const srv = srv4(srvPath)
46
+ project.apps = apps
47
+ const appModules = project.apps.map(app => ( {
48
+ in: 'modules',
49
+ where: { type: 'html5', path: `${appPath}${app.app}` }
50
+ }))
51
+ const additions = [srv, appContent, destination, html5RepoHost, ...appModules]
52
+ const relationships = [{
53
+ insert: [destination, 'name'],
54
+ into: [appContent, 'requires', 'name'],
55
+ }, {
56
+ insert: [html5RepoHost, 'name'],
57
+ into: [appContent, 'requires', 'name'],
58
+ }]
59
+ if (hasApprouter) {
60
+ console.log('aaddd')
61
+ additions.push(approuter, html5Runtime)
62
+ relationships.push({
63
+ insert: [html5Runtime, 'name'],
64
+ into: [approuter, 'requires', 'name'],
65
+ })
66
+ }
67
+ await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project,
68
+ additions,
69
+ relationships
70
+ })
71
+ }
72
+
29
73
  if (hasHelm || hasHelmUnifiedRuntime) {
30
74
  await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
31
75
  await merge({
@@ -10,6 +10,7 @@ build-parameters:
10
10
  before-all:
11
11
  - builder: custom
12
12
  commands:
13
+ - npm ci
13
14
  - npx cds build --production
14
15
  {{/isNodejs}}
15
16
  modules:
@@ -1,6 +1,7 @@
1
1
  const { join } = require('path')
2
2
  const cds = require('../../../cds')
3
3
  const { exists } = cds.utils
4
+ const { bold } = require('../../../util/term')
4
5
  const { copyRenderedYAML } = require('../../../util/fs')
5
6
  const { readProject } = require('../../projectReader')
6
7
  const { merge, sort } = require('../../merge')
@@ -19,4 +20,8 @@ module.exports = class MtaTemplate extends require('../../plugin') {
19
20
  await merge(__dirname, 'files/package.json').into('package.json')
20
21
  await sort('package.json', 'devDependencies')
21
22
  }
23
+
24
+ async finalize() {
25
+ if (!exists('pom.xml')) console.log(`\nRun ${bold('npm update --package-lock-only')} to freeze dependencies.`)
26
+ }
22
27
  }