@sap/cds-dk 7.3.0 → 7.3.2

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 (88) hide show
  1. package/bin/add.js +3 -1
  2. package/bin/build.js +2 -1
  3. package/bin/cds.js +1 -1
  4. package/bin/compile/index.js +11 -0
  5. package/bin/extend.js +5 -1
  6. package/bin/init.js +31 -37
  7. package/bin/repl.js +23 -43
  8. package/bin/watch.js +5 -9
  9. package/lib/bind/bindingResolver.js +2 -1
  10. package/lib/bind/index.js +1 -1
  11. package/lib/build/buildPlugin.js +18 -3
  12. package/lib/build/buildTaskEngine.js +2 -1
  13. package/lib/build/buildTaskFactory.js +33 -9
  14. package/lib/build/buildTaskProvider.js +1 -1
  15. package/lib/build/buildTaskProviderFactory.js +15 -61
  16. package/lib/build/constants.js +2 -0
  17. package/lib/build/index.js +5 -2
  18. package/lib/build/plugins.js +35 -0
  19. package/lib/build/provider/edmxBuildPlugin.js +9 -1
  20. package/lib/build/provider/featureToggleBuildPlugin.js +2 -3
  21. package/lib/build/provider/internalBuildPlugin.js +4 -0
  22. package/lib/build/provider/internalBuildTaskProvider.js +1 -1
  23. package/lib/build/provider/java/index.js +12 -6
  24. package/lib/build/provider/nodejs/index.js +3 -2
  25. package/lib/build/util.js +5 -0
  26. package/lib/client/base_command.js +8 -18
  27. package/lib/client/download_legacy.js +2 -10
  28. package/lib/client/params.js +6 -4
  29. package/lib/client/settings_manager.js +38 -35
  30. package/lib/compile/openapi/csdl2openapi.js +1 -1
  31. package/lib/deploy/to-hana/hana.js +53 -35
  32. package/lib/index.js +7 -1
  33. package/lib/init/constants.js +4 -2
  34. package/lib/init/template/_merging/registry-mta.js +12 -0
  35. package/lib/init/template/enterprise-messaging/files/event-mesh.json.hbs +1 -1
  36. package/lib/init/template/enterprise-messaging/index.js +1 -1
  37. package/lib/init/template/enterprise-messaging-shared/files/event-mesh.json.hbs +1 -1
  38. package/lib/init/template/enterprise-messaging-shared/index.js +19 -5
  39. package/lib/init/template/helm/index.js +1 -1
  40. package/lib/init/template/helm/subcharts/content-deployment/Chart.yaml +4 -4
  41. package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +4 -2
  42. package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +4 -3
  43. package/lib/init/template/helm/subcharts/content-deployment/values.schema.json +9 -83
  44. package/lib/init/template/helm/subcharts/content-deployment/values.yaml +54 -15
  45. package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +4 -4
  46. package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +1 -1
  47. package/lib/init/template/helm/subcharts/service-instance/values.schema.json +0 -17
  48. package/lib/init/template/helm/subcharts/service-instance/values.yaml +28 -0
  49. package/lib/init/template/helm/subcharts/web-application/Chart.yaml +5 -5
  50. package/lib/init/template/helm/subcharts/web-application/templates/_api.tpl +60 -0
  51. package/lib/init/template/helm/subcharts/web-application/templates/_helpers.tpl +34 -73
  52. package/lib/init/template/helm/subcharts/web-application/templates/api-rule.yaml +4 -4
  53. package/lib/init/template/helm/subcharts/web-application/templates/deployment.yaml +96 -17
  54. package/lib/init/template/helm/subcharts/web-application/templates/network-policy.yaml +19 -3
  55. package/lib/init/template/helm/subcharts/web-application/templates/pod-disruption-budget.yaml +3 -3
  56. package/lib/init/template/helm/subcharts/web-application/templates/rbac.yaml +26 -0
  57. package/lib/init/template/helm/subcharts/web-application/templates/secret.yaml +1 -1
  58. package/lib/init/template/helm/subcharts/web-application/templates/service-account.yaml +1 -1
  59. package/lib/init/template/helm/subcharts/web-application/templates/service-binding.yaml +1 -1
  60. package/lib/init/template/helm/subcharts/web-application/templates/service.yaml +21 -3
  61. package/lib/init/template/helm/subcharts/web-application/templates/virtual-service.yaml +36 -0
  62. package/lib/init/template/helm/subcharts/web-application/values.schema.json +535 -142
  63. package/lib/init/template/helm/subcharts/web-application/values.yaml +168 -44
  64. package/lib/init/template/local-messaging/files/package.json.hbs +15 -0
  65. package/lib/init/template/local-messaging/index.js +25 -0
  66. package/lib/init/template/mta/index.js +2 -2
  67. package/lib/init/template/nodejs/files/.gitignore.hbs +3 -0
  68. package/lib/init/template/nodejs/files/.vscode/launch.json +0 -3
  69. package/lib/init/template/notifications/files/mta.yaml.hbs +17 -0
  70. package/lib/init/template/notifications/files/package.json.hbs +5 -0
  71. package/lib/init/template/notifications/index.js +43 -0
  72. package/lib/init/template/typer/files/package.json +1 -1
  73. package/lib/init/util/projectReader.js +1 -0
  74. package/lib/util/pruneAxiosErrors.js +4 -1
  75. package/lib/util/term.js +1 -2
  76. package/lib/watch/livereload-server.js +38 -2
  77. package/lib/watch/node-watch.js +3 -2
  78. package/npm-shrinkwrap.json +438 -2205
  79. package/package.json +2 -2
  80. package/lib/init/template/helm/subcharts/content-deployment/templating.md +0 -37
  81. package/lib/init/template/helm/subcharts/content-deployment/values-lint.yaml +0 -5
  82. package/lib/init/template/helm/subcharts/content-deployment/values.md +0 -1011
  83. package/lib/init/template/helm/subcharts/service-instance/templating.md +0 -18
  84. package/lib/init/template/helm/subcharts/service-instance/values-lint.yaml +0 -2
  85. package/lib/init/template/helm/subcharts/service-instance/values.md +0 -186
  86. package/lib/init/template/helm/subcharts/web-application/templating.md +0 -51
  87. package/lib/init/template/helm/subcharts/web-application/values-lint.yaml +0 -8
  88. package/lib/init/template/helm/subcharts/web-application/values.md +0 -1363
