@sap/cds-dk 8.3.0 → 8.4.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 (54) hide show
  1. package/CHANGELOG.md +59 -13
  2. package/bin/build.js +1 -1
  3. package/bin/cds.js +12 -0
  4. package/bin/compile/index.js +12 -2
  5. package/bin/deploy/index.js +6 -1
  6. package/bin/env.js +3 -2
  7. package/bin/init.js +8 -4
  8. package/bin/repl.js +3 -3
  9. package/lib/build/util.js +32 -20
  10. package/lib/compile/to-xsuaa.js +39 -26
  11. package/lib/deploy/to-hana/hana.js +62 -74
  12. package/lib/env/schemas/cds-rc.js +174 -2
  13. package/lib/import/asyncapi/parserContext.js +4 -30
  14. package/lib/import/odata/v2parser.js +3 -2
  15. package/lib/import/openapi/importOpenAPI.js +616 -569
  16. package/lib/import/openapi/utilities.js +7 -2
  17. package/lib/init/constants.js +2 -1
  18. package/lib/init/index.js +4 -0
  19. package/lib/init/projectReader.js +1 -2
  20. package/lib/init/registries/mta.js +8 -1
  21. package/lib/init/template/application-logging/files/package.json.hbs +6 -2
  22. package/lib/init/template/application-logging/index.js +4 -4
  23. package/lib/init/template/approuter/files/package.json +2 -2
  24. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +3 -1
  25. package/lib/init/template/data/as-csv.js +1 -1
  26. package/lib/init/template/data/as-json.js +46 -42
  27. package/lib/init/template/enterprise-messaging-shared/index.js +1 -1
  28. package/lib/init/template/file-based-messaging/index.js +1 -1
  29. package/lib/init/template/hana/files/db/package.json +1 -1
  30. package/lib/init/template/hana/files/package.json.hbs +2 -0
  31. package/lib/init/template/hana/index.js +1 -1
  32. package/lib/init/template/handler/index.js +1 -1
  33. package/lib/init/template/html5-repo/files/app-package.json.hbs +2 -2
  34. package/lib/init/template/html5-repo/files/ui5-deploy.yaml.hbs +2 -2
  35. package/lib/init/template/http/index.js +6 -7
  36. package/lib/init/template/local-messaging/index.js +1 -1
  37. package/lib/init/template/nodejs/files/.vscode/extensions.json +0 -5
  38. package/lib/init/template/nodejs/files/.vscode/settings.json +1 -1
  39. package/lib/init/template/nodejs/files/.vscode/tasks.json +0 -2
  40. package/lib/init/template/nodejs/files/package.json.hbs +1 -1
  41. package/lib/init/template/postgres/index.js +1 -1
  42. package/lib/init/template/redis-messaging/index.js +1 -1
  43. package/lib/init/template/side-by-side-extensibility/files/mta.yaml.hbs +40 -0
  44. package/lib/init/template/side-by-side-extensibility/files/package.json.hbs +17 -0
  45. package/lib/init/template/side-by-side-extensibility/index.js +34 -0
  46. package/lib/init/template/typer/index.js +0 -1
  47. package/lib/init/template/typescript/files/package.json +2 -2
  48. package/lib/init/template/xsuaa/index.js +1 -1
  49. package/lib/mtx/push.js +0 -1
  50. package/lib/util/fs.js +1 -1
  51. package/lib/util/jsonc.js +1 -1
  52. package/lib/util/jsonc.pegjs +6 -2
  53. package/npm-shrinkwrap.json +74 -151
  54. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,51 @@ 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 8.4.1 - 2024-11-08
