@sap/cds-dk 10.0.7 → 10.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.
- package/CHANGELOG.md +94 -0
- package/bin/add.js +7 -23
- package/bin/bind.js +10 -0
- package/bin/build.js +20 -34
- package/bin/cds.js +1 -1
- package/bin/compile/index.js +15 -41
- package/bin/completion/completionFs.js +11 -8
- package/bin/completion/index.js +592 -80
- package/bin/completion/scripts/cds.fish +568 -0
- package/bin/completion/scripts/cds.ps1 +329 -0
- package/bin/completion/scripts/cds.sh +261 -0
- package/bin/completion/scripts/cds.zsh +230 -0
- package/bin/completion/templates/cds-tmpl.fish +65 -0
- package/bin/completion/templates/cds-tmpl.ps1 +208 -0
- package/bin/completion/templates/cds-tmpl.sh +93 -0
- package/bin/completion/templates/cds-tmpl.zsh +74 -0
- package/bin/deploy/index.js +7 -1
- package/bin/deploy/options.js +25 -0
- package/{lib → bin}/deploy/to-hana/hana.js +8 -8
- package/{lib → bin}/deploy/to-hana/hdiDeployUtil.js +1 -1
- package/bin/deploy/{to-hana.js → to-hana/index.js} +1 -1
- package/{lib → bin}/deploy/to-hana/mtaUtil.js +1 -1
- package/bin/deploy/to-sql.js +0 -2
- package/bin/export.js +35 -5
- package/bin/help/export.md +3 -0
- package/bin/help.js +1 -5
- package/bin/import.js +6 -0
- package/bin/init.js +5 -24
- package/bin/inspect.js +6 -0
- package/bin/login.js +26 -20
- package/bin/pull.js +19 -6
- package/bin/push.js +19 -6
- package/bin/up.js +14 -11
- package/{lib → bin}/upgrade/constants.js +1 -1
- package/bin/{upgrade.js → upgrade/index.js} +2 -2
- package/{lib → bin}/upgrade/preflight/consistency.js +1 -1
- package/{lib → bin}/upgrade/preflight/index.js +1 -1
- package/{lib → bin}/upgrade/steps/analyze/index.js +1 -1
- package/{lib → bin}/upgrade/steps/install.js +1 -1
- package/{lib → bin}/upgrade/steps/openrewrite.js +1 -1
- package/{lib → bin}/upgrade/steps/removals.js +1 -1
- package/{lib → bin}/upgrade/steps/rewrite.js +1 -1
- package/{lib → bin}/upgrade/steps/verify.js +1 -1
- package/{lib/upgrade/index.js → bin/upgrade/upgrade.js} +2 -2
- package/{lib → bin}/upgrade/util/pom.js +2 -2
- package/{lib → bin}/upgrade/util/prompt.js +1 -1
- package/bin/util/containerize.js +8 -4
- package/bin/version.js +10 -1
- package/{lib → bin}/watch/hot-reload.js +1 -1
- package/bin/{watch.js → watch/index.js} +17 -9
- package/{lib → bin}/watch/livereload-connect.js +1 -1
- package/{lib → bin}/watch/vite-watch.js +1 -1
- package/{lib → bin}/watch/watched.js +2 -2
- package/lib/build/constants.js +1 -1
- package/lib/build/plugins/fiori/index.js +31 -2
- package/lib/build/plugins/internal.js +4 -2
- package/lib/build/plugins/mtx-sidecar/index.js +7 -8
- package/lib/build/plugins/nodejs/index.js +64 -7
- package/lib/compile/to_asyncapi.js +1 -1
- package/lib/env/schema.js +16 -0
- package/lib/env/schemas/cds-rc.js +1 -76
- package/lib/import/importapi.js +2 -3
- package/lib/import/message.js +0 -2
- package/lib/init/constants.js +2 -1
- package/lib/init/index.js +2 -2
- package/lib/init/merge.js +123 -280
- package/lib/init/plugin.js +3 -1
- package/lib/init/projectReader.js +22 -6
- package/lib/init/registries/xs-app.js +3 -5
- package/lib/init/template/ai/files/mta.yaml.hbs +1 -1
- package/lib/init/template/ai/index.js +14 -2
- package/lib/init/template/ams/index.js +2 -2
- package/lib/init/template/app-frontend/files/containerize.yaml.hbs +2 -2
- package/lib/init/template/app-frontend/index.js +4 -4
- package/lib/init/template/application-logging/index.js +2 -2
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/approuter/index.js +8 -3
- package/lib/init/template/attachments/files/package.json.hbs +1 -1
- package/lib/init/template/attachments/index.js +2 -2
- package/lib/init/template/audit-logging/index.js +2 -2
- package/lib/init/template/cloud-logging/files/package.json.hbs +4 -4
- package/lib/init/template/cloud-logging/index.js +2 -2
- package/lib/init/template/completion/completionSetup.js +36 -39
- package/lib/init/template/connectivity/index.js +2 -2
- package/lib/init/template/data/as-csv.js +15 -5
- package/lib/init/template/data/as-json.js +114 -42
- package/lib/init/template/data/index.js +16 -2
- package/lib/init/template/destination/index.js +2 -2
- package/lib/init/template/dynatrace/files/package.json.hbs +3 -3
- package/lib/init/template/dynatrace/index.js +2 -2
- package/lib/init/template/enterprise-messaging/index.js +2 -2
- package/lib/init/template/enterprise-messaging-shared/index.js +2 -2
- package/lib/init/template/extensibility/files/mta.yaml.hbs +11 -0
- package/lib/init/template/extensibility/files/xs-security.json.hbs +1 -1
- package/lib/init/template/extensibility/index.js +3 -3
- package/lib/init/template/github-actions/index.js +2 -2
- package/lib/init/template/hana/index.js +3 -2
- package/lib/init/template/hana-serverless/files/db/package.json +14 -0
- package/lib/init/template/hana-serverless/files/identity.values.yaml.hbs +10 -0
- package/lib/init/template/hana-serverless/files/mta.yaml.hbs +64 -0
- package/lib/init/template/hana-serverless/files/package.json.hbs +35 -0
- package/lib/init/template/hana-serverless/files/src/.hdiconfig +139 -0
- package/lib/init/template/hana-serverless/files/undeploy.json +7 -0
- package/lib/init/template/hana-serverless/files/values.yaml.hbs +18 -0
- package/lib/init/template/hana-serverless/index.js +184 -0
- package/lib/init/template/html5-repo/files/containerize.yaml.hbs +2 -2
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +5 -0
- package/lib/init/template/html5-repo/index.js +18 -14
- package/lib/init/template/http/index.js +123 -26
- package/lib/init/template/ias/index.js +2 -2
- package/lib/init/template/kafka/index.js +2 -2
- package/lib/init/template/kyma/index.js +7 -5
- package/lib/init/template/malware-scanner/index.js +2 -2
- package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
- package/lib/init/template/multitenancy/index.js +18 -3
- package/lib/init/template/notifications/index.js +2 -2
- package/lib/init/template/portal/files/mta.yaml.hbs +4 -0
- package/lib/init/template/portal/index.js +13 -8
- package/lib/init/template/postgres/index.js +2 -2
- package/lib/init/template/redis/index.js +2 -2
- package/lib/init/template/sample/files/db/currencies.cds +2 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +1 -1
- package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +2 -2
- package/lib/init/template/workzone-standard/index.js +5 -5
- package/lib/init/template/xsuaa/index.js +20 -2
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/mtx/auth_manager.js +103 -37
- package/lib/mtx/params.js +3 -2
- package/lib/mtx/settings_manager.js +45 -28
- package/lib/mtx/tenant_action.js +0 -1
- package/lib/mtx/util/credentials.js +62 -0
- package/node_modules/@sap/cds/CHANGELOG.md +57 -0
- package/node_modules/@sap/cds/app/index.js +5 -4
- package/node_modules/@sap/cds/eslint.config.mjs +1 -0
- package/node_modules/@sap/cds/lib/compile/minify.js +14 -10
- package/node_modules/@sap/cds/lib/env/cds-env.js +1 -1
- package/node_modules/@sap/cds/lib/env/cds-requires.js +22 -11
- package/node_modules/@sap/cds/lib/env/defaults.js +4 -1
- package/node_modules/@sap/cds/lib/env/schemas/cds-rc.js +5 -2
- package/node_modules/@sap/cds/lib/plugins.js +9 -5
- package/node_modules/@sap/cds/lib/req/spawn.js +1 -1
- package/node_modules/@sap/cds/lib/srv/srv-dispatch.js +1 -1
- package/node_modules/@sap/cds/lib/srv/srv-models.js +1 -1
- package/node_modules/@sap/cds/lib/utils/cds-utils.js +2 -1
- package/node_modules/@sap/cds/libx/_runtime/common/generic/assert.js +2 -3
- package/node_modules/@sap/cds/libx/_runtime/common/generic/auth/restrict.js +8 -1
- package/node_modules/@sap/cds/libx/_runtime/common/generic/crud.js +18 -8
- package/node_modules/@sap/cds/libx/_runtime/fiori/lean-draft.js +25 -17
- package/node_modules/@sap/cds/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +9 -3
- package/node_modules/@sap/cds/libx/_runtime/remote/Service.js +4 -19
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/LruCache.js +42 -0
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js +14 -4
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/cloudSdkProvider.js +2 -9
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/destinationClient.js +150 -0
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/error.js +13 -0
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/fetchClient.js +26 -18
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/query.js +34 -23
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/token.js +82 -0
- package/node_modules/@sap/cds/libx/_runtime/ucl/Service.js +36 -189
- package/node_modules/@sap/cds/libx/common/utils/streaming.js +16 -16
- package/node_modules/@sap/cds/libx/http/location.js +3 -3
- package/node_modules/@sap/cds/libx/odata/middleware/batch.js +16 -10
- package/node_modules/@sap/cds/libx/odata/middleware/metadata.js +9 -6
- package/node_modules/@sap/cds/libx/odata/middleware/service-document.js +1 -1
- package/node_modules/@sap/cds/libx/odata/parse/afterburner.js +19 -3
- package/node_modules/@sap/cds/libx/odata/parse/cqn2odata.js +83 -86
- package/node_modules/@sap/cds/libx/queue/SchedulingService.js +17 -2
- package/node_modules/@sap/cds/libx/queue/processing.js +1 -3
- package/node_modules/@sap/cds/libx/rest/RestAdapter.js +3 -7
- package/node_modules/@sap/cds/libx/rest/middleware/delete.js +3 -3
- package/node_modules/@sap/cds/libx/rest/middleware/parse.js +13 -8
- package/node_modules/@sap/cds/libx/rest/middleware/read.js +3 -3
- package/node_modules/@sap/cds/libx/rest/middleware/upsert.js +2 -2
- package/node_modules/@sap/cds/package.json +1 -1
- package/node_modules/@sap/cds-compiler/CHANGELOG.md +60 -8
- package/node_modules/@sap/cds-compiler/bin/cdsc.js +2 -2
- package/node_modules/@sap/cds-compiler/doc/IncompatibleChanges_v7.md +46 -19
- package/node_modules/@sap/cds-compiler/lib/api/main.js +10 -7
- package/node_modules/@sap/cds-compiler/lib/api/options.js +8 -2
- package/node_modules/@sap/cds-compiler/lib/base/csnRefs.js +5 -2
- package/node_modules/@sap/cds-compiler/lib/base/message-registry.js +4 -0
- package/node_modules/@sap/cds-compiler/lib/base/optionProcessor.js +12 -0
- package/node_modules/@sap/cds-compiler/lib/checks/enricher.js +1 -0
- package/node_modules/@sap/cds-compiler/lib/compiler/assert-consistency.js +8 -7
- package/node_modules/@sap/cds-compiler/lib/compiler/checks.js +3 -3
- package/node_modules/@sap/cds-compiler/lib/compiler/define.js +301 -75
- package/node_modules/@sap/cds-compiler/lib/compiler/dictionaries.js +2 -0
- package/node_modules/@sap/cds-compiler/lib/compiler/extend.js +40 -26
- package/node_modules/@sap/cds-compiler/lib/compiler/populate.js +45 -60
- package/node_modules/@sap/cds-compiler/lib/compiler/propagator.js +16 -7
- package/node_modules/@sap/cds-compiler/lib/compiler/resolve.js +41 -15
- package/node_modules/@sap/cds-compiler/lib/compiler/shared.js +7 -6
- package/node_modules/@sap/cds-compiler/lib/compiler/tweak-assocs.js +62 -50
- package/node_modules/@sap/cds-compiler/lib/compiler/utils.js +29 -14
- package/node_modules/@sap/cds-compiler/lib/edm/edmAnnoPreprocessor.js +6 -5
- package/node_modules/@sap/cds-compiler/lib/gen/CdlGrammar.checksum +1 -1
- package/node_modules/@sap/cds-compiler/lib/gen/CdlParser.js +1119 -1109
- package/node_modules/@sap/cds-compiler/lib/gen/Dictionary.json +19 -3
- package/node_modules/@sap/cds-compiler/lib/json/from-csn.js +10 -16
- package/node_modules/@sap/cds-compiler/lib/json/to-csn.js +58 -39
- package/node_modules/@sap/cds-compiler/lib/main.d.ts +8 -0
- package/node_modules/@sap/cds-compiler/lib/main.js +1 -0
- package/node_modules/@sap/cds-compiler/lib/model/csnUtils.js +2 -0
- package/node_modules/@sap/cds-compiler/lib/parsers/AstBuildingParser.js +2 -1
- package/node_modules/@sap/cds-compiler/lib/parsers/XprTree.js +8 -0
- package/node_modules/@sap/cds-compiler/lib/render/toCdl.js +22 -1
- package/node_modules/@sap/cds-compiler/lib/render/toSql.js +17 -2
- package/node_modules/@sap/cds-compiler/lib/render/utils/common.js +6 -1
- package/node_modules/@sap/cds-compiler/lib/render/utils/operators.js +27 -0
- package/node_modules/@sap/cds-compiler/lib/render/utils/standardDatabaseFunctions.js +125 -3
- package/node_modules/@sap/cds-compiler/lib/tool-lib/revealInternalProperties.js +2 -1
- package/node_modules/@sap/cds-compiler/lib/transform/db/applyTransformations.js +3 -0
- package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +8 -2
- package/node_modules/@sap/cds-compiler/lib/transform/db/backlinks.js +22 -6
- package/node_modules/@sap/cds-compiler/lib/transform/db/constraints.js +62 -1
- package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +40 -0
- package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +1 -0
- package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +6 -1
- package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +19 -8
- package/node_modules/@sap/cds-compiler/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/CHANGELOG.md +15 -0
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +34 -16
- package/node_modules/@sap/cds-mtxs/lib/utils.js +19 -4
- package/node_modules/@sap/cds-mtxs/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +1 -1
- package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +22 -13
- package/node_modules/@sap/cds-mtxs/srv/model-provider.js +17 -2
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +1 -1
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +4 -8
- package/node_modules/@sap/xsenv/CHANGELOG.md +7 -0
- package/node_modules/@sap/xsenv/package.json +10 -7
- package/node_modules/body-parser/node_modules/content-type/README.md +2 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/body-parser/node_modules/content-type/package.json +1 -1
- package/node_modules/hdb/cfg/VERSION +1 -1
- package/node_modules/hdb/lib/protocol/ClientInfo.js +16 -3
- package/node_modules/hdb/lib/protocol/Connection.js +1 -0
- package/node_modules/hdb/package.json +3 -2
- package/node_modules/negotiator/lib/accept.js +54 -0
- package/node_modules/negotiator/lib/charset.js +10 -34
- package/node_modules/negotiator/lib/encoding.js +9 -30
- package/node_modules/negotiator/lib/language.js +15 -36
- package/node_modules/negotiator/lib/mediaType.js +16 -134
- package/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
- package/node_modules/negotiator/node_modules/content-type/README.md +71 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/negotiator/node_modules/content-type/package.json +52 -0
- package/node_modules/negotiator/package.json +16 -10
- package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
- package/node_modules/qs/CHANGELOG.md +15 -0
- package/node_modules/qs/README.md +19 -1
- package/node_modules/qs/dist/qs.js +21 -21
- package/node_modules/qs/eslint.config.mjs +1 -1
- package/node_modules/qs/lib/parse.js +3 -4
- package/node_modules/qs/lib/stringify.js +23 -8
- package/node_modules/qs/lib/utils.js +10 -3
- package/node_modules/qs/package.json +4 -4
- package/node_modules/qs/test/parse.js +192 -3
- package/node_modules/qs/test/stringify.js +317 -0
- package/node_modules/qs/test/utils.js +12 -0
- package/node_modules/type-is/node_modules/content-type/README.md +2 -0
- package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/type-is/node_modules/content-type/package.json +1 -1
- package/node_modules/ws/lib/permessage-deflate.js +3 -1
- package/node_modules/ws/package.json +1 -1
- package/package.json +3 -3
- package/bin/completion/scripts/cds-bash.sh +0 -20
- package/bin/completion/scripts/cds-fish.fish +0 -13
- package/bin/completion/scripts/cds-ps.ps1 +0 -19
- package/bin/completion/scripts/cds-zsh.sh +0 -13
- package/lib/deploy/index.js +0 -25
- package/lib/import/asyncapi/importAsyncAPI.js +0 -33
- package/lib/import/asyncapi/index.js +0 -18
- package/lib/import/asyncapi/parserContext.js +0 -454
- package/lib/import/asyncapi/utils.js +0 -49
- package/node_modules/@sap/cds/libx/_runtime/ucl/queries.js +0 -61
- package/node_modules/negotiator/HISTORY.md +0 -114
- /package/{lib → bin}/upgrade/context.js +0 -0
- /package/{lib → bin}/upgrade/migrations/cds10/migrations.json +0 -0
- /package/{lib → bin}/upgrade/preflight/cds-version.js +0 -0
- /package/{lib → bin}/upgrade/preflight/project-type.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/classification.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/detector.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/evaluator.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/reporter.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/setup.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/detection.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/files.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/grep.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/yaml.js +0 -0
- /package/{lib → bin}/upgrade/util/workspaces.js +0 -0
- /package/{lib → bin}/watch/esm-resolve-registration.js +0 -0
- /package/{lib → bin}/watch/livereload-server.js +0 -0
- /package/{lib → bin}/watch/node-watch.js +0 -0
- /package/{lib → bin}/watch/open.js +0 -0
- /package/{lib → bin}/watch/watcher.js +0 -0
|
@@ -232,44 +232,6 @@ function _xpr(expr, target, kind, isLambda, navPrefix = []) {
|
|
|
232
232
|
return res.join('%20')
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
const _keysOfWhere = (where, kind, target) => {
|
|
236
|
-
if (!Array.isArray(where) || !where.length) return ''
|
|
237
|
-
|
|
238
|
-
if (kind === 'rest') {
|
|
239
|
-
const keys = where.length === 1 ? getProp(where[0], 'val') : getProp(where[2], 'val')
|
|
240
|
-
return `/${keys}`
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (where.length === 3) {
|
|
244
|
-
const [left, op, right] = where
|
|
245
|
-
if (op === '=' && (('val' in left && right.ref) || (left.ref && 'val' in right))) {
|
|
246
|
-
const formattedValue =
|
|
247
|
-
'val' in left
|
|
248
|
-
? formatVal(left.val, right.ref.join('/'), target, kind)
|
|
249
|
-
: formatVal(right.val, left.ref.join('/'), target, kind)
|
|
250
|
-
|
|
251
|
-
return `(${encodeURIComponent(formattedValue)})`
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const res = []
|
|
256
|
-
for (const cur of where) {
|
|
257
|
-
if (hasValidProps(cur, 'ref')) {
|
|
258
|
-
res.push(_format(cur))
|
|
259
|
-
} else if (hasValidProps(cur, 'val')) {
|
|
260
|
-
// find previous ref
|
|
261
|
-
const element = res[res.length - 2]
|
|
262
|
-
res.push(_format(cur, element, target, kind))
|
|
263
|
-
} else if (cur === 'and') {
|
|
264
|
-
res.push(',')
|
|
265
|
-
} else {
|
|
266
|
-
res.push(cur)
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return `(${res.join('')})`
|
|
271
|
-
}
|
|
272
|
-
|
|
273
235
|
function _getQueryTarget(entity, propOrEntity, model) {
|
|
274
236
|
if (!entity) {
|
|
275
237
|
// if there is no entity yet, we need to look it up in the model
|
|
@@ -302,8 +264,8 @@ const _params = (args, kind, target) => {
|
|
|
302
264
|
return `(${_params.join(',')})`
|
|
303
265
|
}
|
|
304
266
|
|
|
305
|
-
function _from(
|
|
306
|
-
let ref = getProp(
|
|
267
|
+
function _from(subject, kind, model) {
|
|
268
|
+
let ref = getProp(subject, 'ref')
|
|
307
269
|
ref = (Array.isArray(ref) && ref) || [ref]
|
|
308
270
|
|
|
309
271
|
const path = []
|
|
@@ -311,21 +273,63 @@ function _from(from, kind, model) {
|
|
|
311
273
|
|
|
312
274
|
for (const curRef of ref) {
|
|
313
275
|
if (hasValidProps(curRef, 'where', 'id')) {
|
|
276
|
+
// Format a request URL based on req.subject[n].ref
|
|
277
|
+
|
|
314
278
|
const { where, id } = curRef
|
|
315
279
|
queryTarget = model && _getQueryTarget(queryTarget, id, model)
|
|
316
|
-
|
|
280
|
+
|
|
281
|
+
// Format URL keys from req.subject.ref[n].where
|
|
282
|
+
let keys = ''
|
|
283
|
+
|
|
284
|
+
if (Array.isArray(where) && where.length) {
|
|
285
|
+
if (kind === 'rest') {
|
|
286
|
+
if (where.length !== 1 && where[1] !== '=')
|
|
287
|
+
cds.error(
|
|
288
|
+
500,
|
|
289
|
+
`Invalid subject: 'where' must specify a key via equality (key = value), got: ${JSON.stringify(where)}`
|
|
290
|
+
)
|
|
291
|
+
const val = where.length === 1 ? getProp(where[0], 'val') : getProp(where[2], 'val')
|
|
292
|
+
keys = `/${val}`
|
|
293
|
+
} else if (where.length === 3) {
|
|
294
|
+
const [left, op, right] = where
|
|
295
|
+
|
|
296
|
+
if (op === '=' && left.ref && 'val' in right) {
|
|
297
|
+
keys = `(${encodeURIComponent(formatVal(right.val, left.ref.join('/'), queryTarget, kind))})`
|
|
298
|
+
// REVISIT: keys in req.subject should already use the correct order
|
|
299
|
+
} else if (op === '=' && right.ref && 'val' in left) {
|
|
300
|
+
keys = `(${encodeURIComponent(formatVal(left.val, right.ref.join('/'), queryTarget, kind))})`
|
|
301
|
+
} else {
|
|
302
|
+
cds.error(
|
|
303
|
+
500,
|
|
304
|
+
`Invalid subject: 'where' must specify a key via equality (key = value), got: ${JSON.stringify(where)}`
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
} else {
|
|
308
|
+
const res = []
|
|
309
|
+
for (const cur of where) {
|
|
310
|
+
if (hasValidProps(cur, 'ref')) {
|
|
311
|
+
res.push(_format(cur))
|
|
312
|
+
} else if (hasValidProps(cur, 'val')) {
|
|
313
|
+
const element = res[res.length - 2]
|
|
314
|
+
res.push(_format(cur, element, queryTarget, kind))
|
|
315
|
+
} else if (cur === 'and') {
|
|
316
|
+
res.push(',')
|
|
317
|
+
} else {
|
|
318
|
+
res.push(cur)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
keys = `(${res.join('')})`
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
317
326
|
path.push(`${id}${keys}`)
|
|
318
327
|
} else if (hasValidProps(curRef, 'id') && 'args' in curRef) {
|
|
319
328
|
const { args, id } = curRef
|
|
320
329
|
queryTarget = model && _getQueryTarget(queryTarget, id, model)
|
|
321
330
|
const params = _params(args, kind, queryTarget)
|
|
322
331
|
path.push(`${id}${params}`)
|
|
323
|
-
|
|
324
|
-
// Check model if that is the case and if so, conform to the OData representation for
|
|
325
|
-
// Views with parameters, meaning the actual entity is behind /Set
|
|
326
|
-
if (queryTarget?.params) {
|
|
327
|
-
path.push(`Set`)
|
|
328
|
-
}
|
|
332
|
+
if (queryTarget?.params) path.push(`Set`)
|
|
329
333
|
} else if (typeof curRef === 'string') {
|
|
330
334
|
queryTarget = model && _getQueryTarget(queryTarget, curRef, model)
|
|
331
335
|
path.push(curRef)
|
|
@@ -523,7 +527,9 @@ function getOptions(cqnPart, url, kind, target, isCount) {
|
|
|
523
527
|
for (const opt in cqnPart) {
|
|
524
528
|
const cqnPartOpt = cqnPart[opt]
|
|
525
529
|
if (cqnPartOpt === undefined) continue
|
|
526
|
-
|
|
530
|
+
|
|
531
|
+
if (!hasValidProps(cqnPart, opt)) cds.error(500, `Feature not supported: SELECT statement with .${opt}`)
|
|
532
|
+
|
|
527
533
|
const parser = parsers[opt]
|
|
528
534
|
const parsed = parser && parser(cqnPartOpt, url, kind, target, isCount)
|
|
529
535
|
const parsedOpts = (Array.isArray(parsed) && parsed) || (parsed && [parsed]) || []
|
|
@@ -541,18 +547,22 @@ const _isCount = SELECT => {
|
|
|
541
547
|
return false
|
|
542
548
|
}
|
|
543
549
|
|
|
544
|
-
const _select = (cqn, kind, model) => {
|
|
550
|
+
const _select = (cqn, subject, kind, model) => {
|
|
551
|
+
const { url, queryTarget } = _from(subject, kind, model)
|
|
552
|
+
|
|
545
553
|
const SELECT = getProp(cqn, 'SELECT')
|
|
546
|
-
const { url, queryTarget } = _from(getProp(SELECT, 'from'), kind, model)
|
|
547
554
|
const isCount = _isCount(SELECT)
|
|
548
555
|
const queryOptions = getOptions(SELECT, url, kind, queryTarget, isCount).join('&')
|
|
549
|
-
|
|
550
|
-
return {
|
|
556
|
+
|
|
557
|
+
return {
|
|
558
|
+
method: 'GET',
|
|
559
|
+
path: `${url}${isCount ? '/$count' : ''}${queryOptions ? `?${queryOptions}` : ''}`
|
|
560
|
+
}
|
|
551
561
|
}
|
|
552
562
|
|
|
553
|
-
const _insert = (cqn, kind, model) => {
|
|
563
|
+
const _insert = (cqn, subject, kind, model) => {
|
|
554
564
|
const INSERT = getProp(cqn, 'INSERT')
|
|
555
|
-
const { url } = _from(
|
|
565
|
+
const { url } = _from(subject, kind, model)
|
|
556
566
|
const body = _copyData(
|
|
557
567
|
Array.isArray(INSERT.entries) && INSERT.entries.length === 1 ? INSERT.entries[0] : INSERT.entries
|
|
558
568
|
)
|
|
@@ -572,44 +582,31 @@ const _copyData = data => {
|
|
|
572
582
|
return copied
|
|
573
583
|
}
|
|
574
584
|
|
|
575
|
-
const _update = (cqn, kind, model, method) => {
|
|
576
|
-
const
|
|
577
|
-
const { url, queryTarget } = _from(getProp(UPDATE, 'entity'), kind, model)
|
|
578
|
-
let keys = ''
|
|
579
|
-
|
|
580
|
-
if (UPDATE.where) {
|
|
581
|
-
if (_isOdataUrlWithKeys(url, kind)) {
|
|
582
|
-
throw new Error('Cannot generate URL for UPDATE CQN. Conflicting .from and .where')
|
|
583
|
-
}
|
|
584
|
-
keys = _keysOfWhere(getProp(UPDATE, 'where'), kind, queryTarget)
|
|
585
|
-
}
|
|
586
|
-
|
|
585
|
+
const _update = (cqn, subject, kind, model, method = 'PATCH') => {
|
|
586
|
+
const { url } = _from(subject, kind, model)
|
|
587
587
|
// TODO: support for .set as well
|
|
588
|
-
const body = _copyData(UPDATE.data)
|
|
589
|
-
return { method
|
|
588
|
+
const body = _copyData(getProp(cqn, 'UPDATE').data)
|
|
589
|
+
return { method, path: url, body }
|
|
590
590
|
}
|
|
591
591
|
|
|
592
|
-
const _delete = (
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
592
|
+
const _delete = (subject, kind, model) => {
|
|
593
|
+
const { url } = _from(subject, kind, model)
|
|
594
|
+
return { method: 'DELETE', path: url }
|
|
595
|
+
}
|
|
596
596
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
throw new Error('Cannot generate URL for DELETE CQN. Conflicting .from and .where')
|
|
600
|
-
}
|
|
597
|
+
module.exports.cqn2odata = (cqn, { kind, model } = {}) => {
|
|
598
|
+
let { query, subject, method } = cqn
|
|
601
599
|
|
|
602
|
-
|
|
600
|
+
if (!subject) {
|
|
601
|
+
query = cds.ql(cqn)
|
|
602
|
+
subject = query._subject && { ref: query._subject.ref }
|
|
603
|
+
method = undefined
|
|
603
604
|
}
|
|
604
605
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (cqn.SELECT) return _select(cqn, kind, model)
|
|
610
|
-
if (cqn.INSERT) return _insert(cqn, kind, model)
|
|
611
|
-
if (cqn.UPDATE) return _update(cqn, kind, model, method)
|
|
612
|
-
if (cqn.DELETE) return _delete(cqn, kind, model)
|
|
606
|
+
if (query.SELECT) return _select(query, subject, kind, model)
|
|
607
|
+
if (query.INSERT) return _insert(query, subject, kind, model)
|
|
608
|
+
if (query.UPDATE) return _update(query, subject, kind, model, method)
|
|
609
|
+
if (query.DELETE) return _delete(subject, kind, model)
|
|
613
610
|
|
|
614
|
-
throw new Error('Unknown CQN object cannot be translated to URL: ' + JSON.stringify(
|
|
611
|
+
throw new Error('Unknown CQN object cannot be translated to URL: ' + JSON.stringify(query))
|
|
615
612
|
}
|
|
@@ -9,6 +9,20 @@ const $taskProcessorRegistered = Symbol('task processor registered')
|
|
|
9
9
|
|
|
10
10
|
const FLUSH = 'flush'
|
|
11
11
|
|
|
12
|
+
// Node's `setTimeout` delay is a 32-bit signed int; larger values emit a
|
|
13
|
+
// `TimeoutOverflowWarning` and are clamped to 1ms (firing almost immediately).
|
|
14
|
+
const MAX_TIMEOUT_MS = 2 ** 31 - 1
|
|
15
|
+
|
|
16
|
+
// Like `setTimeout`, but chains multiple timers when `delay` exceeds the 32-bit
|
|
17
|
+
// limit so the callback still fires at its exact scheduled time. The timer is
|
|
18
|
+
// unref'd so it never keeps the process alive.
|
|
19
|
+
const _setLongTimeout = (cb, delay) => {
|
|
20
|
+
const step = Math.min(delay, MAX_TIMEOUT_MS)
|
|
21
|
+
const remaining = delay - step
|
|
22
|
+
const timer = setTimeout(remaining > 0 ? () => _setLongTimeout(cb, remaining) : cb, step)
|
|
23
|
+
return timer.unref()
|
|
24
|
+
}
|
|
25
|
+
|
|
12
26
|
let T0
|
|
13
27
|
|
|
14
28
|
module.exports = class SchedulingService extends cds.Service {
|
|
@@ -116,7 +130,7 @@ module.exports = class SchedulingService extends cds.Service {
|
|
|
116
130
|
|
|
117
131
|
if (!flushOpts?.after) return cb()
|
|
118
132
|
|
|
119
|
-
|
|
133
|
+
_setLongTimeout(cb, flushOpts.after)
|
|
120
134
|
}
|
|
121
135
|
|
|
122
136
|
scheduleTask = async (tasks, queueName, taskOpts, context = cds.context) => {
|
|
@@ -154,7 +168,8 @@ module.exports = class SchedulingService extends cds.Service {
|
|
|
154
168
|
if (this._markers.has(marker.ID)) return
|
|
155
169
|
|
|
156
170
|
this._markers.add(marker.ID)
|
|
157
|
-
|
|
171
|
+
// Evict the in-memory dedup entry once the marker can no longer be re-derived.
|
|
172
|
+
_setLongTimeout(() => this._markers.delete(marker.ID), after + this.marker_interval_ms * 2)
|
|
158
173
|
|
|
159
174
|
await cds.tx(new cds.EventContext({ tenant: T0 }), async () => {
|
|
160
175
|
LOG._debug && LOG.debug(`Write marker for queue ${queueName} of tenant ${tenant} at ${marker.timestamp}`)
|
|
@@ -152,9 +152,7 @@ const _processTasks = (queueName, tenant, _opts = {}) => {
|
|
|
152
152
|
const config = tenant ? { tenant, user: cds.User.privileged } : { user: cds.User.privileged }
|
|
153
153
|
config.after = 1 // make sure spawn puts its cb on the `timer` queue (via setTimeout), which is also used by `taskRunner`
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
const _spawn = (fn, o) => setTimeout(() => cds._with(o, fn), 1).unref()
|
|
157
|
-
const _begin = cds.db.kind === 'sqlite' ? _spawn : cds.spawn.bind(cds)
|
|
155
|
+
const _begin = cds.spawn.bind(cds)
|
|
158
156
|
const _tx = cds.tx.bind(cds)
|
|
159
157
|
|
|
160
158
|
const processing_fn = async () => {
|
|
@@ -13,11 +13,9 @@ const operation = require('./middleware/operation')
|
|
|
13
13
|
|
|
14
14
|
const { postProcessData } = require('./post-processing')
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
class RestRequest extends cds.Request {}
|
|
18
17
|
RestRequest.prototype.protocol = 'rest' // for batch subrequests where prototype is not properly set
|
|
19
18
|
|
|
20
|
-
|
|
21
19
|
class RestAdapter extends HttpAdapter {
|
|
22
20
|
request4(args) {
|
|
23
21
|
return new RestRequest(args)
|
|
@@ -81,22 +79,20 @@ class RestAdapter extends HttpAdapter {
|
|
|
81
79
|
|
|
82
80
|
if (status && res.statusCode === 200) res.status(status) //> only set status if not yet modified
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
else res.send(typeof result === 'number' ? result.toString() : result)
|
|
82
|
+
res.send(typeof result === 'number' ? result.toString() : result)
|
|
86
83
|
}, next)
|
|
87
84
|
})
|
|
88
85
|
|
|
89
86
|
return router
|
|
90
87
|
}
|
|
91
88
|
|
|
92
|
-
|
|
93
89
|
normalized(err) {
|
|
94
90
|
err = super.normalized(err)
|
|
95
|
-
// Actually `code` is only required by OData, but we had that applied to
|
|
91
|
+
// Actually `code` is only required by OData, but we had that applied to
|
|
96
92
|
// REST as well, so we keep it here for compatibility with legacy behavior.
|
|
97
93
|
if (typeof err.code !== 'string') err.code = String(err.code || err.status || '')
|
|
98
94
|
return err
|
|
99
95
|
}
|
|
100
96
|
}
|
|
101
97
|
|
|
102
|
-
module.exports = RestAdapter
|
|
98
|
+
module.exports = RestAdapter
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {import('../RestAdapter')} adapter
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('../RestAdapter')} adapter
|
|
3
3
|
* the adapter instance in which this middleware is used
|
|
4
4
|
*/
|
|
5
5
|
module.exports = exports = adapter => exports.delete.bind(adapter)
|
|
@@ -8,7 +8,7 @@ module.exports = exports = adapter => exports.delete.bind(adapter)
|
|
|
8
8
|
* @type {import('express').Handler}
|
|
9
9
|
* @this import('../RestAdapter')
|
|
10
10
|
*/
|
|
11
|
-
exports.delete = async function rest_delete
|
|
11
|
+
exports.delete = async function rest_delete(req, res) {
|
|
12
12
|
const { _query: query, _data: data, _params: params } = req
|
|
13
13
|
|
|
14
14
|
await this.service.dispatch(this.request4({ query, data, params, req, res }))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {import('../RestAdapter')} adapter
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('../RestAdapter')} adapter
|
|
3
3
|
* the adapter instance in which this middleware is used
|
|
4
4
|
*/
|
|
5
5
|
module.exports = exports = adapter => exports.parse.bind(adapter)
|
|
@@ -84,12 +84,17 @@ exports.parse = function parse_odata_url(req, res, next) {
|
|
|
84
84
|
cds.error(errorMsg, { code: 400 })
|
|
85
85
|
}
|
|
86
86
|
if (!one) {
|
|
87
|
-
|
|
88
|
-
const entity = definition,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
if (req.method === 'PATCH') throw cds.error({ status: 405, code: `INVALID_${req.method}` })
|
|
88
|
+
const entity = definition,
|
|
89
|
+
keys = {},
|
|
90
|
+
data = req.body || {}
|
|
91
|
+
for (let k in entity.keys) {
|
|
92
|
+
keys[k] =
|
|
93
|
+
data[k] ||
|
|
94
|
+
(entity.keys[k]['@cds.on.insert']?.['='] === '$user' && cds.context?.user?.id) ||
|
|
95
|
+
cds.error({ status: 405, code: `INVALID_${req.method}` })
|
|
96
|
+
}
|
|
97
|
+
from.ref[0] = { id: from.ref[0], where: cds.ql.predicate(keys) }
|
|
93
98
|
}
|
|
94
99
|
query = UPDATE(_target)
|
|
95
100
|
break
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {import('../RestAdapter')} adapter
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('../RestAdapter')} adapter
|
|
3
3
|
* the adapter instance in which this middleware is used
|
|
4
4
|
*/
|
|
5
5
|
module.exports = exports = adapter => exports.read.bind(adapter)
|
|
@@ -8,7 +8,7 @@ module.exports = exports = adapter => exports.read.bind(adapter)
|
|
|
8
8
|
* @type {import('express').Handler}
|
|
9
9
|
* @this import('../RestAdapter')
|
|
10
10
|
*/
|
|
11
|
-
exports.read = async function rest_read
|
|
11
|
+
exports.read = async function rest_read(req, res) {
|
|
12
12
|
const { _query: query, _target: target, _data: data, _params: params } = req
|
|
13
13
|
|
|
14
14
|
let result,
|
|
@@ -15,6 +15,45 @@ might use a deprecated flag only for a limited period of time.
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
## Version 7.1.0 - 2026-08-27
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
- **compiler:**
|
|
23
|
+
+ It is now possible to extend a view/projection with a `where` or `having` clause, even if it already had one.
|
|
24
|
+
Extensions are joined with `and` if such a clause already exists.
|
|
25
|
+
+ Publishing an association with an empty filter is now supported. For a managed association, this turns it
|
|
26
|
+
into an unmanaged one. For an unmanaged association, it has no effect.
|
|
27
|
+
+ `select one` is now supported in `parse.cql` and `parse.expr`.
|
|
28
|
+
+ Compiler adds helper property `$backlink` to CSN. It enables compiler backends and other CSN consumers
|
|
29
|
+
to better handle backlink comparisons with `$self`. This property may vanish in future releases.
|
|
30
|
+
- **odata:**
|
|
31
|
+
+ Update OData vocabularies: Common and UI.
|
|
32
|
+
- **sql:**
|
|
33
|
+
+ Wrap predicate columns in `CASE ... WHEN` for SAP HANA.
|
|
34
|
+
+ Support common `cds.Vector` functions on SAP HANA and Postgres.
|
|
35
|
+
|
|
36
|
+
### Bug Fixes
|
|
37
|
+
|
|
38
|
+
- **compiler:**
|
|
39
|
+
+ Properly render structures with property `...` in CDL.
|
|
40
|
+
+ Extending a `where`, `having` or `group by` clause from unrelated layers no longer results in an error.
|
|
41
|
+
A warning is emitted when extending an `order by` clause from unrelated layers.
|
|
42
|
+
- **effective:**
|
|
43
|
+
+ Correctly rewrite references in annotation expressions inside arrays.
|
|
44
|
+
+ Add option to replace annotation expressions by strings to evade error situations.
|
|
45
|
+
- **sql:**
|
|
46
|
+
+ Don't dump while reporting an error for `$self` in a filter of a `from` reference.
|
|
47
|
+
+ Correctly handle renamed target elements in backlink comparisons.
|
|
48
|
+
|
|
49
|
+
### Improvements
|
|
50
|
+
|
|
51
|
+
- **compiler:**
|
|
52
|
+
+ Issue a warning that a type with an unmanaged association can only be used as an include.
|
|
53
|
+
+ Omit empty extend for `extend … with definitions` from parsed CSN.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
18
57
|
## Version 7.0.3 - 2026-07-21
|
|
19
58
|
|
|
20
59
|
### Bug Fixes
|
|
@@ -34,10 +73,10 @@ might use a deprecated flag only for a limited period of time.
|
|
|
34
73
|
- **compiler:**
|
|
35
74
|
+ Avoid dump for a new association in a projection with backlink comparison while reporting a missing backlink target element.
|
|
36
75
|
+ Soften incompatibility concerning backlink comparisons: missing target elements which are referred to in the foreign keys or ON-condition of the backlink
|
|
37
|
-
association now only lead to a warning.
|
|
76
|
+
association now only lead to a warning, not an error.
|
|
38
77
|
+ Soften incompatibility concerning structure values for annotations: a structure property like `list` won't be rejected; we avoid an ambiguity with an
|
|
39
|
-
_expression_ `(1, 2, 3)` by putting `'=': true` next to `list: …` in the CSN, like in compiler v6.
|
|
40
|
-
though.
|
|
78
|
+
_expression_ `(1, 2, 3)` by putting `'=': true` next to `list: …` in the CSN, like in compiler v6.
|
|
79
|
+
A `xpr` expression and an `#` enum symbol are rendered without a sibling `=`, though.
|
|
41
80
|
|
|
42
81
|
|
|
43
82
|
|
|
@@ -55,9 +94,9 @@ might use a deprecated flag only for a limited period of time.
|
|
|
55
94
|
unless the expression is a simple reference. An object as annotation value with a “primary expression property” like
|
|
56
95
|
`ref` or `xpr` is always interpreted as an expression. Before, it was only interpreted as expression if the object also
|
|
57
96
|
contained a property `=`. In order to avoid ambiguities, it is not allowed to provide structured annotation values that
|
|
58
|
-
could be confused with expressions.
|
|
59
|
-
+ Expression-like values that are not simple references are no longer allowed as comparator value
|
|
60
|
-
extending array
|
|
97
|
+
could be confused with expressions. See also the fix in Version 7.0.2 (`=` is only omitted for `xpr` and `#`).
|
|
98
|
+
+ Expression-like values that are not simple references or literals are no longer allowed (and partly ignored) as comparator value
|
|
99
|
+
for `... up to` when extending array-like annotation values. Simple references now are handled correctly.
|
|
61
100
|
+ `null` as annotation value is now propagated like any other value. Exceptions are `includes` with multiple structures/aspects:
|
|
62
101
|
value `null` from a later include does not overwrite a value from an earlier include (no change compared to previous releases).
|
|
63
102
|
+ The compiler now reports an error when multiple `extend ... with <aspect>` statements introduce the same element or action.
|
|
@@ -66,6 +105,7 @@ might use a deprecated flag only for a limited period of time.
|
|
|
66
105
|
+ The rules for the propagation of `key` in queries have been simplified: Keys are propagated, if no explicit key is set in
|
|
67
106
|
the query and all key elements of the primary base entity and of joined entities are selected.
|
|
68
107
|
+ No longer propagate the `key` property of the elements of structures which are included into a structured type.
|
|
108
|
+
+ Replace option `v7KeyPropagation` by option `v6KeyPropagation` with inverted semantics.
|
|
69
109
|
+ It is no longer possible to extend built-in types by adding type properties.
|
|
70
110
|
+ Always propagate annotation with `elements` and `enum` expansion.
|
|
71
111
|
+ Ensure that recompiling a CSN of flavor `gensrc` / `xtended` does not change the element order.
|
|
@@ -113,6 +153,16 @@ might use a deprecated flag only for a limited period of time.
|
|
|
113
153
|
(for the message IDs `type-missing-argument`, `type-unexpected-argument`, `ref-unsupported-type`, and `ref-unexpected-args`).
|
|
114
154
|
|
|
115
155
|
|
|
156
|
+
## Version 6.9.4 - 2026-07-29
|
|
157
|
+
|
|
158
|
+
### Bug Fixes
|
|
159
|
+
|
|
160
|
+
- **effective:**
|
|
161
|
+
+ Correctly rewrite references in annotation expressions inside arrays.
|
|
162
|
+
+ Add option to replace annotation expressions by strings to evade error situations.
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
116
166
|
## Version 6.9.3 - 2026-06-17
|
|
117
167
|
|
|
118
168
|
### Bug Fixes
|
|
@@ -367,8 +417,10 @@ whose target does not exist.
|
|
|
367
417
|
|
|
368
418
|
### Added
|
|
369
419
|
|
|
370
|
-
- compiler:
|
|
371
|
-
|
|
420
|
+
- compiler:
|
|
421
|
+
+ `annotate … with @extension.code: [..., 'additional code']` even works
|
|
422
|
+
if no value for that annotation has been provided with the base definition.
|
|
423
|
+
+ In the query section of a view definitions, `key` can now also be specified in top level inlines.
|
|
372
424
|
- to.sql: Calculated elements can now be used next to (but not in) nested projections.
|
|
373
425
|
- to.edm(x): The `@cds.api.ignore` annotation can now be applied to actions, functions, and their parameters.
|
|
374
426
|
|
|
@@ -377,7 +377,7 @@ async function executeCommandLine( command, options, args ) {
|
|
|
377
377
|
function forEffective( model ) {
|
|
378
378
|
const features = [
|
|
379
379
|
'resolveSimpleTypes', 'resolveProjections',
|
|
380
|
-
'remapOdataAnnotations', 'keepLocalized',
|
|
380
|
+
'stringifyAnnoXpr', 'remapOdataAnnotations', 'keepLocalized',
|
|
381
381
|
];
|
|
382
382
|
for (const feature of features) {
|
|
383
383
|
if (options[feature]) // map to boolean equivalent
|
|
@@ -390,7 +390,7 @@ async function executeCommandLine( command, options, args ) {
|
|
|
390
390
|
}
|
|
391
391
|
|
|
392
392
|
function forSeal( model ) {
|
|
393
|
-
const features = [ 'remapOdataAnnotations', 'deriveAnalyticalAnnotations' ];
|
|
393
|
+
const features = [ 'stringifyAnnoXpr', 'remapOdataAnnotations', 'deriveAnalyticalAnnotations' ];
|
|
394
394
|
for (const feature of features) {
|
|
395
395
|
if (options[feature]) // map to boolean equivalent
|
|
396
396
|
options[feature] = options[feature] === 'true';
|