@@ -1,27 +1,56 @@
1
+ # Helm global values, for more information, see https://helm.sh/docs/chart_template_guide/subcharts_and_globals/#global-chart-values
1
2
  global:
3
+ # Image Pull Secret configuration, for more information, see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
2
4
  imagePullSecret: {}
3
- # name: ""
4
- # dockerconfigjson: ""
5
+ ## Name of the Kubernetes Secret, used as an image pull secret (must be of type kubernetes.io/dockerconfigjson). Can't be used with the `dockerconfigjson` option.
6
+ # name: ""
7
+ ## The content for the dynamically generated Kubernetes Secret, which will be used as an image pull secret. Can't be used with the `name` option.
8
+ # dockerconfigjson: ""
9
+ # Either name or repository is required.
5
10
  image: {}
6
- # registry: gcr.io/my-project
7
- # tag: latest
11
+ ## Setting the imagePullPolicy, see https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy
12
+ # imagePullPolicy: Always
13
+
14
+ sap:
15
+ _internal:
16
+ web-application:
17
+ versions:
18
+ 1.8.0: true
19
+ ## Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
20
+ # nameOverride: name
21
+
22
+ ## Will be used as an override for the `.fullname` helper function (i.e. `.Release.Name-.Chart.Name`).
23
+ # fullnameOverride: my-name
24
+
25
+ ## The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified.
26
+ # runAsUser: 1000
8
27
 
28
+ # Number of desired pods within the Deployment.
9
29
  replicaCount: 1
30
+ # Application's exposed port.
10
31
  port: 8080
11
- #serviceAccountName: my-serviceaccount
12
-
13
- # To use a digest, change those values like that
14
- # repository: nginx@sha256
15
- # tag: 2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
32
+ ## Name of the Service Account assigned to pods.
33
+ # serviceAccountName: my-serviceaccount
16
34
  image: {}
17
- # repository: repo/image
18
- # registry: gcr.io/my-project
19
- # tag: latest
35
+ ## To use a digest, change those values as shown
36
+ # repository: nginx@sha256
37
+ # tag: 2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
38
+ ## Should also include the image name (i.e. everything before the `:` sign).
39
+ # repository: repo/image
40
+ # registry: gcr.io/my-project
41
+ # tag: latest
20
42
 