11
+
12
+ ### Added
13
+
14
+ - `cds deploy --no-build` lets you skip the implicit `cds build`.
15
+ - `cds add data/http` supports new type `cds.Map`.
16
+
17
+ ### Changed
18
+
19
+ ### Fixed
20
+
21
+ - `cds compile --to <unknown>` shows a cleaner error message.
22
+ - `cds add data` handles composition of one correctly.
23
+ - `cds add http` creates payloads for unbound actions in services.
24
+ - `cds compile --to xsuaa` can now handle annotation expressions in `where` clauses.
25
+ - `cds add http` produces requests for all expected data and no longer relies on existing data on the side.
26
+ - `cds add typer` creates `tsconfig.json` that works with `cds-tsx`.
27
+
28
+ ## Version 8.4.0 - 2024-10-29
29
+
30
+ ### Added
31
+
32
+ - `cds add application-logging` for Java also executes the `cds:add` goal with feature `APPLICATION_LOGGING`.
33
+ - Added support for `import` and `export` for auto-completion in `package.json` and `.cdsrc.json`.
34
+ - `cds add side-by-side-extensibility` adds configuration for logic extensibility via extension points (Java).
35
+ - `cds init --java` can be used as an alias to `cds init --add java`.
36
+ - Add cds schema for `helm` build plugin.
37
+
38
+ ### Changed
39
+
40
+ - `cds init` does not put comments in JSON files within `.vscode/`.
41
+ - `cds import --from asyncapi` now uses CloudEvents type in `@topic` annotation.
42
+ - `cds deploy` does not fall back to the deprecated `hanatrial` service plan any more.
43
+
44
+ ### Fixed
45
+
46
+ - `cds env` now colors is output honoring settings like `FORCE_COLOR`.
47
+ - `cds add` commands correctly detect Java/Node in Microsoft PowerShell.
48
+ - `cds add hana` doesn't add `dependencies` to `.cdsrc.json` any more.
49
+ - `cds add cf-manifest` uses the new `sap_java_buildpack_jakarta` buildpack.
50
+ - `cds build --production` now correctly formats console log output.
51
+ - `cds add` correctly handles entries like `cds.requires.auth` if the following configuration is scoped in a profile.
52
+ - `cds add` plugins can use a shortcut for their options.
53
+ - `cds import` fix for no entity schema in OData V2.
54
+
10
55
  ## Version 8.3.0 - 2024-09-30
11
56
 
12
57
  ### Added
@@ -27,8 +72,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
27
72
 
28
73
  ### Fixed
29
74
 
30
- - With `cds add workzone`, apps can now directly be added via Content Manager in SAP Build Work Zone.
31
- - Less obstrusive warning about `cds` instead of `cds-ts` in Typescript projects.
75
+ - `cds add workzone`-created apps can now directly be added via Content Manager in SAP Build Work Zone.
76
+ - Less obtrusive warning about `cds` instead of `cds-ts` in Typescript projects.
32
77
 
33
78
  ## Version 8.2.3 - 2024-09-25
34
79
 
@@ -64,7 +109,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
64
109
  - `cds add dynatrace` adds configuration for Dynatrace.
65
110
  - `cds add cloud-logging` adds configuration for SAP Cloud Logging. Option `--with-telemetry` allows for configuration with telemetry.
66
111
  - `cds version` shows version information for `@cap-js/db-service`.
67
- - `cds add portal` now adds portal configuration for Kyma.
112
+ - `cds add portal` now adds SAP Cloud Portal configuration for Kyma.
68
113
  - `cds add handler` allows to create handler stubs (for Java only, beta)
69
114
  - `cds init --add java --no-db` lets you create a Java project without persistent database.
70
115
  - `cds import` supports plugins.
@@ -145,7 +190,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
145
190
  - `cds compile --to mermaid` no longer fails for complex queries like joins.
146
191
  - `cds build --for mtx-sidecar` now correctly supports different `srv` folder name.
147
192
  - `cds add audit-log` in combination with `cds add multitenancy` correctly adds the audit-log dependency to the MTX sidecar.
148
- - `cds build` adds the correct hdbtabledata file paths to the hana result set.
193
+ - `cds build` adds the correct hdbtabledata file paths to the HANA result set.
149
194
  - `cds add` plugins can now correctly interpret `cds.cli` properties.
