@sap/cds 6.0.3 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +165 -18
  2. package/apis/cds.d.ts +11 -7
  3. package/apis/log.d.ts +46 -0
  4. package/apis/ql.d.ts +72 -15
  5. package/bin/build/buildTaskHandler.js +5 -2
  6. package/bin/build/constants.js +4 -1
  7. package/bin/build/provider/buildTaskHandlerEdmx.js +11 -39
  8. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +14 -34
  9. package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
  10. package/bin/build/provider/buildTaskProviderInternal.js +22 -14
  11. package/bin/build/provider/hana/index.js +12 -9
  12. package/bin/build/provider/java/index.js +18 -8
  13. package/bin/build/provider/mtx/index.js +7 -4
  14. package/bin/build/provider/mtx/resourcesTarBuilder.js +60 -35
  15. package/bin/build/provider/mtx-extension/index.js +57 -0
  16. package/bin/build/provider/mtx-sidecar/index.js +46 -18
  17. package/bin/build/provider/nodejs/index.js +34 -13
  18. package/bin/deploy/to-hana/cfUtil.js +7 -2
  19. package/bin/deploy/to-hana/hana.js +20 -25
  20. package/bin/deploy/to-hana/hdiDeployUtil.js +13 -2
  21. package/bin/serve.js +7 -4
  22. package/lib/compile/{index.js → cds-compile.js} +0 -0
  23. package/lib/compile/extend.js +15 -5
  24. package/lib/compile/minify.js +1 -15
  25. package/lib/compile/parse.js +1 -1
  26. package/lib/compile/resolve.js +2 -2
  27. package/lib/compile/to/srvinfo.js +6 -4
  28. package/lib/{deploy.js → dbs/cds-deploy.js} +9 -8
  29. package/lib/env/{index.js → cds-env.js} +1 -17
  30. package/lib/env/{requires.js → cds-requires.js} +24 -3
  31. package/lib/env/defaults.js +7 -1
  32. package/lib/env/schemas/cds-package.json +11 -0
  33. package/lib/env/schemas/cds-rc.json +614 -0
  34. package/lib/index.js +19 -16
  35. package/lib/log/{errors.js → cds-error.js} +1 -1
  36. package/lib/log/{index.js → cds-log.js} +0 -0
  37. package/lib/ql/Query.js +9 -3
  38. package/lib/ql/SELECT.js +2 -2
  39. package/lib/ql/{index.js → cds-ql.js} +0 -9
  40. package/lib/req/context.js +49 -17
  41. package/lib/req/locale.js +5 -1
  42. package/lib/{serve → srv}/adapters.js +23 -19
  43. package/lib/{connect → srv}/bindings.js +0 -0
  44. package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
  45. package/lib/{serve/index.js → srv/cds-serve.js} +1 -1
  46. package/lib/{serve → srv}/factory.js +1 -1
  47. package/lib/{serve/Service-api.js → srv/srv-api.js} +22 -6
  48. package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +13 -8
  49. package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
  50. package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
  51. package/lib/srv/srv-models.js +207 -0
  52. package/lib/{serve/Transaction.js → srv/srv-tx.js} +57 -40
  53. package/lib/utils/{tests.js → cds-test.js} +2 -2
  54. package/lib/utils/cds-utils.js +146 -0
  55. package/lib/utils/index.js +2 -145
  56. package/lib/utils/jest.js +43 -0
  57. package/lib/utils/resources/index.js +15 -25
  58. package/lib/utils/resources/tar.js +18 -41
  59. package/libx/_runtime/auth/index.js +14 -11
  60. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +7 -19
  61. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
  62. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -4
  63. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -4
  64. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
  65. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
  66. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
  67. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -4
  68. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
  69. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -4
  70. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +0 -2
  71. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +3 -1
  72. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
  73. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -3
  74. package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
  75. package/libx/_runtime/cds-services/util/errors.js +1 -29
  76. package/libx/_runtime/common/i18n/messages.properties +2 -1
  77. package/libx/_runtime/common/perf/index.js +10 -15
  78. package/libx/_runtime/common/utils/binary.js +3 -4
  79. package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
  80. package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
  81. package/libx/_runtime/common/utils/resolveView.js +1 -1
  82. package/libx/_runtime/common/utils/template.js +1 -1
  83. package/libx/_runtime/db/Service.js +2 -14
  84. package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
  85. package/libx/_runtime/db/expand/rawToExpanded.js +7 -6
  86. package/libx/_runtime/db/generic/input.js +8 -1
  87. package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
  88. package/libx/_runtime/extensibility/activate.js +47 -47
  89. package/libx/_runtime/extensibility/add.js +22 -13
  90. package/libx/_runtime/extensibility/addExtension.js +17 -13
  91. package/libx/_runtime/extensibility/defaults.js +25 -30
  92. package/libx/_runtime/extensibility/handler/transformREAD.js +20 -18
  93. package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
  94. package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
  95. package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
  96. package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
  97. package/libx/_runtime/extensibility/linter.js +32 -0
  98. package/libx/_runtime/extensibility/push.js +77 -20
  99. package/libx/_runtime/extensibility/service.js +29 -12
  100. package/libx/_runtime/extensibility/token.js +56 -0
  101. package/libx/_runtime/extensibility/utils.js +8 -6
  102. package/libx/_runtime/extensibility/validation.js +6 -9
  103. package/libx/_runtime/fiori/generic/new.js +0 -11
  104. package/libx/_runtime/hana/Service.js +0 -1
  105. package/libx/_runtime/hana/conversion.js +12 -1
  106. package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
  107. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
  108. package/libx/_runtime/hana/pool.js +6 -10
  109. package/libx/_runtime/hana/search2Contains.js +0 -5
  110. package/libx/_runtime/hana/search2cqn4sql.js +1 -0
  111. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  112. package/libx/_runtime/messaging/service.js +11 -6
  113. package/libx/_runtime/remote/utils/data.js +5 -0
  114. package/libx/_runtime/sqlite/Service.js +7 -6
  115. package/libx/_runtime/sqlite/execute.js +41 -28
  116. package/libx/odata/afterburner.js +79 -2
  117. package/libx/odata/cqn2odata.js +9 -7
  118. package/libx/odata/grammar.pegjs +157 -76
  119. package/libx/odata/index.js +9 -3
  120. package/libx/odata/parser.js +1 -1
  121. package/libx/odata/utils.js +39 -5
  122. package/libx/rest/RestAdapter.js +3 -7
  123. package/libx/rest/middleware/delete.js +4 -5
  124. package/libx/rest/middleware/parse.js +3 -2
  125. package/package.json +3 -3
  126. package/server.js +1 -1
  127. package/srv/extensibility-service.cds +6 -3
  128. package/srv/model-provider.cds +3 -1
  129. package/srv/model-provider.js +84 -104
  130. package/srv/mtx.js +7 -1
  131. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +0 -240