43
+ # Image Pull Secret configuration, for more information, see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
21
44
  imagePullSecret: {}
22
- # name: ""
23
- # dockerconfigjson: ""
45
+ ## Name of the Kubernetes Secret, used as an image pull secret (must be of type kubernetes.io/dockerconfigjson). Can't be used with the `dockerconfigjson` option.
46
+ # name: ""
47
+ ## The content for the dynamically generated Kubernetes Secret, which will be used as an image pull secret. Can't be used with the `name` option.
48
+ # dockerconfigjson: ""
49
+
50
+ ## Setting the imagePullPolicy, see https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy
51
+ # imagePullPolicy: Always
24
52
 
53
+ # List of volumes, which should be mounted into Pods, see https://kubernetes.io/docs/concepts/storage/volumes/ for full list of options
25
54
  additionalVolumes: []
26
55
  # - name: my-volume
27
56
  # secret:
@@ -30,6 +59,7 @@ additionalVolumes: []
30
59
  # mountPath: /etc/mysecret
31
60
  # readOnly: true
32
61
 
62
+ ## Pod resources configuration, see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ for more information
33
63
  # resources:
34
64
  # limits:
35
65
  # cpu: 100m
@@ -40,33 +70,40 @@ additionalVolumes: []
40
70
  # ephemeral-storage: 1G
41
71
  # memory: 1G
42
72
 
73
+ ## Enable or disable istio sidecars for this workload (other default is taken, e.g. namespace)
74
+ # istio:
75
+ # enabled: true
76
+
77
+ # Availability related configuration
43
78
  availability:
79
+ # The max disruption to the pods, see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ for details
44
80
  podDisruptionBudget:
45
81
  maxUnavailable: 10%
82
+ # How pods ought to spread across topology domains., see https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ for details
46
83
  topologySpreadConstraints:
47
- - topologyKey: topology.kubernetes.io/zone
48
- maxSkew: 1
49
- whenUnsatisfiable: ScheduleAnyway
50
- - topologyKey: kubernetes.io/hostname
51
- maxSkew: 1
52
- whenUnsatisfiable: ScheduleAnyway
53
-
84
+ - topologyKey: topology.kubernetes.io/zone
85
+ maxSkew: 1
86
+ whenUnsatisfiable: ScheduleAnyway
87
+ - topologyKey: kubernetes.io/hostname
88
+ maxSkew: 1
89
+ whenUnsatisfiable: ScheduleAnyway
90
+ # Health-check configuration
54
91
  health:
92
+ # Liveness-probe configuration.
55
93
  liveness:
94
+ # HTTP path used by Kubernetes, to perform liveness-probe calls.
56
95
  path: /healthz
96
+ # Readiness-probe configuration.
57
97
  readiness:
98
+ # HTTP path used by Kubernetes, to perform readiness-probe calls.
58
99
  path: /healthz
59
-
60
- # readOnlyRootFilesystem: false
61
- terminationGracePeriodSeconds: 30
100
+ # Initial timeout in seconds, during which the app must start giving the response to the liveness-probe.
62
101
  startupTimeoutSeconds: 30
102
+ ## Use read only filesystem for the Deployment.
103
+ # readOnlyRootFilesystem: false
63
104
 
64
- envFrom: []
65
- # - configMapRef:
66
- # name: my-configmap1
67
- # - secretRef:
68
- # name: my-secret-ref1
69
-
105
+ # Time in seconds after which the pod will be forcefully stopped after receiving SIGTERM.
106
+ terminationGracePeriodSeconds: 30
70
107
  env: {}
71
108
  # env:
72
109
  # key1: value
@@ -78,7 +115,7 @@ env: {}
78
115
  # configMapKeyRef:
79
116
  # name: my-configmap
80
117
  # key: my-key
81
- # Also can be specified as a list
118
+ ## Also can be specified as a list
82
119
  # env:
83
120
  # - name: key1
84
121
  # value: value1
@@ -87,22 +124,53 @@ env: {}
87
124
  # name: my-configmap
88
125
  # key: my-key
89
126
 
127
+ envFrom: []
128
+ # - configMapRef:
129
+ # name: my-configmap1
130
+ # - secretRef:
131
+ # name: my-secret-ref1
132
+
90
133
  expose:
134
+ ## Specifies the service's dns name for inbound external traffic. If it doesn't contain a dot, the default cluster domain will be appended.
135
+ # host: ""
136
+
137
+ # Expose the application to the internet.
91
138
  enabled: true
