@sap/cds-dk 8.1.2 → 8.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 (65) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/bin/bind.js +44 -11
  3. package/bin/cds-tsx.js +2 -0
  4. package/bin/cds.js +5 -3
  5. package/bin/compile/index.js +2 -1
  6. package/bin/deploy/index.js +19 -1
  7. package/bin/import.js +13 -4
  8. package/bin/init.js +1 -1
  9. package/bin/version.js +1 -0
  10. package/bin/watch.js +2 -2
  11. package/lib/bind/bindingManager.js +1 -1
  12. package/lib/bind/cfKeyProvider.js +1 -1
  13. package/lib/build/buildTaskProviderFactory.js +9 -3
  14. package/lib/build/plugins/helm/files/subcharts/content-deployment/Chart.yaml +1 -1
  15. package/lib/build/plugins/helm/files/subcharts/content-deployment/values.yaml +1 -1
  16. package/lib/build/plugins/helm/files/subcharts/service-instance/Chart.yaml +1 -1
  17. package/lib/build/plugins/helm/files/subcharts/service-instance/values.yaml +1 -1
  18. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
  19. package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +2 -2
  20. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +1 -1
  21. package/lib/build/provider/hana/2migration.js +2 -2
  22. package/lib/build/provider/nodejs/index.js +5 -4
  23. package/lib/build/util.js +2 -1
  24. package/lib/compile/to-mermaid.js +4 -6
  25. package/lib/import/common.js +16 -18
  26. package/lib/import/message.js +6 -5
  27. package/lib/import/odata/index.js +1 -1
  28. package/lib/import/odata/v2parser.js +18 -17
  29. package/lib/import/odata/v4parser.js +62 -62
  30. package/lib/init/constants.js +3 -2
  31. package/lib/init/mvn.js +43 -6
  32. package/lib/init/plugin.js +1 -1
  33. package/lib/init/projectReader.js +1 -1
  34. package/lib/init/template/approuter/files/containerize.yaml.hbs +5 -0
  35. package/lib/init/template/cloud-logging/files/mta.yaml.hbs +25 -0
  36. package/lib/init/template/cloud-logging/files/package.json +14 -0
  37. package/lib/init/template/cloud-logging/index.js +80 -0
  38. package/lib/init/template/containerize/files/containerize.yaml.hbs +5 -0
  39. package/lib/init/template/dynatrace/files/mta.yaml.hbs +24 -0
  40. package/lib/init/template/dynatrace/files/package.json.hbs +14 -0
  41. package/lib/init/template/dynatrace/files/sidecar.package.json +0 -0
  42. package/lib/init/template/dynatrace/index.js +55 -0
  43. package/lib/init/template/hana/files/containerize.yaml.hbs +5 -0
  44. package/lib/init/template/hana/files/package.json.hbs +5 -3
  45. package/lib/init/template/handler/index.js +22 -0
  46. package/lib/init/template/helm/index.js +5 -1
  47. package/lib/init/template/html5-repo/index.js +5 -0
  48. package/lib/init/template/http/index.js +1 -1
  49. package/lib/init/template/java/index.js +2 -2
  50. package/lib/init/template/multitenancy/files/containerize.yaml.hbs +5 -0
  51. package/lib/init/template/portal/files/portal-site/CommonDataModel.json.hbs +2 -2
  52. package/lib/init/template/portal/files/values.yaml.hbs +43 -0
  53. package/lib/init/template/portal/index.js +4 -2
  54. package/lib/init/template/telemetry/index.js +19 -0
  55. package/lib/init/template/typescript/files/package.json +1 -3
  56. package/lib/mtx/auth_manager.js +12 -15
  57. package/lib/mtx/settings_manager.js +1 -1
  58. package/lib/mtx/util/logging.js +4 -4
  59. package/lib/util/cf.js +15 -5
  60. package/lib/util/command.js +3 -3
  61. package/lib/watch/livereload-server.js +3 -3
  62. package/lib/watch/node-watch.js +3 -3
  63. package/npm-shrinkwrap.json +17 -16
  64. package/package.json +3 -2
  65. package/readme.md +2 -2
