@sap/cds 7.5.3 → 7.6.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 (101) hide show
  1. package/CHANGELOG.md +79 -21
  2. package/app/index.js +6 -17
  3. package/lib/auth/index.js +3 -0
  4. package/lib/compile/extend.js +9 -4
  5. package/lib/compile/for/lean_drafts.js +3 -4
  6. package/lib/compile/load.js +11 -15
  7. package/lib/compile/minify.js +2 -4
  8. package/lib/compile/to/sql.js +6 -4
  9. package/lib/compile/to/yaml.js +1 -1
  10. package/lib/dbs/cds-deploy.js +7 -13
  11. package/lib/env/defaults.js +1 -10
  12. package/lib/env/schemas/cds-package.js +27 -0
  13. package/lib/env/schemas/cds-rc.js +693 -0
  14. package/lib/env/schemas/index.js +6 -4
  15. package/lib/index.js +40 -47
  16. package/lib/log/cds-error.js +6 -0
  17. package/lib/log/format/aspects/als.js +1 -0
  18. package/lib/log/format/json.js +5 -1
  19. package/lib/ql/Query.js +2 -1
  20. package/lib/ql/cds-ql.js +1 -2
  21. package/lib/ql/infer.js +0 -2
  22. package/lib/req/cds-context.js +1 -1
  23. package/lib/req/request.js +3 -6
  24. package/lib/srv/middlewares/trace.js +2 -2
  25. package/lib/srv/protocols/hcql.js +44 -30
  26. package/lib/srv/protocols/http.js +60 -0
  27. package/lib/srv/protocols/index.js +0 -7
  28. package/lib/srv/protocols/odata-v4.js +8 -2
  29. package/lib/srv/srv-api.js +129 -62
  30. package/lib/srv/srv-handlers.js +0 -1
  31. package/lib/srv/srv-models.js +1 -0
  32. package/lib/utils/cds-utils.js +26 -0
  33. package/lib/utils/check-version.js +10 -13
  34. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +22 -6
  35. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +3 -4
  36. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +89 -21
  37. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/boundToCQN.js +4 -2
  38. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -24
  39. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +1 -7
  40. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ApplyParser.js +3 -3
  41. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/batch/BatchProcessor.js +1 -1
  42. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/http/HttpHeaderReader.js +1 -1
  43. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +6 -0
  44. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +0 -5
  45. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +2 -0
  46. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +17 -1
  47. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +22 -2
  48. package/libx/_runtime/cds-services/services/utils/columns.js +1 -2
  49. package/libx/_runtime/common/aspects/Association.js +17 -9
  50. package/libx/_runtime/common/generic/crud.js +13 -22
  51. package/libx/_runtime/common/generic/etag.js +1 -1
  52. package/libx/_runtime/common/generic/input.js +9 -1
  53. package/libx/_runtime/common/generic/paging.js +3 -3
  54. package/libx/_runtime/common/generic/sorting.js +25 -15
  55. package/libx/_runtime/common/generic/stream.js +2 -16
  56. package/libx/_runtime/common/i18n/messages.properties +3 -0
  57. package/libx/_runtime/common/utils/copy.js +5 -0
  58. package/libx/_runtime/common/utils/cqn.js +1 -1
  59. package/libx/_runtime/common/utils/cqn2cqn4sql.js +4 -3
  60. package/libx/_runtime/common/utils/csn.js +0 -49
  61. package/libx/_runtime/common/utils/foreignKeyPropagations.js +5 -5
  62. package/libx/_runtime/common/utils/generateOnCond.js +50 -25
  63. package/libx/_runtime/common/utils/resolveView.js +5 -35
  64. package/libx/_runtime/common/utils/rewriteAsterisks.js +17 -4
  65. package/libx/_runtime/common/utils/stream.js +16 -15
  66. package/libx/_runtime/common/utils/streamProp.js +25 -22
  67. package/libx/_runtime/db/Service.js +27 -8
  68. package/libx/_runtime/db/generic/input.js +6 -1
  69. package/libx/_runtime/db/generic/rewrite.js +3 -2
  70. package/libx/_runtime/db/query/read.js +15 -5
  71. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -11
  72. package/libx/_runtime/db/utils/columns.js +1 -0
  73. package/libx/_runtime/db/utils/stream.js +41 -0
  74. package/libx/_runtime/fiori/generic/read.js +2 -1
  75. package/libx/_runtime/fiori/generic/readOverDraft.js +1 -1
  76. package/libx/_runtime/fiori/lean-draft.js +209 -55
  77. package/libx/_runtime/hana/Service.js +1 -1
  78. package/libx/_runtime/hana/execute.js +53 -14
  79. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +2 -1
  80. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +34 -15
  81. package/libx/_runtime/messaging/file-based.js +4 -3
  82. package/libx/_runtime/messaging/redis-messaging.js +2 -1
  83. package/libx/_runtime/remote/Service.js +2 -1
  84. package/libx/_runtime/remote/utils/client.js +1 -1
  85. package/libx/_runtime/sqlite/Service.js +1 -1
  86. package/libx/_runtime/sqlite/execute.js +17 -5
  87. package/libx/odata/afterburner.js +58 -19
  88. package/libx/odata/cqn2odata.js +6 -8
  89. package/libx/odata/create.js +44 -0
  90. package/libx/odata/delete.js +25 -0
  91. package/libx/odata/error.js +8 -3
  92. package/libx/odata/metadata.js +6 -8
  93. package/libx/odata/service-document.js +1 -1
  94. package/libx/odata/update.js +110 -0
  95. package/libx/odata/utils.js +9 -6
  96. package/libx/outbox/index.js +74 -89
  97. package/libx/rest/RestAdapter.js +0 -3
  98. package/package.json +1 -1
  99. package/lib/env/schemas/cds-package.json +0 -17
  100. package/lib/env/schemas/cds-rc.json +0 -740
  101. package/lib/ql/STREAM.js +0 -90