package/CHANGELOG.md CHANGED
@@ -4,6 +4,152 @@
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 6.1.1 - 2022-08-24
8
+
9
+ ### Added
10
+ - The configuration schema now includes `cds.extends` and `new-fields` (in `cds.xt.ExtensibilityService`)
11
+
12
+ - `srv.run(fn)` now accepts a function as first argument, which will be run in an active outer transaction, if any, or in a newly created one. This is in contrast to `srv.tx(fn)` which always creates a new tx.
13
+ ```js
14
+ cds.run (tx => { // nested operations are guaranteed to run in a tx
15
+ await INSERT.into (Foo, ...)
16
+ await INSERT.into (Bar, ...)
17
+ })
18
+ ```
19
+
20
+ ### Fixed
21
+
22
+ - Erroneous checks for `join` in `SELECT.from(SELECT.from('xxx'))`
23
+ - Virtual fields with default values in draft context
24
+ - View resolving without model information doesn't crash
25
+ - Unable to upload large attachments. Uploading a large attachment (base64 encoded) caused a runtime exception.
26
+ - `cds.Query.then()` is using `AsyncResource.runInAsyncScope` from now on. → this avoids callstacks being cut off, e.g. in debuggers.
27
+ - `cds.tx()` and `cds.context` have been fixed to avoid accidential fallbacks to auto-commit mode.
28
+ - HDI configuration data (e.g. `./cfg`, `.hdiignore`) is now included in the `resources.tgz` file which is required for Streamlined MTX.
29
+ - `cds deploy` accepts in addition to `VCAP_SERVICES` also `TARGET_CONTAINER` and `SERVICE_REPLACEMENTS` from vcap file when using `--vcap-file` parameter.
30
+ - `cds build` doesn't duplicate CSV files that are contained in `db/src/**`.
31
+ - Typescript issues in `apis/log.d.ts`
32
+ - `cds build` adds OS agnostic base model path to generated feature CSN.
33
+ - Unhandled promise rejection in `expand` handling
34
+ - `cds.context.model` middleware is not mounted for not extensible services
35
+ - `cds.context` continuation was sometimes not reset in REST adapter
36
+ - Requests don't fail with `RangeError: Unable to get service from service map due to error: Invalid time value` anymore
37
+
38
+ ## Version 6.1.0 - 2022-08-10
39
+
40
+ ### Added
41
+
42
+ - Detailed information about pool state: `borrowed`, `pending`, `size`, `available`, `max` to the timeout error
43
+ - Odata v2 payloads for `cds.Time` are converted from hh:mm:ss to PThhHmmMssS e.g. 12:34:56 to PT12H34M56S if provided in hh:mm:ss format
44
+ - Odata v2 payloads for `cds.Integer` are converted to String if not provided as String
45
+ - New OData parser supports aliased parameters e.g. `...function(ID=@p)?@p=5`
46
+ - Support for locale "en_US_x_saprigi"
47
+ - Parameter `rows` in ql API function `limit` can be omitted for remote services, e.g. `SELECT.limit(undefined, 5)`
48
+ - New OData parser supports $filter with "in" operator, e.g. `$filter=ID in (1,2,3)`
49
+ - `cds build` copies `package.json` and `.cdsrc.json` into _main folder of MTX sidecar app.
50
+ - New OData parser supports null parameter in function/action, e.g `/findBooks(author=1,title=null)`
51
+ - New enviroment variable `schemas` contains locations for json schemas validating `package.json`, `.cdsrc.json` and `.cdsrc-private.json` in VS Code
52
+ - `cds.test` can now listen on a fixed port by way of additional arguments '--port', '<PORT_NUMBER>
53
+ - `cds.requires.db.kind = 'sql-mt'` is introduced as a shorthand for
54
+ ```js
55
+ "db": {
56
+ "kind": "sqlite",
57
+ "[production]": {
58
+ "kind": "hana-mt"
59
+ }
60
+ }
61
+ ```
62
+ - `cds build` support for Streamlined MTX extension projects based on build task `mtx-extension`
63
+ - TS definitions for `SELECT.forSharedLock` and `SELECT.forUpdate`
64
+ - TS definitions for `log`
65
+ - Support for new cds build task option `deploy-format`. Java apps may use this option instead of the corresponding global CDS config option.
66
+ - The `ExtensibilityService` serves an endpoint to retrieve a subdomain-specific JWT, which is used by `cds login`
67
+ - The endpoint `/-/cds/extensibility/push` now checks restrictions for new extensions. The configuration is added to the `cds.xt.ExtensibilityService`
68
+ ```js
69
+ "requires": {
70
+ "cds.xt.ExtensibilityService": {
71
+ "element-prefix": ["Z_", "ZZ_"],
72
+ "namespace-blocklist": ["com.sap.", "sap."],
73
+ "extension-allowlist": [
74
+ {
75
+ "for": ["my.bookshop"],
76
+ "kind": "entity",
77
+ "new-fields": 2
78
+ },
79
+ {
80
+ "for": ["CatalogService"],
81
+ "new-entities": 2
82
+ }
83
+ ]
84
+ }
85
+ }
86
+ ```
87
+ - `cds build` validates required service models `@sap/**` for MTX sidecar app and logs an ERROR if some couldn't be resolved.
88
+ - Configuration schema for many properties of the `cds` configuration block in `package.json` or `.cdsrc.json`, especially for `cds.requires...`
89
+
90
+ ### Changed
91
+
92
+ - Streamlined calculation of the difference for `DELETE` queries using `req.diff()`
93
+ - Improved error messages for rest / new odata parser
94
+ - Adjust types for `SELECT.from` and `SELECT.one` to accept array classes as well
95
+ - No `"` added around search values in OData v2 e.g. Foo?search=name is passed through as is
96
+ - If an entity can not be read after write (e.g. insert only entity) no error is shown in the log
97
+ - Throw not supported error for pagination in `$expand`
98
+
99
+ ### Fixed
100
+
101
+ - Wrong context in `tx.run(query)` when `query` is an array
102
+ - We now detect and ignore erroneous attempts to re-register framework-generated stubs as handlers for custom actions/functions.
103
+ - Emits with `persistent-outbox` also work with manual transactions
104
+ - You can now use `cds.ql` fluent API to query tables not in the model, but in database.
105
+ For example, within `cap/samples/bookshop` this works now:
106
+ ```sql
107
+ await SELECT.from('sqlite_master')
108
+ await cds.read('sqlite_master')
109
+ ```
110
+ Caveat: the following undocumented usage of unqualified names happened to work in the past.
111
+ But this was very fragile and caused lots of issues, and therefore was removed:
112
+ ```sql
113
+ await SELECT.from('Books')
114
+ await cds.read('Books')
115
+ ```
116
+ Always use qualified names, or reflected definitions instead:
117
+ ```sql
118
+ const Books = 'sap.capire.bookshop.Books'
119
+ await SELECT.from(Books)
120
+ await cds.read(Books)
121
+ ```
122
+ ```sql
123
+ const {Books} = cds.entities ('sap.capire.bookshop')
124
+ await SELECT.from(Books)
125
+ await cds.read(Books)
126
+ ```
127
+ - Wrong results for expand to many without `orderBy`
128
+ - `cds deploy` api endpoint regex for cli now ignores trailing version info in url
129
+ - Default values no longer overwrite payload values on fields of new drafts
130
+ - Unmanaged to-one navigation caused malformed SQL statement in draft
131
+ - `cds.compile.to.serviceinfo` fix failure to detect Java services if `odataV4.endpoint.path` or `odataV2.endpoint.path` missing in `cds` configuration in `application.yaml`
132
+ - Data type conversion did not work in some expand cases
133
+ - Failed connection to SAP HANA with no or malformed credentials was leading to credentials being written to the log
134
+ - `cds build` no longer fails with an error `no such file` if one of the following files has been defined in some `srv` subfolder - `package.json, package-lock.json, .cdsrc.json, .npmrc`
135
+ - Tar issue on Windows: 'The command line is too long'.
136
+ - `$search`: Lifecycle issue that causes an empty search result when the `$search` and `$expand` query options were combined
137
+ - Operator `IN` with Tagged Template String Literals e.g.:
138
+ ```sql
139
+ SELECT.from(Object).where`userId IN ${aUserIDs}`
140
+ ```
141
+ - `cds build` now uses a closed version range in the node engines version of the deployed application's `package.json`
142
+ - `cds build` no longer generates EDMX files for services that aren't odata protocol enabled
143
+ - `cds deploy` handles orgs and spaces containing commas correctly
144
+ - Incorrect decoding of special characters when reading data of type `cds.LargeString` from SAP HANA using `hdb@^0.19.5` driver
145
+ - The payload is added to the delete request in rest adapter as req.data
146
+
147
+ ## Version 6.0.4 - 2022-07-20
148
+
149
+ ### Fixed
150
+
151
+ - Local mocking of external services using `cds watch`
152
+
7
153
  ## Version 6.0.3 - 2022-07-14
