@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.
- package/CHANGELOG.md +165 -18
- package/apis/cds.d.ts +11 -7
- package/apis/log.d.ts +46 -0
- package/apis/ql.d.ts +72 -15
- package/bin/build/buildTaskHandler.js +5 -2
- package/bin/build/constants.js +4 -1
- package/bin/build/provider/buildTaskHandlerEdmx.js +11 -39
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +14 -34
- package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
- package/bin/build/provider/buildTaskProviderInternal.js +22 -14
- package/bin/build/provider/hana/index.js +12 -9
- package/bin/build/provider/java/index.js +18 -8
- package/bin/build/provider/mtx/index.js +7 -4
- package/bin/build/provider/mtx/resourcesTarBuilder.js +60 -35
- package/bin/build/provider/mtx-extension/index.js +57 -0
- package/bin/build/provider/mtx-sidecar/index.js +46 -18
- package/bin/build/provider/nodejs/index.js +34 -13
- package/bin/deploy/to-hana/cfUtil.js +7 -2
- package/bin/deploy/to-hana/hana.js +20 -25
- package/bin/deploy/to-hana/hdiDeployUtil.js +13 -2
- package/bin/serve.js +7 -4
- package/lib/compile/{index.js → cds-compile.js} +0 -0
- package/lib/compile/extend.js +15 -5
- package/lib/compile/minify.js +1 -15
- package/lib/compile/parse.js +1 -1
- package/lib/compile/resolve.js +2 -2
- package/lib/compile/to/srvinfo.js +6 -4
- package/lib/{deploy.js → dbs/cds-deploy.js} +9 -8
- package/lib/env/{index.js → cds-env.js} +1 -17
- package/lib/env/{requires.js → cds-requires.js} +24 -3
- package/lib/env/defaults.js +7 -1
- package/lib/env/schemas/cds-package.json +11 -0
- package/lib/env/schemas/cds-rc.json +614 -0
- package/lib/index.js +19 -16
- package/lib/log/{errors.js → cds-error.js} +1 -1
- package/lib/log/{index.js → cds-log.js} +0 -0
- package/lib/ql/Query.js +9 -3
- package/lib/ql/SELECT.js +2 -2
- package/lib/ql/{index.js → cds-ql.js} +0 -9
- package/lib/req/context.js +49 -17
- package/lib/req/locale.js +5 -1
- package/lib/{serve → srv}/adapters.js +23 -19
- package/lib/{connect → srv}/bindings.js +0 -0
- package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
- package/lib/{serve/index.js → srv/cds-serve.js} +1 -1
- package/lib/{serve → srv}/factory.js +1 -1
- package/lib/{serve/Service-api.js → srv/srv-api.js} +22 -6
- package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +13 -8
- package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
- package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
- package/lib/srv/srv-models.js +207 -0
- package/lib/{serve/Transaction.js → srv/srv-tx.js} +57 -40
- package/lib/utils/{tests.js → cds-test.js} +2 -2
- package/lib/utils/cds-utils.js +146 -0
- package/lib/utils/index.js +2 -145
- package/lib/utils/jest.js +43 -0
- package/lib/utils/resources/index.js +15 -25
- package/lib/utils/resources/tar.js +18 -41
- package/libx/_runtime/auth/index.js +14 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +7 -19
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +0 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +3 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -3
- package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
- package/libx/_runtime/cds-services/util/errors.js +1 -29
- package/libx/_runtime/common/i18n/messages.properties +2 -1
- package/libx/_runtime/common/perf/index.js +10 -15
- package/libx/_runtime/common/utils/binary.js +3 -4
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
- package/libx/_runtime/common/utils/resolveView.js +1 -1
- package/libx/_runtime/common/utils/template.js +1 -1
- package/libx/_runtime/db/Service.js +2 -14
- package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
- package/libx/_runtime/db/expand/rawToExpanded.js +7 -6
- package/libx/_runtime/db/generic/input.js +8 -1
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
- package/libx/_runtime/extensibility/activate.js +47 -47
- package/libx/_runtime/extensibility/add.js +22 -13
- package/libx/_runtime/extensibility/addExtension.js +17 -13
- package/libx/_runtime/extensibility/defaults.js +25 -30
- package/libx/_runtime/extensibility/handler/transformREAD.js +20 -18
- package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
- package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
- package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
- package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
- package/libx/_runtime/extensibility/linter.js +32 -0
- package/libx/_runtime/extensibility/push.js +77 -20
- package/libx/_runtime/extensibility/service.js +29 -12
- package/libx/_runtime/extensibility/token.js +56 -0
- package/libx/_runtime/extensibility/utils.js +8 -6
- package/libx/_runtime/extensibility/validation.js +6 -9
- package/libx/_runtime/fiori/generic/new.js +0 -11
- package/libx/_runtime/hana/Service.js +0 -1
- package/libx/_runtime/hana/conversion.js +12 -1
- package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
- package/libx/_runtime/hana/pool.js +6 -10
- package/libx/_runtime/hana/search2Contains.js +0 -5
- package/libx/_runtime/hana/search2cqn4sql.js +1 -0
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/messaging/service.js +11 -6
- package/libx/_runtime/remote/utils/data.js +5 -0
- package/libx/_runtime/sqlite/Service.js +7 -6
- package/libx/_runtime/sqlite/execute.js +41 -28
- package/libx/odata/afterburner.js +79 -2
- package/libx/odata/cqn2odata.js +9 -7
- package/libx/odata/grammar.pegjs +157 -76
- package/libx/odata/index.js +9 -3
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +39 -5
- package/libx/rest/RestAdapter.js +3 -7
- package/libx/rest/middleware/delete.js +4 -5
- package/libx/rest/middleware/parse.js +3 -2
- package/package.json +3 -3
- package/server.js +1 -1
- package/srv/extensibility-service.cds +6 -3
- package/srv/model-provider.cds +3 -1
- package/srv/model-provider.js +84 -104
- package/srv/mtx.js +7 -1
- 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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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 :
|
|
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? :
|
|
34
|
-
byKey (primaryKey? :
|
|
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? :
|
|
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 :
|
|
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 :
|
|
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
|
-
|
|
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 :
|
|
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? :
|
|
80
|
-
byKey (primaryKey? :
|
|
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? :
|
|
90
|
-
static entity <T> (entity:Constructable<T>, primaryKey? :
|
|
91
|
-
static entity <T> (entity:T, primaryKey? :
|
|
92
|
-
byKey (primaryKey? :
|
|
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
|
|
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
|
package/bin/build/constants.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
50
|
-
|
|
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 {
|
|
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)
|
|
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(
|
|
111
|
+
ftCsn.requires = [path.join(path.relative(ftPath, destBase), DEFAULT_CSN_FILE_NAME).replace(/\\/g,'/')]
|
|
131
112
|
|
|
132
|
-
|
|
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
|
}
|