@sap/cds 5.5.2 → 5.6.0

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 (228) hide show
  1. package/CHANGELOG.md +150 -17
  2. package/apis/services.d.ts +27 -1
  3. package/app/index.js +22 -11
  4. package/bin/build/buildTaskFactory.js +1 -1
  5. package/bin/build/provider/buildTaskProviderInternal.js +1 -1
  6. package/bin/build/provider/fiori/index.js +1 -1
  7. package/bin/build/provider/hana/2migration.js +8 -7
  8. package/bin/build/provider/java-cf/index.js +1 -1
  9. package/bin/deploy/to-hana/hana.js +1 -17
  10. package/common.cds +8 -0
  11. package/lib/compile/index.js +1 -1
  12. package/lib/compile/to/sql.js +22 -2
  13. package/lib/connect/bindings.js +2 -1
  14. package/lib/connect/index.js +1 -1
  15. package/lib/core/infer.js +1 -1
  16. package/lib/core/reflect.js +3 -1
  17. package/lib/env/index.js +175 -41
  18. package/lib/env/requires.js +24 -3
  19. package/lib/i18n/localize.js +31 -4
  20. package/lib/index.js +7 -6
  21. package/lib/log/format/kibana.js +6 -2
  22. package/lib/ql/DELETE.js +1 -1
  23. package/lib/ql/INSERT.js +1 -1
  24. package/lib/ql/Query.js +13 -10
  25. package/lib/ql/SELECT.js +15 -8
  26. package/lib/ql/UPDATE.js +1 -1
  27. package/lib/ql/Whereable.js +5 -0
  28. package/lib/req/context.js +87 -37
  29. package/lib/req/{impl.js → request.js} +1 -1
  30. package/lib/req/{res.js → response.js} +0 -0
  31. package/lib/serve/Service-api.js +1 -1
  32. package/lib/serve/Service-dispatch.js +12 -2
  33. package/lib/serve/Service-handlers.js +21 -7
  34. package/lib/serve/Service-methods.js +1 -1
  35. package/lib/serve/Transaction.js +7 -6
  36. package/lib/serve/index.js +1 -1
  37. package/lib/utils/axios.js +7 -0
  38. package/lib/utils/data.js +1 -1
  39. package/lib/utils/tests.js +5 -3
  40. package/libx/_runtime/audit/Service.js +18 -18
  41. package/libx/_runtime/audit/generic/personal/access.js +1 -1
  42. package/libx/_runtime/audit/generic/personal/modification.js +3 -2
  43. package/libx/_runtime/audit/generic/personal/utils.js +23 -63
  44. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +6 -0
  45. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +37 -35
  46. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
  47. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +3 -1
  48. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +5 -5
  49. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -1
  50. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +13 -7
  51. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +84 -34
  52. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +10 -4
  53. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +9 -3
  54. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +8 -6
  55. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -3
  56. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -11
  57. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectHelper.js +11 -95
  58. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ResourcePathParser.js +17 -11
  59. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +2 -1
  60. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +6 -2
  61. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +3 -34
  62. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +3 -3
  63. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +48 -18
  64. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +10 -5
  65. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +1 -1
  66. package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +1 -1
  67. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +1 -3
  68. package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +9 -2
  69. package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +14 -19
  70. package/libx/_runtime/cds-services/services/utils/columns.js +6 -1
  71. package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -8
  72. package/libx/_runtime/cds-services/services/utils/differ.js +7 -26
  73. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -4
  74. package/libx/_runtime/cds-services/util/assert.js +29 -13
  75. package/libx/_runtime/cds.js +2 -1
  76. package/libx/_runtime/common/aspects/Association.js +72 -0
  77. package/libx/_runtime/common/aspects/any.js +8 -45
  78. package/libx/_runtime/common/aspects/entity.js +0 -1
  79. package/libx/_runtime/common/aspects/relation.js +40 -0
  80. package/libx/_runtime/common/aspects/utils.js +73 -1
  81. package/libx/_runtime/common/auth/strategies/utils/uaa.js +1 -12
  82. package/libx/_runtime/common/composition/data.js +3 -2
  83. package/libx/_runtime/common/composition/delete.js +3 -1
  84. package/libx/_runtime/common/composition/tree.js +23 -18
  85. package/libx/_runtime/common/composition/utils.js +34 -8
  86. package/libx/_runtime/common/error/frontend.js +6 -1
  87. package/libx/_runtime/common/generic/auth.js +15 -13
  88. package/libx/_runtime/common/generic/crud.js +2 -2
  89. package/libx/_runtime/common/generic/etag.js +11 -8
  90. package/libx/_runtime/common/generic/input.js +3 -3
  91. package/libx/_runtime/common/generic/paging.js +9 -5
  92. package/libx/_runtime/common/generic/put.js +3 -2
  93. package/libx/_runtime/common/generic/sorting.js +3 -3
  94. package/libx/_runtime/common/generic/temporal.js +3 -3
  95. package/libx/_runtime/common/toggles/alpha.js +1 -1
  96. package/libx/_runtime/common/utils/cqn.js +20 -1
  97. package/libx/_runtime/common/utils/cqn2cqn4sql.js +125 -139
  98. package/libx/_runtime/common/utils/csn.js +50 -52
  99. package/libx/_runtime/common/utils/foreignKeyPropagations.js +41 -176
  100. package/libx/_runtime/common/utils/generateOnCond.js +40 -70
  101. package/libx/_runtime/common/utils/{enrichWithKeysFromWhere.js → keys.js} +29 -28
  102. package/libx/_runtime/common/utils/postProcessing.js +3 -0
  103. package/libx/_runtime/common/utils/propagateForeignKeys.js +84 -0
  104. package/libx/_runtime/common/utils/resolveStructured.js +1 -1
  105. package/libx/_runtime/common/utils/resolveView.js +20 -10
  106. package/libx/_runtime/common/utils/rewriteAsterisks.js +94 -0
  107. package/libx/_runtime/common/utils/search2cqn4sql.js +9 -8
  108. package/libx/_runtime/common/utils/template.js +54 -46
  109. package/libx/_runtime/db/Service.js +9 -2
  110. package/libx/_runtime/db/expand/expandCQNToJoin.js +11 -25
  111. package/libx/_runtime/db/expand/rawToExpanded.js +2 -1
  112. package/libx/_runtime/db/generic/create.js +1 -0
  113. package/libx/_runtime/db/generic/input.js +7 -11
  114. package/libx/_runtime/db/generic/integrity.js +2 -2
  115. package/libx/_runtime/db/generic/rewrite.js +2 -5
  116. package/libx/_runtime/db/generic/update.js +1 -0
  117. package/libx/_runtime/db/query/read.js +10 -5
  118. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +6 -0
  119. package/libx/_runtime/db/sql-builder/SelectBuilder.js +7 -2
  120. package/libx/_runtime/db/sql-builder/annotations.js +1 -0
  121. package/libx/_runtime/db/utils/columns.js +14 -43
  122. package/libx/_runtime/db/utils/deep.js +5 -7
  123. package/libx/_runtime/fiori/generic/activate.js +3 -2
  124. package/libx/_runtime/fiori/generic/before.js +2 -2
  125. package/libx/_runtime/fiori/generic/cancel.js +3 -2
  126. package/libx/_runtime/fiori/generic/delete.js +3 -2
  127. package/libx/_runtime/fiori/generic/edit.js +2 -2
  128. package/libx/_runtime/fiori/generic/new.js +2 -2
  129. package/libx/_runtime/fiori/generic/patch.js +2 -2
  130. package/libx/_runtime/fiori/generic/prepare.js +2 -2
  131. package/libx/_runtime/fiori/generic/read.js +17 -63
  132. package/libx/_runtime/fiori/generic/readOverDraft.js +4 -4
  133. package/libx/_runtime/fiori/uiflex/extensibility/index.cds +15 -0
  134. package/libx/_runtime/fiori/uiflex/extensibility/index.js +148 -0
  135. package/libx/_runtime/fiori/uiflex/handler/transformREAD.js +119 -0
  136. package/libx/_runtime/fiori/uiflex/handler/transformRESULT.js +43 -0
  137. package/libx/_runtime/fiori/uiflex/handler/transformWRITE.js +62 -0
  138. package/libx/_runtime/fiori/uiflex/index.js +35 -0
  139. package/libx/_runtime/fiori/uiflex/utils.js +78 -0
  140. package/libx/_runtime/fiori/utils/handler.js +3 -13
  141. package/libx/_runtime/fiori/utils/where.js +6 -1
  142. package/libx/_runtime/hana/Service.js +5 -2
  143. package/libx/_runtime/hana/execute.js +1 -1
  144. package/libx/_runtime/hana/pool.js +12 -11
  145. package/libx/_runtime/hana/search2cqn4sql.js +34 -43
  146. package/libx/_runtime/hana/searchToContains.js +3 -3
  147. package/libx/_runtime/index.js +5 -2
  148. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +1 -1
  149. package/libx/_runtime/messaging/common-utils/AMQPClient.js +9 -1
  150. package/libx/_runtime/messaging/common-utils/connections.js +11 -14
  151. package/libx/_runtime/messaging/common-utils/naming-conventions.js +1 -1
  152. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -1
  153. package/libx/_runtime/messaging/enterprise-messaging.js +1 -1
  154. package/libx/_runtime/messaging/message-queuing.js +18 -0
  155. package/libx/_runtime/remote/Service.js +14 -2
  156. package/libx/_runtime/remote/utils/client-types.d.ts +7 -0
  157. package/libx/_runtime/remote/utils/client.js +117 -23
  158. package/libx/_runtime/sqlite/Service.js +4 -3
  159. package/libx/_runtime/sqlite/convertAssocToOneManaged.js +1 -3
  160. package/libx/_runtime/sqlite/execute.js +1 -1
  161. package/libx/gql/GraphQLAdapter.js +33 -0
  162. package/libx/gql/constants/adapter.js +69 -0
  163. package/libx/gql/constants/cds.js +18 -0
  164. package/libx/gql/constants/graphql.js +33 -0
  165. package/libx/gql/resolvers/crud/create.js +15 -0
  166. package/libx/gql/resolvers/crud/delete.js +24 -0
  167. package/libx/gql/resolvers/crud/index.js +6 -0
  168. package/libx/gql/resolvers/crud/read.js +25 -0
  169. package/libx/gql/resolvers/crud/update.js +31 -0
  170. package/libx/gql/resolvers/crud/utils/index.js +36 -0
  171. package/libx/gql/resolvers/field.js +5 -0
  172. package/libx/gql/resolvers/index.js +7 -0
  173. package/libx/gql/resolvers/mutation.js +23 -0
  174. package/libx/gql/resolvers/parse/ast/enrich.js +51 -0
  175. package/libx/gql/resolvers/parse/ast/fragment.js +11 -0
  176. package/libx/gql/resolvers/parse/ast/fromObject.js +39 -0
  177. package/libx/gql/resolvers/parse/ast/index.js +3 -0
  178. package/libx/gql/resolvers/parse/ast/meta.js +4 -0
  179. package/libx/gql/resolvers/parse/ast/variable.js +7 -0
  180. package/libx/gql/resolvers/parse/ast2cqn/columns.js +42 -0
  181. package/libx/gql/resolvers/parse/ast2cqn/entries.js +31 -0
  182. package/libx/gql/resolvers/parse/ast2cqn/index.js +8 -0
  183. package/libx/gql/resolvers/parse/ast2cqn/limit.js +6 -0
  184. package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +24 -0
  185. package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +3 -0
  186. package/libx/gql/resolvers/parse/ast2cqn/where.js +70 -0
  187. package/libx/gql/resolvers/parse/utils/index.js +8 -0
  188. package/libx/gql/resolvers/query.js +13 -0
  189. package/libx/gql/resolvers/root.js +34 -0
  190. package/libx/gql/schema/generate.js +18 -0
  191. package/libx/gql/schema/index.js +5 -0
  192. package/libx/gql/schema/mutation.js +76 -0
  193. package/libx/gql/schema/query.js +108 -0
  194. package/libx/gql/schema/typeDefMap.js +45 -0
  195. package/libx/gql/schema/utils/index.js +54 -0
  196. package/libx/gql/utils/index.js +12 -0
  197. package/libx/{_runtime/odata/cqn2odata.js → odata/cqn2odata/index.js} +39 -100
  198. package/libx/odata/index.js +80 -0
  199. package/libx/odata/odata2cqn/afterburner.js +170 -0
  200. package/libx/{_runtime/odata/odata2cqn.pegjs → odata/odata2cqn/grammar.pegjs} +102 -123
  201. package/libx/odata/odata2cqn/index.js +3 -0
  202. package/libx/odata/odata2cqn/parser.js +1 -0
  203. package/libx/odata/utils/index.js +64 -0
  204. package/libx/rest/RestAdapter.js +101 -0
  205. package/libx/rest/RestRequest.js +30 -0
  206. package/libx/rest/index.js +3 -0
  207. package/libx/rest/middleware/auth.js +22 -0
  208. package/libx/rest/middleware/content.js +15 -0
  209. package/libx/rest/middleware/create.js +40 -0
  210. package/libx/rest/middleware/delete.js +20 -0
  211. package/libx/rest/middleware/error.js +56 -0
  212. package/libx/rest/middleware/operation.js +39 -0
  213. package/libx/rest/middleware/parse.js +90 -0
  214. package/libx/rest/middleware/read.js +29 -0
  215. package/libx/rest/middleware/update.js +42 -0
  216. package/libx/rest/utils/data.js +65 -0
  217. package/package.json +4 -1
  218. package/server.js +42 -29
  219. package/lib/req/cls.js +0 -39
  220. package/libx/_runtime/cds-services/services/utils/diff.js +0 -53
  221. package/libx/_runtime/cds-services/util/auditlog.js +0 -247
  222. package/libx/_runtime/cds-services/util/xsenv.js +0 -51
  223. package/libx/_runtime/common/utils/backlinks.js +0 -83
  224. package/libx/_runtime/common/utils/rewriteAsterisk.js +0 -72
  225. package/libx/_runtime/odata/index.js +0 -55
  226. package/libx/_runtime/odata/odata2cqn.js +0 -1
  227. package/libx/_runtime/odata/readToCqn.js +0 -129
  228. package/libx/_runtime/remote/cqn2odata/index.js +0 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,138 @@
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.6.0 - 2021-10-29
8
+
9
+ ### Added
10
+
11
+ - New REST protocol adapter (beta)
12
+ + Makes use of the beta OData URL to CQN parser. Hence, almost all OData requests are supported (see limitations below).
13
+ + Activate via `cds.env.features.rest_new_adapter = true`
14
+ + Out of scope (compared to OData protocol adapter):
15
+ + OData query option `$apply`
16
+ + Batch requests (with or without atomicity groups)
17
+ + Draft handling
18
+ - New GraphQL protocol adapter (alpha)
19
+ + Serves single endpoint for all services based on `served` event at `/graphql` (subject to change).
20
+ + Activate via `cds.env.features.graphql = true`
21
+ + Required additional dependencies: `@graphql-tools/schema`, `express-graphql`, and `graphql`
22
+ + Not meant for productive use! For example, authentication and authorization are out of scope.
23
+ - Support of the following features when using beta OData URL to CQN parser (`cds.env.features.odata_new_parser`):
24
+ + REST-style URLs (example: `GET /Foo/1`)
25
+ + `$expand=*` query option on different nested expand levels (`$levels` is not yet supported)
26
+ + draft handling
27
+ + structured keys
28
+ + streaming
29
+ + navigation to primitive properties without `$value` query option
30
+ - Optimized Search: Support `$filter` query option in combination with optimize `$search` and localized data (when the environment variable `cds.env.features.optimized_search` is set to `true`)
31
+ - `GET` requests support static values in ON-conditions of composition parents when using unmanaged backlinks
32
+ - `destinationOptions` can be configured for Remote Services
33
+ + Example:
34
+ ```json
35
+ {"cds":{"requires":{
36
+ "S4": {
37
+ "destinationOptions": {
38
+ "selectionStrategy": "subscriberFirst",
39
+ ...
40
+ }
41
+ }
42
+ }}}
43
+ ```
44
+ - `forwardAuthToken` can be configured for Remote Services
45
+ + Example:
46
+ ```json
47
+ {"cds":{"requires":{
48
+ "credentials": {
49
+ "url": "...",
50
+ "forwardAuthToken": true
51
+ }
52
+ }
53
+ }}}
54
+ ```
55
+ - File to store private project settings `.cdsrc-private.json` (should not be checked in source code management)
56
+ - Read additional configuration from JSON files or directory structures using `CDS_CONFIG` env variable
57
+ - Missing typescript definitions for services' `.send` shortcuts `get`, `put`, `post`, `patch`, and `delete`
58
+ - Build VCAP_SERVICES env variable dynamically for compatibility (`cds.env.features.emulate_vcap_services`)
59
+ - GET requests to Remote OData Service are automatically sent as `$batch` if the generated URL is too long
60
+ + Can be configured via `cds.env.remote.max_get_url_length` (beta, default: 1028).
61
+ - Provide ETag in response headers in case of `prefer: return=minimal`
62
+ - Kibana formatter: log the user's id via `cds.env.log.user = true` (beta)
63
+ + Consider the data privacy implications!
64
+ - Experimental support for uiflex running locally on sqlite by setting `cds.requires.extensibility.kind = uiflex`
65
+ - Minified `cds.model` (deactivate via `cds.env.features.skip_unused = false`)
66
+
67
+ ### Changed
68
+
69
+ - Query API: Specified keys are now part of the target path, e.g. `SELECT.from('Books', 1)` will move the key condition into `SELECT.from.ref`.
70
+ + Deactivate during two month grace period via compat feature flag `cds.env.features.keys_into_where = true`
71
+ - Removed duplicate integrity checks
72
+ - Optimized search: Optimize queries for non-localized elements
73
+ - Non-specified columns are resolved at database layer
74
+ - `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
75
+ - Target keys are not included into a body when sending `PATCH` requests to external services
76
+
77
+ ### Fixed
78
+
79
+ - Audit logging of non-string values
80
+ - Query API compilation error when keys start with `{`
81
+ - Handling of wrong Edm.DateTimeOffset values
82
+ - Using UUIDs in search with beta OData URL to CQN parser (`cds.env.features.odata_new_parser`)
83
+ - Runtime exception for READ requests with deeply nested navigation and structured keys, for example:
84
+ `GET foo/Bar/b708ad6c-2dd4-40d5-91c0-2e3eacf306d2/Info/sales(a='1010',b='10',c='00')/functions(functionName='error')`
85
+ - The check for the minimum Node.js version now properly enforces version 12.18, i.e. aborts server startup.
86
+ - `cds.test` fails with a clearer error message if the server wasn't started at all
87
+ - Audit logging for modification of personal or sensitive data when using same entity as a composition child in different parent entities
88
+ - Deleting an entity defined with managed composition of one, whereas a dependent entity is defined having an independent managed association to its composition parent no longer crashes the application
89
+ - Audit logging for entities having arrayed elements
90
+ - Filtering for `cds.Date` on Remote OData V2 services
91
+ - Crash when `rollup` function was used in groupBy in odata requests
92
+ - Or for $filter with IsActiveEntity=true for access to active entities
93
+ - Reading draft-enabled entity with `$expand` targeting non-draft associations
94
+ - Delete with sub-select
95
+ - Runtime exception when streaming property annotated with `@Core.MediaType: 'application/json'`
96
+ - Reading streams via navigation when entity containing large data is a part of a draft-enabled composition tree
97
+ - Read draft entity with nested exists restriction
98
+ - Activate draft of entity having `to-one` and `to-many` compositions
99
+ - Caching issue that causes the OData `omit-values` preference in `Prefer` HTTP headers to misbehaves
100
+ - Deletion of draft instances if multiple draft enabled entities are used within one service
101
+ - Queries with `contains` filter targeting a remote odata v2 service
102
+ - Schema evolution support for nested CDS entities in `cds build`
103
+ - I18n texts with quotes and other special characters get escaped correctly if they appear in XML and Json documents
104
+ - Execution of plain SQL statements on SQLite
105
+ - `Content-Disposition` header is now url encoded
106
+
107
+ ### Removed
108
+
109
+ - Usage of `@sap/xsenv` is superseded with `cds.env` in node.js cds-runtime
110
+ - `@odata.on.insert/update` and `#user/now` are deprecated and will be removed in the next major version. Use `@cds.on.insert/update` and `$user/now` instead.
111
+
112
+ ## Version 5.5.5 - 2021-10-20
113
+
114
+ ### Fixed
115
+
116
+ - Action parameters set to null
117
+ - Restrictions with "where exists" clause and filter on ambiguous fields
118
+ - Nulled user attribute in restrictions with "where exists" clause
119
+ - Wait for all queries to settle during deep operation
120
+
121
+ ## Version 5.5.4 - 2021-10-12
122
+
123
+ ### Fixed
124
+
125
+ - Backwards compatibility for `cds.tx({ user: new User ({ tenant, locale }) })`
126
+ - Transaction API fix: `cds.tx ({ tenant }, tx => { ... })` instead of `cds.tx (tx => { ... }, { tenant })`
127
+ - Writable and reliable `query._target`
128
+ - `req.target` in REST with navigations in URL
129
+
130
+ ## Version 5.5.3 - 2021-10-06
131
+
132
+ ### Fixed
133
+
134
+ - Resolving of views for view definitions using aliases
135
+ - `cds.test` in `cds repl` no longer yields an error with the `beforeEach` function not found
136
+ - Aliasing in case of draft union when expanding more than one `to-one` association
137
+ - Resolving of views if intermediate views are defined in database namespace
138
+
7
139
  ## Version 5.5.2 - 2021-09-29
8
140
 
9
141
  ### Fixed
@@ -31,6 +163,7 @@
31
163
  ### Added
32
164
 
33
165
  - Support for minified models
166
+ - Messaging: Support for string payloads
34
167
  - Messaging: Webhooks use 'application/json' as the default content type
35
168
  - Messaging: If senders don't use `data` as a property of the payload, then the whole payload is interpreted as `data`
36
169
  - Messaging: Support for `$namespace` placeholer in queue name
@@ -48,8 +181,8 @@
48
181
  - When calling `cds.tx()` to create new transactions, this now automatically inherits the current event context from `cds.context`. In case that creates issues set `cds.env.features.cds_tx_inheritance = false` to restore the former behaviour. You can still overwrite individual context settings, for example:
49
182
  ```js
50
183
  const tx = cds.tx() // inherits tenant and user
51
- const tx = cds.tx({ // inherits tenant
52
- user: new cds.User.Privileged
184
+ const tx = cds.tx({ // inherits tenant
185
+ user: new cds.User.Privileged
53
186
  })
54
187
  ```
55
188
  - Method `cds.tx()` now allows to pass a function which will be executed within a new managed transaction, with `tx.commit/rollback()` handled automatically. For example:
@@ -82,26 +215,26 @@
82
215
  ```js
83
216
  cds.spawn (async ()=>{
84
217
  await INSERT.into ('Ticker') ...
85
- })
218
+ })
86
219
  ```
87
220
  ```js
88
221
  cds.spawn (async ()=>{
89
222
  await INSERT.into ('Ticker') ...
90
- },{ after: 111 /* ms */ })
223
+ },{ after: 111 /* ms */ })
91
224
  ```
92
225
  ```js
93
226
  let n=0, handle = cds.spawn (async ()=>{
94
227
  await INSERT.into ('Ticker') ...
95
228
  if (++n>9) clearTimeout (handle)
96
- },{ every: 111 /* ms */ })
229
+ },{ every: 111 /* ms */ })
97
230
  ```
98
231
  ```js
99
232
  cds.spawn (async ()=>{
100
233
  await INSERT.into ('Ticker') ...
101
- },{ // inherits tenant
234
+ },{ // inherits tenant
102
235
  every: 111 /* ms */,
103
- user: new cds.User.Privileged
104
- })
236
+ user: new cds.User.Privileged
237
+ })
105
238
  ```
106
239
  - Default server is CORS-enabled for all origins if not in production
107
240
  - Default lock acquire timeout for `SELECT FOR UPDATE` via `cds.env.sql.lock_acquire_timeout`
@@ -111,7 +244,7 @@
111
244
  - Support for reading streams via `GET /<Entity>(<ID>)/$value`
112
245
  - Draft choreography: support of navigation with `SiblingEntity`
113
246
  - Support for where exists with infix filters in `@restrict`
114
- - Support annotation `@Capabilities.ExpandRestrictions.NonExpandableProperties`
247
+ - Support annotation `@Capabilities.ExpandRestrictions.NonExpandableProperties`
115
248
  - `@Core.ContentID` added to OData error responses if `content-id` header is specified
116
249
  - New OData URL to CQN parser (`cds.env.features.odata_new_parser`):
117
250
  + support of navigation to primitive properties using `$value`
@@ -128,7 +261,7 @@
128
261
  - Messaging: In multitenancy mode, messaging artifacts are only deployed to subscribers (unless the service option `deployForProvider` is set to `true`)
129
262
  - Messaging: Incoming messages without corresponding handlers are not acknowledged
130
263
  - If a service executes a query targeting a projection on one of its entities, the query is resolved along with projections to an entity known by the executing service. The result is post-processed to reflect the expected result of the incoming query. The reason is that no handlers of the executing service were executed as they did not know the query target.
131
- + Deactivate during two month grace period via compact feature flag `cds.env.features.resolve_views = false`
264
+ + Deactivate during two month grace period via compat feature flag `cds.env.features.resolve_views = false`
132
265
  - Use `@sap/cds-compiler`'s `smartId` function to determine whether a reference needs to be quoted.
133
266
  + Allows the use of non-word characters in column names, for example `entity Foo { ![bar/bz]: String; }`.
134
267
  + Support for columns with spaces with feature flag `cds.env.features.spaced_columns`.
@@ -175,14 +308,14 @@
175
308
  - `UPDATE(Foo).with({foo:{'=':'bar'})` erroneously produced:
176
309
  ```js
177
310
  {UPDATE:{..., with:{foo:{ref:['bar']}}}} //> wrong
178
- ```
311
+ ```
179
312
  instead of:
180
313
  ```js
181
314
  {UPDATE:{..., data:{foo:'bar'}}} // correct
182
- ```
315
+ ```
183
316
  &rarr; to produce the ref, use one of:
184
317
  ```js
185
- UPDATE(Foo).with ({foo:{ref:['bar']}})
318
+ UPDATE(Foo).with ({foo:{ref:['bar']}})
186
319
  UPDATE(Foo).with `foo=bar`
187
320
  ```
188
321
  - `UPDATE.with` property stays undefined until actually filled with data
@@ -202,26 +335,26 @@
202
335
 
203
336
  - Direct usage of body-parser
204
337
  - Queries constructed from `cds.ql` do not have the _internal_ property `cqn` anymore
205
- - Inofficial variant `SELECT({'expand(foo)':['a','b']})` is not supported anymore
338
+ - Inofficial variant `SELECT({'expand(foo)':['a','b']})` is not supported anymore
206
339
  &rarr; use one of these official APIs for expands instead:
207
340
  ```js
208
341
  SELECT(x => { x.a, x.foo (f =>{ f.b, f.c }) })
209
342
  SELECT(['a',{ref:['foo'], expand:['b','c']}])
210
343
  ```
211
- - Inofficial variant `SELECT.orderBy('foo','desc')` is not supported anymore
344
+ - Inofficial variant `SELECT.orderBy('foo','desc')` is not supported anymore
212
345
  &rarr; use one of these official APIs instead:
213
346
  ```js
214
347
  SELECT.from(Foo).orderBy({foo:'desc'})
215
348
  SELECT.from(Foo).orderBy('foo desc')
216
349
  ```
217
- - Inofficial variant `SELECT.orderBy('foo, bar desc')` is not supported anymore
350
+ - Inofficial variant `SELECT.orderBy('foo, bar desc')` is not supported anymore
218
351
  &rarr; use one of these official APIs instead:
219
352
  ```js
220
353
  SELECT.from(Foo).orderBy({foo:1,bar:-1})
221
354
  SELECT.from(Foo).orderBy('foo','bar desc')
222
355
  SELECT.from(Foo).orderBy `foo, bar desc`
223
356
  ```
224
- - Inofficial variant `SELECT.where({ or: [{ foo: 'bar' }, { foo: 'baz' }] })` is not supported anymore
357
+ - Inofficial variant `SELECT.where({ or: [{ foo: 'bar' }, { foo: 'baz' }] })` is not supported anymore
225
358
  &rarr; use one of these official APIs instead:
226
359
  ```js
227
360
  SELECT.from(Foo).where({ foo: 'bar', or: { foo: 'baz' } })
@@ -140,7 +140,33 @@ export class Service extends QueryAPI {
140
140
  */
141
141
  send (details: { event: Events, data?: object, headers?: object }) : Promise<this>
142
142
 
143
- // The central method to dispatch events
143
+ /**
144
+ * Constructs and sends a GET request.
145
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
146
+ */
147
+ get (entityOrPath: Target, data?: object) : Promise<this>
148
+ /**
149
+ * Constructs and sends a POST request.
150
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
151
+ */
152
+ post (entityOrPath: Target, data?: object) : Promise<this>
153
+ /**
154
+ * Constructs and sends a PUT request.
155
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
156
+ */
157
+ put (entityOrPath: Target, data?: object) : Promise<this>
158
+ /**
159
+ * Constructs and sends a PATCH request.
160
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
161
+ */
162
+ patch (entityOrPath: Target, data?: object) : Promise<this>
163
+ /**
164
+ * Constructs and sends a DELETE request.
165
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
166
+ */
167
+ delete (entityOrPath: Target, data?: object) : Promise<this>
168
+
169
+ // The central method to dispatch events
144
170
  dispatch (msg: EventMessage): Promise<any>
145
171
 
146
172
 
package/app/index.js CHANGED
@@ -6,7 +6,7 @@ module.exports = { get html(){
6
6
  const odata = srv => Object.keys(srv._adapters).find (a => a.startsWith ('odata'))
7
7
  const metadata = srv => odata(srv) ? ` / <a href="${srv.path}/$metadata">$metadata</a>` : ``
8
8
 
9
- const html = fs.readFileSync(path.join(__dirname,'index.html'),'utf-8')
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*/ /\/$/, ''))
@@ -15,16 +15,27 @@ module.exports = { get html(){
15
15
  ).join('\n') || '— none —'
16
16
  )
17
17
  .replace ('{{services}}', cds.service.providers.map (srv => `
18
- <h3>
19
- <a href="${srv.path}">${srv.path}</a>${metadata(srv)} ${_moreLinks(srv)}
20
- </h3>
21
- <ul>${_entities_in(srv).map (e => {
22
- return `
23
- <li>
24
- <a href="${srv.path}/${e.replace(/\./g, '_')}">${e}</a> ${_moreLinks(srv, e)}
25
- </li>`}).join('')}
26
- </ul>
27
- `) .join(''))
18
+ <h3>
19
+ <a href="${srv.path}">${srv.path}</a>${metadata(srv)} ${_moreLinks(srv)}
20
+ </h3>
21
+ <ul>${_entities_in(srv).map (e => {
22
+ return `
23
+ <li>
24
+ <a href="${srv.path}/${e.replace(/\./g, '_')}">${e}</a> ${_moreLinks(srv, e)}
25
+ </li>`}).join('')}
26
+ </ul>
27
+ `).join(''))
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
+ }
28
39
 