150
195
  - `cds deploy --to hana --dry` now shows correct files with their content.
151
196
  - `cds version` now reports the correct version of `@sap/cds` if this one is installed locally along with a local `@sap/cds-dk` installation.
@@ -275,7 +320,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
275
320
  - `cds login` eagerly fetches the passcode URL (if supported by `@sap/cds-mtxs`) and prints it on prompt.
276
321
  - `cds extend` and `cds activate` have been deprecated and are now removed. (You can still migrate and download projects, see `cds migrate --help` and `cds extend --help`.)
277
322
  - Remove obsolete classic MTX checks and enforce `@sap/cds` >= 7.
278
- - `cds build` uses cds.compile.to.hana API with `@sap/cds` 8.
323
+ - `cds build` uses `cds.compile.to.hana` API with `@sap/cds` 8.
279
324
  - `cds bind` and `cds deploy` use direct http requests instead of `cf curl`.
280
325
  - `cds build --for java` no longer generates localized EDMX files by default. It can be enabled using `contentLocalizedEdmx` build task option.
281
326
  - `@cap-js/sqlite`/`better-sqlite3` is used in dependencies instead of `sqlite3`.
@@ -377,7 +422,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
377
422
  - `cds add` doesn't fail for projects with a minimal `package.json` w/o `name` and `version` fields
378
423
  - `cds add data` can be executed in projects w/o `package.json` and `.cdsrc.json` files.
379
424
  - `cds add sample` does not fail if the `srv` folder doesn't exist.
380
- - `cds add helm` fixed xsuaa tenant-mode not updating on adding `multitenancy`
425
+ - `cds add helm` fixed XSUAA tenant-mode not updating on adding `multitenancy`
381
426
  - `cds watched` cannot be called from command line anymore.
382
427
  - `cds login` now correctly handles the case of an expired refresh token and gives more information about token-request errors.
383
428
  - `cds login` now refreshes the token URL if it had previously reverted to a legacy URL.
@@ -659,11 +704,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
659
704
  - `cds add connectivity` does not add `connectivity: true` to your `package.json` any more.
660
705
  - `cds watch` now ignores more files/folders: `app/(webapp|dist|target)`, `app/*/(webapp|dist|target)`, `tsconfig.json`, `*.tsbuildinfo`
661
706
  - `cds build` now uses `compile.to.hdbtable` if no migration tables exist.
662
- - Refactoring `cds build plugin` API
707
+ - `cds build` plugin API is refactored.
663
708
 
664
709
  ### Fixed
665
710
 
666
- - `cds login` now prints shorter errors. (Set `DEBUG=req` in env to see all details again.)
711
+ - `cds login` now prints shorter errors (set `DEBUG=req` in env to see all details again).
667
712
  - Fixed issue when creating a CAP project in SAP Business Application Studio's template wizard.
668
713
  - `cds import` now handles name collision within a Schema for OData V4 EDMX.
669
714
  - `cds build` for mtx extension projects no longer creates CSN containing unresolved model associations.
@@ -709,7 +754,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
709
754
 
710
755
  ### Removed
711
756
 
712
- - Undocumented facet `cds add auditlog`
757
+ - `cds add auditlog` facet.
713
758
 
714
759
  ## Version 7.1.1 - 2023-08-10
715
760
 
@@ -732,7 +777,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
732
777
 
733
778
  - Calls from Business Application Studio `New Project from Template` wizard are now handled correctly.
734
779
  - `cds add cf-manifest` correctly generates the XSUAA instance name.
735
- - `cds build` always uses the configured hana build task when building the MTX sidecar.
780
+ - `cds build` always uses the configured HANA build task when building the MTX sidecar.
736
781
  - `cds import` OData V4 EDMX fix for Annotation Alias and Namespace value replacement.
737
782
 
738
783
  ### Changed
@@ -1215,7 +1260,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1215
1260
  - `cds import` switch from `@openapi.schema` to `@JSON.Schema`.