@@ -0,0 +1,80 @@
1
+ const cds = require('../../../cds')
2
+ const { merge, sort } = require('../../merge')
3
+
4
+ const { readProject } = require('../../projectReader')
5
+ const { srv4, mtxSidecar4, approuter } = require('../../registries/mta')
6
+
7
+ module.exports = class extends require('../../plugin') {
8
+
9
+ static hasInProduction(env) {
10
+ return env.requires?.telemetry?.kind === 'to-cloud-logging'
11
+ }
12
+
13
+ options() {
14
+ return {
15
+ 'plan': {
16
+ type: 'string',
17
+ help: `Override the service plan used for the MTA generation.`,
18
+ },
19
+ 'with-telemetry': {
20
+ type: 'boolean',
21
+ help: 'Add telemetry capabilities.'
22
+ }
23
+ }
24
+ }
25
+
26
+ async canRun() {
27
+ const { hasMta, hasHelm, hasHelmUnifiedRuntime } = readProject()
28
+ if ((hasHelmUnifiedRuntime || hasHelm) && !hasMta) throw `'cds add cloud-logging' is not available for Kyma yet`
29
+ return true
30
+ }
31
+
32
+ async run() {
33
+ const { hasTelemetry } = readProject()
34
+ if (cds.cli.options['with-telemetry'] || hasTelemetry) {
35
+ await merge(__dirname, 'files/package.json').into('package.json')
36
+ await sort('package.json', 'dependencies')
37
+ }
38
+ }
39
+
40
+ async combine() {
41
+ const project = readProject()
42
+ const { hasMta, hasApprouter, isJava, hasMultitenancy, srvPath } = project
43
+
44
+ if (hasMta) {
45
+ const cloudLogging = {
46
+ in: 'resources',
47
+ where: {
48
+ type: 'org.cloudfoundry.managed-service',
49
+ 'parameters.service': 'cloud-logging'
50
+ }
51
+ }
52
+ const srv = srv4(srvPath)
53
+ const additions = [srv, cloudLogging]
54
+ const relationships = [{
55
+ insert: [cloudLogging, 'name'],
56
+ into: [srv, 'requires', 'name']
57
+ }]
58
+ if (hasMultitenancy) {
59
+ const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
60
+ additions.push(mtxSidecar)
61
+ relationships.push({
62
+ insert: [cloudLogging, 'name'],
63
+ into: [mtxSidecar, 'requires', 'name']
64
+ })
65
+ }
66
+ if (hasApprouter) {
67
+ additions.push(approuter)
68
+ relationships.push({
69
+ insert: [cloudLogging, 'name'],
70
+ into: [approuter, 'requires', 'name']
71
+ })
72
+ }
73
+
74
+ project.cloudLoggingServicePlan = cds.cli.options['plan'] ?? 'standard'
75
+ await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
76
+ with: project, additions, relationships
77
+ })
78
+ }
79
+ }
80
+ }
@@ -11,10 +11,15 @@ modules:
11
11
  - name: {{appName}}-srv
12
12
  build-parameters:
13
13
  buildpack:
14
+ {{#hasHelmUnifiedRuntime}}
15
+ builder: proxy-unified-runtime-dmz.int.repositories.cloud.sap/builder/noble
16
+ {{/hasHelmUnifiedRuntime}}
17
+ {{^hasHelmUnifiedRuntime}}
14
18
  {{#isNodejs}}
15
19
  type: nodejs
16
20
  {{/isNodejs}}
17
21
  builder: builder-jammy-base
22
+ {{/hasHelmUnifiedRuntime}}
18
23
  path: {{#isNodejs}}gen/srv{{/isNodejs}}{{#isJava}}srv/target/{{appName}}-exec.jar{{/isJava}}
19
24
  env:
20
25
  {{#isNodejs}}
@@ -0,0 +1,24 @@
1
+ ---
2
+ modules:
3
+ - name: {{appName}}-srv
4
+ type: {{language}}
5
+ path: {{& srvPath}}
6
+ requires:
7
+ - name: {{appName}}-dynatrace
8
+ - name: {{appName}}-mtx
9
+ type: nodejs
10
+ path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
11
+ requires:
12
+ - name: {{appName}}-dynatrace
13
+ resources:
14
+ - name: {{appName}}-dynatrace
15
+ type: org.cloudfoundry.managed-service
16
+ parameters:
17
+ service: dynatrace
18
+ service-plan: standard
19
+ config:
20
+ tokens:
21
+ - name: ingest_apitoken
22
+ scopes:
23
+ - openTelemetryTrace.ingest
24
+ - metrics.ingest
@@ -0,0 +1,14 @@
1
+ {
2
+ "dependencies": {
3
+ "@cap-js/telemetry": ">=0",
4
+ "@opentelemetry/exporter-metrics-otlp-proto": "^0"{{#hasHelm}},
5
+ "@opentelemetry/exporter-trace-otlp-proto": "^0",
6
+ "@opentelemetry/host-metrics": "^0"
7
+ {{/hasHelm}}
8
+ },
9
+ "cds": {
10
+ "requires": {
11
+ "telemetry": "to-dynatrace"
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,55 @@
1
+ const { merge, sort } = require('../../merge')
2
+
3
+ const { readProject } = require('../../projectReader')
4
+ const { srv4, mtxSidecar4 } = require('../../registries/mta')
5
+
6
+ module.exports = class extends require('../../plugin') {
7
+
8
+ static hasInProduction(env) {
9
+ return env.requires?.telemetry?.kind === 'to-dynatrace'
10
+ }
11
+
12
+ async canRun() {
13
+ const { hasMta, hasHelm, hasHelmUnifiedRuntime } = readProject()
14
+ if ((hasHelmUnifiedRuntime || hasHelm) && !hasMta) throw `'cds add dynatrace' is not available for Kyma yet`
15
+ return true
16
+ }
17
+
18
+ async run() {
19
+ const project = readProject()
20
+ await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: project })
21
+ await sort('package.json', 'dependencies')
22
+ }
23
+
24
+ async combine() {
25
+ const project = readProject()
26
+ const { hasMta, isJava, hasMultitenancy, srvPath } = project
27
+
28
+ if (hasMta) {
29
+ const dynatrace = {
30
+ in: 'resources',
31
+ where: {
32
+ type: 'org.cloudfoundry.managed-service',
33
+ 'parameters.service': 'dynatrace'
34
+ }
35
+ }
36
+ const srv = srv4(srvPath)
37
+ const additions = [srv, dynatrace]
38
+ const relationships = [{
39
+ insert: [dynatrace, 'name'],
40
+ into: [srv, 'requires', 'name']
41
+ }]
42
+ if (hasMultitenancy) {
43
+ const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
44
+ additions.push(mtxSidecar)
45
+ relationships.push({
46
+ insert: [dynatrace, 'name'],
47
+ into: [mtxSidecar, 'requires', 'name']
48
+ })
49
+ }
50
+ await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
51
+ with: project, additions, relationships
52
+ })
53
+ }
54
+ }
55
+ }
@@ -3,8 +3,13 @@ modules:
3
3
  - name: {{appName}}-hana-deployer
4
4
  build-parameters:
5
5
  buildpack:
6
+ {{#hasHelmUnifiedRuntime}}
7
+ builder: proxy-unified-runtime-dmz.int.repositories.cloud.sap/builder/noble
8
+ {{/hasHelmUnifiedRuntime}}
9
+ {{^hasHelmUnifiedRuntime}}
6
10
  type: nodejs
7
11
  builder: builder-jammy-base
12
+ {{/hasHelmUnifiedRuntime}}
8
13
  path: {{& db.path}}
9
14
  env:
10
15
  BP_NODE_RUN_SCRIPTS: ""
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "@cap-js/hana": "^1"
4
- }{{#profile}},
4
+ },
5
5
  {{#isNodejs}}
6
6
  "cds": {
7
7
  {{/isNodejs}}
8
+ "sql": {
9
+ "native_hana_associations": false
10
+ }{{#profile}},
8
11
  "requires": {
9
12
  "[{{profile}}]": {
10
13
  {{#shortcut}}
@@ -16,9 +19,8 @@
16
19
  }
17
20
  {{/shortcut}}
18
21
  }
19
- }
22
+ }{{/profile}}
20
23
  {{#isNodejs}}
21
24
  }
22
25
  {{/isNodejs}}
23
- {{/profile}}
24
26
  }
@@ -0,0 +1,22 @@
1
+ const { readProject } = require('../../projectReader')
2
+ const mvn = require('../../mvn')
3
+
4
+
5
+ module.exports = class Handler extends require('../../plugin') {
6
+
7
+ static help() {
8
+ return 'add handler stubs'
9
+ }
10
+
11
+ canRun() {
12
+ const { isJava } = readProject()
13
+ if (!isJava) {
14
+ throw `No Java project detected. 'cds add handler' is currently only supported for Java projects.\n`
15
+ }
16
+ return true
17
+ }
18
+
19
+ async run() {
20
+ await mvn.generate('handler')
21
+ }
22
+ }
@@ -93,7 +93,7 @@ module.exports = class HelmTemplate extends require('../../plugin') {
93
93
  }
94
94
 
95
95
  async combine() {
96
- const { hasDestination, hasEnterpriseMessaging, hasEnterpriseMessagingShared, hasHana, hasMultitenancy, hasXsuaa, hasHtml5Repo, hasApprouter, hasKafka, hasAttachments, hasMalwareScanner } = readProject()
96
+ const { hasDestination, hasEnterpriseMessaging, hasEnterpriseMessagingShared, hasHana, hasMultitenancy, hasXsuaa, hasHtml5Repo, hasApprouter, hasKafka, hasAttachments, hasPortal, hasMalwareScanner } = readProject()
97
97
 
98
98
  if (hasApprouter) {
99
99
  await this._mergeDependency('web-application', 'approuter')
@@ -133,6 +133,10 @@ module.exports = class HelmTemplate extends require('../../plugin') {
133
133
  if (hasKafka) {
134
134
  await this._mergeDependency('service-instance', 'kafka')
135
135
  }
136
+ if (hasPortal) {
137
+ await this._mergeDependency('service-instance', 'portal')
138
+ await this._mergeDependency('content-deployment', 'portal-deployer')
139
+ }
136
140
  if (hasMalwareScanner) {
137
141
  await this._mergeDependency('service-instance', 'malware-scanner')
138
142
  }
@@ -5,6 +5,11 @@ const { srv4, html5RepoHost, html5Runtime, appDeployer, approuter, mtxSidecar4 }
5
5
 
6
6
  module.exports = class Html5RepoTemplate extends require('../../plugin') {
7
7
 
8
+ requires() {
9
+ const { hasHelm, hasHelmUnifiedRuntime } = readProject()
10
+ if (hasHelm || hasHelmUnifiedRuntime) return ['destination']
11
+ }
12
+
8
13
  static help() {
9
14
  return 'SAP BTP HTML5 Application Repository'
10
15
  }
@@ -178,7 +178,7 @@ module.exports = class HttpTemplate extends require('../../plugin') {
178
178
  let id
179
179
  const compositeKey = Object.keys(e.keys).length > 1
180
180
  if (compositeKey) {
181
- id = e.keys.map(k => k.type === 'cds.String' ? `${k.name}='${entityData[k.name]}'` : `${k.name}=${entityData[k.name]}`).join(',')
181
+ id = [...e.keys].map(k => k.type === 'cds.String' ? `${k.name}='${entityData[k.name]}'` : `${k.name}=${entityData[k.name]}`).join(',')
182
182
  } else {
183
183
  id = entityData[Object.keys(e.keys)[0]]
184
184
  }
@@ -40,9 +40,9 @@ module.exports = class JavaTemplate extends require('../../plugin') {
40
40
  if (err.code === 'ENOENT' && err.path === 'mvn') {
41
41
  throw `Maven executable 'mvn' not found. Follow ${info(URLS.MAVEN_INSTALL_HELP)} and install Maven on your machine.`
42
42
  }
43
- throw err;
43
+ throw err
44
44
  } finally {
45
- await rimraf(temp);
45
+ await rimraf(temp)
46
46
  }
47
47
  }
48
48
 
@@ -3,8 +3,13 @@ modules:
3
3
  - name: {{appName}}-sidecar
4
4
  build-parameters:
5
5
  buildpack:
6
+ {{#hasHelmUnifiedRuntime}}
7
+ builder: proxy-unified-runtime-dmz.int.repositories.cloud.sap/builder/noble
8
+ {{/hasHelmUnifiedRuntime}}
9
+ {{^hasHelmUnifiedRuntime}}
6
10
  type: nodejs
7
11
  builder: builder-jammy-base
12
+ {{/hasHelmUnifiedRuntime}}
8
13
  path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar{{#isJava}}/gen{{/isJava}}
9
14
  env:
10
15
  BP_NODE_RUN_SCRIPTS: ""
@@ -19,7 +19,7 @@
19
19
  "viz": [
20
20
  {{#apps}}
21
21
  {
22
- "appId": "{{appName}}.{{app}}",
22
+ "appId": "{{manifestAppId}}",
23
23
  "vizId": "{{vizId}}"
24
24
  }{{#isNotLast}},{{/isNotLast}}
25
25
  {{/apps}}
@@ -41,7 +41,7 @@
41
41
  {{#apps}}
42
42
  {
43
43
  "id": "{{appName}}{{app}}-001",
44
- "appId": "{{appName}}.{{app}}",
44
+ "appId": "{{manifestAppId}}",
45
45
  "vizId": "{{vizId}}"
46
46
  }{{#isNotLast}},{{/isNotLast}}
47
47
  {{/apps}}
@@ -0,0 +1,43 @@
1
+ ---
2
+ approuter:
3
+ bindings:
4
+ portal:
5
+ serviceInstanceName: portal
6
+ portal:
7
+ serviceOfferingName: portal
8
+ servicePlanName: standard
9
+ portal-deployer:
10
+ image:
11
+ repository: {{appName}}-portalcontent
12
+ resources:
13
+ limits:
14
+ ephemeral-storage: 1G
15
+ memory: 500M
16
+ requests:
17
+ ephemeral-storage: 1G
18
+ cpu: 500m
19
+ memory: 500M
20
+ bindings:
21
+ auth:
22
+ serviceInstanceName: xsuaa
23
+ html5-apps-repo-host:
24
+ serviceInstanceName: html5-apps-repo-host
25
+ portal:
26
+ serviceInstanceName: portal
27
+ {{=<% %>=}}
28
+ env:
29
+ SERVICE_BINDING_ROOT: /bindings
30
+ BPL_VCAP_SERVICES_ENABLED: "true"
31
+ XSUAA_CREDENTIALS:
32
+ secretKeyRef:
33
+ name: "{{ .Release.Name }}-approuter-auth"
34
+ key: credentials
35
+ REPOHOST_CREDENTIALS:
36
+ secretKeyRef:
37
+ name: "{{ .Release.Name }}-html5-apps-deployer-html5-apps-repo"
38
+ key: credentials
39
+ PORTAL_CREDENTIALS:
40
+ secretKeyRef:
41
+ name: "{{ .Release.Name }}-approuter-portal"
42
+ key: credentials
43
+ <%={{ }}=%>
@@ -29,7 +29,7 @@ module.exports = class PortalTemplate extends require('../../plugin') {
29
29
 
30
30
  async combine() {
31
31
  const project = readProject()
32
- const { isJava, hasMta, srvPath, hasHtml5Repo, hasXsuaa, hasApprouter, hasMultitenancy } = project
32
+ const { isJava, hasMta, srvPath, hasHtml5Repo, hasXsuaa, hasApprouter, hasMultitenancy, hasHelm, hasHelmUnifiedRuntime } = project
33
33
 
34
34
  if (hasMultitenancy) {
35
35
  await merge(__dirname, 'files/package.sidecar.json').into('mtx/sidecar/package.json')
@@ -79,6 +79,8 @@ module.exports = class PortalTemplate extends require('../../plugin') {
79
79
  })
80
80
  }
81
81
 
82
- // if (hasHelm) TODO
82
+ if (hasHelm || hasHelmUnifiedRuntime) {
83
+ await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
84
+ }
83
85
  }
84
86
  }
@@ -0,0 +1,19 @@
1
+ const cds = require('../../../cds')
2
+ const { readProject } = require('../../projectReader')
3
+
4
+ module.exports = class extends require('../../plugin') {
5
+
6
+ static hasInProduction(env) {
7
+ return !!env.requires?.telemetry || cds.cli.argv?.includes('telemetry') || !!cds.cli.options?.add?.telemetry
8
+ }
9
+
10
+ async canRun() {
11
+ const { hasMta, hasHelm, hasHelmUnifiedRuntime } = readProject()
12
+ if ((hasHelmUnifiedRuntime || hasHelm) && !hasMta) throw `'cds add telemetry' is not available for Kyma yet`
13
+ return true
14
+ }
15
+
16
+ requires() {
17
+ return ['cloud-logging']
18
+ }
19
+ }
@@ -5,8 +5,6 @@
5
5
  "typescript": "^5"
6
6
  },
7
7
  "scripts": {
8
- "watch": "cds-ts w",
9
- "build:ts": "tsc",
10
- "build": "cds build && npm run build:ts"
8
+ "watch": "cds-ts w"
11
9
  }
12
10
  }
@@ -12,20 +12,25 @@ const REASONS = { invalid_scope: /\binvalid_scope\b/ };
12
12
 
13
13
  function assign(params, authData) {
14
14
  if (authData?.access_token) {
15
- let message = 'Retrieved access token';
16
15
  params.set('token', authData.access_token);
16
+ const refresh = authData.refresh_token && params.get('saveRefreshToken');
17
+ if (refresh) {
18
+ params.set('refreshToken', authData.refresh_token);
19
+ } else {
20
+ params.delete('refreshToken');
21
+ }
22
+
23
+ let message = 'Retrieved access token';
17
24
  if (authData.expires_in) {
18
25
  params.set('tokenExpirationDate', Date.now() + authData.expires_in * 1000);
19
26
  if (params.get('saveData')) {
20
- message += ` (expires on ${(new Date(params.get('tokenExpirationDate'))).toLocaleString()})`;
27
+ message += ` (${refresh ? 'refreshed' : 'expiring'} after ${(new Date(params.get('tokenExpirationDate'))).toLocaleString()})`;
21
28
  }
22
29
  } else {
23
30
  params.delete('tokenExpirationDate');
24
- }
25
- if (authData.refresh_token) {
26
- params.set('refreshToken', authData.refresh_token);
27
- } else {
28
- params.delete('refreshToken');
31
+ if (params.get('saveData') && refresh) {
32
+ message += ' (will be refreshed after expiry)';
33
+ }
29
34
  }
30
35
  console.log(message + '.');
31
36
  }
@@ -132,14 +137,6 @@ module.exports = class AuthManager {
132
137
  throw getMessage('Failed to login', { error });
133
138
  }
134
139
  params.set('reqAuth', { headers: { Authorization: 'Bearer ' + params.get('token') } });
135
- if (params.has('refreshToken') && params.get('saveData')) {
136
- if (params.get('saveRefreshToken')) {
137
- console.log('Refresh Token saved. Token will be refreshed automatically.');
138
- } else {
139
- console.log(`Note: Refresh Token is not saved by default for security reasons. Use '--save-refresh-token' to override.`);
140
- params.delete('refreshToken');
141
- }
142
- }
143
140
  }
144
141
 
145
142
  if (params.get('saveData')) {
@@ -13,7 +13,7 @@ const Question = require('./util/question');
13
13
  const { httpSchema, httpsSchema, schemaRegex, localhostRegex } = require('./util/urls');
14
14
  const { capitalize } = require('./util/strings');
15
15
 
16
- const DEBUG = cds.debug('cli');
16
+ const LOG = cds.log('cli'), DEBUG = cds.debug('cli');
17
17
 
18
18
  const { ParamCollection, Persistence } = require('./params');
19
19
 
@@ -1,10 +1,10 @@
1
-
1
+ const cds = require('../../cds')
2
2
 
3
3
  function getMessage(errorText, { error, command, help = command && getCommandHelp(command) } = {}) {
4
+ const DEBUG = cds.log('cli')._debug
4
5
  let message = errorText ? errorText.trim() : '';
5
6
  if (error) {
6
- const debug = require('../../cds').debug('cli');
7
- const includeStack = debug && error.stack?.includes('\n');
7
+ const includeStack = DEBUG && error.stack?.includes('\n');
8
8
  if (message.length) {
9
9
  message = message.replace(/(?<!\p{P})$/u, ':'); // Append colon if no punctuation at the end
10
10
  message += includeStack ? '\n' : ' ';
@@ -17,7 +17,7 @@ function getMessage(errorText, { error, command, help = command && getCommandHel
17
17
  message += (oriMsg ? '\n' : '') + error.stack;
18
18
  }
19
19
  if (error.cause) {
20
- if (debug) {
20
+ if (DEBUG) {
21
21
  message += '\nCaused by: ' + getMessage('', { error: error.cause }).replace(/^(?= *at)/gm, ' ');
22
22
  } else if (error.cause.status) {
23
23
  message += `\nHTTP status: ${error.cause.status}`;
package/lib/util/cf.js CHANGED
@@ -16,6 +16,8 @@ const DEBUG = cds.debug('cli');
16
16
 
17
17
  const { bold, warn } = require('./term');
18
18
 
19
+ const { URLS } = require('../init/constants');
20
+
19
21
  const CF_COMMAND = 'cf';
20
22
 
21
23
  const POLL_COUNTER = 40;
@@ -41,7 +43,7 @@ module.exports = new class CfUtil {
41
43
  async cfRun(...args) {
42
44
  args = args.map(arg => arg.replace(/"/g, '\\"'));
43
45
  const cmdLine = `${CF_COMMAND} "${args.join('" "')}"`;
44
- DEBUG && console.time(cmdLine);
46
+ DEBUG?.time(cmdLine);
45
47
  LOG.debug('>>>', cmdLine);
46
48
 
47
49
  try {
@@ -55,9 +57,14 @@ module.exports = new class CfUtil {
55
57
  } catch (err) {
56
58
  err.stdout = err.stdout?.trim();
57
59
  err.stderr = err.stderr?.trim();
60
+
61
+ if (err.stderr.includes('command')) {
62
+ throw err.message + `\nPlease install the Cloud Foundry CLI from ${URLS.CF_CLI}`;
63
+ }
64
+
58
65
  throw err;
59
66
  } finally {
60
- DEBUG && console.timeEnd(cmdLine);
67
+ DEBUG?.timeEnd(cmdLine);
61
68
  }
62
69
  }
63
70
 
@@ -84,10 +91,13 @@ module.exports = new class CfUtil {
84
91
  } else {
85
92
  response = (await axios.get(url, options));
86
93
  }
87
- if (DEBUG) {
94
+ if (LOG._debug) {
88
95
  options.headers.Authorization = 'bearer <token>';
89
96
  LOG.debug(`POST ${url}\n${JSON.stringify(options, null, 4)}\n${JSON.stringify(response.data, null, 4)}`);
90
97
  }
98
+
99
+ // require('../../test/testUtil/recorder').record(urlPath, options.params, response.data, 'cf.json');
100
+
91
101
  return response.data;
92
102
  } catch (err) {
93
103
  if (err instanceof axios.AxiosError) {
@@ -234,7 +244,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
234
244
  return serviceInstance;
235
245
 
236
246
  case OPERATION_STATE_FAILED:
237
- if (!DEBUG && serviceInstance?.last_operation?.description) {
247
+ if (!LOG._debug && serviceInstance?.last_operation?.description) {
238
248
  throw serviceInstance.last_operation.description;
239
249
  }
240
250
  throw `The returned service reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(serviceInstance, null, 4)}`;
@@ -331,7 +341,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
331
341
  }
332
342
 
333
343
  case OPERATION_STATE_FAILED:
334
- if (!DEBUG && binding?.last_operation?.description) {
344
+ if (!LOG._debug && binding?.last_operation?.description) {
335
345
  throw binding.last_operation.description;
336
346
  }
337
347
  throw `The returned binding reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(binding, null, 4)}`;
@@ -1,7 +1,7 @@
1
1
  const cp = require('child_process');
2
2
  const os = require('os');
3
3
  const cds = require('../cds');
4
- const DEBUG = cds.debug('cli');
4
+ const LOG = cds.log('cli'), DEBUG = cds.debug('cli');
5
5
 
6
6
 
7
7
  const { IS_WIN } = require('../init/constants');
@@ -29,14 +29,14 @@ class CommandUtil {
29
29
  const child = this._getChildProcess(cmd, args, options);
30
30
 
31
31
  // use inplace methods to ensure logger is called in context
32
- const stdLogBuffer = new LogBuffer(showOutput || DEBUG ? (chunk) => console.log(chunk) : undefined, collectResult);
32
+ const stdLogBuffer = new LogBuffer(showOutput || LOG._debug ? (chunk) => console.log(chunk) : undefined, collectResult);
33
33
  child.stdout.on('data', (chunk) => {
34
34
  stdLogBuffer.handleChunk(chunk);
35
35
  });
36
36
 
37
37
  // use inplace methods to ensure logger is called in context
38
38
  // collect error log in case of Win to handle command not found (ENOENT),
39
- const errLogBuffer = new LogBuffer(showOutput || DEBUG ? (chunk) => console.error(chunk) : undefined, (IS_WIN || collectResult));
39
+ const errLogBuffer = new LogBuffer(showOutput || LOG._debug ? (chunk) => console.error(chunk) : undefined, (IS_WIN || collectResult));
40
40
  child.stderr.on('data', (chunk) => {
41
41
  errLogBuffer.handleChunk(chunk);
42
42
  });
@@ -1,5 +1,5 @@
1
1
  const cds = require('../cds')
2
- const DEBUG = cds.debug('cli|watch|livereload')
2
+ const LOG = cds.log('cli|watch|livereload'), DEBUG = cds.debug('cli|watch|livereload')
3
3
 
4
4
  const axios = require('axios')
5
5
  const ws = require('ws')
@@ -70,7 +70,7 @@ module.exports = class LiveReload {
70
70
  }
71
71
  })
72
72
  })
73
- if (DEBUG) {
73
+ if (LOG._debug) {
74
74
  server.on('close', () => DEBUG('⚡️','cds watch - livereload closed'))
75
75
  this.wsServer.on('close', () => DEBUG('⚡️','cds watch - web socket closed'))
76
76
  this.wsServer.on('error', (e) => DEBUG(e))
@@ -92,7 +92,7 @@ module.exports = class LiveReload {
92
92
  return isIn
93
93
  }
94
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'))
95
+ if (LOG._debug) watcher.on('close', ()=> DEBUG('⚡️', 'cds watch - livereload file watcher closed'))
96
96
  watcher.on('change', _coalesceEvents(delay, (files) => {
97
97
  DEBUG?. (`livereload for: ${files.map(f => f.name)}`)
98
98
  this.markPending(files.map(f => f.name))