@sap/cds 5.6.3 → 5.7.3
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 +135 -0
- package/_i18n/i18n_fr.properties +4 -4
- package/apis/cds.d.ts +7 -10
- package/apis/connect.d.ts +3 -3
- package/apis/core.d.ts +2 -4
- package/apis/models.d.ts +2 -3
- package/apis/ql.d.ts +0 -1
- package/apis/services.d.ts +3 -3
- package/bin/build/buildTaskFactory.js +16 -10
- package/bin/build/buildTaskProviderFactory.js +3 -3
- package/bin/build/constants.js +2 -1
- package/bin/build/provider/buildTaskProviderInternal.js +14 -14
- package/bin/build/provider/hana/2migration.js +2 -3
- package/bin/build/provider/hana/index.js +34 -0
- package/bin/build/provider/hana/migrationtable.js +90 -22
- package/bin/build/provider/hana/template/undeploy.json +5 -0
- package/bin/build/provider/node-cf/index.js +9 -2
- package/bin/serve.js +16 -18
- package/lib/compile/cdsc.js +15 -5
- package/lib/compile/etc/_localized.js +4 -4
- package/lib/compile/extend.js +8 -0
- package/lib/compile/index.js +3 -1
- package/lib/compile/minify.js +61 -0
- package/lib/compile/resolve.js +4 -1
- package/lib/compile/to/gql.js +9 -0
- package/lib/compile/to/sql.js +26 -30
- package/lib/connect/index.js +1 -1
- package/lib/core/entities.js +0 -3
- package/lib/core/infer.js +1 -0
- package/lib/core/reflect.js +0 -34
- package/lib/deploy.js +25 -17
- package/lib/env/defaults.js +3 -1
- package/lib/env/index.js +8 -3
- package/lib/env/presets.js +38 -0
- package/lib/env/requires.js +16 -11
- package/lib/index.js +13 -11
- package/lib/log/format/kibana.js +4 -2
- package/lib/log/index.js +2 -2
- package/lib/ql/Whereable.js +1 -0
- package/lib/req/cds-context.js +79 -0
- package/lib/req/context.js +5 -77
- package/lib/req/request.js +1 -1
- package/lib/serve/Service-api.js +8 -4
- package/lib/serve/Service-dispatch.js +0 -7
- package/lib/serve/Service-methods.js +6 -8
- package/lib/serve/Transaction.js +35 -30
- package/lib/serve/adapters.js +1 -4
- package/lib/utils/axios.js +1 -1
- package/libx/_runtime/audit/Service.js +44 -20
- package/libx/_runtime/audit/generic/personal/access.js +16 -11
- package/libx/_runtime/audit/generic/personal/modification.js +5 -5
- package/libx/_runtime/audit/generic/personal/utils.js +46 -37
- package/libx/_runtime/{common/auth → auth}/index.js +21 -7
- package/libx/_runtime/{common/auth → auth}/strategies/JWT.js +2 -2
- package/libx/_runtime/{common/auth → auth}/strategies/basic.js +2 -2
- package/libx/_runtime/{common/auth → auth}/strategies/dummy.js +1 -1
- package/libx/_runtime/{common/auth → auth}/strategies/mock.js +2 -2
- package/libx/_runtime/{common/auth → auth}/strategies/utils/uaa.js +1 -1
- package/libx/_runtime/{common/auth → auth}/strategies/utils/xssec.js +0 -0
- package/libx/_runtime/{common/auth → auth}/strategies/xsuaa.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +7 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +0 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +0 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +3 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +6 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +3 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +16 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +26 -69
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +0 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +3 -66
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +29 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +7 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +9 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +13 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/ConditionalRequestControlCommand.js +0 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/ConditionalRequestValidator.js +0 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +54 -76
- package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +0 -7
- package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +3 -6
- package/libx/_runtime/cds-services/adapter/rest/handlers/delete.js +3 -6
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +3 -6
- package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +3 -6
- package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +3 -6
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +2 -2
- package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +8 -4
- package/libx/_runtime/cds-services/services/Service.js +0 -6
- package/libx/_runtime/cds-services/services/utils/columns.js +10 -3
- package/libx/_runtime/cds-services/services/utils/compareJson.js +4 -7
- package/libx/_runtime/cds-services/services/utils/differ.js +4 -1
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +1 -41
- package/libx/_runtime/cds-services/util/assert.js +1 -262
- package/libx/_runtime/cds.js +6 -9
- package/libx/_runtime/common/aspects/entity.js +1 -1
- package/libx/_runtime/common/composition/delete.js +4 -2
- package/libx/_runtime/common/composition/update.js +22 -38
- package/libx/_runtime/common/composition/utils.js +3 -7
- package/libx/_runtime/common/error/standardError.js +11 -0
- package/libx/_runtime/common/generic/auth.js +63 -33
- package/libx/_runtime/common/generic/crud.js +11 -23
- package/libx/_runtime/common/generic/input.js +20 -0
- package/libx/_runtime/common/generic/paging.js +2 -2
- package/libx/_runtime/common/generic/put.js +4 -10
- package/libx/_runtime/common/generic/sorting.js +12 -30
- package/libx/_runtime/common/i18n/messages.properties +2 -0
- package/libx/_runtime/common/perf/index.js +24 -0
- package/libx/_runtime/common/utils/cqn.js +58 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +298 -121
- package/libx/_runtime/common/utils/csn.js +38 -56
- package/libx/_runtime/common/utils/entityFromCqn.js +6 -6
- package/libx/_runtime/common/utils/resolveView.js +4 -5
- package/libx/_runtime/common/utils/rewriteAsterisks.js +46 -5
- package/libx/_runtime/common/utils/search2cqn4sql.js +21 -9
- package/libx/_runtime/common/utils/structured.js +35 -25
- package/libx/_runtime/db/Service.js +0 -6
- package/libx/_runtime/db/expand/expand-v2.js +130 -0
- package/libx/_runtime/db/expand/expandCQNToJoin.js +38 -52
- package/libx/_runtime/db/expand/index.js +3 -1
- package/libx/_runtime/db/generic/arrayed.js +3 -1
- package/libx/_runtime/db/generic/input.js +52 -10
- package/libx/_runtime/db/generic/integrity.js +367 -26
- package/libx/_runtime/db/generic/virtual.js +51 -13
- package/libx/_runtime/db/query/read.js +12 -8
- package/libx/_runtime/db/query/update.js +9 -3
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +8 -9
- package/libx/_runtime/{common → db}/utils/propagateForeignKeys.js +11 -14
- package/libx/_runtime/fiori/generic/activate.js +1 -0
- package/libx/_runtime/fiori/generic/before.js +2 -1
- package/libx/_runtime/fiori/generic/edit.js +1 -0
- package/libx/_runtime/fiori/generic/patch.js +1 -1
- package/libx/_runtime/fiori/generic/read.js +128 -57
- package/libx/_runtime/fiori/uiflex/handler/transformRESULT.js +0 -4
- package/libx/_runtime/fiori/uiflex/index.js +1 -1
- package/libx/_runtime/fiori/uiflex/{extensibility/index.js → service.js} +6 -4
- package/libx/_runtime/fiori/utils/delete.js +7 -1
- package/libx/_runtime/hana/Service.js +1 -8
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -14
- package/libx/_runtime/hana/execute.js +10 -4
- package/libx/_runtime/hana/pool.js +55 -45
- package/libx/_runtime/hana/search.js +7 -6
- package/libx/_runtime/hana/search2cqn4sql.js +8 -5
- package/libx/_runtime/hana/searchToContains.js +3 -1
- package/libx/_runtime/index.js +5 -5
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +3 -3
- package/libx/_runtime/messaging/Outbox.js +53 -0
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +17 -10
- package/libx/_runtime/messaging/common-utils/connections.js +14 -9
- package/libx/_runtime/messaging/common-utils/waitingTime.js +2 -0
- package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -3
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -2
- package/libx/_runtime/messaging/enterprise-messaging.js +21 -15
- package/libx/_runtime/messaging/file-based.js +5 -5
- package/libx/_runtime/messaging/message-queuing-utils/options-messaging.js +1 -0
- package/libx/_runtime/messaging/message-queuing.js +2 -3
- package/libx/_runtime/messaging/outbox/OutboxRunner.js +75 -0
- package/libx/_runtime/messaging/outbox/utils.js +192 -0
- package/libx/_runtime/messaging/service.js +16 -30
- package/libx/_runtime/remote/Service.js +15 -0
- package/libx/_runtime/remote/utils/client.js +15 -3
- package/libx/_runtime/remote/utils/{dataConversion.js → data.js} +12 -2
- package/libx/_runtime/sqlite/Service.js +7 -10
- package/libx/_runtime/sqlite/customBuilder/CustomExpressionBuilder.js +19 -0
- package/libx/_runtime/sqlite/execute.js +18 -12
- package/libx/_runtime/types/api.js +2 -1
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +1 -1
- package/libx/odata/{odata2cqn/afterburner.js → afterburner.js} +28 -16
- package/libx/odata/{cqn2odata/index.js → cqn2odata.js} +1 -1
- package/libx/odata/{odata2cqn/grammar.pegjs → grammar.pegjs} +222 -130
- package/libx/odata/index.js +23 -14
- package/libx/odata/parser.js +1 -0
- package/libx/odata/utils.js +57 -0
- package/libx/rest/RestAdapter.js +2 -6
- package/libx/rest/utils/data.js +1 -6
- package/package.json +4 -3
- package/server.js +4 -5
- package/srv/audit-log.cds +87 -0
- package/{libx/_runtime/fiori/uiflex/extensibility/index.cds → srv/flex.cds} +0 -0
- package/srv/flex.js +1 -0
- package/srv/outbox.cds +11 -0
- package/srv/outbox.js +0 -0
- package/libx/_runtime/cds-services/adapter/perf/performance.js +0 -104
- package/libx/_runtime/cds-services/adapter/perf/performanceMeasurement.js +0 -33
- package/libx/odata/odata2cqn/index.js +0 -3
- package/libx/odata/odata2cqn/parser.js +0 -1
- package/libx/odata/readme.md +0 -1
- package/libx/odata/utils/index.js +0 -64
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,137 @@
|
|
|
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 5.7.3 - 2021-12-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Message Queuing now accepts `amqp` options
|
|
12
|
+
- OData requests using lambda expressions with `contains` function
|
|
13
|
+
- Result of OData query option `$count=true` when using `$apply`
|
|
14
|
+
- `$filter` with navigation to-one equals value crashes
|
|
15
|
+
- `$skiptoken` query option allows to use arbitrary symbols except of `&` with beta OData URL to CQN parser (`cds.env.features.odata_new_parser`). In this non-integer value case the value will not be parsed into CQN.
|
|
16
|
+
- Function names in `$filter` can now be case insensitive (as per OData 4.01)
|
|
17
|
+
- `$count` in `$expand` caused server to crash
|
|
18
|
+
|
|
19
|
+
## Version 5.7.2 - 2021-12-09
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Instance-based restriction for activation of draft enabled entities
|
|
24
|
+
- `.columns('*')` on projections of remote services using renamed properties
|
|
25
|
+
- GraphQL filters on nested fields are now applied correctly
|
|
26
|
+
- Performance degradation during processing of `where exists`
|
|
27
|
+
- Read drafts via navigation with complex filter expression
|
|
28
|
+
|
|
29
|
+
## Version 5.7.1 - 2021-12-06
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Draft (OData flavors `w4`, `x4` and `v4` with structs): Flags `HasActiveEntity`, `HasDraftEntity`, and `IsActiveEntity` are now included in the HTTP response for GET requests.
|
|
34
|
+
- Instance-based restriction on entities using localized fields in draft
|
|
35
|
+
- Results of actions/functions do not ignore nested data if query options are present
|
|
36
|
+
|
|
37
|
+
## Version 5.7.0 - 2021-12-03
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- Deferred emitting via persistent outbox, enabled through service `outbox` of kind `persistent-outbox`
|
|
42
|
+
- Support for compiler-generated referential constraints (beta)
|
|
43
|
+
+ Activate via `cds.env.features.assert_integrity: '<preset>'`
|
|
44
|
+
+ Available presets:
|
|
45
|
+
+ `off`: no database constraints and no runtime checks
|
|
46
|
+
+ `app`: runtime checks by default
|
|
47
|
+
+ `db`: database constraints by default
|
|
48
|
+
+ "by default": if not excluded, the runtime check or database constraint applies
|
|
49
|
+
+ "opt-in": if included, the runtime check or database constraint applies
|
|
50
|
+
+ Behavior can be overridden via `@assert.integrity: <true/false/'RT'/'DB'>` on property, entity, or service level (lowest applies)
|
|
51
|
+
- Allow `--with-mocks` in production via `cds.env.features.with_mocks = true`
|
|
52
|
+
- Set media type from content type header while inbound streaming
|
|
53
|
+
- Support for navigations with `$count` in `$filter`, for example `GET Entity?$filter=toMany/$count gt 0`
|
|
54
|
+
- Draft: Generate UUIDs for request payloads to which extra data items are added (without the UUID keys) in a custom application handler.
|
|
55
|
+
- Generate GraphQL schema via `cds compile -2 gql` (alpha)
|
|
56
|
+
- Log requests to remote services if respective log level is set to `debug`
|
|
57
|
+
- Beta OData URL to CQN parser (`cds.env.features.odata_new_parser`):
|
|
58
|
+
+ support for `$skiptoken` query option
|
|
59
|
+
+ limited support for `$apply` query option
|
|
60
|
+
+ Supported are following transformations and their combinations: `aggregate`, `groupby`, `topcount`, `bottomcount`, `filter`, `search`
|
|
61
|
+
+ Not supported:
|
|
62
|
+
+ Transformations `topsum`, `bottomsum`, `toppercent`, `bottompercent`, `expand`, `concat`, `compute`, `identity`
|
|
63
|
+
+ `rollup` and `$all` in `groupby` transformation
|
|
64
|
+
+ Filter function `isdefined`
|
|
65
|
+
+ Custom aggregation methods, arithmetic operators (`add`, `sub`, `mul` and so on) and keyword `from` in `aggregate` transformation
|
|
66
|
+
+ OData vocabulary for Data Aggregation, `@Aggregation.default` annotation
|
|
67
|
+
+ Out of scope:
|
|
68
|
+
+ Draft handling
|
|
69
|
+
- Out-of-the-box audit logging for draft enabled entities
|
|
70
|
+
- Support for `@sap/instance-manager`'s hybrid mode
|
|
71
|
+
+ Enable via `cds.env.features.hybrid_instance_manager`
|
|
72
|
+
+ Respective version of `@sap/instance-manager` required
|
|
73
|
+
- `cds.minify()` (alpha) as static method
|
|
74
|
+
- Annotation `@open` for actions in new Rest Adapter
|
|
75
|
+
- Audit logging (`cds.env.features.audit_personal_data`) supports annotation `@PersonalData.EntitySemantics: 'Other'` and allows an arbitrary composition of entities with respect to `@PersonalData.EntitySemantics` annotations
|
|
76
|
+
|
|
77
|
+
### Changed
|
|
78
|
+
|
|
79
|
+
- `if-match` and `if-none-match` headers are ignored for entities without etags
|
|
80
|
+
- Improve response time of `SELECT` queries that check referential integrity by adding an upper bound `LIMIT 1`
|
|
81
|
+
- Leaner implementation for `sap-statistics`
|
|
82
|
+
- Leading and trailing whitespaces are allowed for `$search` query parameter
|
|
83
|
+
- Insert / Update of Composition of one with empty object is not allowed for non UUID keys
|
|
84
|
+
- Search behavior of whitespaces changed as follow:
|
|
85
|
+
+ Searches for plain whitespace, for example, `"$search= "` matches the complete data set.
|
|
86
|
+
+ Searches for whitespace surrounded by double-quotes, for example, `$search=" "` matches all entries containing whitespaces.
|
|
87
|
+
- In single tenant mode, the default SQLite database is used, regardless of `context.tenant`
|
|
88
|
+
- `cds build` for Node.js projects now copies `package-lock.json` files into the staging folder (usually `gen/srv`). This allows the execution of `npm ci` there.
|
|
89
|
+
- Relaxed UUIDs in beta URL to CQN parser (`cds.env.features.odata_new_parser`)
|
|
90
|
+
- Authentication strategies `dummy` and `mock` no longer require `passport`
|
|
91
|
+
- In production, debug logs of `cds.DatabaseService` and `cds.RemoteService` have sanitized values
|
|
92
|
+
+ Deactivate via `cds.env.log.sanitize_values = false`
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- Path resolution for references in sub selects
|
|
97
|
+
- Where exists without infix filter, e.g., `@restrict.where: 'exists author'`
|
|
98
|
+
- `@restrict.where: 'exists [...]'` in draft union scenario
|
|
99
|
+
- Select query with path exists predicates e.g., `WHERE EXISTS books[year = 2000].pages[wordcount > 1000]`
|
|
100
|
+
- Proper registration of audit log event handlers
|
|
101
|
+
- Draft: Generate foreign keys for request payloads to which extra data items are added in a custom application handler.
|
|
102
|
+
- `cds build` correctly merges `hdbmigrationtable` files that have multiple new migration versions defined.
|
|
103
|
+
- `cds.test` converts response data of failed requests to JSON to prevent lost error details
|
|
104
|
+
- Instance based restriction for draft enabled entities
|
|
105
|
+
- Delete requests for localized with compositions
|
|
106
|
+
- Ignore input for static and calculated fields during draft activate
|
|
107
|
+
- Clear extension map entry on error during CSN fetching
|
|
108
|
+
- Do not ignore errors during diff calculation
|
|
109
|
+
- Requests to mocked remote service when using custom service name with `.service` property
|
|
110
|
+
- Rollback on already backrolled or committed transactions are ignored
|
|
111
|
+
- Rollback handling in spawned background job
|
|
112
|
+
- `cds.spawn()` throws error if passed options is an instance of `cds.EventContext`
|
|
113
|
+
- Delete `timestamp` from options passed to `cds.spawn()` (transactions create their own timestamp)
|
|
114
|
+
- Type error during programmatic action/function call if no params defined
|
|
115
|
+
- Fully qualified bound actions/ functions in beta URL to CQN parser (`cds.env.features.odata_new_parser`)
|
|
116
|
+
- Draft handling: `GET` requests with navigation via `SiblingEntity` and expand to-one
|
|
117
|
+
- No audit log if sensitive data not selected
|
|
118
|
+
- Kibana formatter: do not log authorization header value
|
|
119
|
+
- Audit logging (`cds.env.features.audit_personal_data`) no longer crashes the application
|
|
120
|
+
+ when using the same entity as a composition child in different parent entities
|
|
121
|
+
+ when accessing a not existing entity
|
|
122
|
+
|
|
123
|
+
### Removed
|
|
124
|
+
|
|
125
|
+
- Deprecated feature flags `cds.env.runtime.skipWithParameters` and `cds.env.features.skip_with_parameters`. Use `cds.env.features.with_parameters` instead.
|
|
126
|
+
|
|
127
|
+
## Version 5.6.4 - 2021-11-23
|
|
128
|
+
|
|
129
|
+
### Fixed
|
|
130
|
+
|
|
131
|
+
- Preserve log level in Kibana formatter
|
|
132
|
+
- RFC 3986 compliant segment recognition in beta URL to CQN parser (`cds.env.features.odata_new_parser`)
|
|
133
|
+
- Support for `$skiptoken` OData query option when using beta URL to CQN parser (`cds.env.features.odata_new_parser`)
|
|
134
|
+
- OData requests with `$skip` and without `$top` query option to services with defined default limit (`cds.query.limit.default`)
|
|
135
|
+
- Creating entities with binary keys. Currently the binary keys may be provided only as Node.js `Buffer` instances using a custom handler.
|
|
136
|
+
- Requests with payload containing nested arrayed elements no longer crash the application
|
|
137
|
+
|
|
7
138
|
## Version 5.6.3 - 2021-11-15
|
|
8
139
|
|
|
9
140
|
### Fixed
|
|
@@ -102,6 +233,9 @@
|
|
|
102
233
|
+ Deactivate during two month grace period via compat feature flag `cds.env.features.keys_into_where = true`
|
|
103
234
|
- Removed duplicate integrity checks
|
|
104
235
|
- Optimized search: Optimize queries for non-localized elements
|
|
236
|
+
- OData to CQN parsing changed to enable remote service consumption. As a side effect, application code in `srv.on('READ', handler)` custom handlers relaying on CQN might need to be adapted. The following has changed:
|
|
237
|
+
- Previously, columns in `req.query.SELECT.columns` were always defined. Now, in case there is no `$select` and `$expand` query options in the OData query, `req.query.SELECT.columns` is `undefined`.
|
|
238
|
+
- Previously, if the `$expand` query option was specified in the OData query, all elements of the expanded navigation property were listed explicitly in the CQN query. Now, an `*` (asterisk) is listed instead.
|
|
105
239
|
- Non-specified columns are resolved at database layer
|
|
106
240
|
- `cds deploy` no longer enforces the presence of SAP CommonCryptoLib (checked with env variable `SECUDIR`) on Windows since it uses now the built-in security libraries
|
|
107
241
|
- Target keys are not included into a body when sending `PATCH` requests to external services
|
|
@@ -574,6 +708,7 @@
|
|
|
574
708
|
- `SELECT.where(...)` generates CQN with list of values for `in` operator
|
|
575
709
|
- Always use flag `u` during input validation via `@assert.format`
|
|
576
710
|
- Intermediate CQN format for lambda expressions with preceding navigation path
|
|
711
|
+
- Better error messages for draft enabled entities
|
|
577
712
|
|
|
578
713
|
### Fixed
|
|
579
714
|
|
package/_i18n/i18n_fr.properties
CHANGED
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
#----------------------------------------------------------------------------------------------------------------------
|
|
27
27
|
|
|
28
28
|
#XTIT: Created By (Answer to: "Which user has created a certain entity?")
|
|
29
|
-
CreatedBy=
|
|
29
|
+
CreatedBy=Auteur de la cr\u00E9ation
|
|
30
30
|
|
|
31
31
|
#XTIT: Created On (Answer to: "When has a certain entity been created?")
|
|
32
|
-
CreatedAt=
|
|
32
|
+
CreatedAt=Date de cr\u00E9ation
|
|
33
33
|
|
|
34
34
|
#XTIT: Changed By (Answer to: "Which user has changed a certain entity?")
|
|
35
|
-
ChangedBy=
|
|
35
|
+
ChangedBy=Auteur de la modification
|
|
36
36
|
|
|
37
37
|
#XTIT: Changed On (Answer to: "When has a certain entity been changed?")
|
|
38
|
-
ChangedAt=
|
|
38
|
+
ChangedAt=Date de modification
|
|
39
39
|
|
|
40
40
|
#XTIT: Currency
|
|
41
41
|
Currency=Devise
|
package/apis/cds.d.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
declare type cds_facade =
|
|
2
|
-
import ('./core')
|
|
3
|
-
& import ('./models')
|
|
4
|
-
& import ('./connect')
|
|
5
|
-
& import ('./serve')
|
|
6
|
-
& import ('./ql').cds_ql
|
|
7
|
-
& import ('./services').cds_facade
|
|
8
|
-
& import ('./services').QueryAPI
|
|
9
|
-
|
|
10
1
|
declare global {
|
|
11
|
-
const cds :
|
|
2
|
+
const cds : import ('./core')
|
|
3
|
+
& import ('./models')
|
|
4
|
+
& import ('./connect')
|
|
5
|
+
& import ('./serve')
|
|
6
|
+
& import ('./ql').cds_ql
|
|
7
|
+
& import ('./services').cds
|
|
8
|
+
& import ('./services').QueryAPI
|
|
12
9
|
class SELECT<T> extends cds.ql.SELECT<T>{}
|
|
13
10
|
class INSERT<T> extends cds.ql.INSERT<T>{}
|
|
14
11
|
class UPDATE<T> extends cds.ql.UPDATE<T>{}
|
package/apis/connect.d.ts
CHANGED
package/apis/core.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// import types from '../lib/core'
|
|
2
2
|
import { ReflectedModel, LinkedModel, LinkedDefinition } from './reflect'
|
|
3
3
|
import { CSN as csn, Definition } from "./csn"
|
|
4
|
-
import { Query as cqn } from "./cqn"
|
|
5
|
-
import { EventEmitter } from "events";
|
|
6
4
|
|
|
7
|
-
export =
|
|
8
|
-
declare class
|
|
5
|
+
export = cds
|
|
6
|
+
declare class cds {
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
9
|
* Turns the given plain CSN model into a linked model
|
package/apis/models.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import edm from "@sap/cds-compiler/lib/edm/edm"
|
|
2
1
|
import { Query, expr, _xpr } from "./cqn"
|
|
3
2
|
import { CSN } from "./csn"
|
|
4
3
|
|
|
@@ -30,8 +29,8 @@ type EDMX = XML
|
|
|
30
29
|
type filename = string
|
|
31
30
|
|
|
32
31
|
|
|
33
|
-
export =
|
|
34
|
-
declare class
|
|
32
|
+
export = cds
|
|
33
|
+
declare class cds {
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
36
|
* Provides a set of methods to parse a given model, query or expression.
|
package/apis/ql.d.ts
CHANGED
package/apis/services.d.ts
CHANGED
|
@@ -64,8 +64,8 @@ export class QueryAPI {
|
|
|
64
64
|
* Starts or joins a transaction
|
|
65
65
|
* @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-tx)
|
|
66
66
|
*/
|
|
67
|
-
tx (context : object) : Transaction
|
|
68
|
-
transaction (context : object) : Transaction
|
|
67
|
+
tx (context? : object) : Transaction
|
|
68
|
+
transaction (context? : object) : Transaction
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
@@ -204,7 +204,7 @@ export class DatabaseService extends Service {
|
|
|
204
204
|
|
|
205
205
|
export interface ResultSet extends Array<{}> {}
|
|
206
206
|
|
|
207
|
-
export class
|
|
207
|
+
export class cds {
|
|
208
208
|
|
|
209
209
|
/**
|
|
210
210
|
* @see [capire docs](https://cap.cloud.sap/docs/node.js/services)
|
|
@@ -31,7 +31,7 @@ class BuildTaskFactory {
|
|
|
31
31
|
buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
|
|
32
32
|
|
|
33
33
|
// log build tasks
|
|
34
|
-
this.logger.log(`
|
|
34
|
+
this.logger.log(`the following build tasks will be executed`)
|
|
35
35
|
let tasksOutput = " {\n \"build\": {\n \"target\": \"" + this.env.build.target + "\",\n \"tasks\": ["
|
|
36
36
|
for (let i = 0; i < tasks.length; i++) {
|
|
37
37
|
tasksOutput += "\n " + BuildTaskFactory._stringifyTask(tasks[i]) + (i + 1 < tasks.length ? "," : "")
|
|
@@ -63,7 +63,7 @@ class BuildTaskFactory {
|
|
|
63
63
|
|
|
64
64
|
async _createTasks(providerFactory) {
|
|
65
65
|
const buildOptions = providerFactory.buildOptions
|
|
66
|
-
this.logger.log(`
|
|
66
|
+
this.logger.log(`determining build tasks for project [${buildOptions.root}].`)
|
|
67
67
|
|
|
68
68
|
let tasks = this._getExistingTasks()
|
|
69
69
|
if (tasks.length === 0) {
|
|
@@ -118,7 +118,7 @@ class BuildTaskFactory {
|
|
|
118
118
|
|
|
119
119
|
// Java projects use "." as the default build target folder
|
|
120
120
|
if (this._hasJavaNature(buildOptions.root, srv) && this._adaptBuildTargetSettingForJava(buildOptions.root)) {
|
|
121
|
-
this.logger.debug("
|
|
121
|
+
this.logger.debug("using inplace build for java project instead of default staging build")
|
|
122
122
|
}
|
|
123
123
|
buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
|
|
124
124
|
}
|
|
@@ -130,7 +130,7 @@ class BuildTaskFactory {
|
|
|
130
130
|
this.cds.resolve.cache = {}
|
|
131
131
|
|
|
132
132
|
const modelPaths = this.cds.resolve("*", false)
|
|
133
|
-
return
|
|
133
|
+
return this._pushModelPaths(projectPath, [], modelPaths)
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
@@ -241,17 +241,23 @@ class BuildTaskFactory {
|
|
|
241
241
|
return taskOptions
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
_pushModelPaths(projectPath, model, ...modelPaths) {
|
|
245
245
|
model = new Set(model)
|
|
246
246
|
// may contain nested arrays
|
|
247
247
|
modelPaths = BuildTaskFactory._flatten(modelPaths)
|
|
248
|
-
|
|
248
|
+
const { roots } = this.cds.env
|
|
249
249
|
modelPaths.forEach(m => {
|
|
250
250
|
if (m && !model.has(m) && !model.has(m + "/")) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
// filter root model paths that do not exist
|
|
252
|
+
// other entries are added as is, e.g. reuse model entries
|
|
253
|
+
if (roots.includes(m)) {
|
|
254
|
+
const dir = path.resolve(projectPath, m)
|
|
255
|
+
if (fs.existsSync(dir)) {
|
|
256
|
+
model.add(BuildTaskFactory._normalizePath(m))
|
|
257
|
+
} else if (fs.existsSync(dir + FILE_EXT_CDS)) { //might be cds file name, compability to old build configs
|
|
258
|
+
model.add(m)
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
255
261
|
model.add(m)
|
|
256
262
|
}
|
|
257
263
|
}
|
|
@@ -56,7 +56,7 @@ class BuildTaskProviderFactory {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
async lookupTasks() {
|
|
59
|
-
this.logger.debug("
|
|
59
|
+
this.logger.debug("determining CDS build tasks from CDS configuration - applying defaults")
|
|
60
60
|
let tasks = []
|
|
61
61
|
await Promise.all(this.providers.map(async (provider) => {
|
|
62
62
|
let pluginTasks = await this._lookupTasks(provider)
|
|
@@ -81,14 +81,14 @@ class BuildTaskProviderFactory {
|
|
|
81
81
|
createHandler(task) {
|
|
82
82
|
const BuildTaskHandlerClass = this.loadHandler(task)
|
|
83
83
|
const resolvedTask = this.resolveTask(task)
|
|
84
|
-
this.logger._debug && this.logger.debug(`
|
|
84
|
+
this.logger._debug && this.logger.debug(`loaded build task handler [${resolvedTask.use}]`)
|
|
85
85
|
|
|
86
86
|
const handler = new BuildTaskHandlerClass()
|
|
87
87
|
handler._task = resolvedTask
|
|
88
88
|
handler._cds = this.cds
|
|
89
89
|
handler._logger = this.logger
|
|
90
90
|
handler._buildOptions = this.buildOptions
|
|
91
|
-
this.logger._debug && this.logger.debug(`
|
|
91
|
+
this.logger._debug && this.logger.debug(`created BuildTaskHandler [${resolvedTask.use}]`)
|
|
92
92
|
return handler
|
|
93
93
|
}
|
|
94
94
|
|
package/bin/build/constants.js
CHANGED
|
@@ -31,7 +31,8 @@ exports.CONTENT_DEFAULT_CSN = "contentDefaultCsn" // create default CS
|
|
|
31
31
|
exports.CONTENT_EDMX = "contentEdmx" // create EDMX for required languages
|
|
32
32
|
exports.CONTENT_MANIFEST = "contentManifest" // create manifest.yml and .cfignore files
|
|
33
33
|
exports.CONTENT_PACKAGE_JSON = "contentPackageJson" // create package.json file if not existing, or modify existing package.json
|
|
34
|
-
exports.
|
|
34
|
+
exports.CONTENT_PACKAGELOCK_JSON = "contentPackageLockJson" // copy package-lock.json file if existing
|
|
35
|
+
exports.CONTENT_HDBTABLEDATA = "contentHdbtabledata" // create .hdbtabledata files for .csv files if not existing
|
|
35
36
|
|
|
36
37
|
exports.FOLDER_GEN = "gen"
|
|
37
38
|
exports.FILE_EXT_CDS = ".cds"
|
|
@@ -62,7 +62,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
async _createTasks(buildOptions) { // NOSONAR
|
|
65
|
-
this.logger.debug("
|
|
65
|
+
this.logger.debug("determining CDS build tasks from CDS configuration - applying defaults")
|
|
66
66
|
const { root: projectPath } = buildOptions
|
|
67
67
|
let tasks = []
|
|
68
68
|
let db = typeof this.env.folders.db === "string" ? [BuildTaskProviderInternal._normalizePath(this.env.folders.db)] : this.env.folders.db
|
|
@@ -87,7 +87,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
87
87
|
tasks.push(dbTask)
|
|
88
88
|
}
|
|
89
89
|
} else {
|
|
90
|
-
this.logger.log(`
|
|
90
|
+
this.logger.log(`project doesn't have a database module [${this.env.folders.db}]`)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (srv) {
|
|
@@ -117,7 +117,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
} else {
|
|
120
|
-
this.logger.log(`
|
|
120
|
+
this.logger.log(`project doesn't have a service module '${this.env.folders.srv}'`)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// create mtx build task for node applications
|
|
@@ -135,11 +135,11 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
_createDbTask(projectPath, src, taskOptions, buildOptions) {
|
|
138
|
-
this.logger.debug("
|
|
138
|
+
this.logger.debug("determining database kind.")
|
|
139
139
|
let task = null
|
|
140
140
|
|
|
141
141
|
if (this._useHana(projectPath, buildOptions)) {
|
|
142
|
-
this.logger.debug("
|
|
142
|
+
this.logger.debug("found HANA database.")
|
|
143
143
|
// legacy build supports dest property
|
|
144
144
|
const compileDest = this.env.get("data.dest")
|
|
145
145
|
if (compileDest) {
|
|
@@ -154,7 +154,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
154
154
|
options: taskOptions
|
|
155
155
|
}
|
|
156
156
|
} else {
|
|
157
|
-
this.logger.debug("
|
|
157
|
+
this.logger.debug("found sqlite database - skipping HANA build task")
|
|
158
158
|
}
|
|
159
159
|
return task
|
|
160
160
|
}
|
|
@@ -179,28 +179,28 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
_createMtxTask(srv) {
|
|
182
|
-
this.logger.debug("
|
|
182
|
+
this.logger.debug("determining single or multi-tenant strategy.")
|
|
183
183
|
let task = null
|
|
184
184
|
|
|
185
185
|
if (this.env.get("requires.multitenancy") && (this.env.get("requires.db.kind") === "hana" || this.env.get("requires.db.dialect") === "hana")) {
|
|
186
|
-
this.logger.debug("
|
|
186
|
+
this.logger.debug("found multi-tenant app.")
|
|
187
187
|
task = {
|
|
188
188
|
src: ".",
|
|
189
189
|
for: BUILD_TASK_MTX,
|
|
190
190
|
dest: srv
|
|
191
191
|
}
|
|
192
192
|
} else {
|
|
193
|
-
this.logger.debug("
|
|
193
|
+
this.logger.debug("found single-tenant app - skipping mtx build task")
|
|
194
194
|
}
|
|
195
195
|
return task
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
_createSrvTask(projectPath, src, taskOptions) {
|
|
199
|
-
this.logger.debug("
|
|
199
|
+
this.logger.debug("fetermining implementation technology")
|
|
200
200
|
let task = this._createJavaTask(projectPath, src, taskOptions)
|
|
201
201
|
|
|
202
202
|
if (!task) {
|
|
203
|
-
this.logger.debug("
|
|
203
|
+
this.logger.debug("found implementation technology node")
|
|
204
204
|
task = {
|
|
205
205
|
src: src,
|
|
206
206
|
for: BUILD_TASK_NODE,
|
|
@@ -212,7 +212,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
212
212
|
|
|
213
213
|
_createJavaTask(projectPath, src, taskOptions) {
|
|
214
214
|
if (this._hasJavaNature(projectPath, src)) {
|
|
215
|
-
this.logger.debug("
|
|
215
|
+
this.logger.debug("found implementation technology java")
|
|
216
216
|
// legacy build supports dest property
|
|
217
217
|
const compileDest = this.env.get("service.dest")
|
|
218
218
|
if (compileDest) {
|
|
@@ -237,7 +237,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
237
237
|
*/
|
|
238
238
|
_createFioriTasks(projectPath, fioriSrvOptions) {
|
|
239
239
|
let tasks = []
|
|
240
|
-
this.logger.debug("
|
|
240
|
+
this.logger.debug("determining fiori modules - matching modules */webapp/manifest.json")
|
|
241
241
|
// fiori-app build-tasks
|
|
242
242
|
let appDirs = this.env.ui && this.env.ui.apps ? this.env.ui.apps : undefined
|
|
243
243
|
if (!appDirs) {
|
|
@@ -263,7 +263,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
|
263
263
|
return appDir
|
|
264
264
|
})
|
|
265
265
|
}
|
|
266
|
-
this.logger._debug && this.logger.debug(`
|
|
266
|
+
this.logger._debug && this.logger.debug(`found fiori app paths [${appDirs}]`)
|
|
267
267
|
appDirs.forEach(appDir => {
|
|
268
268
|
appDir = BuildTaskProviderInternal._normalizePath(appDir)
|
|
269
269
|
let modelPaths = this._resolveModel(path.resolve(projectPath, appDir))
|
|
@@ -4,8 +4,7 @@ const { getProperty, BuildError } = require('../../util')
|
|
|
4
4
|
const { getArtifactCdsPersistenceName } = require('@sap/cds-compiler')
|
|
5
5
|
const { LOG_MODULE_NAMES } = require('../../constants')
|
|
6
6
|
const cdscVersion = `-- generated by cds-compiler version ${require('@sap/cds-compiler/package.json').version}`
|
|
7
|
-
const cds = require('../../cds'),
|
|
8
|
-
const { compiler: cdsc } = cds
|
|
7
|
+
const cds = require('../../cds'), { compiler: cdsc } = cds
|
|
9
8
|
let logger = cds.log(LOG_MODULE_NAMES)
|
|
10
9
|
|
|
11
10
|
module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
|
|
@@ -35,7 +34,7 @@ module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
|
|
|
35
34
|
|
|
36
35
|
function _toHdiMigration(model, lastDevVersion, journalFileNames, options) {
|
|
37
36
|
options.sqlChangeMode = getProperty(options, 'hana.journal.change-mode')
|
|
38
|
-
const result = cdsc.to.hdi.migration(
|
|
37
|
+
const result = cdsc.to.hdi.migration(cds.minify(model), options, lastDevVersion);
|
|
39
38
|
if (logger._debug) {
|
|
40
39
|
logger.debug('cdsc.to.hdi.migration returned')
|
|
41
40
|
for (const { name, suffix, sql } of result.definitions) {
|
|
@@ -22,6 +22,7 @@ const FILE_NAME_HDINAMESPACE = ".hdinamespace"
|
|
|
22
22
|
const FILE_NAME_PACKAGE_JSON = "package.json"
|
|
23
23
|
const FILE_NAME_MANIFEST_YML = "manifest.yml"
|
|
24
24
|
const PATH_LAST_DEV_CSN = "last-dev/csn.json"
|
|
25
|
+
const FILE_NAME_UNDEPLOY_JSON = "undeploy.json"
|
|
25
26
|
|
|
26
27
|
// add well-known types supported by HANA Cloud Edition - see also https://github.wdf.sap.corp/cap/issues/issues/8056
|
|
27
28
|
const REQUIRED_PLUGIN_TYPES = [FILE_EXT_CSV, FILE_EXT_HDBTABLEDATA, FILE_EXT_HDBTABLE, ".hdbview", ".hdbindex", ".hdbconstraint"]
|
|
@@ -64,6 +65,8 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
64
65
|
await this._copyNativeContent(src, dest)
|
|
65
66
|
await this._writeHdiConfig(plugins)
|
|
66
67
|
await this._writeHdiNamespace()
|
|
68
|
+
// TODO disabled as this contradicts the MTX domain concept which allows partial app deployments
|
|
69
|
+
//await this._writeUndeployJson()
|
|
67
70
|
|
|
68
71
|
if (this.hasBuildOption(CONTENT_HDBTABLEDATA, true)) {
|
|
69
72
|
await this._compileToHdbtabledata(model, dest)
|
|
@@ -344,6 +347,37 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
344
347
|
return await this.write(content).to(hdiNamespace)
|
|
345
348
|
}
|
|
346
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Create undeploy.json file in <dest> folder of db module.
|
|
352
|
+
*/
|
|
353
|
+
async _writeUndeployJson() {
|
|
354
|
+
if (this.isStagingBuild()) {
|
|
355
|
+
// see issue #64 - add .hdinamespace file to prevent HDI from adding gen/ folder to the namespace.
|
|
356
|
+
const undeployJsonDest = path.join(this.task.dest, FILE_NAME_UNDEPLOY_JSON)
|
|
357
|
+
const undeployJsonSrc = path.join(this.task.src, FILE_NAME_UNDEPLOY_JSON)
|
|
358
|
+
const templateEntries = await this._readTemplateAsJson(FILE_NAME_UNDEPLOY_JSON)
|
|
359
|
+
let newEntries = []
|
|
360
|
+
if (await fs.pathExists(undeployJsonSrc)) {
|
|
361
|
+
newEntries = await fs.readJSON(undeployJsonSrc, 'utf-8')
|
|
362
|
+
newEntries = Array.isArray(newEntries) ? newEntries : []
|
|
363
|
+
templateEntries.forEach(entry => {
|
|
364
|
+
if (!newEntries.includes(entry)) {
|
|
365
|
+
newEntries.push(entry)
|
|
366
|
+
}
|
|
367
|
+
})
|
|
368
|
+
} else {
|
|
369
|
+
newEntries = templateEntries
|
|
370
|
+
}
|
|
371
|
+
// formatted output
|
|
372
|
+
let content = '[\n'
|
|
373
|
+
for (let i = 0; i < newEntries.length; i++) {
|
|
374
|
+
content += ` "${newEntries[i]}"${i + 1 < newEntries.length ? ',' : ''}\n`
|
|
375
|
+
}
|
|
376
|
+
content += ']'
|
|
377
|
+
await this.write(content).to(undeployJsonDest)
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
347
381
|
/**
|
|
348
382
|
* Create .cfignore file only for staging build.
|
|
349
383
|
* This is to have a fast-turnaround at development
|