1216
1261
  - `cds add mtx` will now add configuration for streamlined MTX. It effectively acts as a shortcut for `cds add multitenancy,toggles,extensibility`
1217
1262
  - `cds add mtx` no longer includes `hana` and `xsuaa`. To achieve the same effect as before, run `cds add mtx && cds add hana,xsuaa --for production`.
1218
- - `cds bind -2 <xsuaa service instance>` binds the CDS `auth` service to the xsuaa instance. Previously `uaa` was used. This requires `@sap/cds` 6 or higher.
1263
+ - `cds bind -2 <xsuaa service instance>` binds the CDS `auth` service to the XSUAA instance. Previously `uaa` was used. This requires `@sap/cds` 6 or higher.
1219
1264
  - `cds add lint:dev` updated to adjust to new api structure of `@sap/eslint-plugin-cds` v2.5.0
1220
1265
  - `cds init` uses latest Maven Java archetype version 1.27.0 for creating Java projects.
1221
1266
  - `cds login localhost:<port> -u <username>` now saves username (and empty password, if applicable) with project settings for convenience.
@@ -1412,7 +1457,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1412
1457
  - `cds import` bug fixed for `--force` flag. Now overwrites the correct file content.
1413
1458
  - `cds import` fix will no longer capture unwanted annotations in the CSN for OData V4.
1414
1459
  - `cds import` now support annotations for properties of type `Type Definition`
1415
- - `cds import` fix for supporting valid datatypes in unbounded function imports for OData V4.
1460
+ - `cds import` fix for supporting valid data types in unbounded function imports for OData V4.
1416
1461
  - `cds import` bug fixed for missing data imports for parameters with entity type not mapped to an entity set.
1417
1462
  - `cds import` now supports properties with complex type for OData V4.
1418
1463
  - `cds import` fix will now throw error if the key property of an entity is of type `Collection` for both OData V2 and V4 edmx.
@@ -1549,9 +1594,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1549
1594
  - `cds lint` now limits all file extensions to those allowed by the @sap/eslint-plugin-cds ESLint configuration
1550
1595
 
1551
1596
  ## Version 4.6.0 - 2021-11-02
1597
+
1552
1598
  ### Added
1553
1599
 
1554
- - `cds bind` binds the given service to a hana instance by storing the credentials in `.cdsrc.json` in your user home directory [beta].
1600
+ - `cds bind` binds the given service to a HANA instance by storing the credentials in `.cdsrc.json` in your user home directory [beta].
1555
1601
  - `cds import` introduced option `--include-namespaces` which imports the custom defined namespaces.
1556
1602
  - `cds import` preserve documentation in CSN file for actions and functions from OData V4 EDMX file.
1557
1603
  - `cds import` now supports reading values of the `as` option from cds.env
