@sap/cds 7.8.2 → 7.9.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 +45 -0
- package/_i18n/i18n_ar.properties +3 -0
- package/_i18n/i18n_cs.properties +3 -0
- package/_i18n/i18n_da.properties +3 -0
- package/_i18n/i18n_es_MX.properties +3 -0
- package/_i18n/i18n_fi.properties +3 -0
- package/_i18n/i18n_hu.properties +6 -0
- package/_i18n/i18n_ko.properties +3 -0
- package/_i18n/i18n_ms.properties +3 -0
- package/_i18n/i18n_nl.properties +3 -0
- package/_i18n/i18n_no.properties +3 -0
- package/_i18n/i18n_ro.properties +3 -0
- package/_i18n/i18n_sv.properties +3 -0
- package/_i18n/i18n_th.properties +3 -0
- package/_i18n/i18n_tr.properties +6 -0
- package/_i18n/i18n_zh_TW.properties +3 -0
- package/bin/serve.js +5 -5
- package/lib/auth/basic-auth.js +1 -1
- package/lib/compile/cdsc.js +33 -6
- package/lib/compile/etc/_localized.js +14 -7
- package/lib/compile/for/lean_drafts.js +9 -0
- package/lib/compile/to/edm-files.js +116 -0
- package/lib/compile/to/edm.js +8 -1
- package/lib/compile/to/hdbtabledata.js +3 -3
- package/lib/compile/to/sql.js +4 -2
- package/lib/compile/to/srvinfo.js +6 -5
- package/lib/compile/to/yaml.js +22 -21
- package/lib/dbs/cds-deploy.js +5 -6
- package/lib/env/cds-env.js +7 -0
- package/lib/env/cds-requires.js +20 -1
- package/lib/env/defaults.js +21 -5
- package/lib/env/schemas/cds-package.js +1 -1
- package/lib/env/schemas/cds-rc.js +85 -4
- package/lib/index.js +1 -1
- package/lib/linked/entities.js +10 -0
- package/lib/linked/models.js +1 -1
- package/lib/plugins.js +1 -1
- package/lib/ql/INSERT.js +17 -3
- package/lib/ql/Query.js +4 -0
- package/lib/ql/infer.js +1 -1
- package/lib/req/request.js +1 -1
- package/lib/srv/cds-serve.js +1 -0
- package/lib/srv/middlewares/cds-context.js +1 -1
- package/lib/srv/protocols/odata-v4.js +5 -6
- package/lib/srv/srv-models.js +9 -2
- package/lib/utils/cds-test.js +2 -0
- package/lib/utils/cds-utils.js +9 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +3 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +22 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +4 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +4 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +38 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +32 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +1 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +0 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +3 -1
- package/libx/_runtime/cds-services/services/utils/compareJson.js +2 -274
- package/libx/_runtime/{cds-services/services → common}/Service.js +39 -29
- package/libx/_runtime/common/generic/auth/autoexpose.js +41 -0
- package/libx/_runtime/common/generic/auth/index.js +2 -0
- package/libx/_runtime/common/generic/auth/readOnly.js +0 -11
- package/libx/_runtime/common/generic/auth/restrict.js +6 -5
- package/libx/_runtime/common/generic/auth/utils.js +1 -1
- package/libx/_runtime/common/generic/crud.js +5 -8
- package/libx/_runtime/common/generic/etag.js +8 -6
- package/libx/_runtime/common/generic/sorting.js +2 -2
- package/libx/_runtime/common/i18n/messages.properties +1 -0
- package/libx/_runtime/{cds-services/services → common}/utils/columns.js +4 -4
- package/libx/_runtime/common/utils/compareJson.js +274 -0
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +1 -1
- package/libx/_runtime/{cds-services/services → common}/utils/differ.js +8 -8
- package/libx/_runtime/common/utils/ensureIEEE754.js +29 -0
- package/libx/_runtime/common/utils/{postProcessing.js → postProcess.js} +1 -3
- package/libx/_runtime/common/utils/resolveView.js +0 -16
- package/libx/_runtime/common/utils/rewriteAsterisks.js +1 -1
- package/libx/_runtime/common/utils/search2cqn4sql.js +1 -1
- package/libx/_runtime/common/utils/streamProp.js +9 -2
- package/libx/_runtime/common/utils/ucsn.js +1 -1
- package/libx/_runtime/db/expand/expandCQNToJoin.js +5 -3
- package/libx/_runtime/db/generic/rewrite.js +7 -13
- package/libx/_runtime/fiori/generic/activate.js +1 -1
- package/libx/_runtime/fiori/generic/edit.js +1 -1
- package/libx/_runtime/fiori/generic/prepare.js +1 -1
- package/libx/_runtime/fiori/lean-draft.js +151 -46
- package/libx/_runtime/fiori/utils/handler.js +1 -1
- package/libx/_runtime/hana/execute.js +6 -2
- package/libx/_runtime/hana/pool.js +3 -0
- package/libx/_runtime/hana/search2cqn4sql.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -2
- package/libx/_runtime/messaging/event-broker.js +212 -0
- package/libx/_runtime/remote/Service.js +9 -32
- package/libx/_runtime/remote/utils/client.js +13 -21
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +7 -1
- package/libx/_runtime/sqlite/execute.js +8 -3
- package/libx/_runtime/ucl/Service.js +259 -0
- package/libx/common/assert/index.js +5 -11
- package/libx/common/assert/validation.js +6 -1
- package/libx/odata/index.js +47 -25
- package/libx/odata/middleware/batch.js +8 -7
- package/libx/odata/middleware/create.js +42 -16
- package/libx/odata/middleware/delete.js +18 -11
- package/libx/odata/middleware/metadata.js +15 -14
- package/libx/odata/middleware/operation.js +30 -40
- package/libx/odata/middleware/parse.js +2 -3
- package/libx/odata/middleware/read.js +59 -52
- package/libx/odata/middleware/service-document.js +7 -7
- package/libx/odata/middleware/stream.js +26 -24
- package/libx/odata/middleware/update.js +53 -92
- package/libx/odata/parse/afterburner.js +45 -47
- package/libx/odata/parse/grammar.peggy +3 -3
- package/libx/odata/parse/multipartToJson.js +10 -22
- package/libx/odata/parse/parser.js +1 -1
- package/libx/odata/utils/etag.js +13 -0
- package/libx/odata/utils/handler.js +120 -0
- package/libx/odata/utils/index.js +15 -2
- package/libx/odata/utils/metaInfo.js +410 -0
- package/libx/odata/utils/path.js +5 -2
- package/libx/odata/utils/readAfterWrite.js +23 -0
- package/libx/odata/utils/result.js +4 -5
- package/libx/rest/RestAdapter.js +4 -13
- package/libx/rest/middleware/parse.js +40 -7
- package/package.json +1 -1
- package/server.js +1 -0
- package/libx/_runtime/cds-services/util/dataProcessUtils.js +0 -93
- package/libx/_runtime/common/utils/thenable.js +0 -51
- package/libx/_runtime/rest/service.js +0 -2
- package/libx/odata/parse/parseToCqn.js +0 -39
- package/libx/rest/middleware/input.js +0 -54
- package/libx/rest/middleware/payload.js +0 -13
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,51 @@
|
|
|
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 7.9.1 - 2024-05-13
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `cds.compile.to.sql` doesn't fail for older compiler versions if `postgres` keywords aren't defined
|
|
12
|
+
- `cds compile --to serviceinfo` no longer detects a Java project if there is a poml.xml file in a subfolder of `app/`
|
|
13
|
+
- `acquireTimeoutMillis` is ensured if custom pool config is provided
|
|
14
|
+
|
|
15
|
+
## Version 7.9.0 - 2024-04-30
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Option `cds.env.sql.transitive_localized_views: false` to skip generating transitive localized views for entities which don't have own localized elements, but only associations to such. Supported for Java and new database services in Node.js (ignored for old ones).
|
|
20
|
+
- Option `cds.env.sql.native_hana_associations: false` to skip generating native HANA associations.
|
|
21
|
+
- Running `cds compile --to sql` with `@cap-js/sqlite` installed now uses `session_context('$user.locale')` in generated DDL statements instead of generating static localized views for 'en', 'fr', and 'de' (same for `cds.deploy`).
|
|
22
|
+
- `api`: export reserved keywords for postgres via `cds.compiler.to.sql.keywords.postgres`
|
|
23
|
+
- Kind `legacy-hana` and profile `better-hana` for local testing scenarios.
|
|
24
|
+
- Support for PDF files (MIME type `application/pdf`) when the `cds.env.features.odata_new_adapter` flag is set to `true`
|
|
25
|
+
- Lean draft: Support for filtered compositions (remain in the document)
|
|
26
|
+
- Support for `COUNT_DISTINCT` as OData data aggregation default method
|
|
27
|
+
- Better support for `profiles` in cds schema for `package.json` and `.cdsrc.json`
|
|
28
|
+
- Performance improvement for generating `@odata.context` url if `cds.features.odata_new_parser` is enabled
|
|
29
|
+
- Alpha support for SAP Event Broker-based messaging (kind `event-broker`)
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Deprecated *INSERT.into(...) **.as** (SELECT...)* → use *INSERT.into(...) **.entries** (SELECT...)* instead.
|
|
34
|
+
- Default value of `cds.env.log.mask_headers` changed to `['/authorization/i', '/cookie/i', '/cert/i', '/ssl/i']` (adding `'/cert/i'` and `'/ssl/i'`)
|
|
35
|
+
- Error messages for entities annotated with '@cds.autoexpose'
|
|
36
|
+
- For Java apps `cds.sql.transitive_localized_views` now defaults to `false` to create less database views.
|
|
37
|
+
- For Java apps `cdsc.betterSqliteSessionVariables` now defaults to `true` to enable session variables on H2 and SQLite by default.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- `cds.compile.to.yaml` produced invalid YAML for compacted lines
|
|
42
|
+
- Handling of If-None-Match header for non-existing entity
|
|
43
|
+
- Revert json schema for cds schemas to `draft-07` to prevent VS Code warnings about unsupported schema features.
|
|
44
|
+
- Remote services: JSON representation of error shall include `request` and `response`
|
|
45
|
+
- Aliasing of associated entity column in case of expand by CQN build with joins.
|
|
46
|
+
- `$apply` scenarios when used alongside `cds.env.features.odata_new_adapter = true` and the new database layer
|
|
47
|
+
- ETag handling combined with where restrictions
|
|
48
|
+
- `cds compile --to hdbtabledata` now correctly supports CSV files using format `.texts_<lang>.csv`. Before the `include_filter` wasn't set in the generated `.hdbtabledata` files.
|
|
49
|
+
- `cds` commands no longer crash when executed in the `@sap/cds` installation dir.
|
|
50
|
+
- `cds.infer`: exposed association of query is inferred as `cds.Association` and not as it's target
|
|
51
|
+
|
|
7
52
|
## Version 7.8.2 - 2024-04-22
|
|
8
53
|
|
|
9
54
|
### Fixed
|
package/_i18n/i18n_ar.properties
CHANGED
|
@@ -70,6 +70,9 @@ LanguageCode=\u0631\u0645\u0632 \u0627\u0644\u0644\u063A\u0629
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=\u0631\u0645\u0632 \u0627\u0644\u062F\u0648\u0644\u0629 \u0627\u0644\u0645\u062D\u062F\u062F \u062D\u0633\u0628 ISO 639-1
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=\u0631\u0645\u0632 \u0627\u0644\u0645\u0646\u0637\u0642\u0629 \u0627\u0644\u0632\u0645\u0646\u064A\u0629
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=\u0645\u0639\u0631\u0641 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645
|
|
75
78
|
|
package/_i18n/i18n_cs.properties
CHANGED
|
@@ -70,6 +70,9 @@ LanguageCode=K\u00F3d jazyka
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=K\u00F3d jazyka zadan\u00FD dle ISO 639-1
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=K\u00F3d \u010Dasov\u00E9ho p\u00E1sma
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=ID u\u017Eivatele
|
|
75
78
|
|
package/_i18n/i18n_da.properties
CHANGED
|
@@ -70,6 +70,9 @@ LanguageCode=C\u00F3digo de idioma
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=C\u00F3digo de idioma seg\u00FAn especificado por ISO 639-1
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=C\u00F3digo de zona horaria
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=ID de usuario
|
|
75
78
|
|
package/_i18n/i18n_fi.properties
CHANGED
package/_i18n/i18n_hu.properties
CHANGED
|
@@ -49,6 +49,9 @@ CurrencyCode.Description=P\u00E9nznem k\u00F3dja ISO 4217 szerint
|
|
|
49
49
|
#XTIT: Currency Symbol
|
|
50
50
|
CurrencySymbol=P\u00E9nznem szimb\u00F3luma
|
|
51
51
|
|
|
52
|
+
#XTIT: Currency Minor Unit Fractions (Answer to: "How many fractions has a currency's minor unit?", e.g. "0" or "2")
|
|
53
|
+
CurrencyMinorUnit=P\u00E9nznem seg\u00E9degys\u00E9g-h\u00E1nyadok
|
|
54
|
+
|
|
52
55
|
#XTIT: Country/Region
|
|
53
56
|
Country=Orsz\u00E1g/r\u00E9gi\u00F3
|
|
54
57
|
|
|
@@ -67,6 +70,9 @@ LanguageCode=Nyelvk\u00F3d
|
|
|
67
70
|
#XTIT: Language Code Description
|
|
68
71
|
LanguageCode.Description=P\u00E9nznem k\u00F3dja ISO 639-1 szerint
|
|
69
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=Id\u0151z\u00F3na k\u00F3dja
|
|
75
|
+
|
|
70
76
|
#XTIT: User Identifier
|
|
71
77
|
UserID=Felhaszn\u00E1l\u00F3azonos\u00EDt\u00F3
|
|
72
78
|
|
package/_i18n/i18n_ko.properties
CHANGED
|
@@ -70,6 +70,9 @@ LanguageCode=\uC5B8\uC5B4 \uCF54\uB4DC
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=ISO 639-1\uC5D0\uC11C \uC9C0\uC815\uD55C \uC5B8\uC5B4 \uCF54\uB4DC
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=\uC2DC\uAC04\uB300 \uCF54\uB4DC
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=\uC0AC\uC6A9\uC790 ID
|
|
75
78
|
|
package/_i18n/i18n_ms.properties
CHANGED
package/_i18n/i18n_nl.properties
CHANGED
package/_i18n/i18n_no.properties
CHANGED
package/_i18n/i18n_ro.properties
CHANGED
|
@@ -70,6 +70,9 @@ LanguageCode=Cod de limb\u0103
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=Cod de limb\u0103 a\u0219a cum este specificat de ISO 639-1
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=Cod fus orar
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=ID utilizator
|
|
75
78
|
|
package/_i18n/i18n_sv.properties
CHANGED
package/_i18n/i18n_th.properties
CHANGED
|
@@ -70,6 +70,9 @@ LanguageCode=\u0E23\u0E2B\u0E31\u0E2A\u0E20\u0E32\u0E29\u0E32
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=\u0E23\u0E2B\u0E31\u0E2A\u0E20\u0E32\u0E29\u0E32\u0E15\u0E32\u0E21\u0E17\u0E35\u0E48\u0E23\u0E30\u0E1A\u0E38\u0E43\u0E19 ISO 639-1
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=\u0E23\u0E2B\u0E31\u0E2A\u0E40\u0E02\u0E15\u0E40\u0E27\u0E25\u0E32
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=ID \u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49
|
|
75
78
|
|
package/_i18n/i18n_tr.properties
CHANGED
|
@@ -49,6 +49,9 @@ CurrencyCode.Description=ISO 4217'ye g\u00F6re belirtilen para birimi kodu
|
|
|
49
49
|
#XTIT: Currency Symbol
|
|
50
50
|
CurrencySymbol=Para birimi sembol\u00FC
|
|
51
51
|
|
|
52
|
+
#XTIT: Currency Minor Unit Fractions (Answer to: "How many fractions has a currency's minor unit?", e.g. "0" or "2")
|
|
53
|
+
CurrencyMinorUnit=Para biriminin k\u00FC\u00E7\u00FCk birim kesirleri
|
|
54
|
+
|
|
52
55
|
#XTIT: Country/Region
|
|
53
56
|
Country=\u00DClke/b\u00F6lge
|
|
54
57
|
|
|
@@ -67,6 +70,9 @@ LanguageCode=Dil kodu
|
|
|
67
70
|
#XTIT: Language Code Description
|
|
68
71
|
LanguageCode.Description=ISO 639-1'e g\u00F6re belirtilen dil kodu
|
|
69
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=Saat dilimi kodu
|
|
75
|
+
|
|
70
76
|
#XTIT: User Identifier
|
|
71
77
|
UserID=Kullan\u0131c\u0131 tan\u0131t\u0131c\u0131s\u0131
|
|
72
78
|
|
|
@@ -70,6 +70,9 @@ LanguageCode=\u8A9E\u8A00\u4EE3\u78BC
|
|
|
70
70
|
#XTIT: Language Code Description
|
|
71
71
|
LanguageCode.Description=\u5DF2\u6309 ISO 639-1 \u6307\u5B9A\u516C\u53F8\u4EE3\u78BC
|
|
72
72
|
|
|
73
|
+
#XTIT Time zone code
|
|
74
|
+
TimeZoneCode=\u6642\u5340\u4EE3\u78BC
|
|
75
|
+
|
|
73
76
|
#XTIT: User Identifier
|
|
74
77
|
UserID=\u4F7F\u7528\u8005 ID
|
|
75
78
|
|
package/bin/serve.js
CHANGED
|
@@ -300,26 +300,26 @@ function _prepare_logging () { // NOSONAR
|
|
|
300
300
|
// print config deprecation warnings
|
|
301
301
|
if (cds.env.features.deprecated !== 'off') {
|
|
302
302
|
cds.once ('listening', () => {
|
|
303
|
-
// Remove with cds
|
|
303
|
+
// Remove with cds^8
|
|
304
304
|
if (cds.env.drafts?.cancellationTimeout)
|
|
305
305
|
cds.utils.deprecated({
|
|
306
306
|
old: 'cds.drafts.cancellationTimeout',
|
|
307
307
|
use: 'cds.fiori.draft_lock_timeout with adapted value'
|
|
308
308
|
})
|
|
309
309
|
|
|
310
|
-
// Remove with cds
|
|
310
|
+
// Remove with cds^8
|
|
311
311
|
if (!cds.env.fiori.lean_draft)
|
|
312
312
|
cds.utils.deprecated({ old: 'cds.fiori.lean_draft' })
|
|
313
313
|
|
|
314
|
-
// Remove with cds
|
|
314
|
+
// Remove with cds^8
|
|
315
315
|
if (!cds.requires.middlewares)
|
|
316
316
|
cds.utils.deprecated({ old: 'cds.requires.middlewares' })
|
|
317
317
|
|
|
318
|
-
// Remove with cds
|
|
318
|
+
// Remove with cds^8
|
|
319
319
|
if (cds.env.features.serve_on_root)
|
|
320
320
|
cds.utils.deprecated({ old: 'cds.features.serve_on_root', use: '@path annotation or adapt your consumers' })
|
|
321
321
|
|
|
322
|
-
// Remove with cds
|
|
322
|
+
// Remove with cds^8
|
|
323
323
|
if (cds.env.features.stream_compat)
|
|
324
324
|
cds.utils.deprecated({ old: 'cds.features.stream_compat' })
|
|
325
325
|
})
|
package/lib/auth/basic-auth.js
CHANGED
|
@@ -31,7 +31,7 @@ module.exports = function basic_auth (options) {
|
|
|
31
31
|
function login (reason='') {
|
|
32
32
|
const req=this, res=req.res
|
|
33
33
|
// REVISIT: this json response is needed to be OData compliant. however, we should probably throw an error anyway so that a custom error middleware can get invoked.
|
|
34
|
-
res.set('
|
|
34
|
+
res.set('www-authenticate', `Basic realm="Users"`).status(401).json({ error: { code: '401', message: 'Unauthorized' } })
|
|
35
35
|
LOG.info (req.method, decodeURIComponent(req.path), '>', res.statusCode, res.statusMessage, ...(!reason ? [] : ['-', reason]))
|
|
36
36
|
}
|
|
37
37
|
}
|
package/lib/compile/cdsc.js
CHANGED
|
@@ -61,21 +61,48 @@ const _options = {for: Object.assign (_options4, {
|
|
|
61
61
|
})
|
|
62
62
|
},
|
|
63
63
|
|
|
64
|
-
sql(
|
|
64
|
+
sql (_o, _env, _conf = cds.requires.db || cds.requires.kinds.sql) {
|
|
65
65
|
// REVISIT: compiler requires to only provide assertIntegrityType if defined
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return _options4 ({ ...constraints, ..._env||cds.env.sql, ...o }, {
|
|
66
|
+
if (_o?._4sql) return _o
|
|
67
|
+
const o = _options4 ({ ..._env||cds.env.sql, ..._o, _4sql: true }, {
|
|
69
68
|
sql_mapping : 'names', //> legacy
|
|
70
69
|
sqlDialect : 'dialect', //> legacy
|
|
71
70
|
sqlMapping : 'names',
|
|
72
71
|
dialect : 'sqlDialect',
|
|
73
72
|
names : (o,v) => v !== 'plain' ? o.sqlMapping = v : undefined,
|
|
74
73
|
})
|
|
74
|
+
if (_conf?.impl === '@cap-js/sqlite') {
|
|
75
|
+
o.fewerLocalizedViews = !cds.env.sql.transitive_localized_views
|
|
76
|
+
o.betterSqliteSessionVariables = true
|
|
77
|
+
// REVISIT: compiler only considers o.betterSqliteSessionVariables if o.sqlDialect == 'sqlite'.
|
|
78
|
+
// Yet, dialect: 'plain' is configured in cap/sflight -> below is a dirty hack which overrides that.
|
|
79
|
+
// We should rather have a proper way to configure the dialect in the cap/sflight project, and/or
|
|
80
|
+
// have a better way to handle o.betterSqliteSessionVariables in compiler, independent of dialect.
|
|
81
|
+
if (!_o?.dialect && (!cds.env.sql.dialect || cds.env.sql.dialect === 'plain')) o.sqlDialect = 'sqlite'
|
|
82
|
+
}
|
|
83
|
+
else if (_conf?.impl === '@cap-js/hana') {
|
|
84
|
+
o.fewerLocalizedViews = !cds.env.sql.transitive_localized_views
|
|
85
|
+
o.withHanaAssociations = cds.env.sql.native_hana_associations
|
|
86
|
+
}
|
|
87
|
+
else if (!cds.db && !cds.requires.db) { // e.g. for Java
|
|
88
|
+
o.fewerLocalizedViews = !cds.env.sql.transitive_localized_views
|
|
89
|
+
o.withHanaAssociations = cds.env.sql.native_hana_associations
|
|
90
|
+
if (_conf?.impl === '@cap-js/sqlite') {
|
|
91
|
+
o.betterSqliteSessionVariables = true
|
|
92
|
+
// REVISIT: compiler only considers o.betterSqliteSessionVariables if o.sqlDialect == 'sqlite'.
|
|
93
|
+
// Yet, dialect: 'plain' is configured in cap/sflight -> below is a dirty hack which overrides that.
|
|
94
|
+
// We should rather have a proper way to configure the dialect in the cap/sflight project, and/or
|
|
95
|
+
// have a better way to handle o.betterSqliteSessionVariables in compiler, independent of dialect.
|
|
96
|
+
if (!_o?.dialect && (!cds.env.sql.dialect || cds.env.sql.dialect === 'plain')) o.sqlDialect = 'sqlite'
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// console.trace(o)
|
|
100
|
+
if (cds.env.features.assert_integrity) o.assertIntegrityType = cds.env.features.assert_integrity.toUpperCase()
|
|
101
|
+
return o
|
|
75
102
|
},
|
|
76
103
|
|
|
77
104
|
hana(o) {
|
|
78
|
-
let cdsc = this.sql (o, cds.env.hana) // returns clone
|
|
105
|
+
let cdsc = this.sql (o, cds.env.hana, cds.requires.kinds.hana) // returns clone
|
|
79
106
|
cdsc.sqlChangeMode ??= cdsc.journal && cdsc.journal['change-mode']
|
|
80
107
|
cdsc.disableHanaComments ??= !cdsc.comments
|
|
81
108
|
delete cdsc.journal // cleanup avoiding side effects
|
|
@@ -138,4 +165,4 @@ module.exports = exports = {__proto__:compile, _options,
|
|
|
138
165
|
compile.to.cdl // smart* functions
|
|
139
166
|
),
|
|
140
167
|
},
|
|
141
|
-
}
|
|
168
|
+
}
|
|
@@ -11,14 +11,15 @@ const _been_here = Symbol('is _localized')
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* In case of, for each localized_<view> we get from the
|
|
15
|
-
* create additional views localized_<locale>_<views>
|
|
14
|
+
* In case of old SQLite service, for each localized_<view> we get from the
|
|
15
|
+
* compiler, create additional views localized_<locale>_<views>
|
|
16
16
|
*/
|
|
17
17
|
function unfold_ddl (ddl, csn, o={}) { // NOSONAR
|
|
18
|
+
if (o.betterSqliteSessionVariables) return ddl
|
|
19
|
+
if (o.fewerLocalizedViews) return ddl
|
|
18
20
|
const _locales = _locales_4sql[o.dialect]; if (!_locales) return ddl
|
|
19
21
|
const localized_views = ddl.filter (each => each.startsWith('CREATE VIEW localized_') || each.startsWith('DROP VIEW localized_'))
|
|
20
22
|
// REVISIT: analyze ddl statements. Problem is with schevo calling this function containing only drops
|
|
21
|
-
if (o.sqlDialect === 'sqlite' && o.betterSqliteSessionVariables) return ddl
|
|
22
23
|
for (const localized_view of localized_views) {
|
|
23
24
|
for (const locale of _locales) ddl.push (localized_view
|
|
24
25
|
.replace (/localized_/g, `localized_${locale}_`)
|
|
@@ -45,9 +46,16 @@ function unfold_csn (m) { // NOSONAR
|
|
|
45
46
|
DEBUG && DEBUG ('unfolding csn...')
|
|
46
47
|
const pass2 = []
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
// REVISIT: Fixing $localized obtained from compiler when fewerLocalizedViews is set
|
|
50
|
+
const o = cds.compiler._options.for.sql()
|
|
51
|
+
if (o.fewerLocalizedViews) for (let each in m.definitions) {
|
|
52
|
+
const d = m.definitions [each]
|
|
53
|
+
if (d.$localized && d.elements && !d.elements.localized) delete d.$localized
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const _conf = env.requires.db || env.requires.sql || env.requires.kinds.sql
|
|
49
57
|
const _on_sqlite = _conf.kind === 'sqlite' || _conf.dialect === 'sqlite'
|
|
50
|
-
const _locales = _on_sqlite && _locales_4sql.sqlite
|
|
58
|
+
const _locales = !o.fewerLocalizedViews && !o.betterSqliteSessionVariables && _on_sqlite && _locales_4sql.sqlite
|
|
51
59
|
|
|
52
60
|
// Pass 1 - add localized.<locale> entities and views
|
|
53
61
|
for (const each in cds.linked(m).definitions) {
|
|
@@ -60,7 +68,6 @@ function unfold_csn (m) { // NOSONAR
|
|
|
60
68
|
if (_localized_entries !== false && _is_localized(d)) {
|
|
61
69
|
_add_proxy4 (d,`localized.${each}`, x => pass2.push([x]))
|
|
62
70
|
// if running on sqlite add additional localized.<locale>. views
|
|
63
|
-
if (_conf?.impl === '@cap-js/sqlite') continue
|
|
64
71
|
if (_locales) for (const locale of _locales) {
|
|
65
72
|
_add_proxy4 (d,`localized.${locale}.${each}`, x => pass2.push([x,locale]))
|
|
66
73
|
}
|
|
@@ -73,7 +80,7 @@ function unfold_csn (m) { // NOSONAR
|
|
|
73
80
|
for (const each in x.elements) {
|
|
74
81
|
const e = x.elements [each]
|
|
75
82
|
if (e._target && _is_localized(e._target)) {
|
|
76
|
-
const elements = overlayed
|
|
83
|
+
const elements = overlayed ??= x.elements = {__proto__:x.elements}
|
|
77
84
|
const target = locale ? `localized.${locale}.${e.target}` : `localized.${e.target}`
|
|
78
85
|
const _target = m.definitions[target]
|
|
79
86
|
if (_target) {
|
|
@@ -107,8 +107,16 @@ module.exports = function cds_compile_for_lean_drafts(csn) {
|
|
|
107
107
|
draft['@Capabilities.NavigationRestrictions.RestrictedProperties'] = undefined
|
|
108
108
|
|
|
109
109
|
// Recursively add drafts for compositions
|
|
110
|
+
let _2manies
|
|
110
111
|
for (const each in draft.elements) {
|
|
111
112
|
const e = draft.elements[each]
|
|
113
|
+
// add @odata.draft.enclosed to filtered compositions
|
|
114
|
+
if (e.$enclosed) {
|
|
115
|
+
e['@odata.draft.enclosed'] = true
|
|
116
|
+
} else if (e.$filtered) { //> REVISIT: remove with cds^8
|
|
117
|
+
_2manies ??= Object.keys(draft.elements).map(k => draft.elements[k]).filter(c => c.isComposition && c.is2many)
|
|
118
|
+
if (_2manies.find(c => c.name !== e.name && c.target.replace(/\.drafts$/, '') === e.target)) e['@odata.draft.enclosed'] = true
|
|
119
|
+
}
|
|
112
120
|
const newEl = Object.create(e)
|
|
113
121
|
if (
|
|
114
122
|
e.isComposition ||
|
|
@@ -135,6 +143,7 @@ module.exports = function cds_compile_for_lean_drafts(csn) {
|
|
|
135
143
|
|
|
136
144
|
draft.elements[each] = newEl
|
|
137
145
|
}
|
|
146
|
+
|
|
138
147
|
return draft
|
|
139
148
|
}
|
|
140
149
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const { Worker, parentPort, isMainThread, workerData } = require('node:worker_threads')
|
|
2
|
+
const cds = require('../../index.js'), { path, local, read, exists } = cds.utils
|
|
3
|
+
const TRACE = cds.debug('trace')
|
|
4
|
+
const LOG = cds.log('cds|edmx')
|
|
5
|
+
const OUT = process.env.cds_test_temp || path.join (cds.root,'_out')
|
|
6
|
+
|
|
7
|
+
// -----------------------------------------------------------------------
|
|
8
|
+
//
|
|
9
|
+
// Main Thread Part
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
if (isMainThread) {
|
|
13
|
+
|
|
14
|
+
module.exports = exports = (csn, tenant, features) => {
|
|
15
|
+
const defs = Object.entries(csn.definitions), protocols = cds.service.protocols
|
|
16
|
+
const services = defs.filter(([,d]) => d.kind === 'service' && 'odata' in protocols.for(d)).map(([k]) => k)
|
|
17
|
+
if (!services.length) return LOG.debug (`No service definitions found in given model(s).`)
|
|
18
|
+
let dir = path.join (OUT, tenant||'', features||'')
|
|
19
|
+
LOG.info ('generating edmx files to', { dir: local(dir) }, '\n')
|
|
20
|
+
return GENERATE ({ csn, dir, services })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const GENERATE = _generate_using_workers // for running in worker threads
|
|
24
|
+
// const GENERATE = _generate_edmxs // for running in main thread
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line no-inner-declarations
|
|
27
|
+
async function _generate_using_workers (workerData) {
|
|
28
|
+
await new Promise((resolve, reject) => new Worker (__filename, { workerData })
|
|
29
|
+
.on('error', reject)
|
|
30
|
+
.on('message', msg => {
|
|
31
|
+
if (msg.error) return reject (new cds.error(msg.error))
|
|
32
|
+
if (msg === 'done') return resolve()
|
|
33
|
+
else LOG.debug (msg)
|
|
34
|
+
}))
|
|
35
|
+
exports.get = _read_generated_edmx4
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// eslint-disable-next-line no-inner-declarations
|
|
39
|
+
function _read_generated_edmx4 (srv, kind='edmx', { tenant, features }={}) {
|
|
40
|
+
let dir = path.join (OUT, tenant||'', features||'')
|
|
41
|
+
let file = path.join (dir, srv.definition.name+'.'+kind)
|
|
42
|
+
if (!exists(file)) throw new Error (`No generated edm(x) file found at: ${file}`)
|
|
43
|
+
return read (file)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
exports.dir = OUT
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// -----------------------------------------------------------------------
|
|
52
|
+
//
|
|
53
|
+
// Worker Thread Part
|
|
54
|
+
//
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if (!isMainThread) _generate_edmxs (workerData)
|
|
58
|
+
.catch (e => parentPort.postMessage({ error: e }))
|
|
59
|
+
.then (() => parentPort.postMessage('done'))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async function _generate_edmxs ({ csn, dir, services }) {
|
|
63
|
+
|
|
64
|
+
const { mkdir, writeFile } = cds.utils.fs.promises
|
|
65
|
+
await mkdir (dir, { recursive: true })
|
|
66
|
+
const cdsc = cds.compiler
|
|
67
|
+
const promises = []
|
|
68
|
+
|
|
69
|
+
TRACE?.time(`cdsc.generate edmxs`.padEnd(22))
|
|
70
|
+
|
|
71
|
+
// call cdsc.to.odata to generate edm/xs
|
|
72
|
+
let odataVersion = cds.env.odata.version
|
|
73
|
+
let suffixes = { edmx: '.edmx' }
|
|
74
|
+
let compile = cdsc.to.edmx // default is edmx only
|
|
75
|
+
if (!cds.env.features.odata_new_adapter) {
|
|
76
|
+
compile = cdsc.to.odata // edmx and edm.json
|
|
77
|
+
suffixes.edm = '.edm.json'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let result = compile.all (csn, { serviceNames: services, messages:[] })
|
|
81
|
+
|
|
82
|
+
// write edmx files to disk
|
|
83
|
+
for (let [name,x] of Object.entries(result[odataVersion])) {
|
|
84
|
+
for (let suffix in suffixes) {
|
|
85
|
+
let content = suffix === 'edmx'? x[suffix] : JSON.stringify (x[suffix], minify);
|
|
86
|
+
let file = path.join (dir, name + suffixes[suffix])
|
|
87
|
+
let p = writeFile (file, content)
|
|
88
|
+
.then (() => parentPort?.postMessage ({ generated: local(file) }))
|
|
89
|
+
promises.push(p)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
await Promise.all (promises)
|
|
93
|
+
TRACE?.timeEnd(`cdsc.generate edmxs`.padEnd(22))
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
function minify (k,v) {
|
|
99
|
+
if (k === '$ReferentialConstraint') return
|
|
100
|
+
if (k === '$Reference') return
|
|
101
|
+
if (k === '$OnDelete') return
|
|
102
|
+
if (k === '$MaxLength') return
|
|
103
|
+
if (k === '$Annotations') {
|
|
104
|
+
const v2 = {}
|
|
105
|
+
for (let a in v) {
|
|
106
|
+
const a1=v[a], a2 = {}
|
|
107
|
+
for (let p in a1) {
|
|
108
|
+
if (!/^@(UI|Common|Analytics|Core.Description|Core.Operation|Capabilities.Navigation|Measures|Validation)/.test(p)) a2[p] = a1[p]
|
|
109
|
+
}
|
|
110
|
+
if (Object.keys(a2).length) v2[a] = a2
|
|
111
|
+
}
|
|
112
|
+
return v2
|
|
113
|
+
}
|
|
114
|
+
// if (k === '$Type' && v === 'Edm.Guid') return
|
|
115
|
+
else return v
|
|
116
|
+
}
|
package/lib/compile/to/edm.js
CHANGED
|
@@ -69,4 +69,11 @@ function* _many (suffix, all, callback = x=>x) {
|
|
|
69
69
|
for (let file in all) yield [ callback(all[file]), { file, suffix } ]
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
module.exports =
|
|
72
|
+
module.exports = exports = cds_compile_to_edm
|
|
73
|
+
cds_compile_to_edm.x = cds_compile_to_edmx
|
|
74
|
+
if (cds.env.features.pre_compile_edmxs) {
|
|
75
|
+
cds_compile_to_edmx.files = require('./edm-files')
|
|
76
|
+
} else {
|
|
77
|
+
cds_compile_to_edmx.files = ()=> null
|
|
78
|
+
}
|
|
79
|
+
cds_compile_to_edmx.files.get = ()=> null
|
|
@@ -61,7 +61,7 @@ async function _tabledata4(dir, csvFile, model, baseDir, naming) {
|
|
|
61
61
|
|
|
62
62
|
// add a locale filter for mono-lingual files that refer to generated text tables
|
|
63
63
|
if (entity.elements.locale) {
|
|
64
|
-
const locale = /
|
|
64
|
+
const locale = /[._]texts_(.+)\.csv$/.test(csvFile) ? RegExp.$1 : null
|
|
65
65
|
if (locale) {
|
|
66
66
|
const localeKey = getElementCdsPersistenceName(entity.elements.locale.name/*usually 'LOCALE'*/, naming, 'hana');
|
|
67
67
|
_import.import_settings.include_filter.push({ [localeKey]: locale })
|
|
@@ -83,7 +83,7 @@ async function _tabledata4(dir, csvFile, model, baseDir, naming) {
|
|
|
83
83
|
function _entity4(name, csn) {
|
|
84
84
|
const entity = csn.definitions[name]
|
|
85
85
|
if (!entity) {
|
|
86
|
-
if (/(.+)[._]texts_?/.test(name)) { // 'Books_texts', 'Books_texts_de'
|
|
86
|
+
if (/(.+)[._]texts_?/.test(name)) { // 'Books_texts', 'Books_texts_de', 'Books.texts', 'Books.texts_de'
|
|
87
87
|
const base = csn.definitions[RegExp.$1]
|
|
88
88
|
if (base && base.elements && base.elements.texts) {
|
|
89
89
|
return _entity4(base.elements.texts.target, csn)
|
|
@@ -119,7 +119,7 @@ function _csvDirs(sources) {
|
|
|
119
119
|
|
|
120
120
|
function _csvs(filename, _, allFiles) {
|
|
121
121
|
if (filename[0] === '-' || !filename.endsWith('.csv')) return false
|
|
122
|
-
// ignores 'Books_texts.csv' if there is any 'Books_texts_LANG.csv'
|
|
122
|
+
// ignores 'Books_texts.csv'|'Books.texts.csv' if there is any 'Books_texts_LANG.csv'|'Books.texts_LANG.csv'
|
|
123
123
|
if (/(.*)[._]texts\.csv$/.test(filename)) {
|
|
124
124
|
const basename = RegExp.$1
|
|
125
125
|
const monoLangFiles = allFiles.filter(file => new RegExp(basename + '_texts_').test(file))
|
package/lib/compile/to/sql.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const cds = require ('../..')
|
|
2
2
|
const cdsc = require ('../cdsc')
|
|
3
|
-
const
|
|
3
|
+
const sqliteKeywords = cdsc.to.sql.sqlite.keywords
|
|
4
|
+
const postgresKeywords = cdsc.to.sql.postgres?.keywords // requires @sap/cds-compiler >= 4.8.0
|
|
4
5
|
const { unfold_ddl } = require ('../etc/_localized')
|
|
5
6
|
const TRACE = cds.debug('trace')
|
|
6
7
|
|
|
@@ -53,5 +54,6 @@ module.exports = Object.assign (cds_compile_to_sql, {
|
|
|
53
54
|
hdbcds: cds_compile_to_hdbcds,
|
|
54
55
|
hdbtable: cds_compile_to_hdbtable,
|
|
55
56
|
delta: cds_compile_to_deltaSql,
|
|
56
|
-
sqlite: { keywords },
|
|
57
|
+
sqlite: { keywords: sqliteKeywords },
|
|
58
|
+
postgres: { keywords: postgresKeywords },
|
|
57
59
|
})
|
|
@@ -8,7 +8,7 @@ module.exports = (model, options={}) => {
|
|
|
8
8
|
|
|
9
9
|
const result = []
|
|
10
10
|
const isNodeProject = _isNodeProject(options.root || cds.root)
|
|
11
|
-
const javaPrefix = _javaPrefix()
|
|
11
|
+
const javaPrefix = _javaPrefix(options.root || cds.root)
|
|
12
12
|
const isJavaProject = !!javaPrefix
|
|
13
13
|
|
|
14
14
|
cds.linked(model) .all ('service')
|
|
@@ -85,11 +85,12 @@ module.exports = (model, options={}) => {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
function _javaPrefix() {
|
|
88
|
+
function _javaPrefix(root) {
|
|
89
89
|
let is_java
|
|
90
90
|
const javaPrefixDefault = 'odata/v4/'
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const roots = [ cds.env.folders.db, cds.env.folders.srv ].map(d => join(root, d))
|
|
92
|
+
for (let r of roots) {
|
|
93
|
+
const file = isfile (join (r,'../src/main/resources/application.yaml'))
|
|
93
94
|
if (file) {
|
|
94
95
|
const yaml = cds.load.yaml(file)
|
|
95
96
|
for (let yamlDoc of Array.isArray(yaml) ? yaml : [yaml]) {
|
|
@@ -103,7 +104,7 @@ module.exports = (model, options={}) => {
|
|
|
103
104
|
}
|
|
104
105
|
return javaPrefixDefault
|
|
105
106
|
}
|
|
106
|
-
else if (isfile (join(
|
|
107
|
+
else if (isfile (join(r,'../pom.xml'))) is_java = true
|
|
107
108
|
}
|
|
108
109
|
return is_java && javaPrefixDefault
|
|
109
110
|
}
|