@sap/cds 7.5.2 → 7.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.
- package/CHANGELOG.md +79 -22
- package/app/index.js +1 -1
- package/lib/auth/index.js +3 -0
- package/lib/compile/extend.js +9 -4
- package/lib/compile/for/lean_drafts.js +3 -4
- package/lib/compile/load.js +11 -15
- package/lib/compile/minify.js +2 -4
- package/lib/compile/to/sql.js +6 -4
- package/lib/compile/to/srvinfo.js +25 -3
- package/lib/compile/to/yaml.js +1 -1
- package/lib/dbs/cds-deploy.js +7 -13
- package/lib/env/defaults.js +1 -10
- package/lib/env/schemas/cds-package.js +27 -0
- package/lib/env/schemas/cds-rc.js +693 -0
- package/lib/env/schemas/index.js +6 -4
- package/lib/i18n/localize.js +15 -1
- package/lib/index.js +40 -47
- package/lib/log/cds-error.js +6 -0
- package/lib/ql/Query.js +2 -1
- package/lib/ql/cds-ql.js +1 -2
- package/lib/ql/infer.js +0 -2
- package/lib/req/request.js +3 -6
- package/lib/srv/middlewares/trace.js +2 -2
- package/lib/srv/protocols/hcql.js +44 -30
- package/lib/srv/protocols/http.js +60 -0
- package/lib/srv/protocols/index.js +0 -7
- package/lib/srv/protocols/odata-v4.js +8 -2
- package/lib/srv/srv-api.js +129 -62
- package/lib/srv/srv-handlers.js +0 -1
- package/lib/srv/srv-models.js +1 -0
- package/lib/utils/cds-test.js +1 -1
- package/lib/utils/cds-utils.js +26 -0
- package/lib/utils/check-version.js +10 -13
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +22 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +3 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +89 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/boundToCQN.js +4 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -24
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +1 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ApplyParser.js +3 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +7 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +0 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +2 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +17 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +22 -2
- package/libx/_runtime/cds-services/services/utils/columns.js +1 -2
- package/libx/_runtime/common/aspects/Association.js +17 -9
- package/libx/_runtime/common/generic/crud.js +13 -22
- package/libx/_runtime/common/generic/etag.js +1 -1
- package/libx/_runtime/common/generic/input.js +9 -1
- package/libx/_runtime/common/generic/paging.js +3 -3
- package/libx/_runtime/common/generic/sorting.js +25 -15
- package/libx/_runtime/common/generic/stream.js +2 -16
- package/libx/_runtime/common/utils/copy.js +5 -0
- package/libx/_runtime/common/utils/cqn.js +1 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +4 -3
- package/libx/_runtime/common/utils/csn.js +0 -49
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +5 -5
- package/libx/_runtime/common/utils/generateOnCond.js +50 -25
- package/libx/_runtime/common/utils/resolveView.js +5 -44
- package/libx/_runtime/common/utils/rewriteAsterisks.js +17 -4
- package/libx/_runtime/common/utils/stream.js +16 -15
- package/libx/_runtime/common/utils/streamProp.js +25 -22
- package/libx/_runtime/db/Service.js +27 -8
- package/libx/_runtime/db/generic/input.js +6 -1
- package/libx/_runtime/db/generic/rewrite.js +3 -2
- package/libx/_runtime/db/query/read.js +15 -5
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -11
- package/libx/_runtime/db/utils/columns.js +1 -0
- package/libx/_runtime/db/utils/stream.js +41 -0
- package/libx/_runtime/fiori/generic/read.js +2 -1
- package/libx/_runtime/fiori/generic/readOverDraft.js +1 -1
- package/libx/_runtime/fiori/lean-draft.js +216 -59
- package/libx/_runtime/hana/Service.js +1 -1
- package/libx/_runtime/hana/execute.js +53 -14
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +34 -15
- package/libx/_runtime/remote/Service.js +2 -1
- package/libx/_runtime/remote/utils/client.js +1 -1
- package/libx/_runtime/sqlite/Service.js +1 -1
- package/libx/_runtime/sqlite/execute.js +17 -5
- package/libx/odata/afterburner.js +58 -19
- package/libx/odata/cqn2odata.js +6 -8
- package/libx/odata/create.js +44 -0
- package/libx/odata/delete.js +25 -0
- package/libx/odata/error.js +8 -3
- package/libx/odata/metadata.js +6 -8
- package/libx/odata/service-document.js +1 -1
- package/libx/odata/update.js +110 -0
- package/libx/odata/utils.js +9 -6
- package/libx/outbox/index.js +48 -78
- package/libx/rest/RestAdapter.js +0 -3
- package/package.json +1 -1
- package/lib/env/schemas/cds-package.json +0 -17
- package/lib/env/schemas/cds-rc.json +0 -740
- package/lib/ql/STREAM.js +0 -90
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,63 @@
|
|
|
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.1 - 2024-01-30
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Garbage collection of draft is configured with `cds.fiori.draft_deletion_timeout`
|
|
12
|
+
|
|
13
|
+
## Version 7.6.0 - 2024-01-29
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `cds.upsert` as shortcut for `cds.db.upsert`
|
|
18
|
+
- 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).
|
|
19
|
+
- Support for default exports (ESM/TS) in custom authentication
|
|
20
|
+
- Support for executing SAP HANA procedures from SYS schema
|
|
21
|
+
- Support for more complex on-conditions in case of READ requests
|
|
22
|
+
- Best effort mechanism for supporting lambda expressions targeting remote odata-v2 services
|
|
23
|
+
- Support for actions and functions which are bound to singletons
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Draft: Standard Sorting Behavior for SAP Fiori List Report Floorplan
|
|
28
|
+
- Use new CDS schema for validation and code completion in `package.json` and `.cdsrc.json` files
|
|
29
|
+
- Media Data Streaming
|
|
30
|
+
+ 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.
|
|
31
|
+
+ 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.
|
|
32
|
+
+ 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> }`.
|
|
33
|
+
+ Backward Compatibility: To restore previous behavior use `stream_compat`.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- `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.
|
|
38
|
+
- Handling of read-only fields in drafts
|
|
39
|
+
- Event Mesh: Better error message for incoming messages without a topic
|
|
40
|
+
- `cds build` now logs a better error message if an incompatible `@sap/cds` version is used.
|
|
41
|
+
- Better error message for runtime requests to non-existing tenants in extensibility scenario.
|
|
42
|
+
- Do not generate UUIDs for association key during `CREATE` operation.
|
|
43
|
+
- OData aggregation with lean draft
|
|
44
|
+
- Sorting in new odata parser with nested select statements. The default sort order is now added to the outer select statement.
|
|
45
|
+
- Server crash in case of misformatted `groupby` transformation in `$apply`
|
|
46
|
+
- Switched EM webhook endpoints to also use new authentication implementation
|
|
47
|
+
- `odata_new_parser`: better error message and code for expand on non-existing elements
|
|
48
|
+
|
|
49
|
+
### Removed
|
|
50
|
+
|
|
51
|
+
- Experimental `STREAM` CQN is removed and cannot be used anymore
|
|
52
|
+
|
|
53
|
+
## Version 7.5.3 - 2024-01-23
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- `cds.localize` and `cds build` produce `i18n.json` again with keys from all base languages
|
|
58
|
+
- `cds.compile.to.serviceinfo` now correctly parses SpringBoot config with nested objects, e.g. for `cds.odata-v4.endpoint.path`
|
|
59
|
+
- Recommend to use `chai` 4 for the time being, as `chai` 5 doesn't properly work yet (requires ESM, `chai-as-promised` not working)
|
|
60
|
+
- View resolving for entities using property names that are identical to entity names
|
|
61
|
+
- Direct modifications with `cds.fiori.bypass_draft` if `cds.fiori.draft_compat` is not enabled
|
|
62
|
+
- Draft: Field validation error message does not display the name of the field
|
|
63
|
+
|
|
7
64
|
## Version 7.5.2 - 2024-01-05
|
|
8
65
|
|
|
9
66
|
### Fixed
|
|
@@ -23,7 +80,7 @@
|
|
|
23
80
|
### Added
|
|
24
81
|
|
|
25
82
|
- Support for expressions in where clause of `@restrict` annotation.
|
|
26
|
-
|
|
83
|
+
+ Example: `@(restrict : [{ grant : ['*'], where : (NAME = $user) }])`
|
|
27
84
|
- Function `cds.unboxed(srv)` to get the non-outboxed variant of the service
|
|
28
85
|
- Service implementations can now be provided in .mjs modules.
|
|
29
86
|
- Remote services: advanced configurable `CSRF` token fetching HTTP method and the URL.
|
|
@@ -37,16 +94,16 @@
|
|
|
37
94
|
"csrf": { // this configuration implies `csrf: true`
|
|
38
95
|
"method": "get",
|
|
39
96
|
"url": "..."
|
|
40
|
-
}
|
|
97
|
+
}
|
|
41
98
|
}
|
|
42
99
|
}
|
|
43
100
|
}
|
|
44
101
|
```
|
|
45
102
|
- `cds.log`'s built-in JSON formatter:
|
|
46
103
|
+ Extract custom fields (`cds.env.log.als_custom_fields`) and categories from args (not only error-like first objects)
|
|
47
|
-
|
|
104
|
+
+ Example: `LOG.info('foo', { query: 'SELECT * FROM DUMMY' }, 'bar', { categories: ['baz'] })`
|
|
48
105
|
+ `cds.env.log.mask_headers = [...]` allows to specify a list of matchers for which the header value shall be masked (i.e., printed as `***`)
|
|
49
|
-
|
|
106
|
+
+ Default: `['/authorization/i', '/cookie/i']`
|
|
50
107
|
- `cds.env.fiori.bypass_draft` feature flag, designed to enable direct modifications via `POST` and `PATCH` of
|
|
51
108
|
active instances in lean draft mode (`cds.env.fiori.lean_draft=true`). For example:
|
|
52
109
|
|
|
@@ -57,29 +114,29 @@ POST /Orders
|
|
|
57
114
|
}
|
|
58
115
|
```
|
|
59
116
|
|
|
60
|
-
- Auth kind `ias`: same SAML attr
|
|
117
|
+
- Auth kind `ias`: same SAML attr API as auth kind `xsuaa` for easier migration
|
|
61
118
|
|
|
62
119
|
### Changed
|
|
63
120
|
|
|
64
121
|
- Removed and integrated former `ctx-auth` middleware into `cds.auth` middleware
|
|
65
122
|
- `cds.log`:
|
|
66
123
|
+ `cds.env.log.format = 'plain'|'json'` allows to configure which built-in formatter is used. Defaults to `json` in production, `plain` otherwise.
|
|
67
|
-
+ If built-in JSON formatter is used:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
+ Config `cds.env.log.kibana_custom_fields` changed to `cds.env.log.als_custom_fields` (ALS = Application Logging Service) with compatibility until next major
|
|
124
|
+
+ If a built-in JSON formatter is used:
|
|
125
|
+
+ Field `tenant_subdomain` is filled if running on CF and information is available through authentication
|
|
126
|
+
+ Additional CF-related fields are filled if running on CF
|
|
127
|
+
+ Custom fields (`cds.env.log.als_custom_fields`) are filled if bound to an instance of Application Logging Service
|
|
128
|
+
+ Field `categories` is filled if bound to an instance of Application Logging Service
|
|
129
|
+
+ 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
|
|
73
130
|
- Package `passport` is no longer required (if `cds.env.requires.middlewares` is not set to `false`)
|
|
74
131
|
- 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).
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
132
|
+
+ If you used one of the types `CSN`, `Definitions`, `entity` of _@sap/cds/apis/reflect_, use the `Linked` counterparts instead.
|
|
133
|
+
+ If you used the type `CQNQuery` of _@sap/cds/apis/cqn_, use `SELECT` or a union type instead.
|
|
134
|
+
+ This also includes various fixes to Typings for
|
|
135
|
+
+ `req.subject` like `SELECT.from(req.subject)`
|
|
136
|
+
+ `SELECT.columns([...])`
|
|
137
|
+
+ `cds.db`
|
|
138
|
+
+ `cds.util`
|
|
139
|
+
+ `cds.context.features`
|
|
83
140
|
- 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.
|
|
84
141
|
- `express.static` is only mounted if the target folder (`cds.folders.app`) exists
|
|
85
142
|
- `cds.outbox.Messages` no longer uses aspect `cuid` to reduce model size impact in case `@sap/cds/common` is not used otherwise
|
|
@@ -97,18 +154,18 @@ POST /Orders
|
|
|
97
154
|
- Use original logic (based on `NODE_ENV`) to load cds plugins from `devDependencies`
|
|
98
155
|
- Property `tenant` also available on express' `req` object with basic and mocked auth
|
|
99
156
|
- Empty `req.data` in before `DELETE` handler in draft
|
|
100
|
-
- Loading `cds-plugins` now offers a hook to add more flexible plugin loader, e.g
|
|
157
|
+
- Loading `cds-plugins` now offers a hook to add a more flexible plugin loader, e.g., for corrupt `package.json` files.
|
|
101
158
|
- Ignore default values of associations for draft entities
|
|
102
159
|
- OData: client-side errors (4xx) logged as warnings instead of errors
|
|
103
160
|
- IAS authentication: use `tokenInfo.getClientId()` instead of `payload.azp` as it implements a fallback
|
|
104
161
|
- Deep updates with binary keys
|
|
105
162
|
- Allow `null` values in `cds.env` (example package.json excerpt: `{ "cds": { "features": { "foo": null } } }`)
|
|
106
|
-
- Collection
|
|
163
|
+
- Collection-bound actions/functions called via navigation
|
|
107
164
|
|
|
108
165
|
### Removed
|
|
109
166
|
|
|
110
167
|
- Deprecated global configuration feature flag `cds.env.features.fetch_csrf`.
|
|
111
|
-
Instead, please use `csrf` and `csrfInBatch`
|
|
168
|
+
Instead, please use `csrf` and `csrfInBatch` to configure your remote services.
|
|
112
169
|
These options will allow to configure CSRF-token handling.
|
|
113
170
|
- Compat for deprecated `cds.env.auth.passport`. Use `cds.env.requires.auth` instead.
|
|
114
171
|
|
package/app/index.js
CHANGED
|
@@ -11,7 +11,7 @@ module.exports = { get html(){
|
|
|
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(
|
|
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 ? '' : `
|
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
|
|
package/lib/compile/extend.js
CHANGED
|
@@ -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
|
package/lib/compile/load.js
CHANGED
|
@@ -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
|
|
6
|
-
if (!
|
|
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 (
|
|
10
|
+
return this.get (any,options,'inferred')
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
exports.parsed = function cds_get (files, options, _flavor) {
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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) => {
|
package/lib/compile/minify.js
CHANGED
|
@@ -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,
|
|
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 =
|
|
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})
|
package/lib/compile/to/sql.js
CHANGED
|
@@ -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 =
|
|
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],
|
|
65
|
-
if (
|
|
66
|
-
if (!
|
|
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
|
|
@@ -79,10 +79,12 @@ module.exports = (model, options={}) => {
|
|
|
79
79
|
if (file) {
|
|
80
80
|
const yaml = cds.load.yaml(file)
|
|
81
81
|
for (let yamlDoc of Array.isArray(yaml) ? yaml : [yaml]) {
|
|
82
|
-
|
|
82
|
+
let cds = yamlDoc?.cds;
|
|
83
83
|
if (!cds) continue
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
cds = _normalizeSpringBootCfg(cds)
|
|
85
|
+
// https://cap.cloud.sap/docs/java/application-services#configure-base-path
|
|
86
|
+
return cds.odataV4?.endpoint?.path || cds.odataV2?.endpoint?.path
|
|
87
|
+
|| cds['odata-v4']?.endpoint?.path || cds['odata-v2']?.endpoint?.path // alternative config
|
|
86
88
|
|| javaPrefixDefault
|
|
87
89
|
}
|
|
88
90
|
return javaPrefixDefault
|
|
@@ -92,4 +94,24 @@ module.exports = (model, options={}) => {
|
|
|
92
94
|
return is_java && javaPrefixDefault
|
|
93
95
|
}
|
|
94
96
|
|
|
97
|
+
// SpringBoot allows dots in keys to express nested objects, so we need to split them
|
|
98
|
+
function _normalizeSpringBootCfg(obj) {
|
|
99
|
+
if (typeof obj !== 'object') return obj
|
|
100
|
+
Object.keys(obj).forEach(k => {
|
|
101
|
+
const prop = k.split('.')
|
|
102
|
+
const last = prop.pop()
|
|
103
|
+
// and define the object if not already defined
|
|
104
|
+
const res = prop.reduce((o, key) => {
|
|
105
|
+
// define the object if not defined and return
|
|
106
|
+
return o[key] = o[key] ?? {}
|
|
107
|
+
}, obj)
|
|
108
|
+
res[last] = obj[k]
|
|
109
|
+
// recursively normalize
|
|
110
|
+
_normalizeSpringBootCfg(obj[k])
|
|
111
|
+
// delete the original property from object if it was rewritten
|
|
112
|
+
if (prop.length) delete obj[k]
|
|
113
|
+
})
|
|
114
|
+
return obj
|
|
115
|
+
}
|
|
116
|
+
|
|
95
117
|
}
|
package/lib/compile/to/yaml.js
CHANGED
|
@@ -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 || /^[
|
|
31
|
+
return !s || /^[\^@#:,*]/.test(s) ? '"'+ o.replace(/\\/g,'\\\\') +'"' : s
|
|
32
32
|
}
|
|
33
33
|
else return o
|
|
34
34
|
|
package/lib/dbs/cds-deploy.js
CHANGED
|
@@ -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 (
|
|
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,
|
|
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
|
-
|
|
144
|
-
db.kind === '
|
|
145
|
-
|
|
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)
|
|
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
|
-
|
package/lib/env/defaults.js
CHANGED
|
@@ -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:
|
|
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
|
+
}
|