29
40
  Object.defineProperty (this,'html',{value:html})
30
41
  return html
@@ -150,7 +150,7 @@ class BuildTaskFactory {
150
150
  _adaptBuildTargetSettingForJava(projectPath) {
151
151
  if (this.env.build.target !== ".") {
152
152
  // filter user settings of cds.env
153
- const userEnv = this.env.for("cds", projectPath, false, true)
153
+ const userEnv = this.env.for("cds", projectPath, false)
154
154
 
155
155
  // use helper as env.build might be undefined
156
156
  if (!getProperty(userEnv, "build.target")) {
@@ -174,7 +174,7 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
174
174
  }
175
175
  // check whether cds config represents a legacy build system config for which requires.db was not configured
176
176
  // Note: compat layer sets requires.db: {}
177
- const userEnv = this.cds.env.for("cds", projectPath, false, true)
177
+ const userEnv = this.cds.env.for("cds", projectPath, false)
178
178
  return userEnv && (userEnv.get("data.model") || userEnv.get("service.model"))
179
179
  }
180
180
 
@@ -51,7 +51,7 @@ class FioriAppModuleBuilder extends BuildTaskHandlerEdmx {
51
51
 
52
52
  if (javaTask
53
53
  && await isOldJavaStack([javaTask.src, this.buildOptions.root])
54
- && !this.env.for("cds", this.buildOptions.root, false, true).get(ODATA_VERSION)) {
54
+ && !this.env.for("cds", this.buildOptions.root, false).get(ODATA_VERSION)) {
55
55
 
56
56
  // old java stack
57
57
  // default is now v4 and not v2 anymore, so overwrite with v2 if using default
@@ -1,6 +1,7 @@
1
1
  const path = require('path')
2
2
  const parser = require('./migrationtable')
3
3
  const { getProperty, BuildError } = require('../../util')
4
+ const { getArtifactCdsPersistenceName } = require('@sap/cds-compiler')
4
5
  const { LOG_MODULE_NAMES } = require('../../constants')
5
6
  const cdscVersion = `-- generated by cds-compiler version ${require('@sap/cds-compiler/package.json').version}`
6
7
  const cds = require('../../cds'), minified = csn => cds.linked(csn).minified()
@@ -12,15 +13,15 @@ module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
12
13
  logger = options.logger
13
14
  }
14
15
 
15
- const journalEntityNames = _getJournalEntityNames(model)
16
- const { definitions, deletions, migrations, afterImage } = _toHdiMigration(model, lastDevVersion, journalEntityNames, options)
16
+ const journalFileNames = _getJournalFileNames(model)
17
+ const { definitions, deletions, migrations, afterImage } = _toHdiMigration(model, lastDevVersion, journalFileNames, options)
17
18
  const definitionResult = []
18
19
 
19
20
  for (const { name, suffix, sql } of definitions) {
20
21
  let definitionEntry = { name, suffix, content: sql }
21
22
 
22
23
  if (suffix === '.hdbtable') {
23
- if (journalEntityNames.has(name)) {
24
+ if (journalFileNames.has(name)) {
24
25
  const migration = migrations.find(migration => migration.name === name)
25
26
  definitionEntry = await _2migrationtable(srcPath, migration || _emptyMigration(name), sql, options)
26
27
  }
@@ -32,14 +33,14 @@ module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
32
33
  return { definitions: definitionResult, deletions, afterImage }
33
34
  }
34
35
 
35
- function _toHdiMigration(model, lastDevVersion, journalEntityNames, options) {
36
+ function _toHdiMigration(model, lastDevVersion, journalFileNames, options) {
36
37
  options.sqlChangeMode = getProperty(options, 'hana.journal.change-mode')
37
38
  const result = cdsc.to.hdi.migration(minified(model), options, lastDevVersion);
38
39
  if (logger._debug) {
39
40
  logger.debug('cdsc.to.hdi.migration returned')
40
41
  for (const { name, suffix, sql } of result.definitions) {
41
42
  if (suffix === '.hdbtable' || suffix === '.hdbmigrationtable') {
42
- if (journalEntityNames.has(name)) {
43
+ if (journalFileNames.has(name)) {
43
44
  const migration = result.migrations.find(migration => migration.name === name)
44
45
  logger.debug(`
45
46
  File ${name + '.hdbmigrationtable'} - ${migration ? migration.changeset.length : 0} new changes
@@ -132,7 +133,7 @@ function _emptyMigration(name) {
132
133
  return { name, suffix: ".hdbmigrationtable", changeset: [] }
133
134
  }
134
135
 
135
- function _getJournalEntityNames(model) {
136
+ function _getJournalFileNames(model) {
136
137
  const journalNames = new Set(cds.reflect(model).all(item => {
137
138
  if (item.kind === 'entity' && item['@cds.persistence.journal'] === true) {
138
139
  if (item['@cds.persistence.skip'] === true || item['@cds.persistence.exists'] === true) {
@@ -141,7 +142,7 @@ function _getJournalEntityNames(model) {
141
142
  return true
142
143
  }
143
144
  return false
144
- }).map(entity => entity.name))
145
+ }).map(entity => getArtifactCdsPersistenceName(entity.name, 'quoted', model)))
145
146
 
146
147
  logger._debug && logger.debug(`\n[hdbmigrationtable] found ${journalNames.size} model entities annotated with '@cds.persistence.journal`)
147
148
  logger._debug && logger.debug(`[hdbmigrationtable] ${[...journalNames].join(', ')}\n`)
@@ -27,7 +27,7 @@ class JavaCfModuleBuilder extends BuildTaskHandlerEdmx {
27
27
  throw new BuildError('CDS compiler version 2 does no longer support the classic CAP Java runtime. It is recommended to migrate to the current CAP Java runtime SDK. See https://cap.cloud.sap/docs/java/migration for more.')
28
28
  }
29
29
  // default is now v4 and not v2 anymore, so warn and overwrite with v2 if using default
30
- if (!this.env.for('cds', this.buildOptions.root, false, true).get(ODATA_VERSION)) {
30
+ if (!this.env.for('cds', this.buildOptions.root, false).get(ODATA_VERSION)) {
31
31
  odataOptions.version = ODATA_VERSION_V2
32
32
  this.pushMessage('Forcing OData v2 for building though the default is v4. Make sure to define OData v2 in cds configuration.', INFO)
33
33
  }
@@ -11,7 +11,7 @@ const { defaultLogger, nullLogger } = require('./logger');
11
11
  const hdiDeployUtil = require('./hdiDeployUtil');
12
12
  const mtaUtil = require('../../build/mtaUtil');
13
13
  const runCommand = require('./runCommand');
14
- const { bold, error, info } = require('../../utils/term');
14
+ const { bold, info } = require('../../utils/term');
15
15
 
16
16
 
17
17
  const IS_WIN = (os.platform() === 'win32');
@@ -27,8 +27,6 @@ class HanaDeployer {
27
27
  logger.log(`[cds.deploy] - ${bold('Starting deploy to SAP HANA ...')}`);
28
28
  logger.log();
29
29
 
30
- this._validateEnvironment(logger);
31
-
32
30
  const projectPath = path.resolve(process.env._TEST_CWD || process.cwd());
33
31
 
34
32
  const { buildResults } = await this._build(buildTaskOptions, model, logger);
@@ -276,20 +274,6 @@ ${entry}
276
274
  }
277
275
  }
278
276
 
279
-
280
- _validateEnvironment(logger) {
281
- if (IS_WIN && !process.env.SECUDIR) {
282
- const helpUrl = info('https://help.sap.com/viewer/e54136ab6a4a43e6a370265bf0a2d744/latest/en-US/c049e28431ee4e8280cd6f5d1a8937d8.html');
283
- const errMessage = error('[ERROR]') + ` [cds.deploy] - In order to use the hdi deployer on ${bold("Windows")} you require the ${bold("SAP CommonCryptoLib")}.
284
- Please follow ${helpUrl}
285
- for further information on how to obtain ${bold("SAP CommonCryptoLib")}.
286
- `;
287
- logger.error(errMessage);
288
- throw new Error(`[cds.deploy] - Missing SAP CommonCryptoLib`);
289
- }
290
- }
291
-
292
-
293
277
  _getVCAPServicesEntry(serviceInstanceName, serviceKey) {
294
278
  return {
295
279
  hana: [
package/common.cds CHANGED
@@ -65,6 +65,13 @@ aspect temporal {
65
65
  type User : String(255);
66
66
 
67
67
 
68
+ /*
69
+ * Aspects for extensible entities.
70
+ */
71
+ aspect extensible {
72
+ @cds.api.ignore extensions__ : String
73
+ };
74
+
68
75
  //---------------------------------------------------------------------------
69
76
  // Annotations for Fiori UIs...
70
77
 
@@ -122,6 +129,7 @@ annotate managed with {
122
129
  //---------------------------------------------------------------------------
123
130
  // Temporary Workarounds...
124
131
 
132
+ // REVISIT: Remove support for @odata.on... and #... with @sap/cds ^6
125
133
  // REVISIT: change @odata.on... to @cds.on...
126
134
  // REVISIT: @cds.on... should automatically result in @readonly @Core.Computed
127
135
 
@@ -58,7 +58,7 @@ function cds_compile (model, options, _flavor) {
58
58
  for (let each in csn.definitions) {
59
59
  const d = csn.definitions[each]
60
60
  if (d.kind === 'service' && cds.requires[each] && (!o.mocked || cds.requires[each].credentials)) {
61
- d['@cds.external'] = cds.requires[each].kind || true
61
+ Object.defineProperty (d,'@cds.external', { value: cds.requires[each].kind || true })
62
62
  }
63
63
  }
64
64
  if (!csn.meta) csn.meta = {}
@@ -1,9 +1,9 @@
1
1
  const cds = require ('../..'), minified = csn => cds.linked(csn).minified()
2
2
  const cdsc = require ('../cdsc')
3
3
  const {unfold_ddl} = cds.alpha_localized
4
+ const EXT_BACK_PACK = 'extensions__'
4
5
 
5
-
6
- function cds_compile_to_sql (csn,_o) {
6
+ function cds_compile_to_sql_ (csn,_o) {
7
7
  const o = cdsc._options.for.sql(_o) //> used twice below...
8
8
  const all = cdsc.to.sql (minified(csn),o)
9
9
  const sql = unfold_ddl (all.map (each => each
@@ -13,6 +13,26 @@ function cds_compile_to_sql (csn,_o) {
13
13
  return sql
14
14
  }
15
15
 
16
+ function cds_compile_to_sql (csn,_o) {
17
+ const defs = cds.linked(csn).definitions
18
+ for (let each in defs) {
19
+ const d = defs[each], q = d.query
20
+ // q may have SET instead of SELECT
21
+ if (q && q.SELECT && q.SELECT.columns && _is_extensible(d)) _add_extensions2 (q.SELECT.columns)
22
+ }
23
+ function _is_extensible (d) {
24
+ if(!d || !d.elements) return false
25
+ if (EXT_BACK_PACK in d.elements) return true
26
+ else return _is_extensible (d.__proto__)
27
+ }
28
+ function _add_extensions2 (cols) {
29
+ if (cols.some(({ref}) => ref && ref[0] === EXT_BACK_PACK)) return
30
+ cols.push({ref:[EXT_BACK_PACK]})
31
+ }
32
+ const ddl = cds_compile_to_sql_ (csn,_o)
33
+ return ddl
34
+ }
35
+
16
36
 
17
37
  function cds_compile_to_hdbtable (csn,o) {
18
38
  const all = cdsc.to.hdi (minified(csn),o)
@@ -19,9 +19,10 @@ module.exports = class Bindings {
19
19
  return bindings.import() .then (r,e)
20
20
  }
21
21
 
22
- constructor() {
22
+ constructor(url) {
23
23
  this._source = require ('path') .resolve (cds.root, registry.replace(/^~/, require('os').homedir()))
24
24
  this.cds = {provides:{}}
25
+ this.url = url
25
26
  }
26
27
 
27
28
  async load (sync) {
@@ -46,7 +46,7 @@ connect.to = async (datasource, options) => {
46
46
  await srv.prepend (srv.init, srv.options.impl)
47
47
  if (datasource === 'db') cds.db = srv
48
48
  _done (cds.services[datasource] = srv)
49
- cds.emit ('connect',srv)
49
+ if (!o.silent) cds.emit ('connect',srv)
50
50
  return srv
51
51
  }
52
52
 
package/lib/core/infer.js CHANGED
@@ -8,7 +8,7 @@ module.exports = (q,defs) => {
8
8
  q.UPDATE ? _resolve (q.UPDATE.entity, defs) :
9
9
  q.DELETE ? _resolve (q.DELETE.from, defs) :
10
10
  _resolve (undefined)
11
- )})
11
+ ), configurable:true, writable:true })
12
12
  return q._target
13
13
  }
14
14
 
@@ -1,5 +1,6 @@
1
1
  const { types, classes:{ service, entity, action, event, any, struct, array, context, annotation } } = require('.')
2
2
  const _kinds = { annotation, context, service, action, event, entity, view:entity }
3
+ const _minified = Symbol('minified')
3
4
 
4
5
  class LinkedCSN extends any {
5
6
 
@@ -48,6 +49,7 @@ class LinkedCSN extends any {
48
49
 
49
50
  minified (skip = global.cds.env.features.skip_unused) {
50
51
  if (!skip) return this
52
+ if (this[_minified]) return this; else _set (this,_minified,true)
51
53
  const csn = this, all = csn.definitions, reached = new Set
52
54
  const roots = skip === 'all' ? this.services : this.each(_root)
53
55
  for (let each of roots) _visit (each)
@@ -74,7 +76,7 @@ class LinkedCSN extends any {
74
76
  if (n.endsWith('.texts')) delete all[n.replace('.texts','_texts')]
75
77
  }
76
78
  }
77
- return csn
79
+ return this
78
80
  }
79
81
 
80
82
  *each (x, defs=this.definitions) {