package/CHANGELOG.md CHANGED
@@ -4,6 +4,64 @@
4
4
  - The format is based on [Keep a Changelog](http://keepachangelog.com/).
5
5
  - This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## Version 7.6.2 - 2024-02-09
8
+
9
+ ### Fixed
10
+
11
+ - Introduce i18n `BATCH_TOO_MANY_REQ` key for error message: "Batch request contains too many requests"
12
+ - Properly handle `$orderby` in lean draft
13
+ - View resolving in combination with `@cap-js/cds-db`
14
+ - Allow `cds.requires.someService.outbox` to be a string
15
+ - `cds.log`: errors, when not the first argument, were considered objects carrying custom fields
16
+ - `accept` header parsing for OData requests if quality factor `q` is included
17
+ - Broken links on index page if multiple protocols are configured
18
+
19
+ ## Version 7.6.1 - 2024-01-30
20
+
21
+ ### Fixed
22
+
23
+ - Garbage collection of draft is configured with `cds.fiori.draft_deletion_timeout`
24
+
25
+ ## Version 7.6.0 - 2024-01-29
26
+
27
+ ### Added
28
+
29
+ - `cds.upsert` as shortcut for `cds.db.upsert`
30
+ - Automatic deletion of stale drafts. Feature is enabled if `cds.env.fiori.deletionTimeout` is set to a value of `true`; `true` uses the default timeout of `30d` (30 days).
31
+ - Support for default exports (ESM/TS) in custom authentication
32
+ - Support for executing SAP HANA procedures from SYS schema
33
+ - Support for more complex on-conditions in case of READ requests
34
+ - Best effort mechanism for supporting lambda expressions targeting remote odata-v2 services
35
+ - Support for actions and functions which are bound to singletons
36
+
37
+ ### Changed
38
+
39
+ - Draft: Standard Sorting Behavior for SAP Fiori List Report Floorplan
40
+ - Use new CDS schema for validation and code completion in `package.json` and `.cdsrc.json` files
41
+ - Media Data Streaming
42
+ + OData: Large binaries without `@Core.MediaType` annotation were previously returned as base64-encoded buffer. Starting from this `@sap/cds` version also not-annotated large binaries are ignored by OData. It is strongly recommended to annotate all large binary properties with `@Core.MediaType` and use it according to streaming scenarios.
43
+ + Custom Handlers: `SELECT` with explicitely listed `SELECT.columns` of type `cds.LargeBinary` returns them as Readable streams. Large binary columns requested implicitely by `SELECT` (for example, with `.columns('*')`) are ignored.
44
+ + Streaming API: `cds.stream()` and `srv.stream()` are deprecated and will be removed with the next major release. Use `SELECT` with a single `cds.LargeBinary` column instead. The resulting object will contain the name of the column and a stream value. For example, `SELECT.one.from(E).columns(['image']).where(...)` returns `{ image: <media stream> }`.
45
+ + Backward Compatibility: To restore previous behavior use `stream_compat`.
46
+
47
+ ### Fixed
48
+
49
+ - `cds.minify` returned a shallow clone. When callers like 2sql `cds.linked` that subsequently, this left the passed-in csn in a broken, partially linked state. Now, `cds.minify` doesn't clone anymore, but modifies the passed in csn.
50
+ - Handling of read-only fields in drafts
51
+ - Event Mesh: Better error message for incoming messages without a topic
52
+ - `cds build` now logs a better error message if an incompatible `@sap/cds` version is used.
53
+ - Better error message for runtime requests to non-existing tenants in extensibility scenario.
54
+ - Do not generate UUIDs for association key during `CREATE` operation.
55
+ - OData aggregation with lean draft
56
+ - Sorting in new odata parser with nested select statements. The default sort order is now added to the outer select statement.
57
+ - Server crash in case of misformatted `groupby` transformation in `$apply`
58
+ - Switched EM webhook endpoints to also use new authentication implementation
59
+ - `odata_new_parser`: better error message and code for expand on non-existing elements
60
+
61
+ ### Removed
62
+
63
+ - Experimental `STREAM` CQN is removed and cannot be used anymore
64
+
7
65
  ## Version 7.5.3 - 2024-01-23
8
66
 
9
67
  ### Fixed
@@ -34,7 +92,7 @@
34
92
  ### Added
35
93
 
36
94
  - Support for expressions in where clause of `@restrict` annotation.
37
- - Example: `@(restrict : [{ grant : ['*'], where : (NAME = $user) }])`
95
+ + Example: `@(restrict : [{ grant : ['*'], where : (NAME = $user) }])`
38
96
  - Function `cds.unboxed(srv)` to get the non-outboxed variant of the service
39
97
  - Service implementations can now be provided in .mjs modules.
40
98
  - Remote services: advanced configurable `CSRF` token fetching HTTP method and the URL.
@@ -55,9 +113,9 @@
55
113
  ```
56
114
  - `cds.log`'s built-in JSON formatter:
57
115
  + Extract custom fields (`cds.env.log.als_custom_fields`) and categories from args (not only error-like first objects)
58
- * Example: `LOG.info('foo', { query: 'SELECT * FROM DUMMY' }, 'bar', { categories: ['baz'] })`
116
+ + Example: `LOG.info('foo', { query: 'SELECT * FROM DUMMY' }, 'bar', { categories: ['baz'] })`
59
117
  + `cds.env.log.mask_headers = [...]` allows to specify a list of matchers for which the header value shall be masked (i.e., printed as `***`)
60
- * Default: `['/authorization/i', '/cookie/i']`
118
+ + Default: `['/authorization/i', '/cookie/i']`
61
119
  - `cds.env.fiori.bypass_draft` feature flag, designed to enable direct modifications via `POST` and `PATCH` of
62
120
  active instances in lean draft mode (`cds.env.fiori.lean_draft=true`). For example:
63
121
 
@@ -68,29 +126,29 @@ POST /Orders
68
126
  }
69
127
  ```
70
128
 
71
- - Auth kind `ias`: same SAML attr api as auth kind `xsuaa` for easier migration
129
+ - Auth kind `ias`: same SAML attr API as auth kind `xsuaa` for easier migration
72
130
 
73
131
  ### Changed
74
132
 
75
133
  - Removed and integrated former `ctx-auth` middleware into `cds.auth` middleware
76
134
  - `cds.log`:
77
135
  + `cds.env.log.format = 'plain'|'json'` allows to configure which built-in formatter is used. Defaults to `json` in production, `plain` otherwise.
78
- + If built-in JSON formatter is used:
79
- * Field `tenant_subdomain` is filled if running on CF and information is available through authentication
80
- * Additional CF-related fields are filled if running on CF
81
- * Custom fields (`cds.env.log.als_custom_fields`) are filled if bound to an instance of Application Logging Service
82
- * Field `categories` is filled if bound to an instance of Application Logging Service
83
- + Config `cds.env.log.kibana_custom_fields` changed to `cds.env.log.als_custom_fields` (ALS = Application Logging Service) with compatibility until next major
136
+ + If a built-in JSON formatter is used:
137
+ + Field `tenant_subdomain` is filled if running on CF and information is available through authentication
138
+ + Additional CF-related fields are filled if running on CF
139
+ + Custom fields (`cds.env.log.als_custom_fields`) are filled if bound to an instance of Application Logging Service
140
+ + Field `categories` is filled if bound to an instance of Application Logging Service
141
+ + Config `cds.env.log.kibana_custom_fields` changed to `cds.env.log.als_custom_fields` (ALS = Application Logging Service) with compatibility until the next major
84
142
  - Package `passport` is no longer required (if `cds.env.requires.middlewares` is not set to `false`)
85
143
  - Type definitions for the APIs of this package are now maintained in package [`@cap-js/cds-types`](https://npmjs.com/package/@cap-js/cds-types).
86
- - If you used one of the types `CSN`, `Definitions`, `entity` of _@sap/cds/apis/reflect_, use the `Linked` counterparts instead.
87
- - If you used the type `CQNQuery` of _@sap/cds/apis/cqn_, use `SELECT` or a union type instead.
88
- - This also includes various fixes to Typings for
89
- - `req.subject` like `SELECT.from(req.subject)`
90
- - `SELECT.columns([...])`
91
- - `cds.db`
92
- - `cds.util`
93
- - `cds.context.features`
144
+ + If you used one of the types `CSN`, `Definitions`, `entity` of _@sap/cds/apis/reflect_, use the `Linked` counterparts instead.
145
+ + If you used the type `CQNQuery` of _@sap/cds/apis/cqn_, use `SELECT` or a union type instead.
146
+ + This also includes various fixes to Typings for
147
+ + `req.subject` like `SELECT.from(req.subject)`
148
+ + `SELECT.columns([...])`
149
+ + `cds.db`
150
+ + `cds.util`
151
+ + `cds.context.features`
94
152
  - The number of files logged on `cds serve` is now limited to 30 by default. You can run with `DEBUG=serve` to show all files.
95
153
  - `express.static` is only mounted if the target folder (`cds.folders.app`) exists
96
154
  - `cds.outbox.Messages` no longer uses aspect `cuid` to reduce model size impact in case `@sap/cds/common` is not used otherwise
@@ -108,18 +166,18 @@ POST /Orders
108
166
  - Use original logic (based on `NODE_ENV`) to load cds plugins from `devDependencies`
109
167
  - Property `tenant` also available on express' `req` object with basic and mocked auth
110
168
  - Empty `req.data` in before `DELETE` handler in draft
111
- - Loading `cds-plugins` now offers a hook to add more flexible plugin loader, e.g. for corrupt `package.json` files.
169
+ - Loading `cds-plugins` now offers a hook to add a more flexible plugin loader, e.g., for corrupt `package.json` files.
112
170
  - Ignore default values of associations for draft entities
113
171
  - OData: client-side errors (4xx) logged as warnings instead of errors
114
172
  - IAS authentication: use `tokenInfo.getClientId()` instead of `payload.azp` as it implements a fallback
115
173
  - Deep updates with binary keys
116
174
  - Allow `null` values in `cds.env` (example package.json excerpt: `{ "cds": { "features": { "foo": null } } }`)
117
- - Collection bound actions/functions called via navigation
175
+ - Collection-bound actions/functions called via navigation
118
176
 
119
177
  ### Removed
120
178
 
121
179
  - Deprecated global configuration feature flag `cds.env.features.fetch_csrf`.
122
- Instead, please use `csrf` and `csrfInBatch` in the configuration of your remote services.
180
+ Instead, please use `csrf` and `csrfInBatch` to configure your remote services.
123
181
  These options will allow to configure CSRF-token handling.
124
182
  - Compat for deprecated `cds.env.auth.passport`. Use `cds.env.requires.auth` instead.
125
183
 
package/app/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  const cds = require('../lib')
2
2
  const { find, path, fs } = cds.utils
3
3
 
4
- module.exports = { get html(){
4
+ const odata = srv => srv.endpoints?.[0]?.kind.startsWith('odata')
5
+ const metadata = srv => odata(srv) ? ` / <a href="${srv.path}/$metadata">$metadata</a>` : ``
5
6
 
6
- const odata = srv => srv._adapters && Object.keys(srv._adapters).find (a => a.startsWith ('odata'))
7
- const metadata = srv => odata(srv) ? ` / <a href="${srv.path}/$metadata">$metadata</a>` : ``
7
+ module.exports = { get html(){
8
8
 
9
9
  let html = fs.readFileSync(path.join(__dirname,'index.html'),'utf-8')
10
10
  // .replace ('{{subtitle}}', 'Version ' + cds.version)
11
11
  .replace (/{{package}}/g, _project())
12
12
  .replace (/{{app}}/g, cds.env.folders.app.replace(/*trailing slash*/ /\/$/, ''))
13
13
  .replace ('{{apps}}', _app_links().map(
14
- html => `\n<li><a href="${html}">/${html.replace(/^[/]/,'')}</a></li>`
14
+ html => `\n<li><a href="${html}">/${html.replace(/^\//,'').replace('/index.html','')}</a></li>`
15
15
  ).join('\n') || '— none —'
16
16
  )
17
17
  .replace ('{{services}}', cds.service.providers.map (srv => srv._is_dark ? '' : `
@@ -26,17 +26,6 @@ module.exports = { get html(){
26
26
  </ul>
27
27
  `).join(''))
28
28
 
29
- // add /graphql
30
- if (cds.env.features.graphql) {
31
- html = html.replace(/\n\s*<footer>/, `
32
-
33
- <h3>
34
- <a href="/graphql">/graphql</a>
35
- </h3>
36
-
37
- <footer>`)
38
- }
39
-
40
29
  Object.defineProperty (this,'html',{value:html})
41
30
  return html
42
31
 
@@ -64,12 +53,12 @@ function _entities_in (service) {
64
53
  }
65
54
 
66
55
  function _moreLinks (srv, entity) {
67
- return (srv.$linkProviders || [])
56
+ return odata(srv) ? (srv.$linkProviders || [])
68
57
  .map (linkProv => linkProv(entity))
69
58
  .filter (l => l && l.href && l.name)
70
59
  .sort ((l1, l2) => l1.name.localeCompare(l2))
71
60
  .map (l => ` <a class="preview" href="${l.href}" title="${l.title||l.name}"> &rarr; ${l.name}</a>`)
72
- .join (' ')
61
+ .join (' ') : ''
73
62
  }
74
63
 
75
64
  function _project(){
package/lib/auth/index.js CHANGED
@@ -39,6 +39,9 @@ module.exports = function auth_factory (o) {
39
39
  cds.log().info ('using auth strategy', config, '\n')
40
40
  let auth = require (impl)
41
41
 
42
+ // default export of ESM / .ts auth
43
+ if (auth && auth.default) auth = auth.default
44
+
42
45
  // if auth is a factory itself, call it to get the middleware
43
46
  if (typeof auth === 'function' && auth.length < 3) auth = auth(options)
44
47
 
@@ -1,6 +1,11 @@
1
- const compile = require ('./cds-compile')
1
+ const cds = new class { get compile(){ return super.compile = require ('./cds-compile') }}
2
2
  const { extend } = require ('../lazy')
3
3
 
4
+ /** @type <T> (target:T) => ({
5
+ with <X,Y,Z> (x:X, y:Y, z:Z): ( T & X & Y & Z )
6
+ with <X,Y> (x:X, y:Y): ( T & X & Y )
7
+ with <X> (x:X): ( T & X )
8
+ }) */
4
9
  module.exports = o => o.definitions ? { with(...csns) {
5
10
 
6
11
  // merge all extension csns
@@ -11,9 +16,9 @@ module.exports = o => o.definitions ? { with(...csns) {
11
16
  }
12
17
 
13
18
  // extend given base csn with merged extensions
14
- const extended = compile({
15
- 'base.csn': compile.to.json(csn),
16
- 'ext.csn': compile.to.json(merged)
19
+ const extended = cds.compile({
20
+ 'base.csn': cds.compile.to.json(csn),
21
+ 'ext.csn': cds.compile.to.json(merged)
17
22
  })
18
23
 
19
24
  // handle localized extension elements
@@ -123,12 +123,11 @@ module.exports = function cds_compile_for_lean_drafts(csn) {
123
123
  for (const key in newEl) {
124
124
  if (
125
125
  key.startsWith('@assert') ||
126
- key.startsWith('@FieldControl') ||
127
- key.startsWith('@Common.FieldControl') ||
128
126
  key.startsWith('@PersonalData') ||
127
+ key === '@Common.FieldControl' && newEl[key]?.['#'] === 'Mandatory' ||
128
+ key === '@Common.FieldControl.Mandatory' ||
129
+ key === '@FieldControl.Mandatory' ||
129
130
  key === '@mandatory' ||
130
- key === '@readonly' ||
131
- key === '@Core.Computed' ||
132
131
  key === '@Core.Immutable'
133
132
  )
134
133
  newEl[key] = undefined
@@ -2,22 +2,21 @@ const cds = require('..')
2
2
  const TRACE = cds.debug('trace')
3
3
 
4
4
  module.exports = exports = function load (files, options) {
5
- const all = cds.resolve(files,options)
6
- if (!all) return Promise.reject (new cds.error ({
5
+ const any = cds.resolve(files,options)
6
+ if (!any) return Promise.reject (new cds.error ({
7
7
  message: `Couldn't find a CDS model for '${files}' in ${cds.root}`,
8
8
  code: 'MODEL_NOT_FOUND', files,
9
9
  }))
10
- return this.get (all,options,'inferred')
10
+ return this.get (any,options,'inferred')
11
11
  }
12
12
 
13
13
 
14
- exports.parsed = function cds_get (files, options, _flavor) { // NOSONAR
15
-
14
+ exports.parsed = function cds_get (files, options, _flavor) {
16
15
  const o = typeof options === 'string' ? { flavor:options } : options || {}
17
- if (!o.silent) TRACE?.time('cds.load model ')
18
16
  if (!files) files = ['*']; else if (!Array.isArray(files)) files = [files]
19
17
  if (o.files || o.flavor === 'files') return cds.resolve(files,o)
20
18
  if (o.sources || o.flavor === 'sources') return _sources4 (cds.resolve(files,o))
19
+ if (!o.silent) TRACE?.time('cds.load model')
21
20
 
22
21
  const csn = cds.compile (files,o,
23
22
  o.parse ? 'parsed' :
@@ -25,15 +24,12 @@ exports.parsed = function cds_get (files, options, _flavor) { // NOSONAR
25
24
  o.clean ? 'xtended' : // for compatibility
26
25
  o.flavor || _flavor || 'parsed'
27
26
  )
28
- return csn.then
29
- ? csn.then (_csn => _finalize(_csn,o)) // async compile
30
- : _finalize (csn,o) // synchronous compile
31
- }
32
-
33
- const _finalize = (csn,o) => {
34
- if (!o.silent) cds.emit ('loaded', csn)
35
- if (!o.silent) TRACE?.timeEnd('cds.load model ')
36
- return csn
27
+ return csn.then?.(_finalize) || _finalize(csn)
28
+ function _finalize (csn) {
29
+ if (!o.silent) cds.emit ('loaded', csn)
30
+ if (!o.silent) TRACE?.timeEnd('cds.load model ')
31
+ return csn
32
+ }
37
33
  }
38
34
 
39
35
  const _sources4 = async (files) => {
@@ -1,8 +1,7 @@
1
1
  const cds = require('../index')
2
2
  const DEBUG = cds.debug('minify')
3
3
 
4
- module.exports = function cds_minify (csn, _roots) { // IMPORTANT: don't add cds.env.features.skip_unused as default for _roots here, as that will break VSCode's IntelliSense
5
- const roots = _roots !== undefined ? _roots : cds.env.features.skip_unused
4
+ module.exports = function cds_minify (csn, roots = cds.env.features.skip_unused) {
6
5
  if (roots === false) return csn
7
6
  if (csn[_minified]) return csn
8
7
  const all = csn.definitions, reached = new Set
@@ -56,8 +55,7 @@ module.exports = function cds_minify (csn, _roots) { // IMPORTANT: don't add cds
56
55
  for (let a in d.actions) _visit (d.actions[a])
57
56
  for (let p in d.params) _visit (d.params[p])
58
57
  }
59
- const minified = Object.create (csn.__proto__, Object.getOwnPropertyDescriptors(csn))
60
- const less = minified.definitions = {}
58
+ const minified = csn, less = minified.definitions = {}
61
59
  for (let n in all) if (reached.has(all[n])) less[n] = all[n]
62
60
  else DEBUG?.('skipping', all[n].kind, n)
63
61
  Object.defineProperty (minified,_minified,{value:true})
@@ -4,7 +4,8 @@ const keywords = require("@sap/cds-compiler").to.sql.sqlite.keywords
4
4
  const { unfold_ddl } = require ('../etc/_localized')
5
5
 
6
6
  function cds_compile_to_sql (csn,_o) {
7
- csn = _extended(cds.minify(csn))
7
+ csn = cds.minify(csn)
8
+ csn = _extended(csn)
8
9
  const o = cdsc._options.for.sql(_o) //> used twice below...
9
10
  const all = cdsc.to.sql(csn,o) .map (each => each.replace(/^-- .+\n/,'')) //> strip comments
10
11
  const sql = unfold_ddl(all, csn, o)
@@ -58,12 +59,13 @@ module.exports = Object.assign (cds_compile_to_sql, {
58
59
 
59
60
  /////////////////////////////////////////////////////////////////////////////
60
61
  // UI Flex - read extensions__ to views, when ext fields are read
62
+ // REVISIT: We planned to remove the uiflex feature -> should do so
61
63
  const _extended = (csn) => {
62
64
  const defs = cds.linked(csn).definitions
63
65
  for (let each in defs) {
64
- const d = defs[each], q = d.query // TODO: q may have SET instead of SELECT
65
- if (q && q.SELECT && q.SELECT.columns && _is_extensible(d)) {
66
- if (!q.SELECT.columns.some(({ref}) => ref && ref[0] === _extensions)) q.SELECT.columns.push({ref:[_extensions]})
66
+ const d = defs[each], columns = d.query?.SELECT?.columns || d.projection?.columns
67
+ if (columns && _is_extensible(d)) {
68
+ if (!columns.some(({ref}) => ref?.[0] === _extensions)) columns.push({ref:[_extensions]})
67
69
  }
68
70
  }
69
71
  return csn
@@ -28,7 +28,7 @@ module.exports = function _2yaml (object, options={}) { // NOSONAR
28
28
  if (typeof o === 'string') {
29
29
  if (o.indexOf('\n')>=0) return '|'+'\n'+indent+ o.replace(/\n/g,'\n'+indent)
30
30
  let s = o.trim()
31
- return !s || /^[@#:,*]/.test(s) ? '"'+ o +'"' : s
31
+ return !s || /^[\^@#:,*]/.test(s) ? '"'+ o.replace(/\\/g,'\\\\') +'"' : s
32
32
  }
33
33
  else return o
34
34
 
@@ -21,14 +21,14 @@ module.exports = exports = function cds_deploy (model,options,csvs) {
21
21
  TRACE?.time('cds.deploy db ')
22
22
 
23
23
  if (!model) throw new Error('Must provide a model or a path to model, received: ' + model)
24
- if (model && !model.definitions) model = await cds.load(model).then(cds.minify)
24
+ if (!model?.definitions) model = await cds.load(model).then(cds.minify)
25
25
 
26
26
  if (o.mocked) exports.include_external_entities_in(model)
27
27
  else exports.exclude_external_entities_in(model)
28
28
 
29
29
  if (!db.run) db = await cds.connect.to(db)
30
30
  if (!cds.db) cds.db = cds.services.db = db
31
- if (!db.model) db.model = model
31
+ if (!db.model) db.model = model // NOTE: this calls compile.for.nodejs!
32
32
 
33
33
  // eslint-disable-next-line no-console
34
34
  const LOG = o.silent || o.dry || !cds.log('deploy')._info ? () => {} : console.log
@@ -99,7 +99,7 @@ exports.create = async function cds_deploy_create (db, csn=db.model, o) {
99
99
  drops = d
100
100
  } else {
101
101
  // cds deploy -- w/o auto schema evoution > drop-create db
102
- creas = cds.compile.to.sql(csn, o)
102
+ creas = cds.compile.to.sql(csn,o) // NOTE: this used to call cds.linked(cds.minify) and thereby corrupted the passed in csn
103
103
  }
104
104
 
105
105
  if (!drops) {
@@ -125,8 +125,6 @@ exports.create = async function cds_deploy_create (db, csn=db.model, o) {
125
125
  return
126
126
  }
127
127
 
128
- // Set the context model while deploying for cqn42sql in new db layers
129
- db.model = cds.compile.for.nodejs(csn)
130
128
  await db.run(drops)
131
129
  await db.run(creas)
132
130
  return true
@@ -140,12 +138,9 @@ exports.create = async function cds_deploy_create (db, csn=db.model, o) {
140
138
  if (o.dry) return {}
141
139
 
142
140
  let [table_exists] = await db.run(
143
- // REVISIT: prettier forced this horrible, unreadable formatting:
144
- db.kind === 'postgres'
145
- ? `SELECT 1 from pg_tables WHERE tablename = 'cds_model' and schemaname = current_schema()`
146
- : db.kind === 'sqlite'
147
- ? `SELECT 1 from sqlite_schema WHERE name = 'cds_model'`
148
- : cds.error`Schema evolution is not supported for ${db.kind} databases`,
141
+ db.kind === 'postgres' ? `SELECT 1 from pg_tables WHERE tablename = 'cds_model' and schemaname = current_schema()` :
142
+ db.kind === 'sqlite' ? `SELECT 1 from sqlite_schema WHERE name = 'cds_model'` :
143
+ cds.error`Schema evolution is not supported for ${db.kind} databases`,
149
144
  )
150
145
 
151
146
  if (o['model-only'])
@@ -209,7 +204,7 @@ exports.init = async function cds_deploy_init (db, csn=db.model, o, srces, log=(
209
204
  const t = cds.context?.tenant; if (t && t === cds.requires.multitenancy?.t0) return
210
205
  return db.run (async tx => {
211
206
 
212
- const m = tx.model = cds.compile.for.nodejs(csn) //> use correct model while deploying
207
+ const m = tx.model = cds.compile.for.nodejs(csn) // NOTE: this used to create a redundant 4nodejs model for tha same csn
213
208
  const data = await exports.data (m,srces)
214
209
  const query = _queries4 (db,m)
215
210
  const INSERT_from = INSERT_from4 (db,m,o)
@@ -432,4 +427,3 @@ if (!module.parent) (async () => {
432
427
  await db?.disconnect?.()
433
428
  }
434
429
  })().catch(console.error)
435
-
@@ -19,12 +19,6 @@ const defaults = module.exports = {
19
19
  'hcql' : { path: '/hcql' },
20
20
  },
21
21
 
22
- // kept for backwards compatibility
23
- schemas: {
24
- 'cds-rc.json': join(__dirname, 'schemas/cds-rc.json'),
25
- 'cds-package.json': join(__dirname, 'schemas/cds-package.json'),
26
- },
27
-
28
22
  features: {
29
23
  folders: 'fts/*', // where to find feature toggles -> switch on by default when released
30
24
  live_reload: !production,
@@ -65,10 +59,7 @@ const defaults = module.exports = {
65
59
  '[production]': { format: 'json' },
66
60
  levels: {
67
61
  compile: 'warn',
68
- cli: 'warn',
69
- deploy: 'info',
70
- serve: 'info',
71
- server: 'info'
62
+ cli: 'warn'
72
63
  },
73
64
  service: false,
74
65
  // the rest is only applicable for the json formatter
@@ -0,0 +1,27 @@
1
+ const cds = require('../../index')
2
+
3
+ module.exports = {
4
+ _version: cds.version,
5
+
6
+ // base schema file for package.json
7
+ // includes cdsRoot schema from cds-rc.js to enforce cds configuration only in cds section
8
+ // and not in the root of the package.json
9
+
10
+ title: 'JSON schema for CDS configuration in package.json',
11
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
12
+ description: 'This is a JSON schema representation of the CDS project configuration inside a project root level package.json',
13
+ type: 'object',
14
+ properties: {
15
+ extends: {
16
+ description: 'Name of the application that shall be extended',
17
+ type: 'string'
18
+ },
19
+ cds: {
20
+ type: 'object',
21
+ additionalProperties: true,
22
+ $ref: 'cdsJsonSchema://schemas/cds-rc.json#/$defs/cdsRoot',
23
+ description: 'CDS configuration',
24
+ default: {}
25
+ }
26
+ }
27
+ }