@sap/cds 6.0.4 → 6.1.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 (120) hide show
  1. package/CHANGELOG.md +128 -18
  2. package/apis/cds.d.ts +11 -7
  3. package/apis/log.d.ts +48 -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 +13 -32
  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 +8 -7
  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 +64 -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/serve.js +7 -4
  20. package/lib/compile/{index.js → cds-compile.js} +0 -0
  21. package/lib/compile/extend.js +15 -5
  22. package/lib/compile/minify.js +1 -15
  23. package/lib/compile/parse.js +1 -1
  24. package/lib/compile/resolve.js +2 -2
  25. package/lib/compile/to/srvinfo.js +6 -4
  26. package/lib/{deploy.js → dbs/cds-deploy.js} +7 -6
  27. package/lib/env/{index.js → cds-env.js} +1 -17
  28. package/lib/env/{requires.js → cds-requires.js} +24 -3
  29. package/lib/env/defaults.js +7 -1
  30. package/lib/env/schemas/cds-package.json +11 -0
  31. package/lib/env/schemas/cds-rc.json +605 -0
  32. package/lib/index.js +19 -16
  33. package/lib/log/{errors.js → cds-error.js} +1 -1
  34. package/lib/log/{index.js → cds-log.js} +0 -0
  35. package/lib/ql/SELECT.js +1 -1
  36. package/lib/ql/{index.js → cds-ql.js} +0 -0
  37. package/lib/req/context.js +35 -7
  38. package/lib/req/locale.js +5 -1
  39. package/lib/{serve → srv}/adapters.js +23 -19
  40. package/lib/{connect → srv}/bindings.js +0 -0
  41. package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
  42. package/lib/{serve/index.js → srv/cds-serve.js} +0 -0
  43. package/lib/{serve → srv}/factory.js +1 -1
  44. package/lib/{serve/Service-api.js → srv/srv-api.js} +14 -6
  45. package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +3 -2
  46. package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
  47. package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
  48. package/lib/srv/srv-models.js +206 -0
  49. package/lib/{serve/Transaction.js → srv/srv-tx.js} +6 -1
  50. package/lib/utils/{tests.js → cds-test.js} +2 -2
  51. package/lib/utils/cds-utils.js +146 -0
  52. package/lib/utils/index.js +2 -145
  53. package/lib/utils/jest.js +43 -0
  54. package/lib/utils/resources/index.js +14 -24
  55. package/lib/utils/resources/tar.js +18 -41
  56. package/libx/_runtime/auth/index.js +13 -10
  57. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +7 -19
  58. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
  59. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -4
  60. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -4
  61. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
  62. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
  63. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
  64. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -4
  65. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
  66. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -4
  67. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
  68. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -3
  69. package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
  70. package/libx/_runtime/cds-services/util/errors.js +1 -29
  71. package/libx/_runtime/common/i18n/messages.properties +2 -1
  72. package/libx/_runtime/common/perf/index.js +10 -15
  73. package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
  74. package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
  75. package/libx/_runtime/common/utils/template.js +1 -1
  76. package/libx/_runtime/db/Service.js +2 -14
  77. package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
  78. package/libx/_runtime/db/generic/input.js +4 -0
  79. package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
  80. package/libx/_runtime/extensibility/activate.js +47 -47
  81. package/libx/_runtime/extensibility/add.js +19 -13
  82. package/libx/_runtime/extensibility/addExtension.js +17 -13
  83. package/libx/_runtime/extensibility/defaults.js +25 -30
  84. package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
  85. package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
  86. package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
  87. package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
  88. package/libx/_runtime/extensibility/linter.js +32 -0
  89. package/libx/_runtime/extensibility/push.js +78 -21
  90. package/libx/_runtime/extensibility/service.js +29 -12
  91. package/libx/_runtime/extensibility/token.js +56 -0
  92. package/libx/_runtime/extensibility/validation.js +6 -9
  93. package/libx/_runtime/fiori/generic/new.js +0 -11
  94. package/libx/_runtime/hana/Service.js +0 -1
  95. package/libx/_runtime/hana/conversion.js +12 -1
  96. package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
  97. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
  98. package/libx/_runtime/hana/pool.js +6 -10
  99. package/libx/_runtime/hana/search2Contains.js +0 -5
  100. package/libx/_runtime/hana/search2cqn4sql.js +1 -0
  101. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  102. package/libx/_runtime/messaging/service.js +11 -6
  103. package/libx/_runtime/remote/utils/data.js +5 -0
  104. package/libx/_runtime/sqlite/Service.js +0 -1
  105. package/libx/odata/afterburner.js +79 -2
  106. package/libx/odata/cqn2odata.js +9 -7
  107. package/libx/odata/grammar.pegjs +157 -76
  108. package/libx/odata/index.js +9 -3
  109. package/libx/odata/parser.js +1 -1
  110. package/libx/odata/utils.js +39 -5
  111. package/libx/rest/RestAdapter.js +1 -2
  112. package/libx/rest/middleware/delete.js +4 -5
  113. package/libx/rest/middleware/parse.js +3 -2
  114. package/package.json +3 -3
  115. package/server.js +1 -1
  116. package/srv/extensibility-service.cds +6 -3
  117. package/srv/model-provider.cds +3 -1
  118. package/srv/model-provider.js +84 -104
  119. package/srv/mtx.js +7 -1
  120. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +0 -240