8
154
 
9
155
  ### Changed
@@ -32,17 +178,18 @@
32
178
  ## Version 6.0.1 - 2022-07-05
33
179
 
34
180
  ### Added
181
+
35
182
  - Config option `cds.env.server.port` allows to configure the port to use (in addition to `process.env.PORT` and CLI option `--port`)
36
183
 
184
+ ### Changed
185
+
186
+ - Plugins cannot be loaded as ES modules, but need to remain CommonJS modules
187
+
37
188
  ### Fixed
38
189
 
39
190
  - Removed debug log about shutdown from `cds serve`
40
191
  - Hiding timeout error in production mode
41
192
 
42
- ### Changed
43
-
44
- - Plugins cannot be loaded as ES modules, but need to remain CommonJS modules
45
-
46
193
  ## Version 6.0.0 - 2022-06-30
47
194
 
48
195
  ### Added
@@ -89,7 +236,7 @@
89
236
  - Support for `FOR SHARE LOCK` on SAP HANA to acquire shared locks on the queried records so that the locked records
90
237
  stay intact until the transaction is committed or rolled back.
91
238
  - Consistent error information for remote batch requests
92
- - `cds.env` now supports expanding scalar `cds.requires` entries from `cds.requires.kinds`as follows:
239
+ - `cds.env` now supports expanding scalar `cds.requires` entries from `cds.requires.kinds` as follows:
93
240
  ```jsonc
94
241
  { "cds": {
95
242
  "requires": {
@@ -108,23 +255,23 @@ stay intact until the transaction is committed or rolled back.
108
255
  - Ordering by aggregated value for draft-enabled active entity
109
256
  - `cds build` support for model provider service-based resource deployment.
110
257
  - Remote service:
111
- - Conversion of OData V2 (`"kind": "odata-v2"`) function and action results to OData V4 format
112
- - Conversion of binary data in CQN queries to `base64url` in URL and payload
113
- - Key predicate is omitted for single-key entities in resulting URL (e.g. `GET /Foo(1)` instead of `GET /Foo(ID=1)`)
114
- - Support of views with parameters
258
+ + Conversion of OData V2 (`"kind": "odata-v2"`) function and action results to OData V4 format
259
+ + Conversion of binary data in CQN queries to `base64url` in URL and payload
260
+ + Key predicate is omitted for single-key entities in resulting URL (e.g. `GET /Foo(1)` instead of `GET /Foo(ID=1)`)
261
+ + Support of views with parameters
115
262
  - Add `@odata.mediaContentType` if selecting stream property
116
263
  - Kubernetes service bindings: Support for servicebinding.io and SAP BTP Service Operator based bindings
117
264
  - `cds build` copies an existing `.npmrc` file located in the root or srv folder of your project into the deployment folder (usually `gen/srv`). This allows for dedicated npm configuration in cloud environments. Can be switched off by cds build option `contentNpmrc`.
118
265
  - `cds build` copies an existing `.cdsrc.json` file located in the root or srv folder of your project into the deployment folder (usually `gen/srv`). The effective CDS configuration is created from the `.cdsrc.json` and CDS configuration defined in the `package.json` file. Can be switched off by cds build option `contentCdsrcJson`.
119
266
  - Beta OData URL to CQN parser (`cds.env.features.odata_new_parser = true`):
120
- - `@odata.context` is derived without using okra, not yet supported:
121
- - `$expand=*` query option
122
- - Support for actions and functions
123
- - Further `$apply` transformations supported
124
- - (nested) `concat` transformations
125
- - `orderBy` transformation
126
- - `top` & `skip` transformation
127
- - `identity` transformation
267
+ + `@odata.context` is derived without using okra, not yet supported:
268
+ + `$expand=*` query option
269
+ + Support for actions and functions
270
+ + Further `$apply` transformations supported
271
+ + (nested) `concat` transformations
272
+ + `orderBy` transformation
273
+ + `top` & `skip` transformation
274
+ + `identity` transformation
128
275
  - Log `BEGIN`/`COMMIT`/`ROLLBACK` commands when using SAP HANA as the underlying database
129
276
  - Binary data in payload is validated to be RFC-4648 and OData ABNF conformed
130
277
  - Support multiple media (streaming) properties in one entity
@@ -134,7 +281,6 @@ stay intact until the transaction is committed or rolled back.
134
281
  - $filter in $expand for remote services
135
282
  - Mapping of aliases in $expand for remote services
136
283
 
137
-
138
284
  ### Changed
139
285
 
140
286
  - `@sap/cds` can now be loaded from different install locations like any other module, i.e. `@require('@sap/cds')` will no longer return the same singleton instance.
@@ -188,6 +334,7 @@ Note that this is a breaking change for appliations that rely on error sanitizat
188
334
 
189
335
  ### Fixed
190
336
 
337
+ - We don't rely on `global.cds` anymore -> allows to load and correctly work with multiple versions of `cds`
191
338
  - Improved shutdown for AMQP connections and file listeners
192
339
  - Using `CQL` with a tagged template string `SELECT from Foo { null as boo }` throwed an exception.
193
340
  - In case of `MULTIPLE_ERRORS` throw an `Error` instead of an object
package/apis/cds.d.ts CHANGED
@@ -1,11 +1,15 @@
1
+
2
+ type cds_facade = import('./core')
3
+ & import('./models')
4
+ & import('./connect')
5
+ & import('./serve')
6
+ & import('./ql').cds_ql
7
+ & import('./services').cds
8
+ & import('./services').QueryAPI
9
+ & import('./log')
10
+
1
11
  declare global {
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
+ const cds : cds_facade
9
13
  class SELECT<T> extends cds.ql.SELECT<T>{}
10
14
  class INSERT<T> extends cds.ql.INSERT<T>{}
11
15
  class UPDATE<T> extends cds.ql.UPDATE<T>{}
package/apis/log.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Returns a trace logger for the given module if trace is switched on for it,
3
+ * otherwise returns null. All cds runtime packages use this method for their
4
+ * trace and debug output.
5
+ *
6
+ * @see [capire](https://cap.cloud.sap/docs/node.js/cds-log)
7
+ *
8
+ * By default this logger would prefix all output with '[sql] - '.
9
+ * You can change this by specifying another prefix in the options:
10
+ *
11
+ * const LOG = cds.log('sql|db',{ prefix:'cds.ql' })
12
+ *
13
+ * Call cds.log() for a given module again to dynamically change the log level
14
+ * of all formerly created loggers, for example:
15
+ *
16
+ * const LOG = cds.log('sql')
17
+ * LOG.info ('this will show, as default level is info')
18
+ * cds.log('sql','warn')
19
+ * LOG.info ('this will be suppressed now')
20
+ *
21
+ */
22
+ export = cds
23
+ declare class cds {
24
+ log(name: string, options?: string | number | { level: number, prefix: string }): Logger
25
+ }
26
+
27
+ declare class Logger {
28
+ /**
29
+ * Formats a log outputs by returning an array of arguments which are passed to
30
+ * console.log() et al.
31
+ * You can assign custom formatters like that:
32
+ *
33
+ * cds.log.format = (module, level, ...args) => [ '[', module, ']', ...args ]
34
+ */
35
+ format(module: string, level: number, args: any[]): any[]
36
+ trace(message?: any, ...optionalParams: any[]): void
37
+ debug(message?: any, ...optionalParams: any[]): void
38
+ log(message?: any, ...optionalParams: any[]): void
39
+ info(message?: any, ...optionalParams: any[]): void
40
+ warn(message?: any, ...optionalParams: any[]): void
41
+ error(message?: any, ...optionalParams: any[]): void
42
+ }
43
+
44
+ declare enum levels {
45
+ SILENT = 0, ERROR = 1, WARN = 2, INFO = 3, DEBUG = 4, TRACE = 5, SILLY = 5, VERBOSE = 5
46
+ }
package/apis/ql.d.ts CHANGED
@@ -15,6 +15,31 @@ export class cds_ql {
15
15
  ql:QL & ((context:object) => QL)
16
16
  }
17
17
 
18
+ export type PK = number | string | object
19
+
20
+ // to support path expressions: https://pages.github.tools.sap/cap/docs/java/query-api#path-expressions
21
+ // `Book.title` == `Proxy<Book>.title()`
22
+ type Proxy<T> = {
23
+ [Key in keyof T]: () => Proxy<T[Key]>
24
+ } & {
25
+ /**
26
+ * Accesses any nested attribute based on a path:
27
+ * `X.get('a.b.c.d')`. Note that you will not receive
28
+ * proper typing after this call.
29
+ * To still have access to typed results, use
30
+ * `X.a().b().c().d()` instead.
31
+ */
32
+ get: (path: string) => Proxy<unknown>
33
+ }
34
+
35
+ // any class (not value) of array to represent plural types used in cds-typer.
36
+ // Mainly used as pattern match for SingularType
37
+ type ArrayClass = {new():Array<unknown>}
38
+
39
+ // concrete singular type.
40
+ // `SingularType<typeof Books>` == `Book`.
41
+ type SingularType<T extends ArrayClass> = InstanceType<T>[number]
42
+
18
43
  declare class QL {
19
44
  SELECT : typeof SELECT & ((...columns:string[]) => SELECT<any>) & ((columns:string[]) => SELECT<any>)
20
45
  INSERT : typeof INSERT & ((...entries:object[]) => INSERT<any>) & ((entries:object[]) => INSERT<any>)
@@ -26,12 +51,14 @@ declare class QL {
26
51
 
27
52
  // (new QL).SELECT.from('Foo').byKey(11).a
28
53
 
54
+
55
+
29
56
  export class SELECT<T> extends ConstructedQuery {
30
57
  static one : SELECT_one & { from: SELECT_one }
31
58
  static distinct : typeof SELECT
32
59
  static from : SELECT_from
33
- from (entity: Definition | string, primaryKey? : number | string | object, projection? : (e:any)=>void) : this
34
- byKey (primaryKey? : number | string | object) : this
60
+ from (entity: Definition | string, primaryKey? : PK, projection? : (e:any)=>void) : this
61
+ byKey (primaryKey? : PK) : this
35
62
  columns (projection:(e:T)=>void) : this
36
63
  columns (...col:string[]) : this
37
64
  where (predicate:object) : this
@@ -43,23 +70,53 @@ export class SELECT<T> extends ConstructedQuery {
43
70
  groupBy (...expr : string[]) : this
44
71
  orderBy (...expr : string[]) : this
45
72
  limit (rows : number, offset? : number) : this
73
+ forSharedLock () : this
74
+ forUpdate () : this
46
75
  SELECT : CQN.SELECT
47
76
  }
48
77
 
49
78
  type SELECT_one =
50
- ((entity: Definition | string, primaryKey? : number | string | object, projection? : (e:any)=>void) => SELECT<any>)
79
+ ((entity: Definition | string, primaryKey? : PK, projection? : (e:any)=>void) => SELECT<any>)
80
+
81
+ // calling with class
82
+ & (<T extends ArrayClass>
83
+ (entityType: T)
84
+ => SELECT<SingularType<T>> & Promise<SingularType<T>>)
85
+ &
86
+ (<T extends ArrayClass>
87
+ (entityType: T, projection: (e: Proxy<SingularType<T>>) => void)
88
+ => SELECT<SingularType<T>> & Promise<SingularType<T>>)
89
+ &
90
+ (<T extends ArrayClass>
91
+ (entityType: T, primaryKey : PK, projection: (e: Proxy<SingularType<T>>) => void)
92
+ => SELECT<SingularType<T>> & Promise<SingularType<T>>)
93
+
94
+
51
95
  & (<T> (entity: T[], projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
52
- & (<T> (entity: T[], primaryKey : number | string | object, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
96
+ & (<T> (entity: T[], primaryKey : PK, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
53
97
  & (<T> (entity: {new():T}, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
54
- & (<T> (entity: {new():T}, primaryKey : number | string | object, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
98
+ & (<T> (entity: {new():T}, primaryKey : PK, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
99
+
55
100
 
56
101
 
57
102
  type SELECT_from =
58
- ((entity: Definition | string, primaryKey? : number | string | object, projection? : (e:any)=>void) => SELECT<any>)
103
+ // calling with class
104
+ (<T extends ArrayClass>
105
+ (entityType: T)
106
+ => SELECT<SingularType<T>> & Promise<SingularType<T>>)
107
+ &
108
+ (<T extends ArrayClass>
109
+ (entityType: T, projection: (e: Proxy<SingularType<T>>) => void)
110
+ => SELECT<SingularType<T>> & Promise<SingularType<T>>)
111
+ &
112
+ (<T extends ArrayClass>
113
+ (entityType: T, primaryKey : PK, projection: (e: Proxy<SingularType<T>>) => void)
114
+ => SELECT<SingularType<T>> & Promise<SingularType<T>>)
115
+ // calling with definition
116
+ & ((entity: Definition | string, primaryKey? : PK, projection? : (e:any)=>void) => SELECT<any>)
117
+ // calling with concrete list
59
118
  & (<T> (entity: T[], projection? : (e:T)=>void) => SELECT<T> & Promise<T[]>)
60
- & (<T> (entity: T[], primaryKey : number | string | object, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
61
- & (<T> (entity: {new():T}, projection? : (e:T)=>void) => SELECT<T> & Promise<T[]>)
62
- & (<T> (entity: {new():T}, primaryKey : number | string | object, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
119
+ & (<T> (entity: T[], primaryKey : PK, projection? : (e:T)=>void) => SELECT<T> & Promise<T>)
63
120
 
64
121
 
65
122
  export class INSERT<T> extends ConstructedQuery {
@@ -76,8 +133,8 @@ export class INSERT<T> extends ConstructedQuery {
76
133
  }
77
134
 
78
135
  export class DELETE<T> extends ConstructedQuery {
79
- static from (entity : Definition | string, primaryKey? : number | string | object) : DELETE<any>
80
- byKey (primaryKey? : number | string | object) : this
136
+ static from (entity : Definition | string, primaryKey? : PK) : DELETE<any>
137
+ byKey (primaryKey? : PK) : this
81
138
  where (predicate:object) : this
82
139
  where (...expr : any[]) : this
83
140
  and (predicate:object) : this
@@ -86,10 +143,10 @@ export class DELETE<T> extends ConstructedQuery {
86
143
  }
87
144
 
88
145
  export class UPDATE<T> extends ConstructedQuery {
89
- static entity (entity : Definition | string, primaryKey? : number | string | object) : UPDATE<any>
90
- static entity <T> (entity:Constructable<T>, primaryKey? : number | string | object) : UPDATE<T>
91
- static entity <T> (entity:T, primaryKey? : number | string | object) : UPDATE<T>
92
- byKey (primaryKey? : number | string | object) : this
146
+ static entity (entity : Definition | string, primaryKey? : PK) : UPDATE<any>
147
+ static entity <T> (entity:Constructable<T>, primaryKey? : PK) : UPDATE<T>
148
+ static entity <T> (entity:T, primaryKey? : PK) : UPDATE<T>
149
+ byKey (primaryKey? : PK) : this
93
150
  // with (block: (e:T)=>void) : this
94
151
  // set (block: (e:T)=>void) : this
95
152
  set (data:object) : this
@@ -187,9 +187,8 @@ class BuildTaskHandler {
187
187
  return null
188
188
  }
189
189
  this._logger._debug && this._logger.debug(`model: ${relativePaths(this._buildOptions.root, files).join(", ")}`)
190
- const options = { messages: this._messages }
191
190
  // $location paths are relative to current working dir by default - make sure a given project root folder is taken
192
- options.cwd = this._buildOptions.root
191
+ const options = { ...this.options(), cwd: this._buildOptions.root }
193
192
 
194
193
  const model = await this._cds.load(files, options)
195
194
  if (!model) {
@@ -198,6 +197,10 @@ class BuildTaskHandler {
198
197
  return model
199
198
  }
200
199
 
200
+ options() {
201
+ return { messages: this._messages }
202
+ }
203
+
201
204
  /**
202
205
  * Adds the given fully qualified file path to the list of files that are written by this build task.
203
206
  * @param {string} filePath
@@ -14,7 +14,8 @@ exports.BUILD_TASK_HANA = "hana"
14
14
  exports.BUILD_TASK_FIORI = "fiori"
15
15
  exports.BUILD_TASK_MTX = "mtx"
16
16
  exports.BUILD_TASK_MTX_SIDECAR = "mtx-sidecar"
17
- exports.BUILD_TASKS = [this.BUILD_TASK_JAVA, this.BUILD_TASK_JAVA_CF, this.BUILD_TASK_NODEJS, this.BUILD_TASK_NODE_CF, this.BUILD_TASK_HANA, this.BUILD_TASK_FIORI, this.BUILD_TASK_MTX, this.BUILD_TASK_MTX_SIDECAR]
17
+ exports.BUILD_TASK_MTX_EXTENSION = "mtx-extension"
18
+ exports.BUILD_TASKS = [this.BUILD_TASK_JAVA, this.BUILD_TASK_JAVA_CF, this.BUILD_TASK_NODEJS, this.BUILD_TASK_NODE_CF, this.BUILD_TASK_HANA, this.BUILD_TASK_FIORI, this.BUILD_TASK_MTX, this.BUILD_TASK_MTX_SIDECAR, this.BUILD_TASK_MTX_EXTENSION]
18
19
 
19
20
  exports.ODATA_VERSION = "odata.version"
20
21
  exports.ODATA_VERSION_V2 = "v2"
@@ -44,6 +45,7 @@ exports.CSV_FILE_DETECTION = "csvFileDetection" // detect CSV files
44
45
  exports.FOLDER_GEN = "gen"
45
46
  exports.FILE_EXT_CDS = ".cds"
46
47
  exports.MTX_SIDECAR_FOLDER = "mtx/sidecar" // default name of the mtx sidecar folder
48
+ exports.DEFAULT_CSN_FILE_NAME = "csn.json"
47
49
 
48
50
  exports.CDS_CONFIG_PATH_SEP = "/"
49
51
  exports.SKIP_ASSERT_COMPILER_V2 = "skip-assert-compiler-v2"
@@ -59,3 +61,4 @@ exports.LOG_LEVEL_DEBUG = "debug"
59
61
  exports.LOG_LEVELS = [exports.LOG_LEVEL_ERROR, exports.LOG_LEVEL_WARN, exports.LOG_LEVEL_INFO, exports.LOG_LEVEL_DEBUG]
60
62
  exports.LOG_MODULE_NAMES = "cds|build"
61
63
  exports.OVERRIDE_METHOD_MSG = "Must override method"
64
+ exports.SEMVER_REGEX = /^(\D*)(\d+\.)?(\d+\.)?(\*|\d+)/
@@ -5,16 +5,21 @@ const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY } = require('../consta
5
5
  class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
6
6
  async compileToEdmx(model, edmxDest, compileOptions = {}) { // NOSONAR
7
7
  const promises = []
8
- const services = this.cds.reflect(model).services
8
+
9
+ // generate edmx for services only that have the odata protocol
10
+ const serviceNames = this.cds.reflect(model).services
11
+ .filter(service => this._isOdataProtocol(service))
12
+ .map(service => service.name)
9
13
 
10
14
  // TODO mtx build_helper tests currently expects this, strange...
11
15
  this._result.languages.add('')
12
16
 
13
17
  // new compile impl is throwing error in case no services exist!
14
- if (services.length > 0) {
18
+ if (serviceNames.length > 0) {
15
19
  const options = {
16
20
  ...this._options4edmx(),
17
- ...compileOptions
21
+ ...compileOptions,
22
+ serviceNames
18
23
  }
19
24
  this.logger._debug && this.logger.debug(`compiling edmx files using OData version ${options.version}`)
20
25
 
@@ -45,42 +50,9 @@ class BuildTaskHandlerEdmx extends BuildTaskHandlerFeatureToggles {
45
50
  return Promise.all(promises)
46
51
  }
47
52
 
48
- /**
49
- * Collect and write language bundles into a single i18n.json file.
50
- * @param {Object} model
51
- * @param {string} bundleDest
52
- */
53
- async collectLanguageBundles(model, bundleDest, saveResult = true) {
54
- // collect effective i18n properties...
55
- let bundles = {}
56
- const bundleGenerator = this.cds.localize.bundles4(model)
57
- if (bundleGenerator && bundleGenerator[Symbol.iterator]) {
58
- for (let [locale, bundle] of bundleGenerator) {
59
- // fallback bundle has the name ""
60
- if (typeof locale === 'string') {
61
- bundles[locale] = bundle
62
- }
63
- }
64
- }
65
-
66
- // omit bundles in case the fallback bundle is the only existing entry
67
- const keys = Object.keys(bundles)
68
- if (keys.length === 1 && keys[0] === "" && Object.keys(bundles[keys[0]]).length === 0) {
69
- bundles = {}
70
- }
71
- // copied from ../compile/i18n.js
72
- const { folders = ['i18n'], file = 'i18n' } = this.env.i18n
73
-
74
- // bundleDest might be null
75
- if (bundleDest && Object.keys(bundles).length > 0) {
76
- if (!this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
77
- await this.write(bundles).to(path.join(bundleDest, folders[0], file + '.json'))
78
- }
79
- }
80
- if (saveResult) {
81
- this._result.languageBundles = bundles
82
- }
83
- return bundles
53
+ _isOdataProtocol(service) {
54
+ const { _protocol4Service } = this.cds.service.adapters
55
+ return /^odata/.test(_protocol4Service(service))
84
56
  }
85
57
 
86
58
  _options4odata() {
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
- const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY } = require('../constants')
3
+ const { DEFAULT_CSN_FILE_NAME } = require('../constants')
4
4
  const BuildTaskHandlerInternal = require('./buildTaskHandlerInternal')
5
5
 
6
6
  class FeatureToggleBuilder extends BuildTaskHandlerInternal {
@@ -31,7 +31,10 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
31
31
  dictionary.base = csn
32
32
  }
33
33
  // preserve @location as @source properties
34
- await this.compileToJson(dictionary.base, destBase)
34
+ const csnStr = await this.compileToJson(dictionary.base, path.join(destBase, DEFAULT_CSN_FILE_NAME))
35
+ const csnModel = JSON.parse(csnStr)
36
+ csnModel.meta = csn.meta
37
+ this._result.csn = csnModel
35
38
 
36
39
  if (sources.features) {
37
40
  dictionary.features = await this._compileFeatures(sources.features, destBase, destFts)
@@ -41,13 +44,17 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
41
44
 
42
45
  async collectAllLanguageBundles(dictionary, paths, destBase, destFts) {
43
46
  // create language bundle for base model
44
- await this.collectLanguageBundles(dictionary.base, destBase)
47
+ const i18n = await this.collectLanguageBundles(dictionary.base, destBase)
48
+ if (i18n) {
49
+ this._result.languageBundles = i18n.bundles
50
+ }
51
+
45
52
  if (dictionary.features) {
46
53
  // create language bundles for all features
47
54
  for (const ftName in dictionary.features) {
48
55
  // attach the sources information for i18n location reference
49
56
  dictionary.features[ftName]['$sources'] = paths.features[ftName]
50
- await this.collectLanguageBundles(dictionary.features[ftName], path.join(destFts, this.ftsName, ftName), false)
57
+ await this.collectLanguageBundles(dictionary.features[ftName], path.join(destFts, this.ftsName, ftName))
51
58
  }
52
59
  }
53
60
  }
@@ -87,50 +94,23 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
87
94
  return paths
88
95
  }
89
96
 
90
- async compileToJson(model, csnDest, saveResult = true) {
91
- // This will als add a @source prop containing the relative path to the origin .cds source file
92
- // and a parsed _where clause for @restrict.{grant,where} annotations.
93
- // The @source annotation is required for correct custom handler resolution if no @impl annotation has been defined as
94
- // custom service handler implementations are relative to the origin .cds source files.
95
- // For staging builds (task.src !== task.dest) the csn.json file that is served at runtime is copied into a corresponding srv subfolder.
96
- // As a consequence the src folder name has to be included in the @source file name while for inplace builds (task.src === task.dest) this is not the case.
97
- // This ensures that the paths are relative to the cwd when executing cds run.
98
- const jsonOptions = {
99
- cwd: this.buildOptions.root,
100
- src: this.task.src === this.task.dest ? this.task.src : this.buildOptions.root
101
- }
102
- const csnStr = this.cds.compile.to.json(model, jsonOptions)
103
- const csn = JSON.parse(csnStr)
104
- if (saveResult) {
105
- this._result.csn = csn
106
- this._result.csn.meta = model.meta
107
- }
108
-
109
- // csnDest might be null
110
- if (csnDest && !this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
111
- await this.write(csnStr).to(path.join(csnDest, 'csn.json'))
112
- }
113
- return csn
114
- }
115
-
116
97
  async _compileFeatures(ftsPaths, destBase, destFts) {
117
98
  if (!ftsPaths) {
118
99
  return
119
100
  }
120
101
  const features = {}
121
102
  const options = { ...this.options(), flavor: 'parsed' }
122
- const srvFolder = path.relative(destFts, destBase)
123
103
 
124
104
  // create feature models
125
105
  for (const ftName in ftsPaths) {
126
106
  const ftCsn = await this.cds.load(ftsPaths[ftName], options)
107
+ const ftPath = path.join(destFts, this.ftsName, ftName)
127
108
 
128
109
  // replace require paths by base model path to ensure precedence of feature annos
129
110
  // see https://pages.github.tools.sap/cap/docs/cds/compiler-messages#anno-duplicate-unrelated-layer
130
- ftCsn.requires = [path.join('../..', srvFolder, 'csn.json')]
111
+ ftCsn.requires = [path.join(path.relative(ftPath, destBase), DEFAULT_CSN_FILE_NAME).replace(/\\/g,'/')]
131
112
 
132
- const ftPath = path.join(destFts, this.ftsName, ftName)
133
- await this.compileToJson(ftCsn, ftPath, false)
113
+ await this.compileToJson(ftCsn, path.join(ftPath, DEFAULT_CSN_FILE_NAME))
134
114
  await this._validateFeature(ftPath)
135
115
  features[ftName] = ftCsn
136
116
  }