package/bin/build.js CHANGED
@@ -148,7 +148,7 @@ async function build([project], options = {}) {
148
148
  // IMPORTANT: call plugins before subsequent access to cds.env
149
149
  await cds.plugins
150
150
 
151
- cds.env = cds.env.for('cds', cds.root);
151
+ cds.env = cds.env.for('cds', cds.root)
152
152
  delete options.project // avoid that relative project paths are resolved twice
153
153
 
154
154
  if (typeof options["options-model"] === "string") {
package/bin/cds.js CHANGED
@@ -68,6 +68,10 @@ const cli = {
68
68
  const flags = all.filter(([,f]) => f.type === 'boolean')
69
69
  const options = all.filter(([,o]) => o.type !== 'boolean')
70
70
  task.options.push(...options.map(([key]) => '--'+key))
71
+ task.shortcuts.push(...options.map(([_, { short }]) => short ? '-'+short : undefined).filter(Boolean))
72
+ const byShortcut = (a, b) => (b.short ? 1 : 0) - (a.short ? 1 : 0)
73
+ task.options.sort(byShortcut)
74
+ task.shortcuts.sort(byShortcut)
71
75
  task.flags.push(...flags.map(([key]) => '--'+key))
72
76
  }
73
77
  }
@@ -138,6 +142,14 @@ const cli = {
138
142
  add (k, e[path[0]] = v)
139
143
  }
140
144
 
145
+ // always use 'plain' log format for cds-dk logging
146
+ // by default 'plain' log format is used for development while 'json' format is used for production, see cap/cds/blob/main/lib/env/defaults.js#L97
147
+ // the json formatter logs stringified JSON which causing any line breaks to get replaced by '\n'
148
+ // using the env variable ensures that cds.env isn't loaded too early
149
+ env ??= {}
150
+ env.log ??= {}
151
+ env.log.format = 'plain'
152
+
141
153
  // if (env) require('../lib/cds').env.add (env) //> avoid loading env
142
154
  // unless it has already explicitly been set by the user
143
155
  if (env) process.env.CDS_CONFIG ??= JSON.stringify(env)
@@ -4,7 +4,7 @@ const {colors} = require('../../lib/util/term')
4
4
  module.exports = Object.assign ( compile, {
5
5
  handleCompletion,
6
6
  options: [
7
- '--from', '--service', '--lang', '--for', '--to', '--dest', '--log-level', '--flavor', '--dialect', '--sql-dialect', '--openapi:url', '--openapi:servers', '--odata-version'
7
+ '--from', '--service', '--lang', '--for', '--to', '--dest', '--log-level', '--flavor', '--dialect', '--sql-dialect', '--openapi:url', '--openapi:servers', '--openapi:config-file', '--odata-version'
8
8
  ],
9
9
  shortcuts: [
10
10
  undefined, '-s', '-l', '-4', '-2', '-o', undefined, '-f'
@@ -135,6 +135,11 @@ module.exports = Object.assign ( compile, {
135
135
 
136
136
  Include YUML diagram in the generated OpenAPI document, default: *false*.
137
137
 
138
+ *--openapi:config-file* filename
139
+
140
+ The passed configuration file will be read to generate the OpenAPI document, incorporating all specified options.
141
+ Precedence of Options: Inline options specified in the command line will take precedence over those defined in the configuration file.
142
+
138
143
  *--asyncapi:merged*
139
144
 
140
145
  A single AsyncAPI document is generated using the details of all input services. Information of _title_
@@ -233,6 +238,12 @@ async function compile (models, options={}) {
233
238
  if (/mta.*\.ya?ml/.test(models[0])) {
234
239
  model = Promise.resolve(models[0])
235
240
  } else {
241
+ for (const kind of ['to', 'for']) {
242
+ const tail = options[kind]
243
+ if (typeof tail === 'string' && !cds.compile[kind][tail]) {
244
+ throw `Unknown model processor: cds.compile.${kind}.${tail}`
245
+ }
246
+ }
236
247
  model = cds.load (models, options)
237
248
  src = models[0] .replace (/\.[^.]+$/,'') //> excluding source file extension, e.g. .cds
238
249
  }
@@ -300,7 +311,6 @@ async function compile (models, options={}) {
300
311
  let p = cds.compile[kind]
301
312
  for (let each of tail.split('.')) {
302
313
  p = p[each]
303
- if (!p) throw `Unknown model processor: cds.compile.${kind}.${tail}`
304
314
  }
305
315
  return p
306
316
  }
@@ -1,6 +1,6 @@
1
1
  module.exports = Object.assign(deploy, {
2
2
  options: ['--to', '--for', '--out', '--tunnel-address', '--vcap-file', '--delta-from' ],
3
- flags: ['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--model-only', '--script', '--with-auto-schema-evolution' ],
3
+ flags: ['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--no-build', '--model-only', '--script', '--with-auto-schema-evolution' ],
4
4
  shortcuts: ['-2', '-4', '-o'],
5
5
  help: `
6
6
  # SYNOPSIS
@@ -37,6 +37,10 @@ module.exports = Object.assign(deploy, {
37
37
 
38
38
  Just print the SQL statements without executing them.
39
39
 
40
+ *--no-build* (only in combination with *--to hana*)
41
+
42
+ Skip running *cds build*.
43
+
40
44
  *--out* | *-o* <file>
41
45
 
42
46
  Write the DDL statements to the given file.
@@ -97,6 +101,7 @@ module.exports = Object.assign(deploy, {
97
101
  cds deploy --to sqlite:db
98
102
  cds deploy --to hana
99
103
  cds deploy --to hana:myService --auto-undeploy
104
+ cds deploy --to hana --no-build
100
105
 
101
106
  `})
102
107
 
package/bin/env.js CHANGED
@@ -72,6 +72,7 @@ async function env ([cmd, key, value], options={}) {
72
72
 
73
73
 
74
74
  const { inspect, format } = require('node:util')
75
+ const {colors} = require('../lib/util/term')
75
76
  const commands = {
76
77
 
77
78
  json: (env,k,v,o) => commands.get (env,k,v,{...o,json:true}),
@@ -87,7 +88,7 @@ const commands = {
87
88
  },
88
89
 
89
90
  get (conf, key, val, options) {
90
- let fmt = x => inspect (x, {depth:22,colors:true})
91
+ let fmt = x => inspect (x, {depth:22, colors})
91
92
 
92
93
  let obj = (
93
94
  !key ? conf
@@ -96,7 +97,7 @@ const commands = {
96
97
  : conf.get(key.replace(/^cds\./,''))
97
98
  )
98
99
 
99
- if (!process.stdout.isTTY) {
100
+ if (!colors) {
100
101
  fmt = x => typeof x !== 'object' ? x : JSON.stringify(x,0,2)
101
102
  }
102
103
  if (options.json) {
package/bin/init.js CHANGED
@@ -9,7 +9,7 @@ module.exports = Object.assign(init, {
9
9
  handleCompletion,
10
10
  options: ['--add', '--java:mvn', '--java:package', '--lint:custom', '--lint:custom:example', '--no-db'],
11
11
  shortcuts: ['-a'],
12
- flags: ['--force', '--verbose'],
12
+ flags: ['--java', '--force', '--verbose'],
13
13
  help: `
14
14
  # SYNOPSIS
15
15
 
@@ -20,6 +20,10 @@ module.exports = Object.assign(init, {
20
20
 
21
21
  # OPTIONS
22
22
 
23
+ *--java*
24
+
25
+ Create a CAP Java project.
26
+
23
27
  *--add* <feature | comma-separated list of features>
24
28
 
25
29
  Add one or more features while creating the project.
@@ -40,10 +44,10 @@ ${require('../lib/init').help()}
40
44
  # EXAMPLES
41
45
 
42
46
  *cds init* bookshop
43
- *cds init* bookshop --add java
44
- *cds init* bookshop --add java,hana
47
+ *cds init* bookshop --java
48
+ *cds init* bookshop --add hana
45
49
  *cds init* bookshop --add multitenancy,mta
46
- *cds init* --add java --java:mvn groupId=myGroup,artifactId=newId,package=my.company
50
+ *cds init* --java --java:mvn groupId=myGroup,artifactId=newId,package=my.company
47
51
 
48
52
  # SEE ALSO
49
53
 
package/bin/repl.js CHANGED
@@ -35,9 +35,9 @@ async function repl (_, options={}) {
35
35
 
36
36
  Object.defineProperty (cds,'repl',{value:repl})
37
37
  cds.extend (repl.context) .with ( class {
38
- get Foo() { return ctx.Foo ??= new cds.entity({ name: 'Foo' }) }
39
- get Bar() { return ctx.Bar ??= new cds.entity({ name: 'Bar' }) }
40
- get expect() { return cds.test.expect }
38
+ get Foo() { return ctx.Foo ??= new cds.entity({ name: 'Foo' }) }; set Foo(v) { ctx.Foo = v }
39
+ get Bar() { return ctx.Bar ??= new cds.entity({ name: 'Bar' }) }; set Bar(v) { ctx.Bar = v }
40
+ get expect() { return ctx.expect ??= cds.test.expect }; set expect(v) { ctx.expect = v }
41
41
  } .prototype )
42
42
  const ctx={}
43
43
 
package/lib/build/util.js CHANGED
@@ -6,6 +6,7 @@ const execAsync = require('util').promisify(cp.exec)
6
6
  const IS_WIN = require('os').platform() === 'win32'
7
7
  const { SEVERITY_ERROR, FILE_EXT_CDS } = require('./constants');
8
8
  const DEBUG = cds.debug('cli|build')
9
+ const SECRETS = /(passw)|(cert)|(ca)|(secret)|(key)/i
9
10
 
10
11
  function getProperty(src, segments) {
11
12
  segments = Array.isArray(segments) ? segments : segments.split('.')
@@ -68,31 +69,42 @@ function relativePaths(root, qualifiedPaths) {
68
69
  return qualifiedPaths
69
70
  }
70
71
 
71
- function redactCredentials(config, o) {
72
- return JSON.stringify(config, (k, v) => {
73
- if (!v) {
74
- return v
75
- }
76
- if (k === 'credentials') {
77
- try {
78
- return _redacted(v)
79
- } catch (e) {/* ignored */ }
72
+ function redactCredentials(config) {
73
+ if (typeof config !== 'object' || config === null) {
74
+ return config;
75
+ }
76
+
77
+ if (Array.isArray(config)) {
78
+ return config.map(item => redactCredentials(item));
79
+ } else {
80
+ const newConfig = Object.assign({}, config);
81
+ for (let key in newConfig) {
82
+ if (key === 'credentials') {
83
+ newConfig[key] = _redacted(newConfig[key]);
84
+ } else {
85
+ newConfig[key] = redactCredentials(newConfig[key]);
86
+ }
80
87
  }
81
- return v
82
- }, o && o.indents || 2)
88
+ return newConfig;
89
+ }
83
90
  }
84
91
 
85
- /** redacts password-like strings, also reducing clutter in output */
92
+ /**
93
+ * Masks password-like strings, also reducing clutter in output
94
+ * @param {any} cred - object or array with credentials
95
+ * @returns {any}
96
+ */
86
97
  function _redacted(cred) {
87
- const secrets = /(password)|(certificate)|(ca)/i // 'certificate' and 'ca' on HANA
88
- const newCred = Object.assign({}, cred)
89
- Object.keys(newCred)
90
- .filter(k => typeof newCred[k] === 'string' && secrets.test(k))
91
- .forEach(k => newCred[k] = '...')
92
- return newCred
98
+ if (!cred) return cred
99
+ if (Array.isArray(cred)) return cred.map(c => typeof c === 'string' ? '...' : _redacted(c))
100
+ if (typeof cred === 'object') {
101
+ const newCred = Object.assign({}, cred)
102
+ Object.keys(newCred).forEach(k => (typeof newCred[k] === 'string' && SECRETS.test(k)) ? (newCred[k] = '...') : (newCred[k] = _redacted(newCred[k])))
103
+ return newCred
104
+ }
105
+ return cred
93
106
  }
94
-
95
-
107
+
96
108
  /**
97
109
  * Returns a list of fully qualified model names belonging to the '@sap' namespace that cannot be resolved.
98
110
  * E.g. the module might NOT have been installed.
@@ -7,44 +7,57 @@ const hardcoded = {
7
7
  Attributes: ['id', 'tenant', 'ext_attr']
8
8
  }
9
9
 
10
-
11
10
  module.exports = function compile_to_xsuaa (model, options) {
12
11
 
13
12
  const base = getBaseModel(options)
14
13
  const scopes = {}
15
14
  const attributes = {}
16
15
 
16
+ const findUserAttrInExpression = (expr, attributes = []) => {
17
+ // find `$user` ref, but not e.g. `$self.$user`
18
+ if (typeof expr === 'object' && expr.ref?.length && expr.ref[0] === '$user') {
19
+ if (expr.ref.length === 2) {
20
+ const attr = expr.ref[1]
21
+ if (!/^[a-zA-Z0-9_]*$/.test(attr)) {
22
+ // see https://help.sap.com/docs/CP_AUTHORIZ_TRUST_MNG/ae8e8427ecdf407790d96dad93b5f723/517895a9612241259d6941dbf9ad81cb.html#attributes
23
+ throw new Error(`Illegal attribute name '${attr}' in '${expr}'. Only characters a-z, A-Z, 0-9, _ are allowed.`)
24
+ }
25
+ if (!hardcoded.Attributes.includes(attr)) attributes.push(attr)
26
+ }
27
+ // Reject expressions like `$user.foo.bar`, as xsuaa attributes are primitive, not structured
28
+ else if (expr.ref.length > 2) {
29
+ throw new Error (`Structured attributes like '${expr.ref.join('.')}' are not supported`)
30
+ }
31
+ }
32
+ else if (typeof expr === 'object') { // descend sub expressions etc.
33
+ Object.values(expr).forEach(e => findUserAttrInExpression(e, attributes))
34
+ }
35
+ else if (Array.isArray(expr)) { // descend arrays
36
+ expr.forEach(e => findUserAttrInExpression(e, attributes))
37
+ }
38
+ return attributes
39
+ }
40
+
41
+ /**
42
+ * @param {string|object} condition - the condition object or string
43
+ * @returns string[] - the attributes found in the condition
44
+ */
17
45
  const parseAttributes = (condition) => { // e.g. 'foo = $user.bar or baz = $user.boo'
18
46
  if (!condition) return []
19
47
 
20
- // first validate basic syntax of expression by parsing it
21
48
  let expr
22
- try {
23
- expr = cds.parse.expr(condition).xpr
24
- } catch (err) {
25
- throw new Error(`Invalid expression': ${err.message}`)
26
- }
27
-
28
- // Reject expressions like `$user.foo.bar`, as xsuaa attributes are primitive, not structured
29
- expr.forEach(expr => {
30
- const userIdx = expr.ref?.indexOf('$user')
31
- if (userIdx >= 0 && expr.ref.length > userIdx+2) {
32
- throw new Error (`Structured attributes like '${expr.ref.join('.')}' are not supported`)
49
+ if (typeof condition === 'object') {
50
+ if (!condition.xpr && !condition['=']) throw new Error(`Invalid expression: ${JSON.stringify(condition)}`)
51
+ expr = condition.xpr
52
+ } else {
53
+ try {
54
+ expr = cds.parse.expr(condition).xpr
55
+ } catch (err) {
56
+ throw new Error(`Invalid expression': ${err.message}`, { cause: err })
33
57
  }
34
- })
58
+ }
35
59
 
36
- // Reject expressions like `$user.foo-bar`
37
- // Impl. note: use the expression string rather than the parsed expression as the above example would be
38
- // `[ { ref: [ '$user', 'foo' ] }, '-', { ref: [ 'bar' ] } ]`
39
- // making it ambiguous to tell if it was `$user.foo-bar` or `$user.foo - bar`
40
- return Array.from(condition.matchAll(/\$user\s*\.\s*(\S*)/g))
41
- .map(m => m[1])
42
- .filter(m => !hardcoded.Attributes.includes(m))
43
- .map(m => {
44
- // see https://help.sap.com/docs/CP_AUTHORIZ_TRUST_MNG/ae8e8427ecdf407790d96dad93b5f723/517895a9612241259d6941dbf9ad81cb.html#attributes
45
- if (!/^[a-zA-Z0-9_]*$/.test(m)) throw new Error(`Illegal attribute name '${m}' in '${condition}'. Only characters a-z, A-Z, 0-9, _ are allowed.`)
46
- return m
47
- })
60
+ return findUserAttrInExpression(expr)
48
61
  }
49
62
 
50
63
  cds.reflect(model).foreach(def => {