139
+ # Use this istio gateway for incoming traffic.
92
140
  gateway: kyma-gateway.kyma-system.svc.cluster.local
93
- # host: ""
94
- rules:
95
- - accessStrategies:
96
- - handler: allow
97
- methods:
98
- - GET
99
- - POST
100
- - PUT
101
- - PATCH
102
- - DELETE
103
- - HEAD
104
- path: /.*
141
+ ## Custom Istio Gateway to use with the VirtualService created using the TENANT_HOST_PATTERN.
142
+ ## If your TENANT_HOST_PATTERN uses top level domain for the tenants (like tenant-name.<provider>.<cluster-domain>), you need to create custom Certificate and Gateway since the default Kyma Gateway will not work.
143
+ # tenantGateway: tenants-gateway.my-ns.svc.cluster.local
105
144
 
145
+ # Rules represents collection of Rule to apply.
146
+ rules:
147
+ - accessStrategies:
148
+ - handler: allow
149
+ methods:
150
+ - GET
151
+ - POST
152
+ - PUT
153
+ - PATCH
154
+ - DELETE
155
+ - HEAD
156
+ path: /.*
157
+ prometheus:
158
+ # Add annotations to the Service for Prometheus Service Discovery
159
+ enabled: false
160
+ # URI used by Prometheus for scraping
161
+ path: /metrics
162
+ ## Custom port for Prometheus scraping, defaults to the application port
163
+ # port: 8081
164
+ # Open Telemetry support
165
+ otlp:
166
+ metrics:
167
+ enabled: true
168
+ # Metrics endpoint
169
+ endpoint: http://telemetry-otlp-metrics.kyma-system.svc.cluster.local:4317
170
+ traces:
171
+ enabled: true
172
+ # Trace endpoint
173
+ endpoint: http://telemetry-otlp-traces.kyma-system.svc.cluster.local:4317
106
174
  networkSecurity:
107
175
  enabled: true
108
176
  # allowNamespaceInternal: true
@@ -111,14 +179,25 @@ networkSecurity:
111
179
  # - namespace: my-namespace
112
180
  # podLabelsSelector:
113
181
  # app: my-app
182
+ # RBAC configuration https://kubernetes.io/docs/reference/access-authn-authz/rbac/. Only one of "role", "clusterRole" or "rules" can be specified.
183
+ rbac: {}
184
+ ## Name of the existing Role to use
185
+ # role: existing-role-name
186
+
187
+ ## Name of the existing ClusterRole to use
188
+ # clusterRole: existingClusterRoleName
114
189
 
190
+ ## List of RBAC rules assigned to the new Role.
191
+ # rules:
192
+ # - apiGroups: [""]
193
+ # resources: ["pods"]
194
+ # verbs: ["get", "watch", "list"]
115
195
  bindings:
116
196
  defaultProperties:
117
197
  credentialsRotationPolicy:
118
198
  enabled: false
119
199
  rotationFrequency: "720h"
120
200
  rotatedBindingTTL: "24h"
121
-
122
201
  # ui5-repo-servicerepo:
123
202
  # serviceInstanceName: ui5-repo-instance
124
203
  # externalName: ui5-kyma-binding
@@ -135,3 +214,48 @@ bindings:
135
214
  # serviceInstanceName: hana-manual
136
215
  # portal:
137
216
  # fromSecret: manual-secret # user-provided-service