package/CHANGELOG.md CHANGED
@@ -4,6 +4,115 @@
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.0 - 2022-08-10
8
+
9
+ ### Added
10
+
11
+ - Detailed information about pool state: `borrowed`, `pending`, `size`, `available`, `max` to the timeout error
12
+ - 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
13
+ - Odata v2 payloads for `cds.Integer` are converted to String if not provided as String
14
+ - New OData parser supports aliased parameters e.g. `...function(ID=@p)?@p=5`
15
+ - Support for locale "en_US_x_saprigi"
16
+ - Parameter `rows` in ql API function `limit` can be omitted for remote services, e.g. `SELECT.limit(undefined, 5)`
17
+ - New OData parser supports $filter with "in" operator, e.g. `$filter=ID in (1,2,3)`
18
+ - `cds build` copies `package.json` and `.cdsrc.json` into _main folder of MTX sidecar app.
19
+ - New OData parser supports null parameter in function/action, e.g `/findBooks(author=1,title=null)`
20
+ - New enviroment variable `schemas` contains locations for json schemas validating `package.json`, `.cdsrc.json` and `.cdsrc-private.json` in VS Code
21
+ - `cds.test` can now listen on a fixed port by way of additional arguments '--port', '<PORT_NUMBER>
22
+ - `cds.requires.db.kind = 'sql-mt'` is introduced as a shorthand for
23
+ ```js
24
+ "db": {
25
+ "kind": "sqlite",
26
+ "[production]": {
27
+ "kind": "hana-mt"
28
+ }
29
+ }
30
+ ```
31
+ - `cds build` support for Streamlined MTX extension projects based on build task `mtx-extension`
32
+ - TS definitions for `SELECT.forSharedLock` and `SELECT.forUpdate`
33
+ - TS definitions for `log`
34
+ - Support for new cds build task option `deploy-format`. Java apps may use this option instead of the corresponding global CDS config option.
35
+ - The `ExtensibilityService` serves an endpoint to retrieve a subdomain-specific JWT, which is used by `cds login`
36
+ - The endpoint `/-/cds/extensibility/push` now checks restrictions for new extensions. The configuration is added to the `cds.xt.ExtensibilityService`
37
+ ```js
38
+ "requires": {
39
+ "cds.xt.ExtensibilityService": {
40
+ "element-prefix": ["Z_", "ZZ_"],
41
+ "namespace-blocklist": ["com.sap.", "sap."],
42
+ "extension-allowlist": [
43
+ {
44
+ "for": ["my.bookshop"],
45
+ "kind": "entity",
46
+ "new-fields": 2
47
+ },
48
+ {
49
+ "for": ["CatalogService"],
50
+ "new-entities": 2
51
+ }
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+ - `cds build` validates required service models `@sap/**` for MTX sidecar app and logs an ERROR if some couldn't be resolved.
57
+ - Configuration schema for many properties of the `cds` configuration block in `package.json` or `.cdsrc.json`, especially for `cds.requires...`
58
+
59
+ ### Changed
60
+
61
+ - Streamlined calculation of the difference for `DELETE` queries using `req.diff()`
62
+ - Improved error messages for rest / new odata parser
63
+ - Adjust types for `SELECT.from` and `SELECT.one` to accept array classes as well
64
+ - No `"` added around search values in OData v2 e.g. Foo?search=name is passed through as is
65
+ - If an entity can not be read after write (e.g. insert only entity) no error is shown in the log
66
+ - Throw not supported error for pagination in `$expand`
67
+
68
+ ### Fixed
69
+
70
+ - Wrong context in `tx.run(query)` when `query` is an array
71
+ - We now detect and ignore erroneous attempts to re-register framework-generated stubs as handlers for custom actions/functions.
72
+ - Emits with `persistent-outbox` also work with manual transactions
73
+ - You can now use `cds.ql` fluent API to query tables not in the model, but in database.
74
+ For example, within `cap/samples/bookshop` this works now:
75
+ ```sql
76
+ await SELECT.from('sqlite_master')
77
+ await cds.read('sqlite_master')
78
+ ```
79
+ Caveat: the following undocumented usage of unqualified names happened to work in the past.
80
+ But this was very fragile and caused lots of issues, and therefore was removed:
81
+ ```sql
82
+ await SELECT.from('Books')
83
+ await cds.read('Books')
84
+ ```
85
+ Always use qualified names, or reflected definitions instead:
86
+ ```sql
87
+ const Books = 'sap.capire.bookshop.Books'
88
+ await SELECT.from(Books)
89
+ await cds.read(Books)
90
+ ```
91
+ ```sql
92
+ const {Books} = cds.entities ('sap.capire.bookshop')
93
+ await SELECT.from(Books)
94
+ await cds.read(Books)
95
+ ```
96
+ - Wrong results for expand to many without `orderBy`
97
+ - `cds deploy` api endpoint regex for cli now ignores trailing version info in url
98
+ - Default values no longer overwrite payload values on fields of new drafts
99
+ - Unmanaged to-one navigation caused malformed SQL statement in draft
100
+ - `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`
101
+ - Data type conversion did not work in some expand cases
102
+ - Failed connection to SAP HANA with no or malformed credentials was leading to credentials being written to the log
103
+ - `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`
104
+ - Tar issue on Windows: 'The command line is too long'.
105
+ - `$search`: Lifecycle issue that causes an empty search result when the `$search` and `$expand` query options were combined
106
+ - Operator `IN` with Tagged Template String Literals e.g.:
107
+ ```sql
108
+ SELECT.from(Object).where`userId IN ${aUserIDs}`
109
+ ```
110
+ - `cds build` now uses a closed version range in the node engines version of the deployed application's `package.json`
111
+ - `cds build` no longer generates EDMX files for services that aren't odata protocol enabled
112
+ - `cds deploy` handles orgs and spaces containing commas correctly
113
+ - Incorrect decoding of special characters when reading data of type `cds.LargeString` from SAP HANA using `hdb@^0.19.5` driver
114
+ - The payload is added to the delete request in rest adapter as req.data
115
+
7
116
  ## Version 6.0.4 - 2022-07-20
8
117
 
9
118
  ### Fixed
@@ -38,17 +147,18 @@
38
147
  ## Version 6.0.1 - 2022-07-05
39
148
 
40
149
  ### Added
150
+
41
151
  - Config option `cds.env.server.port` allows to configure the port to use (in addition to `process.env.PORT` and CLI option `--port`)
42
152
 
153
+ ### Changed
154
+
155
+ - Plugins cannot be loaded as ES modules, but need to remain CommonJS modules
156
+
43
157
  ### Fixed
44
158
 
45
159
  - Removed debug log about shutdown from `cds serve`
46
160
  - Hiding timeout error in production mode
47
161
 
48
- ### Changed
49
-
50
- - Plugins cannot be loaded as ES modules, but need to remain CommonJS modules
51
-
52
162
  ## Version 6.0.0 - 2022-06-30
53
163
 
54
164
  ### Added
@@ -95,7 +205,7 @@
95
205
  - Support for `FOR SHARE LOCK` on SAP HANA to acquire shared locks on the queried records so that the locked records
96
206
  stay intact until the transaction is committed or rolled back.
97
207
  - Consistent error information for remote batch requests
98
- - `cds.env` now supports expanding scalar `cds.requires` entries from `cds.requires.kinds`as follows:
208
+ - `cds.env` now supports expanding scalar `cds.requires` entries from `cds.requires.kinds` as follows:
99
209
  ```jsonc
100
210
  { "cds": {
101
211
  "requires": {
@@ -114,23 +224,23 @@ stay intact until the transaction is committed or rolled back.
114
224
  - Ordering by aggregated value for draft-enabled active entity
115
225
  - `cds build` support for model provider service-based resource deployment.
116
226
  - Remote service:
117
- - Conversion of OData V2 (`"kind": "odata-v2"`) function and action results to OData V4 format
118
- - Conversion of binary data in CQN queries to `base64url` in URL and payload
119
- - Key predicate is omitted for single-key entities in resulting URL (e.g. `GET /Foo(1)` instead of `GET /Foo(ID=1)`)
120
- - Support of views with parameters
227
+ + Conversion of OData V2 (`"kind": "odata-v2"`) function and action results to OData V4 format
228
+ + Conversion of binary data in CQN queries to `base64url` in URL and payload
229
+ + Key predicate is omitted for single-key entities in resulting URL (e.g. `GET /Foo(1)` instead of `GET /Foo(ID=1)`)
230
+ + Support of views with parameters
121
231
  - Add `@odata.mediaContentType` if selecting stream property
122
232
  - Kubernetes service bindings: Support for servicebinding.io and SAP BTP Service Operator based bindings
123
233
  - `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`.
124
234
  - `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`.
125
235
  - Beta OData URL to CQN parser (`cds.env.features.odata_new_parser = true`):
126
- - `@odata.context` is derived without using okra, not yet supported:
127
- - `$expand=*` query option
128
- - Support for actions and functions
129
- - Further `$apply` transformations supported
130
- - (nested) `concat` transformations
131
- - `orderBy` transformation
132
- - `top` & `skip` transformation
133
- - `identity` transformation
236
+ + `@odata.context` is derived without using okra, not yet supported:
237
+ + `$expand=*` query option
238
+ + Support for actions and functions
239
+ + Further `$apply` transformations supported
240
+ + (nested) `concat` transformations
241
+ + `orderBy` transformation
242
+ + `top` & `skip` transformation
243
+ + `identity` transformation
134
244
  - Log `BEGIN`/`COMMIT`/`ROLLBACK` commands when using SAP HANA as the underlying database
135
245
  - Binary data in payload is validated to be RFC-4648 and OData ABNF conformed
136
246
  - Support multiple media (streaming) properties in one entity
@@ -140,7 +250,6 @@ stay intact until the transaction is committed or rolled back.
140
250
  - $filter in $expand for remote services
141
251
  - Mapping of aliases in $expand for remote services
142
252
 
143
-
144
253
  ### Changed
145
254
 
146
255
  - `@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.
@@ -194,6 +303,7 @@ Note that this is a breaking change for appliations that rely on error sanitizat
194
303
 
195
304
  ### Fixed
196
305
 
306
+ - We don't rely on `global.cds` anymore -> allows to load and correctly work with multiple versions of `cds`
197
307
  - Improved shutdown for AMQP connections and file listeners
198
308
  - Using `CQL` with a tagged template string `SELECT from Foo { null as boo }` throwed an exception.
199
309
  - 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,48 @@
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
+ 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 const levels = {
45
+ SILENT: 0, ERROR: 1, WARN: 2, INFO: 3, DEBUG: 4, TRACE: 5, SILLY: 5, VERBOSE: 5
46
+ }
47
+
48
+ declare const { ERROR, WARN, INFO, DEBUG, TRACE } = levels
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,32 +94,6 @@ 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
@@ -127,10 +108,10 @@ class FeatureToggleBuilder extends BuildTaskHandlerInternal {
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('../..', srvFolder, DEFAULT_CSN_FILE_NAME)]
131
112
 
132
113
  const ftPath = path.join(destFts, this.ftsName, ftName)
133
- await this.compileToJson(ftCsn, ftPath, false)
114
+ await this.compileToJson(ftCsn, path.join(ftPath, DEFAULT_CSN_FILE_NAME))
134
115
  await this._validateFeature(ftPath)
135
116
  features[ftName] = ftCsn
136
117
  }