@sap/cds-dk 6.5.2 → 6.6.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 (124) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/bin/activate.js +7 -0
  3. package/bin/add.js +1 -2
  4. package/bin/build/all.js +14 -9
  5. package/bin/cds.js +11 -8
  6. package/bin/compile/index.js +13 -3
  7. package/bin/env.js +16 -25
  8. package/bin/extend.js +8 -0
  9. package/bin/init.js +0 -3
  10. package/bin/login.js +3 -7
  11. package/bin/logout.js +2 -7
  12. package/bin/watch.js +4 -5
  13. package/lib/client/activate.js +1 -1
  14. package/lib/client/helper/errors.js +4 -1
  15. package/lib/client/params.js +4 -3
  16. package/lib/client/pull.js +31 -5
  17. package/lib/client/push.js +3 -3
  18. package/lib/client/settings_manager.js +6 -6
  19. package/lib/client/subscription.js +1 -1
  20. package/lib/compile/asyncapi/channels.js +22 -0
  21. package/lib/compile/asyncapi/components/messageTraits/index.js +89 -0
  22. package/lib/compile/asyncapi/components/messages/index.js +150 -0
  23. package/lib/compile/asyncapi/components/schemas/annotations.js +13 -0
  24. package/lib/compile/asyncapi/components/schemas/array.js +8 -0
  25. package/lib/compile/asyncapi/components/schemas/cache.js +14 -0
  26. package/lib/compile/asyncapi/components/schemas/definition.js +187 -0
  27. package/lib/compile/asyncapi/components/schemas/enum.js +16 -0
  28. package/lib/compile/asyncapi/components/schemas/examples.js +10 -0
  29. package/lib/compile/asyncapi/components/schemas/index.js +14 -0
  30. package/lib/compile/asyncapi/components/schemas/localized.js +29 -0
  31. package/lib/compile/asyncapi/components/schemas/primitiveElement.js +41 -0
  32. package/lib/compile/asyncapi/components/schemas/ref.js +45 -0
  33. package/lib/compile/asyncapi/components/schemas/utils.js +108 -0
  34. package/lib/compile/asyncapi/index.js +226 -0
  35. package/lib/compile/asyncapi/message.js +13 -0
  36. package/lib/compile/asyncapi/utils.js +27 -0
  37. package/lib/compile/index.js +1 -0
  38. package/lib/compile/openapi/csdl2openapi.js +42 -18
  39. package/lib/import/message.js +4 -1
  40. package/lib/import/odata/metadataconverter/MetadataConverter.js +8 -3
  41. package/lib/import/odata/v2parser.js +131 -50
  42. package/lib/import/odata/v4parser.js +292 -112
  43. package/lib/import/openapi/importOpenAPI.js +14 -14
  44. package/lib/init/constants.js +1 -1
  45. package/lib/init/index.js +11 -21
  46. package/lib/init/template/_merging/registry-mta.js +15 -26
  47. package/lib/init/template/approuter/files/package.json +2 -2
  48. package/lib/init/template/approuter/index.js +6 -12
  49. package/lib/init/template/auditlog/files/auditlog.yaml +4 -1
  50. package/lib/init/template/auditlog/index.js +23 -8
  51. package/lib/init/template/cf-manifest/index.js +4 -14
  52. package/lib/init/template/connectivity/files/connectivity-proxy-info.yaml +2 -6
  53. package/lib/init/template/connectivity/files/values.yaml.hbs +5 -8
  54. package/lib/init/template/connectivity/index.js +2 -9
  55. package/lib/init/template/data/index.js +0 -4
  56. package/lib/init/template/destinations/files/destination.yaml +4 -1
  57. package/lib/init/template/destinations/index.js +25 -10
  58. package/lib/init/template/enterprise-messaging/files/event-mesh.yaml +4 -1
  59. package/lib/init/template/enterprise-messaging/files/values.yaml +1 -2
  60. package/lib/init/template/enterprise-messaging/index.js +28 -20
  61. package/lib/init/template/extensibility/index.js +23 -31
  62. package/lib/init/template/hana/files/hana.yaml +4 -1
  63. package/lib/init/template/hana/index.js +44 -24
  64. package/lib/init/template/helm/chart/templates/_helpers.tpl +12 -0
  65. package/lib/init/template/helm/chart/values.root.schema.json +40 -0
  66. package/lib/init/template/helm/chart/values.schema.json +32 -69
  67. package/lib/init/template/helm/index.js +26 -16
  68. package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +13 -26
  69. package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +3 -3
  70. package/lib/init/template/helm/subcharts/content-deployment/templates/service-account.yaml +2 -0
  71. package/lib/init/template/helm/subcharts/content-deployment/templates/service-binding.yaml +3 -3
  72. package/lib/init/template/helm/subcharts/content-deployment/templating.md +37 -0
  73. package/lib/init/template/helm/subcharts/content-deployment/values.md +182 -185
  74. package/lib/init/template/helm/subcharts/content-deployment/values.schema.json +18 -22
  75. package/lib/init/template/helm/subcharts/content-deployment/values.yaml +2 -0
  76. package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +5 -0
  77. package/lib/init/template/helm/subcharts/service-instance/templates/_helpers.tpl +65 -0
  78. package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +23 -0
  79. package/lib/init/template/helm/subcharts/service-instance/templating.md +18 -0
  80. package/lib/init/template/helm/subcharts/service-instance/values-lint.yaml +2 -0
  81. package/lib/init/template/helm/subcharts/service-instance/values.md +186 -0
  82. package/lib/init/template/helm/subcharts/service-instance/values.schema.json +102 -0
  83. package/lib/init/template/helm/subcharts/service-instance/values.yaml +15 -0
  84. package/lib/init/template/html5-repo/files/html5-apps-deployer-configmap.yaml +2 -2
  85. package/lib/init/template/html5-repo/files/html5-apps-repo-host.yaml +4 -1
  86. package/lib/init/template/html5-repo/index.js +30 -21
  87. package/lib/init/template/java/index.js +3 -6
  88. package/lib/init/template/kibana-logging/index.js +7 -10
  89. package/lib/init/template/lint/index.js +2 -3
  90. package/lib/init/template/mta/files/mta.yaml.hbs +4 -2
  91. package/lib/init/template/mta/index.js +7 -11
  92. package/lib/init/template/mtx/index.js +0 -5
  93. package/lib/init/template/multitenancy/files/java/package.json +16 -7
  94. package/lib/init/template/multitenancy/files/mta.yaml.hbs +11 -3
  95. package/lib/init/template/multitenancy/files/saas-registry-secret.yaml +9 -0
  96. package/lib/init/template/multitenancy/files/saas-registry.yaml +4 -17
  97. package/lib/init/template/multitenancy/files/service-manager.yaml +4 -1
  98. package/lib/init/template/multitenancy/files/values.yaml.hbs +15 -3
  99. package/lib/init/template/multitenancy/index.js +56 -31
  100. package/lib/init/template/nodejs/index.js +4 -7
  101. package/lib/init/template/notebook/index.js +1 -3
  102. package/lib/init/template/pipeline/index.js +2 -5
  103. package/lib/init/template/samples/index.js +6 -11
  104. package/lib/init/template/templateBase.js +10 -17
  105. package/lib/init/template/toggles/index.js +2 -6
  106. package/lib/init/template/xsuaa/files/values.yaml.hbs +0 -1
  107. package/lib/init/template/xsuaa/files/xsuaa.yaml +4 -1
  108. package/lib/init/template/xsuaa/index.js +27 -23
  109. package/lib/init/types.d.ts +0 -81
  110. package/lib/init/util/merge.js +23 -25
  111. package/lib/init/util/mvnArchetypeUtil.js +34 -2
  112. package/lib/init/util/projectReader.js +27 -24
  113. package/lib/lint/Linter.js +31 -13
  114. package/lib/watch/livereload-server.js +29 -17
  115. package/lib/watch/node-watch.js +51 -49
  116. package/npm-shrinkwrap.json +548 -467
  117. package/package.json +4 -4
  118. package/readme.md +5 -0
  119. package/lib/init/template/connectivity/files/connectivity-binding.yaml +0 -9
  120. package/lib/init/template/connectivity/files/connectivity.yaml +0 -1
  121. package/lib/init/template/multitenancy/files/xsuaa.yaml +0 -1
  122. /package/lib/init/template/hana/files/{chart.yaml → hana-deployer.yaml} +0 -0
  123. /package/lib/init/template/html5-repo/files/{chart.yaml → html5-apps-deployer.yaml} +0 -0
  124. /package/lib/init/template/multitenancy/files/{chart.yaml → sidecar.yaml} +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,46 @@ This project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
  The format is based on [Keep a Changelog](http://keepachangelog.com/).
9
9
 
10
+ ## Version 6.6.1 - 2023-03-09
11
+
12
+ ### Added
13
+
14
+ - `cds compile --to openapi` now adds extension validation keywords `x-sap-precision` and `x-sap-scale` for decimal values.
15
+
16
+ ### Fixed
17
+
18
+ - `cds add helm` fixed html5 cloud service is now read properly.
19
+ - `cds import` now flattens the `@Capabilities` anotation in the CSN for OData V4 files.
20
+ - `cds import` for OData V4 files now captures the `EnumTypes` information in the CSN according to `UnderlyingType`.
21
+ - `cds import` now captures the `@Common.Text` annotation value properly in the CSN for OData V4 files.
22
+ - `cds init --add java` now uses local Java version when creating new Java project.
23
+ - `cds watch` terminates properly in case livereload websocket clients are connected
24
+ - `cds watch`'s livereload feature works again on Node.js >= 17, where local IPv6 addresses are the default (`::1` instead of `127.0.0.1`)
25
+
26
+ ## Version 6.6.0 - 2023-02-28
27
+
28
+ ### Added
29
+
30
+ - `cds compile` added a new target format `asyncapi` to convert CDS models to AsyncAPI documents.
31
+ - `cds pull` now hints at base-model name for `using` statement.
32
+
33
+ ### Changed
34
+
35
+ - `cds env` now allows inspecting entries with optional `get` command. E.g. `cds env requires.db`.
36
+ - `cds add multitenancy` now uses async SaaS Provisioning Service onboarding by default.
37
+ - `cds add multitenancy` for Java will now add `sqlite3` to `devDependencies` in the sidecar `package.json`.
38
+ - `cds add extensibility` now works for Java projects out-of-the-box.
39
+ - `cds import` now captures the Edm Primitive types without [CDS mapping](https://github.tools.sap/cap/cds-dk/blob/main/edm2cdsTypeMapping.md) with annotation `@odata.Type` and marks the type as `cds.String`.
40
+ - `cds add helm` connectivity service instance is no longer created.
41
+ - `cds init` uses latest Maven Java archetype version 1.32.0 for creating Java projects.
42
+
43
+ ### Fixed
44
+
45
+ - `cds unsubscribe --from` flag now recognized
46
+ - `cds import` now adds `cds.Boolean` as dummy return type if `ReturnType` for `FunctionImport` is missing in the OData V2 edmx.
47
+ - `cds import` resolves the `$Cast` construct in the CSN for OData V4 files.
48
+ - `cds lint` now reports like ESLint in case of missing plugin `@sap/eslint-plugin-cds`
49
+
10
50
  ## Version 6.5.2 - 2023-02-10
11
51
 
12
52
  ### Changed
package/bin/activate.js CHANGED
@@ -7,6 +7,8 @@ module.exports = Object.assign(activate, {
7
7
 
8
8
  *cds activate* [ <extension-project-directory> ]
9
9
 
10
+ **Deprecated - for use with previous MTX Services (@sap/cds-mtx).**
11
+
10
12
  Activate an extension project.
11
13
  By default, the current working directory is used as project directory.
12
14
 
@@ -44,6 +46,11 @@ module.exports = Object.assign(activate, {
44
46
 
45
47
  Use the synchronous server API to upload extensions.
46
48
 
49
+ # SEE ALSO
50
+
51
+ *cds push* to push an extension to a SaaS app based on current MTX Services (@sap/cds-mtxs).
52
+ https://cap.cloud.sap/docs/guides/multitenancy/mtxs for information on @sap/cds-mtxs.
53
+
47
54
  `})
48
55
 
49
56
 
package/bin/add.js CHANGED
@@ -44,8 +44,7 @@ module.exports = Object.assign(add, {
44
44
 
45
45
  *helm* - adds helm chart folder that contains the files needed to deploy the application using Kyma.
46
46
 
47
- To add a specific feature in the helm chart you can use the command 'cds add helm:<featureName>'.
48
- For example cds add helm:xsuaa and cds add helm:html5_apps_deployer.
47
+ *html5-repo* - adds configuration for HTML5 Application Deployer to Helm Chart (Kyma Only).
49
48
 
50
49
 
51
50
  # OPTIONS
package/bin/build/all.js CHANGED
@@ -48,7 +48,7 @@ module.exports = Object.assign(build, {
48
48
  `
49
49
  })
50
50
 
51
- function build([project], options = {}) {
51
+ async function build([project], options = {}) {
52
52
  options.project = options.project || project
53
53
  // switch-off error logging as CLI is logging any exceptions by default
54
54
  // otherwise errors are logged twice
@@ -66,14 +66,19 @@ function build([project], options = {}) {
66
66
  }
67
67
 
68
68
  const cds = require('../../lib/cds')
69
- if (typeof cds.build === 'function') {
70
- return cds.build(options)
69
+ try {
70
+ if (typeof cds.build === 'function') {
71
+ return await cds.build(options)
72
+ }
73
+ console.warn(`
74
+ > WARNING: This application uses a very old version ${cds.version} of package '@sap/cds',
75
+ > which will no longer be supported with the next major version of '@sap/cds-dk'.
76
+ > We strongly recommend an upgrade to latest version 6 of '@sap/cds'.
77
+ `)
78
+ return await cds.build.build(options)
79
+ } catch (e) {
80
+ process.exitCode = 1
81
+ cds._log(e.errors || e, { 'log-level': cds.env.log.levels.cli })
71
82
  }
72
- console.warn(`
73
- > WARNING: This application uses a very old version ${cds.version} of package '@sap/cds',
74
- > which will no longer be supported with the next major version of '@sap/cds-dk'.
75
- > We strongly recommend an upgrade to latest version 6 of '@sap/cds'.
76
- `)
77
- return cds.build.build(options)
78
83
 
79
84
  }
package/bin/cds.js CHANGED
@@ -25,14 +25,13 @@ const cli = { //NOSONAR
25
25
  '-e':'eval'
26
26
  },
27
27
 
28
- exec (cmd = process.argv[2], ...argv) {
28
+ async exec (cmd = process.argv[2], ...argv) {
29
29
  if (!argv.length) argv = process.argv.slice(3)
30
30
  if (!cmd) cmd = process.stdin.isTTY ? 'help' : 'compile'
31
31
  if (cmd in this.Shortcuts) cmd = process.argv[2] = this.Shortcuts[cmd]
32
32
  if (argv.some(a => this.Shortcuts[a]==='help')) return this.help (cmd)
33
33
 
34
34
  const cds_cli = require (_local('@sap/cds/bin/cds'))
35
- if (cmd !== 'repl' && process.env.NODE_ENV !== 'test') cds_cli.errorHandlers()
36
35
  DEBUG && DEBUG (`[cds] - @sap/cds ${require('../lib/cds').version} loaded: ${require('../lib/cds').home}`)
37
36
 
38
37
  const task = this.load (cmd, /*else*/ (f)=> argv.unshift(cmd) && _defaultCompile (argv,f))
@@ -44,11 +43,15 @@ const cli = { //NOSONAR
44
43
  appendArgs = argv.slice(endOfOptions+1)
45
44
  argv = argv.slice(0, endOfOptions)
46
45
  }
47
- const args = cds_cli.args(task,argv)
48
- args[0].push(...appendArgs)
49
- const resolveBindings = cmd in { run: 1, serve: 1, migrate: 1 } && argv.includes('--resolve-bindings')
50
- if (resolveBindings) return _resolveBindings().then(() => task.apply(this, args))
51
- else return task.apply(this, args)
46
+ try {
47
+ const args = cds_cli.args(task,argv)
48
+ args[0].push(...appendArgs)
49
+ if (args[1]?.['resolve-bindings']) await _resolveBindings()
50
+ return task.apply(this, args)
51
+ } catch (e) {
52
+ process.exitCode = 1
53
+ console.error (e)
54
+ }
52
55
  }
53
56
  },
54
57
 
@@ -135,7 +138,7 @@ function _dieForUnknownCommand(cmd) {
135
138
  `
136
139
  console.error(msg)
137
140
 
138
- process.exit(1)
141
+ process.exitCode = 1
139
142
  }
140
143
 
141
144
  function _require (id,o) {
@@ -1,3 +1,5 @@
1
+ const path = require("path");
2
+
1
3
  module.exports = Object.assign ( compile, {
2
4
  options: [
3
5
  '--from', '--service', '--lang', '--for', '--to', '--dest', '--log-level', '--flavor', '--dialect', '--sql-dialect', '--openapi:url', '--openapi:servers'
@@ -6,7 +8,7 @@ module.exports = Object.assign ( compile, {
6
8
  undefined, '-s', '-l', '-4', '-2', '-o', undefined, '-f'
7
9
  ],
8
10
  flags: [
9
- '--parse', '--plain', '--clean', '--files', '--sources', '--resolved', '--all', '--beta', '--conceptual', '--min', '--docs', '--locations', '--openapi:diagram'
11
+ '--parse', '--plain', '--clean', '--files', '--sources', '--resolved', '--all', '--beta', '--conceptual', '--min', '--docs', '--locations', '--openapi:diagram', '--asyncapi:merged'
10
12
  ],
11
13
  help: `
12
14
  # SYNOPSIS
@@ -41,6 +43,7 @@ module.exports = Object.assign ( compile, {
41
43
  - cdl [beta]
42
44
  - xsuaa
43
45
  - openapi
46
+ - asyncapi
44
47
 
45
48
  *-4* | *--for* <target>
46
49
 
@@ -54,6 +57,7 @@ module.exports = Object.assign ( compile, {
54
57
  *-s* | *--service* <name> | all
55
58
 
56
59
  Chooses a specific service or _all_ to force output for all services.
60
+ The service name must be fully qualified, including the namespace, if any.
57
61
 
58
62
  *-l* | *--lang* <languages> | all
59
63
 
@@ -114,11 +118,17 @@ module.exports = Object.assign ( compile, {
114
118
 
115
119
  Include YUML diagram in the generated OpenAPI document, default: *false*.
116
120
 
121
+ *--asyncapi:merged*
122
+
123
+ A single AsyncAPI document is generated using the details of all input services. Information of _title_
124
+ and _version_ should be provided as preset.
125
+
117
126
  # EXAMPLES
118
127
 
119
128
  *cds* compile model.cds
120
129
  *cds* c model.json --to sql
121
130
  *cds* srv -s all -l all -2 edmx -o _out
131
+ *cds* compile srv -s sap.sample.TestService -2 asyncapi -o _out
122
132
 
123
133
  `})
124
134
 
@@ -196,12 +206,11 @@ function compile (models, options={}) {
196
206
  }()
197
207
  }))
198
208
  }
199
-
200
209
  // add output processor
201
210
  const write = require ('../../lib/util/write')
202
211
  chain = chain.then (write.to ({
203
212
  folder: options.dest,
204
- file: options.file || options.service === 'all' ? src : options.service,
213
+ file: options.file || options.service === 'all' ? path.basename(src) : options.service,
205
214
  suffix: options.suffix || suffix4(_suffix),
206
215
  [options.dest ? 'foreach' : 'log']: options.log || consoleLog
207
216
  }))
@@ -274,6 +283,7 @@ function compile (models, options={}) {
274
283
  ddl: '.sql',
275
284
  sql: '.sql',
276
285
  edm: '.json',
286
+ asyncapi: '.json',
277
287
  xsuaa: '.json'
278
288
  }[x] || '.'+x) }
279
289
 
package/bin/env.js CHANGED
@@ -3,19 +3,16 @@ module.exports = Object.assign (env, {
3
3
  help: `
4
4
  # SYNOPSIS
5
5
 
6
- *cds env*
7
- *cds env* <ls | list> [<key>]
8
- *cds env* set <key> <value>
9
- *cds env* get <key>
6
+ *cds env* [get] [<key>]
7
+ *cds env* list [<key>]
8
+ *cds env* ls [<key>]
10
9
  *cds env* src
11
10
 
12
11
  # EXPLANATION
13
12
 
14
- Lists the effective configuration of the current environment in
15
- _.properties_ format if no command, *ls*, or *list* is given.
16
-
17
- The other commands either get or set a single property or display
18
- the sources from which the effective configuration has been loaded.
13
+ Displays the effective configuration for the given key, or all of the
14
+ current environment. By default and when using *get* the output is in
15
+ _object_ format. When using *list* or *ls* it's in _.properties_ format.
19
16
 
20
17
  # OPTIONS
21
18
 
@@ -45,13 +42,12 @@ const info = (s) => process.stdout.isTTY ? term.info (s) : s
45
42
  async function env ([cmd, key, value], options={}) {
46
43
 
47
44
  const cds = require('../lib/cds')
48
- const fn = (options["process-env"] ? processEnvCommands[cmd] : commands[cmd]) || (()=>{
49
- this.help ('env')
50
- throw new Error (`Don't understand '${cmd}' here...`)
51
- })
45
+ const fn = (
46
+ options["process-env"] ? processEnvCommands[cmd] :
47
+ commands[cmd] || ((key = cmd), commands.get)
48
+ )
52
49
 
53
50
  let env = options.for ? cds.env.for(options.for) : cds.env
54
-
55
51
  if (options["resolve-bindings"]) {
56
52
  const BindingManager = require('../lib/bind/bindingManager')
57
53
  const bindingManager = new BindingManager({ env, silent: true })
@@ -59,25 +55,20 @@ async function env ([cmd, key, value], options={}) {
59
55
  Object.assign(process.env, bindingEnv)
60
56
  env = cds.env.for(options.for || 'cds') // reload env
61
57
  }
62
-
63
-
64
58
  env['_home_cds-dk'] = path.resolve(__dirname, '..') // to help tools find the DK
65
59
 
66
60
  if (!options.for && options.mocked) await cds.service.bindings
67
-
68
- fn (env, key, value)
61
+ return fn (env, key, value)
69
62
  }
70
63
 
71
64
 
72
65
  const commands = {
73
66
 
74
- get [undefined]() { return commands.list },
75
- get ''() { return commands.list },
76
- get ls() { return commands.list },
67
+ get ls() { return this.list },
77
68
 
78
69
  // eslint-disable-next-line no-unused-vars
79
70
  list (conf, _key, val) { // NOSONAR
80
- (function _list (o = _key ? conf.get(_key) : conf, key = _key || '') { // NOSONAR, ...tzefix!!
71
+ (function _list (o = _key ? conf.get(_key.replace(/^cds\./,'')) : conf, key = _key || '') { // NOSONAR, ...tzefix!!
81
72
  if (o && typeof o === 'object' && !Array.isArray(o)) for (let p of Object.keys(o).sort()) {
82
73
  const d = Reflect.getOwnPropertyDescriptor (o,p)
83
74
  if (d.value === undefined && d.get === undefined) continue
@@ -96,19 +87,19 @@ const commands = {
96
87
  get (conf, key, val) {
97
88
  if (!process.stdout.isTTY) return commands.json (conf, key, val)
98
89
  // tty: display formatted object
99
- const obj = (key ? conf.get(key) : conf)
90
+ const obj = key ? conf.get(key.replace(/^cds\./,'')) : conf
100
91
  console.log (inspect (obj, {depth:22,colors:true}).replace(/\s+use:.*\[Getter\][^,]+,?/g,''))
101
92
  },
102
93
 
103
94
  // eslint-disable-next-line no-unused-vars
104
95
  json (conf, key, val) {
105
- const obj = (key ? conf.get(key) : conf)
96
+ const obj = (key ? conf.get(key.replace(/^cds\./,'')) : conf)
106
97
  const str = JSON.stringify(obj, null, 2)
107
98
  return console.log (str ? str.replace(/\s+use:.*\[Getter\][^,]+,?/g,'') : str)
108
99
  },
109
100
 
110
101
  set () {
111
- throw new Error ('cds config set is not yet implemented, sorry')
102
+ console.error ('cds env set is not yet implemented, sorry.')
112
103
  }
113
104
  }
114
105
 
package/bin/extend.js CHANGED
@@ -7,6 +7,8 @@ module.exports = Object.assign(extend, {
7
7
 
8
8
  *cds extend* <app-url>
9
9
 
10
+ **Deprecated - for use with previous MTX Services (@sap/cds-mtx).**
11
+
10
12
  Create an extension project from an extensible SaaS app.
11
13
  Obtain the app URL from the SaaS application provider.
12
14
 
@@ -45,6 +47,12 @@ module.exports = Object.assign(extend, {
45
47
  # SEE ALSO
46
48
 
47
49
  *cds activate* to activate an extension project.
50
+
51
+ # SEE ALSO
52
+
53
+ *cds pull* to get the CDS model of a SaaS app based on current MTX Services (@sap/cds-mtxs).
54
+ https://cap.cloud.sap/docs/guides/multitenancy/mtxs for information on @sap/cds-mtxs.
55
+
48
56
  `})
49
57
 
50
58
 
package/bin/init.js CHANGED
@@ -52,9 +52,6 @@ module.exports = Object.assign(init, {
52
52
 
53
53
  *helm* - adds helm chart folder that contains the files needed to deploy the application using Kyma.
54
54
 
55
- To add a specific feature in the helm chart you can use the command 'cds add helm:<featureName>'.
56
- For example cds add helm:xsuaa and cds add helm:html5_apps_deployer.
57
-
58
55
  *--java:mvn* <Comma separated maven archetype specific parameters>
59
56
 
60
57
  Add the given parameters to the archetype call.
package/bin/login.js CHANGED
@@ -1,19 +1,15 @@
1
- const { bold } = require('../lib/util/term');
2
-
3
1
  module.exports = Object.assign(login, {
4
2
  options: ['--subdomain', '--directory', '--passcode', '--user', '--client'],
5
3
  shortcuts: ['-s', '-d', '-p', '-u', '-c'],
6
4
  flags: ['--plain'],
7
5
  get help() {
8
6
  const config = require('../lib/client/settings_manager').SettingsManager.config
9
- const cdsExtendAndCdsActivate = `${bold('cds extend')} and ${bold('cds activate')}`
10
- const keyring = config.keyringDesignation
11
7
  return `
12
8
  # SYNOPSIS
13
9
 
14
10
  *cds login* [ <app-url> ]
15
11
 
16
- Simplifies usage of ${cdsExtendAndCdsActivate} commands related to multitenant
12
+ Simplifies usage of *cds extend* and *cds activate* commands related to multitenant
17
13
  SaaS applications by providing them with automatic authentication: fetches and
18
14
  saves authentication tokens and provides relevant tokens to those commands.
19
15
 
@@ -25,7 +21,7 @@ module.exports = Object.assign(login, {
25
21
  When re-running this command with different app URLs and subdomains, previous
26
22
  logins are not affected, allowing simultaneous logins to different API endpoints
27
23
  on SAP Business Technology Platform, Cloud Foundry environment.
28
- ${cdsExtendAndCdsActivate} will be authenticated according to the given target.
24
+ *cds extend* and *cds activate* will be authenticated according to the given target.
29
25
 
30
26
  If the Cloud-Foundry command-line client is installed, the SaaS-app URL <app-url>
31
27
  may be omitted. In that case, suitable apps from the org and space you're currently
@@ -41,7 +37,7 @@ module.exports = Object.assign(login, {
41
37
  *Storing Authentication Data*
42
38
 
43
39
  Authentication data for all logins is saved by <app-url> and <tenant-subdomain> in the
44
- desktop keyring (${keyring} on your platform) or, if requested, in config
40
+ desktop keyring (${(config.keyringDesignation)} on your platform) or, if requested, in config
45
41
  file ${config.paths.auth}.
46
42
 
47
43
  To make use of keyring storage, the 'keytar' Node.js module must be installed.
package/bin/logout.js CHANGED
@@ -1,20 +1,15 @@
1
- const { bold } = require('../lib/util/term');
2
-
3
1
  module.exports = Object.assign(logout, {
4
2
  options: ['--url', '--subdomain'],
5
3
  shortcuts: ['-l', '-s'],
6
4
  flags: ['--delete-settings', '--clear-invalid'],
7
5
  get help() {
8
- const cdsLogin = `${bold('cds login')}`
9
- const cdsExtend = bold('cds extend')
10
- const cdsActivate = bold('cds activate')
11
6
  return `
12
7
  # SYNOPSIS
13
8
 
14
9
  *cds logout* [ <extension-project-directory> ]
15
10
 
16
- Removes authentication data saved locally by ${cdsLogin} for use by ${cdsExtend}
17
- and ${cdsActivate}. In default mode, deletes only data for a specific app URL
11
+ Removes authentication data saved locally by *cds login* for use by *cds extend*
12
+ and *cds activate*. In default mode, deletes only data for a specific app URL
18
13
  and subdomain, optionally including relevant project settings.
19
14
 
20
15
  <app-url> and <tenant-subdomain> will be determined from project settings unless given
package/bin/watch.js CHANGED
@@ -109,8 +109,8 @@ async function watch ([cwd], {
109
109
  }
110
110
  log ()
111
111
  log (`${t.bold}cds ${args.join(' ')}`)
112
- log (`watching: ${ext}...`)
113
- DEBUG && log (`also watching: ${includes.source}`)
112
+ log (process.pid, 'watching:', ext, '...')
113
+ if (includes) DEBUG && log (`also watching: ${includes.source}`)
114
114
  if (liveReload) log (`live reload enabled for browsers`)
115
115
 
116
116
  const BindingManager = require('../lib/bind/bindingManager')
@@ -125,7 +125,6 @@ async function watch ([cwd], {
125
125
  options
126
126
  }).on('restart', (files)=>{
127
127
  log (`\n${t.bold} ___________________________\n\n`)
128
- DEBUG && DEBUG (files)
129
128
  if (liveReload) liveReload.markPending(files)
130
129
  if (this.delayed) clearTimeout (this.delayed)
131
130
  this.delayed = setTimeout(()=>{
@@ -137,7 +136,7 @@ async function watch ([cwd], {
137
136
  }
138
137
  })
139
138
  FileHandlers.changed (files,cwd)
140
- }, 111)
139
+ }, 111) .unref()
141
140
  }).on('message', async (msg) => { switch (msg.code) { // messages from child process
142
141
  case 'listening':
143
142
  env.PORT = (msg.address && msg.address.port) || msg.port
@@ -210,7 +209,7 @@ if (!module.parent) (async()=>{ // launched by nodemon
210
209
  case 'NO_SERVICES_FOUND': return _no_services_found(e)
211
210
  case 'MODEL_NOT_FOUND': return _no_models_found(e)
212
211
  case 'EADDRINUSE': return process.send(e) //> tell cds watch
213
- default: { throw e } // cli error handling will catch and format
212
+ default: console.error('\n❗️ Error on server start: ❗️'); throw e
214
213
  }}
215
214
  function _no_models_found(e) { console.log (`
216
215
  No models found in ${cds.resolve(e.model||'*',false)}.
@@ -198,7 +198,7 @@ module.exports = class Activate extends BaseCommand {
198
198
  finished: false,
199
199
  timer: null
200
200
  };
201
- finisher.timer = setInterval(checkFinished.bind(undefined, jobId, statusUrl, params, finisher), 250);
201
+ finisher.timer = setInterval(checkFinished.bind(undefined, jobId, statusUrl, params, finisher), 250).unref();
202
202
  });
203
203
  });
204
204
  }
@@ -4,7 +4,10 @@ class CliError extends Error {
4
4
  // noinspection JSAnnotator
5
5
  constructor(message, { error, command } = {}) {
6
6
  const help = command && getCommandHelp(command);
7
- throw getMessage(message, { error, help });
7
+ const stackLimit = Error.stackTraceLimit;
8
+ Error.stackTraceLimit = 0
9
+ super(getMessage(message, { error, help }));
10
+ Error.stackTraceLimit = stackLimit;
8
11
  }
9
12
  }
10
13
 
@@ -176,8 +176,9 @@ class BasicParams {
176
176
 
177
177
  // PERSISTED PARAMS (SETTINGS)
178
178
  this.appUrl = new Param('appUrl', '', { persist: Persistence.setting });
179
- this.to = this.appUrl.newAlias('to');
180
179
  this.url = this.appUrl.newAlias('url');
180
+ this.from = this.appUrl.newAlias('from');
181
+ this.to = this.appUrl.newAlias('to');
181
182
  this.subdomain = new Param('subdomain', '', { persist: Persistence.setting }); // only needed to fetch token
182
183
  this.passcodeUrl = new Param('passcodeUrl', '', { persist: Persistence.setting, abbreviate: true });
183
184
  this.passcode_url = this.passcodeUrl.newAlias('passcode_url');
@@ -398,7 +399,7 @@ class ParamCollection {
398
399
  * Return an object mapping each of the contained params' names to its corresponding value.
399
400
  * @param persistence the type of persistence to filter for (omit to disable filtering)
400
401
  */
401
- toValueMap(persistence) {
402
+ toEntries(persistence) {
402
403
  return this.toArray()
403
404
  .filter(param => param.persist === persistence || persistence === undefined)
404
405
  .reduce(collect, {});
@@ -409,7 +410,7 @@ class ParamCollection {
409
410
  * Used by `JSON.stringify`.
410
411
  */
411
412
  toJSON() {
412
- return this.toValueMap();
413
+ return this.toEntries();
413
414
  }
414
415
 
415
416
  /**
@@ -18,20 +18,25 @@ module.exports = class Pull extends BaseCommand {
18
18
 
19
19
  const params = await login(paramValues);
20
20
  const url = params.get('appUrl')
21
- const home = params.get('projectFolder');
22
- const target = join(home, 'node_modules', this.getAppPackageName(home));
21
+ const projectFolder = params.get('projectFolder');
22
+ const env = cds.env.for('cds', projectFolder);
23
+ const target = join(projectFolder, 'node_modules', this.getAppPackageName(env));
23
24
  const subdomain = params.get('subdomain') // REVISIT: Why are subdomains not transparently encoded in URLs?
25
+
26
+ this.amendPackageJson(projectFolder, env);
27
+
24
28
  console.log(`Pulling app base model`, Object.assign({ from: url, to: local(target) }, subdomain && {subdomain}))
25
29
 
26
30
  fs.rmSync(target, { force: true, recursive: true });
27
31
  fs.mkdirSync(target, { recursive: true });
28
32
 
29
33
  const baseModelTgz = await this.getTgz(params);
30
- return tar.xz(baseModelTgz).to(target);
34
+ await tar.xz(baseModelTgz).to(target);
35
+
36
+ console.log(`Finished. Refer to the base model like so: using from '${this.getAppPackageName(env)}'`);
31
37
  }
32
38
 
33
- static getAppPackageName(projectFolder) {
34
- const env = cds.env.for('cds', projectFolder);
39
+ static getAppPackageName(env) {
35
40
  return env.extends || '_base';
36
41
  }
37
42
 
@@ -43,4 +48,25 @@ module.exports = class Pull extends BaseCommand {
43
48
  .then(response => Buffer.from(response.data))
44
49
  .catch(error => this.handleHttpError(error, params, { url: pullUrl }));
45
50
  }
51
+
52
+ static amendPackageJson(projectFolder, env) {
53
+ if ('extends' in env) {
54
+ return;
55
+ }
56
+ console.log(`Amending extension package.json with project configuration`);
57
+ const packageJson = join(projectFolder, 'package.json');
58
+ let packageContents;
59
+ try {
60
+ packageContents = JSON.parse(fs.readFileSync(packageJson, { encoding: 'utf-8' }));
61
+ } catch (error) {
62
+ throw new CliError('package.json missing or unreadable', { error });
63
+ }
64
+ fs.writeFileSync(packageJson, JSON.stringify({
65
+ ...packageContents,
66
+ cds: {
67
+ ...(packageContents.cds ?? {}),
68
+ extends: this.getAppPackageName(projectFolder) // Default unless configured through current process.env
69
+ }
70
+ }));
71
+ }
46
72
  }
@@ -1,6 +1,6 @@
1
1
  const cds = require ('../cds'), { local } = cds.utils;
2
- const fs = require('fs');
3
2
  const { join } = require('path');
3
+ const { readFileSync, existsSync } = require('fs');
4
4
  const axios = require('axios');
5
5
 
6
6
  const { login } = require('./auth_manager');
@@ -33,8 +33,8 @@ module.exports = class Push extends BaseCommand {
33
33
  static async readSource(params, pushOptions) {
34
34
  let src = pushOptions?.extArchive ?? join(params.get('projectFolder'), 'gen/extension.tgz');
35
35
  let content;
36
- if (fs.existsSync(src)) {
37
- content = fs.readFileSync(src, { encoding: 'base64' });
36
+ if (existsSync(src)) {
37
+ content = readFileSync(src, { encoding: 'base64' });
38
38
  src = local(src);
39
39
  } else {
40
40
  if (!schemaRegex.test(src)) {
@@ -158,7 +158,7 @@ class SettingsManager {
158
158
  static async saveSettings(params) {
159
159
  log.debug(`Saving settings for project ${params.get('projectFolder')}`);
160
160
 
161
- const paramsMap = params.toValueMap(Persistence.setting);
161
+ const paramsMap = params.toEntries(Persistence.setting);
162
162
  if (params.has('username')) {
163
163
  // Save username only for localhost for security reasons.
164
164
  if (localhostRegex.test(params.get('appUrl'))) {
@@ -182,10 +182,10 @@ class SettingsManager {
182
182
  }
183
183
 
184
184
  if (params.get('tokenStorage') === 'plain') {
185
- await this._saveAuthToFile(params, params.toValueMap(Persistence.auth));
185
+ await this._saveAuthToFile(params, params.toEntries(Persistence.auth));
186
186
  } else if (params.get('tokenStorage') === 'keyring') {
187
- await this.checkKeytar(params);
188
- await this._saveAuthToKeyring(params, params.toValueMap(Persistence.auth));
187
+ await this.setKeytar(params);
188
+ await this._saveAuthToKeyring(params, params.toEntries(Persistence.auth));
189
189
  } else {
190
190
  console.log('Note: the authentication token is not saved by default. To save the token for later commands, please run `cds login`.');
191
191
  }
@@ -211,7 +211,7 @@ class SettingsManager {
211
211
  params.set('skipToken', true);
212
212
  }
213
213
  await this.updateUrls(params, logout, loadedAppUrl);
214
- await this.checkKeytar(params, logout);
214
+ await this.setKeytar(params, logout);
215
215
  await this.addAuth(params, logout);
216
216
  log.debug(`Effective project settings: ${params.format()}`);
217
217
  }
@@ -282,7 +282,7 @@ class SettingsManager {
282
282
  }
283
283
  }
284
284
 
285
- static async checkKeytar(params, logout = false) {
285
+ static async setKeytar(params, logout = false) {
286
286
  if (params.get('skipToken')) {
287
287
  return;
288
288
  }
@@ -29,7 +29,7 @@ module.exports = class ToggleSubscription extends BaseCommand {
29
29
  await this.runWithServer(params, tenant);
30
30
  } else {
31
31
  // Connect to running MTXS server
32
- params = await AuthManager.login(params.toValueMap());
32
+ params = await AuthManager.login(params.toEntries());
33
33
  if (!params.has('username')) {
34
34
  throw new CliError('Username is required if app URL is given.', { command: this.command });
35
35
  }