217
+
218
+ ## Annotations to add to objects
219
+ annotations:
220
+ ## Annotations to add to the Deployment and underlying Pods
221
+ deployment: {}
222
+ # sidecars:
223
+ # sidecar-1:
224
+ # image:
225
+ # repository: gcr.io/my-sidecar-1
226
+ # tag: latest
227
+ # imagePullPolicy: Always
228
+ # resources:
229
+ # limits:
230
+ # cpu: 100m
231
+ # ephemeral-storage: 1G
232
+ # memory: 1G
233
+ # requests:
234
+ # cpu: 100m
235
+ # ephemeral-storage: 1G
236
+ # memory: 1G
237
+ # env:
238
+ # - name: SIDECAR_PROXY_REQUEST_TIMEOUT
239
+ # value: "60000"
240
+ # envFrom:
241
+ # - configMapRef:
242
+ # name: my-configmap1
243
+ # sidecar-2:
244
+ # image:
245
+ # repository: gcr.io/my-sidecar-2
246
+ # tag: latest
247
+ # imagePullPolicy: Always
248
+ # resources:
249
+ # limits:
250
+ # cpu: 100m
251
+ # ephemeral-storage: 1G
252
+ # memory: 1G
253
+ # requests:
254
+ # cpu: 100m
255
+ # ephemeral-storage: 1G
256
+ # memory: 1G
257
+ # env:
258
+ # SIDECAR_PROXY_REQUEST_TIMEOUT: 30000
259
+ # envFrom:
260
+ # - configMapRef:
261
+ # name: my-configmap1
@@ -0,0 +1,15 @@
1
+ {
2
+ "cds": {
3
+ "requires": {
4
+ {{#profile}}
5
+ "[{{profile}}]": {
6
+ {{/profile}}
7
+ "messaging": {
8
+ "kind": "local-messaging"
9
+ }
10
+ {{#profile}}
11
+ }
12
+ {{/profile}}
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,25 @@
1
+ const { join } = require('path')
2
+ const cds = require('../../../cds')
3
+ const { read } = cds.utils
4
+ const { readProject } = require('../../util/projectReader')
5
+ const { mergeJSON } = require('../../util/merge')
6
+
7
+ module.exports = class LocalMessagingTemplate extends require('../templateBase') {
8
+
9
+ async canRun() {
10
+ const { isJava } = await readProject()
11
+ if (isJava) throw `'cds add local-messaging' is not available for Java yet`
12
+ return true
13
+ }
14
+
15
+ static hasFacet(env) {
16
+ return env.requires?.messaging?.kind === 'local-messaging'
17
+ }
18
+
19
+ async run() {
20
+ const project = await readProject()
21
+ const { configFile } = project
22
+ project.shortcut = !(await read(configFile)).cds?.requires?.messaging?.kind
23
+ await mergeJSON(configFile, join(__dirname, 'files', 'package.json.hbs'), project)
24
+ }
25
+ }
@@ -9,7 +9,7 @@ const {
9
9
  MTA, HELM,
10
10
  HANA, POSTGRES,
11
11
  ENTERPRISE_MESSAGING, ENTERPRISE_MESSAGING_SHARED, REDIS_MESSAGING,
12
- CONNECTIVITY, DESTINATION
12
+ CONNECTIVITY, DESTINATION, NOTIFICATIONS
13
13
  } = require('../../constants').OPTIONS
14
14
  module.exports = class MtaTemplate extends require('../templateBase') {
15
15
 
@@ -20,7 +20,7 @@ module.exports = class MtaTemplate extends require('../templateBase') {
20
20
  }
21
21
 
22
22
  getRelatedFacets() {
23
- return [APPROUTER, XSUAA, MULTITENANCY, HANA, POSTGRES, EXTENSIBILITY, ENTERPRISE_MESSAGING, ENTERPRISE_MESSAGING_SHARED, REDIS_MESSAGING, CONNECTIVITY, DESTINATION]
23
+ return [APPROUTER, XSUAA, MULTITENANCY, HANA, POSTGRES, EXTENSIBILITY, ENTERPRISE_MESSAGING, ENTERPRISE_MESSAGING_SHARED, REDIS_MESSAGING, CONNECTIVITY, DESTINATION, NOTIFICATIONS]
24
24
  }
25
25
 
26
26
  async run() {
@@ -29,3 +29,6 @@ mta_archives/
29
29
  # IDEs
30
30
  # .vscode
31
31
  # .idea
32
+
33
+ # @cap-js/cds-typer
34
+ @cds-models
@@ -1,7 +1,4 @@
1
1
  {
2
- // Use IntelliSense to learn about possible attributes.
3
- // Hover to view descriptions of existing attributes.
4
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
2
  "version": "0.2.0",
6
3
  "configurations": [
7
4
  {
@@ -0,0 +1,17 @@
1
+ ---
2
+ modules:
3
+ - name: notification-content-deployment
4
+ type: nodejs
5
+ path: gen/srv
6
+ parameters:
7
+ no-route: true
8
+ no-start: true
9
+ memory: 256MB
10
+ disk-quota: 256MB
11
+ tasks:
12
+ - name: notification-content-deployment
13
+ command: "node node_modules/@cap-js/notifications/lib/content-deployment.js"
14
+ memory: 256MB
15
+ disk-quota: 256MB
16
+ requires:
17
+ - name: {{appName}}-destination
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "@cap-js/notifications": "*"
4
+ }
5
+ }
@@ -0,0 +1,43 @@
1
+ const { join } = require('path')
2
+ const { readProject } = require('../../util/projectReader')
3
+ const { mergeJSON, mergeYAML } = require('../../util/merge')
4
+ const { DESTINATION } = require('../../constants').OPTIONS
5
+
6
+ const { notificationTypesDeployer } = require('../_merging/registry-mta')
7
+
8
+ module.exports = class NotificationsTemplate extends require('../templateBase') {
9
+
10
+ static hasFacet(env) {
11
+ return !!env.requires?.notifications;
12
+ }
13
+
14
+ async canRun() {
15
+ const project = await readProject()
16
+ const { isJava } = project
17
+ if (isJava) {
18
+ throw `'cds add notifications' is not available for Java yet`
19
+ }
20
+ return true
21
+ }
22
+
23
+ getDependencies() {
24
+ return [DESTINATION]
25
+ }
26
+
27
+ async run() {
28
+ const project = await readProject()
29
+ const { configFile } = project
30
+ await mergeJSON(configFile, join(__dirname, 'files', 'package.json.hbs'), project)
31
+ }
32
+
33
+ async runDependentMerging() {
34
+ const project = await readProject()
35
+ const { hasMta } = project
36
+
37
+ if (hasMta) {
38
+ await mergeYAML('mta.yaml', join(__dirname, 'files', 'mta.yaml.hbs'), project, {
39
+ additions: [notificationTypesDeployer]
40
+ })
41
+ }
42
+ }
43
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "devDependencies": {
3
- "@cap-js/cds-typer": "^0"
3
+ "@cap-js/cds-typer": ">=0.1"
4
4
  },
5
5
  "imports": {
6
6
  "#cds-models/*": "./@cds-models/*/index.js"
@@ -83,6 +83,7 @@ module.exports = new class ProjectReader {
83
83
  get appPath() { return env.folders.app ?? 'app' },
84
84
  get appVersion() { return appVersion },
85
85
  get appName() { return appName },
86
+ get cleanedAppName() { return appName.replace('_', '-') }, // Required when _ isn't allowed in the namespace
86
87
  get appId() { return appId },
87
88
  get appDescription() { return appDescription },
88
89
  }
@@ -15,7 +15,10 @@ require('axios').interceptors.response.use(
15
15
  const { status, statusText } = response;
16
16
  let { data } = response;
17
17
  if (Buffer.isBuffer(data)) {
18
- data = JSON.parse(data.toString());
18
+ data = data.toString();
19
+ try {
20
+ data = JSON.parse(data);
21
+ } catch (error) { /* unexpected; data will be included in error below */ }
19
22
  }
20
23
  const reason = data?.error /* RFC 6749 */ && (typeof data.error === 'string' ? data.error : inspect(data.error));
21
24
  const message = (url && method ? `${method.toUpperCase()} ${url} ` : '') +
package/lib/util/term.js CHANGED
@@ -1,4 +1,3 @@
1
- // FIXME: Nicht gut, das wir das zweimal redundant haben!
2
1
  const DEBUG = /\b(y|all|cli)\b/.test(process.env.DEBUG) ? console.debug : undefined
3
2
 
4
3
  // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
@@ -16,7 +15,7 @@ const t = module.exports.codes = {
16
15
  Object.defineProperty(module.exports, 'isTTY', { get: () => process.stdin.isTTY && process.stderr.isTTY })
17
16
 
18
17
  const as = module.exports.as = (codes, o) => {
19
- return module.exports.isTTY ? (codes + o + t.reset) : ('' + o)
18
+ return module.exports.isTTY && !process.env.NO_COLOR ? (codes + o + t.reset) : ('' + o)
20
19
  }
21
20
 
22
21
  const asErr = module.exports.error = o => DEBUG ? o : as(t.red + t.bold, o)
@@ -5,9 +5,14 @@ const axios = require('axios')
5
5
  const ws = require('ws')
6
6
  const express = require('express')
7
7
  const { URL } = require('url')
8
+ const { relative, sep } = require ('path')
9
+
10
+ const ext = 'css,gif,html,jpg,png,svg,ts,mjs,cjs,js,json,properties,change,variant,ctrl_variant,ctrl_variant_change,ctrl_variant_management_change'
11
+ const watchIncludes = RegExp(`\\.(${ext.replace(/,/g,'|')})$|\\${sep}(webapp|appconfig)`)
12
+ const watchExcludes = RegExp(`@cds-models\\${sep}|@types\\${sep}`)
8
13
 
9
14
  module.exports = class LiveReload {
10
- async start(port) {
15
+ async start(port, cwd, delay=0) {
11
16
  if (!parseInt(port)) port = 35729
12
17
  this.files = []
13
18
 
@@ -43,7 +48,7 @@ module.exports = class LiveReload {
43
48
  this.wsServer.on('connection', (socket) => {
44
49
  DEBUG?.('Client connected')
45
50
  socket.on('message', (msg) => {
46
- DEBUG?.('Client message', msg)
51
+ DEBUG?.('Client message', msg.toString())
47
52
  const request = JSON.parse(msg)
48
53
 
49
54
  if (request.command === 'hello') {
@@ -77,6 +82,24 @@ module.exports = class LiveReload {
77
82
  this.wsServer.close()
78
83
  server.close()
79
84
  })
85
+
86
+ // Watching for touched files...
87
+ const watch = require('node-watch')
88
+ const filter = f => {
89
+ const isIn = !watchExcludes.test(f) && watchIncludes.test(f)
90
+ if (!isIn) DEBUG?. (`livereload ignored: ${relative(cwd||process.cwd(), f)}`)
91
+ // else DEBUG?. (`livereload NOT ignored: ${relative(cwd||process.cwd(), f)}`, watchIncludes)
92
+ return isIn
93
+ }
94
+ const watcher = watch (cwd||process.cwd(),{ recursive:true, filter, delay:0 })
95
+ if (DEBUG) watcher.on('close', ()=> DEBUG('⚡️', 'cds watch - livereload file watcher closed'))
96
+ watcher.on('change', _coalesceEvents(delay, (files) => {
97
+ DEBUG?. (`livereload for: ${files.map(f => f.name)}`)
98
+ this.markPending(files.map(f => f.name))
99
+ this.reload()
100
+ }))
101
+ process.once('shutdown', ()=> watcher.close())
102
+
80
103
  })
81
104
  }
82
105
 
@@ -99,6 +122,19 @@ module.exports = class LiveReload {
99
122
  }
100
123
  }
101
124
 
125
+ // reduces mutiple node-watch events in a time frame into a bulk
126
+ function _coalesceEvents(delay, fn) {
127
+ let timer, cache = []
128
+ return function(type, name) { // node-watch callback signature
129
+ if (type) cache.push({type, name})
130
+ if (!timer) timer = setTimeout(() => {
131
+ fn(cache)
132
+ timer = null
133
+ cache = []
134
+ }, delay).unref();
135
+ }
136
+ }
137
+
102
138
  function broadcast(data, sockets) {
103
139
  sockets.forEach(socket => {
104
140
  DEBUG?.(`Sending ${data}`)
@@ -2,7 +2,7 @@ const cds = require ('../cds')
2
2
  const DEBUG = cds.debug('cli|watch')
3
3
  const { relative } = require('path')
4
4
 
5
- module.exports = ({ cwd, script, ext, includes=RegExp(), ignore=RegExp(), env={}, delay=200, options={} })=>{
5
+ module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, options={} })=>{
6
6
 
7
7
  let child
8
8
 
@@ -52,10 +52,11 @@ module.exports = ({ cwd, script, ext, includes=RegExp(), ignore=RegExp(), env={}
52
52
 
53
53
  // Watching for touched files...
54
54
  const watch = require('node-watch')
55
- const include = RegExp(`\\.(${ext.replace(/,/g,'|')})$|${includes.source}`)
55
+ const include = RegExp(`\\.(${ext.replace(/,/g,'|')})$`)
56
56
  const filter = f => {
57
57
  const isIn = !ignore.test(f) && include.test(f)
58
58
  if (!isIn) DEBUG?. (`ignored: ${relative(cwd||process.cwd(), f)}`)
59
+ // else DEBUG?. (`NOT ignored: ${relative(cwd||process.cwd(), f)}`, include.test(f), include)
59
60
  return isIn
60
61
  }
61
62
  const watcher = watch (cwd||process.cwd(),{ recursive:true, filter, delay:0 })