@sap/cds 7.9.4 → 8.0.4
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 +128 -3659
- package/_i18n/i18n_en_US_saptrc.properties +113 -0
- package/_i18n/i18n_zh_CN.properties +7 -4
- package/app/index.css +129 -0
- package/app/index.html +16 -64
- package/app/index.js +14 -9
- package/bin/args.js +34 -0
- package/bin/serve.js +18 -24
- package/bin/test.js +97 -0
- package/common.cds +5 -12
- package/eslint.config.mjs +133 -0
- package/lib/auth/basic-auth.js +16 -20
- package/lib/auth/dummy-auth.js +1 -1
- package/lib/auth/ias-auth.js +9 -41
- package/lib/auth/index.js +1 -14
- package/lib/auth/jwt-auth.js +10 -40
- package/lib/compile/cds-compile.js +1 -2
- package/lib/compile/cdsc.js +21 -26
- package/lib/compile/etc/_localized.js +1 -6
- package/lib/compile/etc/csv.js +1 -1
- package/lib/compile/etc/properties.js +1 -1
- package/lib/compile/for/java.js +1 -1
- package/lib/compile/for/lean_drafts.js +4 -6
- package/lib/compile/for/nodejs.js +1 -1
- package/lib/compile/parse.js +4 -0
- package/lib/compile/resolve.js +4 -4
- package/lib/compile/to/edm-files.js +16 -23
- package/lib/compile/to/hana.js +27 -0
- package/lib/compile/to/json.js +1 -1
- package/lib/compile/to/sql.js +5 -1
- package/lib/compile/to/yaml.js +3 -3
- package/lib/dbs/cds-deploy.js +4 -2
- package/lib/env/cds-env.js +10 -14
- package/lib/env/cds-requires.js +30 -13
- package/lib/env/defaults.js +46 -16
- package/lib/env/plugins.js +1 -1
- package/lib/env/schemas/cds-rc.js +8 -4
- package/lib/env/schemas/index.js +7 -7
- package/lib/env/serviceBindings.js +1 -1
- package/lib/index.js +12 -10
- package/lib/lazy.js +1 -1
- package/lib/linked/classes.js +36 -8
- package/lib/linked/entities.js +2 -10
- package/lib/linked/models.js +2 -1
- package/lib/linked/validate.js +292 -0
- package/lib/log/cds-error.js +0 -6
- package/lib/log/cds-log.js +3 -3
- package/lib/log/format/json.js +1 -1
- package/lib/log/service/index.js +0 -1
- package/lib/plugins.js +2 -2
- package/lib/ql/Query.js +2 -10
- package/lib/ql/SELECT.js +1 -1
- package/lib/ql/Whereable.js +3 -2
- package/lib/req/cds-context.js +14 -25
- package/lib/req/context.js +23 -25
- package/lib/req/request.js +1 -34
- package/lib/req/user.js +47 -35
- package/lib/srv/bindings.js +1 -1
- package/lib/srv/cds-connect.js +4 -4
- package/lib/srv/cds-serve.js +2 -2
- package/lib/srv/factory.js +1 -1
- package/lib/srv/middlewares/cds-context.js +11 -22
- package/lib/srv/middlewares/ctx-model.js +2 -3
- package/lib/srv/middlewares/errors.js +41 -8
- package/lib/srv/middlewares/index.js +3 -3
- package/lib/srv/middlewares/trace.js +0 -2
- package/lib/srv/protocols/hcql.js +15 -10
- package/lib/srv/protocols/http.js +44 -49
- package/lib/srv/protocols/index.js +1 -23
- package/lib/srv/protocols/odata-v4.js +12 -74
- package/lib/srv/protocols/rest.js +1 -13
- package/lib/srv/srv-api.js +0 -20
- package/lib/srv/srv-dispatch.js +3 -2
- package/lib/srv/srv-handlers.js +22 -11
- package/lib/srv/srv-methods.js +2 -2
- package/lib/srv/srv-models.js +3 -36
- package/lib/test/expect.js +343 -0
- package/lib/test/index.js +2 -0
- package/lib/test/reporter.js +176 -0
- package/lib/utils/axios.js +10 -9
- package/lib/utils/cds-test.js +85 -36
- package/lib/utils/cds-utils.js +54 -7
- package/lib/utils/check-version.js +0 -4
- package/lib/utils/colors.js +49 -0
- package/lib/utils/data.js +5 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +3 -30
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +6 -12
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +4 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +12 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +2 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +1 -0
- 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 +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/AbstractEdmStructuredType.js +1 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +5 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +9 -43
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +8 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +4 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +1 -3
- package/libx/_runtime/cds-services/util/assert.js +1 -1
- package/libx/_runtime/cds.js +10 -3
- package/libx/_runtime/common/Service.js +12 -32
- package/libx/_runtime/common/aspects/any.js +1 -0
- package/libx/_runtime/common/code-ext/execute.js +1 -1
- package/libx/_runtime/common/code-ext/worker.js +0 -1
- package/libx/_runtime/common/composition/data.js +0 -1
- package/libx/_runtime/common/composition/delete.js +0 -1
- package/libx/_runtime/common/composition/tree.js +0 -1
- package/libx/_runtime/common/composition/update.js +3 -3
- package/libx/_runtime/common/error/frontend.js +21 -12
- package/libx/_runtime/common/error/log.js +36 -0
- package/libx/_runtime/common/error/utils.js +2 -5
- package/libx/_runtime/common/generic/auth/autoexpose.js +18 -17
- package/libx/_runtime/common/generic/auth/expand.js +1 -1
- package/libx/_runtime/common/generic/auth/readOnly.js +1 -2
- package/libx/_runtime/common/generic/auth/restrict.js +23 -42
- package/libx/_runtime/common/generic/auth/restrictions.js +2 -7
- package/libx/_runtime/common/generic/auth/utils.js +91 -88
- package/libx/_runtime/common/generic/crud.js +6 -5
- package/libx/_runtime/common/generic/etag.js +7 -12
- package/libx/_runtime/common/generic/input.js +70 -68
- package/libx/_runtime/common/generic/paging.js +1 -0
- package/libx/_runtime/common/generic/sorting.js +1 -0
- package/libx/_runtime/common/generic/temporal.js +8 -2
- package/libx/_runtime/common/i18n/index.js +1 -1
- package/libx/_runtime/common/i18n/messages.properties +3 -1
- package/libx/_runtime/common/utils/binary.js +8 -2
- package/libx/_runtime/common/utils/compareJson.js +5 -1
- package/libx/_runtime/common/utils/copy.js +6 -11
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +16 -14
- package/libx/_runtime/common/utils/differ.js +3 -6
- package/libx/_runtime/common/utils/keys.js +77 -18
- package/libx/_runtime/common/utils/postProcess.js +12 -15
- package/libx/_runtime/common/utils/propagateForeignKeys.js +0 -1
- package/libx/_runtime/common/utils/resolveView.js +2 -3
- package/libx/_runtime/common/utils/restrictions.js +45 -17
- package/libx/_runtime/common/utils/rewriteAsterisks.js +1 -8
- package/libx/_runtime/common/utils/stream.js +3 -16
- package/libx/_runtime/common/utils/streamProp.js +8 -18
- package/libx/_runtime/common/utils/structured.js +1 -1
- package/libx/_runtime/common/utils/ucsn.js +0 -2
- package/libx/_runtime/db/Service.js +0 -72
- package/libx/_runtime/db/data-conversion/post-processing.js +0 -1
- package/libx/_runtime/db/expand/expandCQNToJoin.js +9 -9
- package/libx/_runtime/db/expand/rawToExpanded.js +0 -8
- package/libx/_runtime/db/generic/input.js +3 -8
- package/libx/_runtime/db/generic/rewrite.js +1 -0
- package/libx/_runtime/db/query/read.js +2 -2
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -1
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
- package/libx/_runtime/db/utils/columns.js +2 -6
- package/libx/_runtime/fiori/lean-draft.js +138 -56
- package/libx/_runtime/hana/Service.js +0 -1
- package/libx/_runtime/hana/driver.js +1 -1
- package/libx/_runtime/hana/dynatrace.js +1 -2
- package/libx/_runtime/hana/pool.js +11 -21
- package/libx/_runtime/hana/streaming.js +0 -1
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +0 -1
- package/libx/_runtime/messaging/common-utils/authorizedRequest.js +1 -1
- package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -33
- package/libx/_runtime/messaging/event-broker.js +54 -27
- package/libx/_runtime/messaging/file-based.js +3 -3
- package/libx/_runtime/messaging/http-utils/token.js +1 -1
- package/libx/_runtime/messaging/kafka.js +2 -2
- package/libx/_runtime/messaging/redis-messaging.js +0 -1
- package/libx/_runtime/remote/Service.js +25 -25
- package/libx/_runtime/remote/utils/client.js +4 -5
- package/libx/_runtime/remote/utils/cloudSdkProvider.js +0 -3
- package/libx/_runtime/remote/utils/data.js +0 -1
- package/libx/_runtime/sqlite/Service.js +1 -2
- package/libx/_runtime/ucl/Service.js +37 -78
- package/libx/common/assert/index.js +22 -21
- package/libx/common/assert/type-relaxed.js +39 -0
- package/libx/common/assert/utils.js +3 -2
- package/libx/common/assert/validation.js +3 -8
- package/libx/common/utils/index.js +5 -0
- package/libx/common/utils/path.js +51 -0
- package/libx/odata/ODataAdapter.js +126 -0
- package/libx/odata/index.js +15 -2
- package/libx/odata/middleware/batch.js +320 -84
- package/libx/odata/middleware/body-parser.js +33 -0
- package/libx/odata/middleware/create.js +44 -59
- package/libx/odata/middleware/delete.js +23 -12
- package/libx/odata/middleware/error.js +30 -6
- package/libx/odata/middleware/metadata.js +38 -26
- package/libx/odata/middleware/operation.js +93 -69
- package/libx/odata/middleware/parse.js +6 -8
- package/libx/odata/middleware/read.js +117 -93
- package/libx/odata/middleware/service-document.js +22 -19
- package/libx/odata/middleware/stream.js +54 -56
- package/libx/odata/middleware/update.js +79 -87
- package/libx/odata/parse/afterburner.js +191 -175
- package/libx/odata/parse/cqn2odata.js +5 -5
- package/libx/odata/parse/grammar.peggy +27 -20
- package/libx/odata/parse/multipartToJson.js +17 -9
- package/libx/odata/parse/parser.js +1 -1
- package/libx/odata/utils/etag.js +14 -6
- package/libx/odata/utils/index.js +84 -12
- package/libx/odata/utils/metadata.js +161 -0
- package/libx/odata/utils/postProcess.js +89 -0
- package/libx/odata/utils/readAfterWrite.js +134 -17
- package/libx/odata/utils/result.js +36 -142
- package/libx/outbox/index.js +4 -3
- package/libx/rest/RestAdapter.js +115 -182
- package/libx/rest/middleware/create.js +28 -24
- package/libx/rest/middleware/delete.js +7 -10
- package/libx/rest/middleware/error.js +26 -16
- package/libx/rest/middleware/operation.js +48 -41
- package/libx/rest/middleware/parse.js +128 -126
- package/libx/rest/middleware/read.js +20 -27
- package/libx/rest/middleware/update.js +26 -31
- package/package.json +17 -8
- package/server.js +4 -2
- package/apis/cds.d.ts +0 -3
- package/apis/core.d.ts +0 -21
- package/apis/cqn.d.ts +0 -18
- package/apis/csn.d.ts +0 -21
- package/apis/events.d.ts +0 -18
- package/apis/internal/inference.d.ts +0 -18
- package/apis/linked.d.ts +0 -18
- package/apis/log.d.ts +0 -20
- package/apis/models.d.ts +0 -18
- package/apis/ql.d.ts +0 -18
- package/apis/reflect.d.ts +0 -32
- package/apis/server.d.ts +0 -18
- package/apis/services.d.ts +0 -22
- package/bin/cds-serve.js +0 -56
- package/lib/compile/to/gql.js +0 -15
- package/lib/srv/protocols/_legacy.js +0 -44
- package/lib/utils/jest.js +0 -43
- package/libx/_runtime/auth/index.js +0 -193
- package/libx/_runtime/auth/strategies/JWT.js +0 -37
- package/libx/_runtime/auth/strategies/basic.js +0 -20
- package/libx/_runtime/auth/strategies/dummy.js +0 -14
- package/libx/_runtime/auth/strategies/ias-auth.js +0 -1
- package/libx/_runtime/auth/strategies/mock.js +0 -77
- package/libx/_runtime/auth/strategies/xssecUtils.js +0 -93
- package/libx/_runtime/auth/strategies/xsuaa.js +0 -38
- package/libx/_runtime/common/perf/index.js +0 -19
- package/libx/_runtime/common/utils/ensureIEEE754.js +0 -29
- package/libx/_runtime/fiori/draft.js +0 -2
- package/libx/_runtime/fiori/generic/activate.js +0 -190
- package/libx/_runtime/fiori/generic/before.js +0 -201
- package/libx/_runtime/fiori/generic/cancel.js +0 -19
- package/libx/_runtime/fiori/generic/delete.js +0 -21
- package/libx/_runtime/fiori/generic/edit.js +0 -157
- package/libx/_runtime/fiori/generic/index.js +0 -25
- package/libx/_runtime/fiori/generic/new.js +0 -82
- package/libx/_runtime/fiori/generic/patch.js +0 -101
- package/libx/_runtime/fiori/generic/prepare.js +0 -57
- package/libx/_runtime/fiori/generic/read.js +0 -1340
- package/libx/_runtime/fiori/generic/readOverDraft.js +0 -146
- package/libx/_runtime/fiori/utils/csn.js +0 -13
- package/libx/_runtime/fiori/utils/delete.js +0 -114
- package/libx/_runtime/fiori/utils/handler.js +0 -264
- package/libx/_runtime/fiori/utils/lockInfo.js +0 -27
- package/libx/_runtime/fiori/utils/req.js +0 -23
- package/libx/_runtime/fiori/utils/stream.js +0 -36
- package/libx/_runtime/fiori/utils/where.js +0 -254
- package/libx/_runtime/index.js +0 -22
- package/libx/odata/utils/handler.js +0 -120
- package/libx/odata/utils/metaInfo.js +0 -410
- package/libx/odata/utils/path.js +0 -75
- package/libx/rest/RestRequest.js +0 -32
- package/libx/rest/index.js +0 -3
- package/libx/rest/readme.md +0 -1
- /package/libx/common/assert/{type.js → type-strict.js} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const cds = require('../../../../cds')
|
|
2
|
+
|
|
2
3
|
const { isStandardError } = require('../../../../common/error/standardError')
|
|
3
4
|
|
|
4
5
|
const { StatusCodes: HttpStatusCodes } = require('../okra/odata-commons/http/HttpStatusCode')
|
|
@@ -21,7 +22,7 @@ const ERROR_TO_HTTP_CODE = {
|
|
|
21
22
|
DeserializationError: HttpStatusCodes.BAD_REQUEST
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
const { normalizeError } = require('../../../../common/error/frontend')
|
|
25
|
+
const { normalizeError, unwrapMultipleErrors } = require('../../../../common/error/frontend')
|
|
25
26
|
|
|
26
27
|
const _beautifyMessage = msg => (msg.endsWith('.') ? msg : msg + '.')
|
|
27
28
|
|
|
@@ -83,7 +84,6 @@ const _betterOkraError = err => {
|
|
|
83
84
|
* @returns {Function}
|
|
84
85
|
*/
|
|
85
86
|
const getErrorHandler = (crashOnError = true, srv) => {
|
|
86
|
-
// eslint-disable-next-line complexity
|
|
87
87
|
return async (odataReq, odataRes, next, err) => {
|
|
88
88
|
// REVISIT: crashOnError
|
|
89
89
|
if (isStandardError(err) && crashOnError) {
|
|
@@ -124,7 +124,7 @@ const getErrorHandler = (crashOnError = true, srv) => {
|
|
|
124
124
|
// lost cds.context -> as we fixed that we don't get into this if branch anymore,
|
|
125
125
|
// but then the ctx in the else branch below isn't the ODataRequest anymore
|
|
126
126
|
// > error before req was dispatched
|
|
127
|
-
const creq = new cds.Request({ req, res: req.res, user:
|
|
127
|
+
const creq = new cds.Request({ req, res: req.res, user: cds.context.user })
|
|
128
128
|
for (const each of srv._handlers._error) each.handler.call(srv, err, creq)
|
|
129
129
|
} else if (ctx._tx?._done !== 'rolled back') {
|
|
130
130
|
// > error after req was dispatched, e.g., serialization error in okra
|
|
@@ -146,18 +146,12 @@ const getErrorHandler = (crashOnError = true, srv) => {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
const { error, statusCode } = normalizeError(err, req)
|
|
149
|
+
|
|
149
150
|
// REVISIT: We should also pass stack traces in development
|
|
150
151
|
// if (!cds.env.production) error.stack = err.stack
|
|
151
152
|
|
|
152
|
-
if (cds.env.fiori.wrap_multiple_errors === false) {
|
|
153
|
-
|
|
154
|
-
// Root level: First error, Details: Other errors
|
|
155
|
-
if (error.details) {
|
|
156
|
-
const [firstDetail, ...restDetails] = error.details
|
|
157
|
-
Object.assign(error, firstDetail)
|
|
158
|
-
if (restDetails.length) error.details = restDetails
|
|
159
|
-
else delete error.details
|
|
160
|
-
}
|
|
153
|
+
if (error.details && cds.env.fiori.wrap_multiple_errors === false) {
|
|
154
|
+
unwrapMultipleErrors(error)
|
|
161
155
|
}
|
|
162
156
|
|
|
163
157
|
next(null, Object.assign(error, { statusCode }))
|
|
@@ -20,9 +20,7 @@ const mpSupportsEmptyLocale = () => {
|
|
|
20
20
|
const metadata = service => {
|
|
21
21
|
return async (odataReq, odataRes, next) => {
|
|
22
22
|
const req = odataReq.getIncomingRequest()
|
|
23
|
-
const tenant
|
|
24
|
-
// REVISIT: can we take locale from user, or is there some odata special wrt metadata?
|
|
25
|
-
const locale = odataRes.getContract().getLocale()
|
|
23
|
+
const { tenant, locale } = cds.context
|
|
26
24
|
|
|
27
25
|
try {
|
|
28
26
|
const { 'cds.xt.ModelProviderService': mps } = cds.services
|
|
@@ -7,16 +7,13 @@ module.exports = srv => {
|
|
|
7
7
|
const containsRestrictions = containsAnyRestrictions(srv)
|
|
8
8
|
const accessRestrictions = getAccessRestrictions(srv)
|
|
9
9
|
|
|
10
|
-
// eslint-disable-next-line complexity
|
|
11
10
|
return function ODataRequestHandler(odataReq, odataRes, next) {
|
|
12
11
|
const req = odataReq.getBatchApplicationData()
|
|
13
12
|
? odataReq.getBatchApplicationData().req
|
|
14
13
|
: odataReq.getIncomingRequest()
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const { res, user, path, headers } = req
|
|
15
|
+
const { res, path, headers } = req
|
|
16
|
+
const { user } = cds.context
|
|
20
17
|
|
|
21
18
|
const { protectMetadata } = cds.env.odata
|
|
22
19
|
if (protectMetadata === false && (path === '/' || path.endsWith('/$metadata'))) {
|
|
@@ -25,7 +22,7 @@ module.exports = srv => {
|
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
// in case of $batch we need to challenge directly, as the header is not processed if in $batch response body
|
|
28
|
-
if (containsRestrictions && path.endsWith('/$batch') &&
|
|
25
|
+
if (containsRestrictions && path.endsWith('/$batch') && user._is_anonymous) {
|
|
29
26
|
// NOTE: "return req._login()" would not invoke custom error handlers
|
|
30
27
|
if (req._login) res.set('www-authenticate', `Basic realm="Users"`)
|
|
31
28
|
else if (user._challenges) res.set('www-authenticate', user._challenges.join(';'))
|
|
@@ -35,7 +32,7 @@ module.exports = srv => {
|
|
|
35
32
|
// check @restrict and @requires as soon as possible (DoS)
|
|
36
33
|
if (!accessRestrictions.some(r => user.is(r))) {
|
|
37
34
|
// > unauthorized or forbidden?
|
|
38
|
-
if (
|
|
35
|
+
if (user._is_anonymous) {
|
|
39
36
|
// NOTE: "return req._login()" would not invoke custom error handlers
|
|
40
37
|
if (req._login) res.set('www-authenticate', `Basic realm="Users"`)
|
|
41
38
|
else if (user._challenges) res.set('www-authenticate', user._challenges.join(';'))
|
|
@@ -14,14 +14,19 @@ const { hasOmitValuesPreference } = require('../utils/omitValues')
|
|
|
14
14
|
|
|
15
15
|
const { getSapMessages } = require('../../../../common/error/frontend')
|
|
16
16
|
|
|
17
|
+
const _extractIfNoneMatch = header => {
|
|
18
|
+
if (header) {
|
|
19
|
+
if (header.startsWith('W/')) header = header.substring(2)
|
|
20
|
+
if (header.startsWith('"') && header.endsWith('"')) header = header.substring(1, header.length - 1)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return header
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
const _isUpsertAllowed = req => {
|
|
18
27
|
return (
|
|
19
28
|
!(cds.env.runtime && cds.env.runtime.allow_upsert === false) &&
|
|
20
|
-
!(
|
|
21
|
-
req.target &&
|
|
22
|
-
req.target._isDraftEnabled &&
|
|
23
|
-
(!cds.env.fiori.lean_draft || (!req.data.IsActiveEntity && req.event === 'PATCH'))
|
|
24
|
-
)
|
|
29
|
+
!(req.target && req.target._isDraftEnabled && !req.data.IsActiveEntity && req.event === 'PATCH')
|
|
25
30
|
)
|
|
26
31
|
}
|
|
27
32
|
|
|
@@ -102,7 +107,8 @@ const _updateThenCreate = async (req, odataReq, odataRes, tx) => {
|
|
|
102
107
|
} catch (e) {
|
|
103
108
|
const is404 = e.code === 404 || e.status === 404 || e.statusCode === 404
|
|
104
109
|
const isForcedInsert =
|
|
105
|
-
(e.code === 412 || e.status === 412 || e.statusCode === 412) &&
|
|
110
|
+
(e.code === 412 || e.status === 412 || e.statusCode === 412) &&
|
|
111
|
+
_extractIfNoneMatch(req.headers?.['if-none-match']) === '*'
|
|
106
112
|
if ((is404 || isForcedInsert) && _isUpsertAllowed(req)) {
|
|
107
113
|
// PUT/ PATCH with if-match header means "only if already exists", i.e., no insert if not
|
|
108
114
|
if (req.headers['if-match']) {
|
|
@@ -56,7 +56,7 @@ class ExpressionToCQN {
|
|
|
56
56
|
// cut off ms if cds.DateTime
|
|
57
57
|
return { val: new Date(value).toISOString().replace(/\.\d\d\dZ$/, 'Z') }
|
|
58
58
|
return { val: normalizeTimestamp(value) }
|
|
59
|
-
} catch
|
|
59
|
+
} catch {
|
|
60
60
|
throw Object.assign(new Error(`The type Edm.DateTimeOffset is not compatible with "${value}"`), {
|
|
61
61
|
status: 400
|
|
62
62
|
})
|
|
@@ -189,14 +189,13 @@ class ExpressionToCQN {
|
|
|
189
189
|
ele.list = JSON.parse(ele.val).map(ele => ({ val: ele }))
|
|
190
190
|
delete ele.val
|
|
191
191
|
}
|
|
192
|
-
} catch
|
|
192
|
+
} catch {
|
|
193
193
|
// ignore
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
return operator ? [operator, { func: `${methodName}`, args }] : { func: `${methodName}`, args }
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
/* eslint-disable complexity */
|
|
200
199
|
/**
|
|
201
200
|
* Evaluate an method expression, which in SQL would be 'column condition value'.
|
|
202
201
|
* Can also be nested.
|
|
@@ -241,7 +240,6 @@ class ExpressionToCQN {
|
|
|
241
240
|
throw getFeatureNotSupportedError(`Method "${method}" in $filter or $orderby query options`)
|
|
242
241
|
}
|
|
243
242
|
}
|
|
244
|
-
/* eslint-enable complexity */
|
|
245
243
|
|
|
246
244
|
_ensureArr(something) {
|
|
247
245
|
return Array.isArray(something) ? something : [something]
|
|
@@ -230,6 +230,7 @@ const applyToCQN = (transformations, entity, model) => {
|
|
|
230
230
|
break
|
|
231
231
|
default: {
|
|
232
232
|
const numericKind = transformation.getKind()
|
|
233
|
+
// eslint-disable-next-line no-unused-vars
|
|
233
234
|
const stringKind = Object.entries(TransformationKind).find(([_, v]) => v === numericKind)?.[0]
|
|
234
235
|
throw getFeatureNotSupportedError(`Transformation "${stringKind || numericKind}" with query option $apply`)
|
|
235
236
|
}
|
|
@@ -222,7 +222,7 @@ const expandToCQN = (expandItems, type, service, options) => {
|
|
|
222
222
|
const allElements = []
|
|
223
223
|
const isAll = expandItems.some(item => item.isAll())
|
|
224
224
|
|
|
225
|
-
for (const [name, navigationProperty] of type.getNavigationProperties(
|
|
225
|
+
for (const [name, navigationProperty] of type.getNavigationProperties()) {
|
|
226
226
|
const expandItem = _getExpandItem(isAll, expandItems, name)
|
|
227
227
|
|
|
228
228
|
if (isAll || expandItem) {
|
|
@@ -40,7 +40,6 @@ const parseToCqn = (component, service, target, data, odataReq, upsert) => {
|
|
|
40
40
|
return DELETE.from(_target)
|
|
41
41
|
}
|
|
42
42
|
case 'UPDATE':
|
|
43
|
-
// eslint-disable-next-line no-throw-literal
|
|
44
43
|
if (!one) throw { statusCode: 400, code: '400', message: `INVALID_${odataReq.getMethod()}` }
|
|
45
44
|
return UPDATE(_target).data(data)
|
|
46
45
|
default:
|
|
@@ -44,8 +44,7 @@ const { isStreaming } = require('../utils/stream')
|
|
|
44
44
|
const { getPageSize } = require('../../../../common/generic/paging')
|
|
45
45
|
const { isAsteriskColumn } = require('../../../../common/utils/rewriteAsterisks')
|
|
46
46
|
const { handleStreamProperties } = require('../../../../common/utils/streamProp')
|
|
47
|
-
|
|
48
|
-
const { ensureUnlocalized } = require('../../../../fiori/utils/handler')
|
|
47
|
+
const { ensureUnlocalized } = require('../../../../common/utils/draft')
|
|
49
48
|
|
|
50
49
|
const { skipToken: handleSkipToken } = require('../../../../../odata/utils')
|
|
51
50
|
|
|
@@ -309,7 +308,6 @@ const _skipToken = (token, cqn) => {
|
|
|
309
308
|
* @param {object} odataReq - OKRA's req
|
|
310
309
|
* @private
|
|
311
310
|
*/
|
|
312
|
-
// eslint-disable-next-line complexity
|
|
313
311
|
const readToCQN = (service, target, odataReq) => {
|
|
314
312
|
const uriInfo = odataReq.getUriInfo()
|
|
315
313
|
const segments = uriInfo.getPathSegments()
|
|
@@ -195,7 +195,7 @@ const getSegmentKeyValue = segmentParam => {
|
|
|
195
195
|
try {
|
|
196
196
|
val = value === 'undefined' ? undefined : JSON.parse(value)
|
|
197
197
|
return { keyName, val }
|
|
198
|
-
} catch
|
|
198
|
+
} catch {
|
|
199
199
|
// plain string
|
|
200
200
|
}
|
|
201
201
|
val = _parsePrimitiveValue(edmRef, value) //> REVISIT: undefined handling needed here as well?
|
|
@@ -190,11 +190,10 @@ class AbstractEdmStructuredType extends EdmType {
|
|
|
190
190
|
* Returns a map of navigation properties including those from base type.
|
|
191
191
|
* @returns {Map.<string, EdmNavigationProperty>} A Map of navigation properties
|
|
192
192
|
*/
|
|
193
|
-
getNavigationProperties (
|
|
193
|
+
getNavigationProperties () {
|
|
194
194
|
if (!this._navigationProperties) {
|
|
195
195
|
this._navigationProperties = new Map(this.getBaseType() ? this.getBaseType().getNavigationProperties() : [])
|
|
196
196
|
for (const [name, property] of this.getOwnNavigationProperties()) {
|
|
197
|
-
if (!cds.env.fiori.lean_draft && ignoreSibling && name === 'SiblingEntity') continue; // This will cause subtle caching bugs but will enable expand=* in old draft
|
|
198
197
|
this._navigationProperties.set(name, property)
|
|
199
198
|
}
|
|
200
199
|
}
|
|
@@ -214,6 +214,11 @@ class ResourceJsonDeserializer {
|
|
|
214
214
|
throw new DeserializationError(`Parameter '${paramName}' is not nullable`)
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
if (edmParam.isCollection() && !paramValue) {
|
|
218
|
+
if (paramValue === undefined) break
|
|
219
|
+
throw new DeserializationError(`'${edmParam.getName()}' must be a collection.`)
|
|
220
|
+
}
|
|
221
|
+
|
|
217
222
|
if (paramValue === undefined) {
|
|
218
223
|
// OData JSON Format Version 4.0 Plus Errata 03 - 17 Action Invocation:
|
|
219
224
|
// "Any parameter values not specified in the JSON object are assumed to have the null value."
|
|
@@ -354,7 +354,7 @@ class ContextURLFactory {
|
|
|
354
354
|
// Define a local function because navigation properties must be searched recursively.
|
|
355
355
|
const getExpandPaths = structuredType => {
|
|
356
356
|
let structureResult = []
|
|
357
|
-
for (const name of structuredType.getNavigationProperties(
|
|
357
|
+
for (const name of structuredType.getNavigationProperties().keys()) structureResult.push(name)
|
|
358
358
|
for (const [name, property] of structuredType.getProperties()) {
|
|
359
359
|
if (property.getType().getKind() === EdmTypeKind.COMPLEX) {
|
|
360
360
|
for (const innerPath of getExpandPaths(property.getType())) {
|
|
@@ -160,53 +160,35 @@ const _addForeignKeys = (service, odataReq, data) => {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
const _getFunctionParameters = (lastSegment, keyValues, service, target
|
|
164
|
-
const { cds_assert: CDS_ASSERT } = cds.env.features
|
|
165
|
-
|
|
163
|
+
const _getFunctionParameters = (lastSegment, keyValues, service, target) => {
|
|
166
164
|
const functionParameters = lastSegment.getFunctionParameters()
|
|
167
165
|
const paramValues = _getParamData(functionParameters)
|
|
168
166
|
|
|
169
167
|
// Working assumption for the case of name collisions: take the entity's key
|
|
170
168
|
for (const key in keyValues) paramValues[key] = keyValues[key]
|
|
171
169
|
|
|
172
|
-
let assertTarget
|
|
173
|
-
|
|
174
170
|
const errors = []
|
|
175
171
|
if (lastSegment.getKind() === 'BOUND.FUNCTION') {
|
|
176
172
|
const targetFunction = target && target.actions && target.actions[lastSegment.getFunction().getName()]
|
|
177
173
|
if (!targetFunction.params) return {}
|
|
178
|
-
|
|
179
|
-
else assertTarget = targetFunction
|
|
174
|
+
convertStructured(service, targetFunction, paramValues, { errors })
|
|
180
175
|
} else if (lastSegment.getKind() === 'FUNCTION.IMPORT') {
|
|
181
176
|
const { namespace, name } = lastSegment.getFunctionImport().getFullQualifiedName()
|
|
182
177
|
const targetFunction = service.model && service.model.definitions[`${namespace}.${name}`]
|
|
183
178
|
if (!targetFunction.params) return {}
|
|
184
|
-
|
|
185
|
-
else assertTarget = targetFunction
|
|
179
|
+
convertStructured(service, targetFunction, paramValues, { errors })
|
|
186
180
|
}
|
|
187
181
|
|
|
188
182
|
if (errors.length > 1) throw Object.assign(new Error(MULTIPLE_ERRORS), { details: errors })
|
|
189
183
|
if (errors.length === 1) throw errors[0]
|
|
190
184
|
|
|
191
|
-
if (CDS_ASSERT) {
|
|
192
|
-
const assertOptions = { filter: true, http: { req: odataReq.getIncomingRequest() } }
|
|
193
|
-
const errs = cds.assert(paramValues, assertTarget, assertOptions)
|
|
194
|
-
if (errs) {
|
|
195
|
-
if (errs.length === 1) throw errs[0]
|
|
196
|
-
throw Object.assign(new Error('MULTIPLE_ERRORS'), { statusCode: 400, details: errs })
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
185
|
return paramValues
|
|
201
186
|
}
|
|
202
187
|
|
|
203
188
|
const _getCopiedData = (odataReq, segments, service, target) => {
|
|
204
|
-
const { cds_assert: CDS_ASSERT } = cds.env.features
|
|
205
|
-
|
|
206
189
|
const lastSegment = segments[segments.length - 1]
|
|
207
190
|
|
|
208
191
|
let data = odataReq.getBody() || {}
|
|
209
|
-
let assertTarget = target
|
|
210
192
|
|
|
211
193
|
if (lastSegment.getKind() === 'PRIMITIVE.PROPERTY') {
|
|
212
194
|
data = { [lastSegment.getProperty().getName()]: data }
|
|
@@ -224,20 +206,18 @@ const _getCopiedData = (odataReq, segments, service, target) => {
|
|
|
224
206
|
if (lastSegment.getKind() === 'BOUND.ACTION') {
|
|
225
207
|
const targetAction = target.actions && target.actions[lastSegment.getAction().getName()]
|
|
226
208
|
if (!targetAction || !targetAction.params) return { data: {} }
|
|
227
|
-
|
|
228
|
-
else assertTarget = targetAction
|
|
209
|
+
convertStructured(service, targetAction, data)
|
|
229
210
|
} else if (lastSegment.getKind() === 'ACTION.IMPORT') {
|
|
230
211
|
const { namespace, name } = lastSegment.getActionImport().getFullQualifiedName()
|
|
231
212
|
const targetAction = service.model && service.model.definitions[`${namespace}.${name}`]
|
|
232
213
|
if (!targetAction || !targetAction.params) return { data: {} }
|
|
233
|
-
|
|
234
|
-
else assertTarget = targetAction
|
|
214
|
+
convertStructured(service, targetAction, data)
|
|
235
215
|
} else {
|
|
236
|
-
|
|
216
|
+
convertStructured(service, target, data)
|
|
237
217
|
}
|
|
238
218
|
}
|
|
239
219
|
|
|
240
|
-
return
|
|
220
|
+
return data
|
|
241
221
|
}
|
|
242
222
|
|
|
243
223
|
/**
|
|
@@ -263,7 +243,7 @@ const getData = (component, odataReq, service, target) => {
|
|
|
263
243
|
const keyValues = _getParamData(keyPredicates)
|
|
264
244
|
|
|
265
245
|
if (component === DATA_READ_HANDLER && _isFunctionInvocation(odataReq)) {
|
|
266
|
-
return _getFunctionParameters(lastSegment, keyValues, service, target
|
|
246
|
+
return _getFunctionParameters(lastSegment, keyValues, service, target)
|
|
267
247
|
}
|
|
268
248
|
|
|
269
249
|
if (component === DATA_DELETE_HANDLER || component === DATA_READ_HANDLER) {
|
|
@@ -274,7 +254,7 @@ const getData = (component, odataReq, service, target) => {
|
|
|
274
254
|
}
|
|
275
255
|
|
|
276
256
|
// copy so that original payload is preserved
|
|
277
|
-
const
|
|
257
|
+
const data = _getCopiedData(odataReq, segments, service, target)
|
|
278
258
|
|
|
279
259
|
// Only to be done for post via navigation
|
|
280
260
|
if (
|
|
@@ -295,20 +275,6 @@ const getData = (component, odataReq, service, target) => {
|
|
|
295
275
|
Array.isArray(data) ? Object.assign(data[0], keyValues) : Object.assign(data, keyValues)
|
|
296
276
|
}
|
|
297
277
|
|
|
298
|
-
// we need the (foreign) keys from the URL before asserting -> we can't assert in _getCopiedData()
|
|
299
|
-
if (cds.env.features.cds_assert && assertTarget) {
|
|
300
|
-
const assertOptions = {
|
|
301
|
-
filter: true,
|
|
302
|
-
http: { req: odataReq.getIncomingRequest() },
|
|
303
|
-
mandatories: component === 'CREATE' || undefined
|
|
304
|
-
}
|
|
305
|
-
const errs = cds.assert(data, assertTarget, assertOptions)
|
|
306
|
-
if (errs) {
|
|
307
|
-
if (errs.length === 1) throw errs[0]
|
|
308
|
-
throw Object.assign(new Error('MULTIPLE_ERRORS'), { statusCode: 400, details: errs })
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
278
|
return data
|
|
313
279
|
}
|
|
314
280
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const { removeDraftUUIDIfNecessary } = require('../../../../fiori/utils/handler')
|
|
2
1
|
const cds = require('../../../../cds')
|
|
3
2
|
const {
|
|
4
3
|
Request,
|
|
@@ -10,13 +9,19 @@ const { hasDeepUpdate } = require('../../../../common/composition/update')
|
|
|
10
9
|
const { WRITE_EVENTS, CDS_EVENTS } = require('../../../../common/constants/events')
|
|
11
10
|
const { addEtagColumns } = require('../../../../common/utils/etag')
|
|
12
11
|
|
|
12
|
+
// Only works for root entity, otherwise the relative position needs to be adapted
|
|
13
|
+
const removeDraftUUIDIfNecessary = req =>
|
|
14
|
+
req.http?.req?.headers?.['x-cds-odata-version'] === 'v2'
|
|
15
|
+
? () => {}
|
|
16
|
+
: result => delete result.DraftAdministrativeData_DraftUUID
|
|
17
|
+
|
|
13
18
|
const setLocationHeader = (req, { model }) => {
|
|
14
19
|
const { odataRes } = req._
|
|
15
20
|
const cqn = getSimpleSelectCQN(req.target, req.data)
|
|
16
21
|
const { path: location } = cds.odata.urlify(cqn, { kind: 'odata', model, method: 'GET' })
|
|
17
22
|
// REVISIT: needs reworking for new adapter, especially re $batch
|
|
18
23
|
if (odataRes) {
|
|
19
|
-
odataRes.setHeader('
|
|
24
|
+
odataRes.setHeader('location', location.replace(/\?.*$/, ''))
|
|
20
25
|
} else if (req.http?.res) {
|
|
21
26
|
req.http.res.set('location', location.replace(/\?.*$/, ''))
|
|
22
27
|
}
|
|
@@ -51,7 +56,7 @@ const _ensureKeysAreSelected = query => {
|
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
const readAfterWrite = async (req, srv, { operation,
|
|
59
|
+
const readAfterWrite = async (req, srv, { operation, columns }) => {
|
|
55
60
|
let query
|
|
56
61
|
|
|
57
62
|
if (_isActionOrFunction(req)) {
|
|
@@ -35,7 +35,9 @@ const validateResourcePath = (odataReq, service) => {
|
|
|
35
35
|
if (segment.getKind() === ENTITY || segment.getKind() === ENTITY_COLLECTION) {
|
|
36
36
|
const name = segment.getEntitySet().getName()
|
|
37
37
|
// REVISIT: This validation is violating all principles of locality
|
|
38
|
-
const entity =
|
|
38
|
+
const entity =
|
|
39
|
+
service.model.definitions[`${service.definition.name}.${name}`] ||
|
|
40
|
+
service.model.definitions[`${service.definition.name}.${name.replace(/_texts$/, '.texts')}`]
|
|
39
41
|
if (!entity) return
|
|
40
42
|
|
|
41
43
|
/*
|
|
@@ -50,7 +52,7 @@ const validateResourcePath = (odataReq, service) => {
|
|
|
50
52
|
return
|
|
51
53
|
}
|
|
52
54
|
throw getError(405, entity['@cds.autoexpose'] ? 'ENTITY_IS_AUTOEXPOSE_READONLY' : 'ENTITY_IS_AUTOEXPOSED', [
|
|
53
|
-
|
|
55
|
+
`${service.definition.name}.${name}`
|
|
54
56
|
])
|
|
55
57
|
}
|
|
56
58
|
}
|
|
@@ -53,7 +53,7 @@ const setStreamingHeaders = (result, req) => {
|
|
|
53
53
|
if ('$mediaContentDispositionFilename' in result && req) {
|
|
54
54
|
const cdt = result.$mediaContentDispositionType || 'attachment'
|
|
55
55
|
req._.odataRes.setHeader(
|
|
56
|
-
'
|
|
56
|
+
'content-disposition',
|
|
57
57
|
`${cdt}; filename="${encodeURIComponent(result.$mediaContentDispositionFilename)}"`
|
|
58
58
|
)
|
|
59
59
|
}
|
|
@@ -88,8 +88,6 @@ const _cleanupMetadata = (odataResult, result, req) => {
|
|
|
88
88
|
* @param {*} [req]
|
|
89
89
|
* @returns {string | object}
|
|
90
90
|
*/
|
|
91
|
-
// REVISIT: complexity
|
|
92
|
-
// eslint-disable-next-line complexity
|
|
93
91
|
const toODataResult = (result, req) => {
|
|
94
92
|
if (result == null) return ''
|
|
95
93
|
|
|
@@ -5,7 +5,7 @@ const templatePathSerializer = require('../../common/utils/templateProcessorPath
|
|
|
5
5
|
// REVISIT: replace with cds.Request
|
|
6
6
|
const getEntry = require('../../common/error/entry')
|
|
7
7
|
|
|
8
|
-
const typeCheckers = require('../../../common/assert/type')
|
|
8
|
+
const typeCheckers = require('../../../common/assert/type-strict')
|
|
9
9
|
const { 'cds.Decimal': checkDecimal } = typeCheckers
|
|
10
10
|
const { checkMandatory, checkEnum, checkRange, checkFormat } = require('../../../common/assert/validation')
|
|
11
11
|
|
package/libx/_runtime/cds.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** @type {import('../../lib')} */
|
|
2
1
|
const cds = require('../../lib')
|
|
3
2
|
module.exports = cds
|
|
4
3
|
|
|
@@ -11,6 +10,14 @@ cds.extend(Association).with(require('./common/aspects/Association'))
|
|
|
11
10
|
cds.extend(entity).with(require('./common/aspects/entity'))
|
|
12
11
|
|
|
13
12
|
/*
|
|
14
|
-
*
|
|
13
|
+
* Determines whether a request requires resolving of the target entity.
|
|
14
|
+
* Added to cds.Service so it can be reused in cds.ApplicationService and cds.RemoteService.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
cds.Service.prototype._requires_resolving = function (req) {
|
|
17
|
+
const already_resolved = req._resolved
|
|
18
|
+
const belongs_to_me = req.target?.name?.startsWith(this.definition?.name + '.')
|
|
19
|
+
const is_resolvable = this.model && _is_simple_cqn_query(req.query)
|
|
20
|
+
const requires_resolving = !(already_resolved || belongs_to_me) && is_resolvable
|
|
21
|
+
return requires_resolving
|
|
22
|
+
}
|
|
23
|
+
const _is_simple_cqn_query = q => typeof q === 'object' && q !== null && !Array.isArray(q) && Object.keys(q).length > 0
|
|
@@ -2,9 +2,6 @@ const cds = require('../cds')
|
|
|
2
2
|
|
|
3
3
|
const { resolveView, findQueryTarget } = require('./utils/resolveView')
|
|
4
4
|
const postProcess = require('./utils/postProcess')
|
|
5
|
-
const ensureIEEE754 = require('./utils/ensureIEEE754')
|
|
6
|
-
|
|
7
|
-
const _isSimpleCqnQuery = q => typeof q === 'object' && q !== null && !Array.isArray(q) && Object.keys(q).length > 0
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
7
|
* Generic Application Service Provider
|
|
@@ -70,7 +67,7 @@ class ApplicationService extends cds.Service {
|
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
static handle_fiori() {
|
|
73
|
-
require('../fiori/draft').impl.call(this)
|
|
70
|
+
require('../fiori/lean-draft').impl.call(this)
|
|
74
71
|
}
|
|
75
72
|
|
|
76
73
|
static handle_crud() {
|
|
@@ -80,37 +77,20 @@ class ApplicationService extends cds.Service {
|
|
|
80
77
|
// Overload .handle in order to resolve projections up to a definition that is known by the remote service instance.
|
|
81
78
|
// Result is post processed according to the inverse projection in order to reflect the correct result of the original query.
|
|
82
79
|
async handle(req) {
|
|
83
|
-
let result
|
|
84
|
-
|
|
80
|
+
let result
|
|
81
|
+
let target = req.target
|
|
85
82
|
|
|
86
|
-
if (
|
|
83
|
+
if (!this._requires_resolving(req)) {
|
|
87
84
|
result = await super.handle(req)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// REVISIT: get rid of this
|
|
97
|
-
if (req.query.SELECT?._4odata) Object.defineProperty(q.SELECT, '_4odata', { value: true })
|
|
98
|
-
|
|
99
|
-
// REVISIT: We need to provide target explicitly because it's cached already within ensure_target
|
|
100
|
-
const _req = new cds.Request({ query: q, target, _resolved: true })
|
|
85
|
+
} else {
|
|
86
|
+
const query = resolveView(req.query, this.model, this)
|
|
87
|
+
target = findQueryTarget(query) || req.target
|
|
88
|
+
// REVISIT: get rid of _4odata
|
|
89
|
+
if (req.query.SELECT?._4odata) Object.defineProperty(query.SELECT, '_4odata', { value: true })
|
|
90
|
+
// we need to provide target explicitly because it's cached within ensure_target
|
|
91
|
+
const _req = new cds.Request({ query, target, _resolved: true })
|
|
101
92
|
result = await super.dispatch(_req)
|
|
102
|
-
result = postProcess(
|
|
103
|
-
}
|
|
104
|
-
// default to super.handle()
|
|
105
|
-
else {
|
|
106
|
-
result = await super.handle(req)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// REVISIT: when do?
|
|
110
|
-
// const ieee754 = req.headers.accept?.match(/IEEE754Compatible=(\w+)/i)?.[1]
|
|
111
|
-
// if (cds.env.features.ensure_ieee754 || (cds.env.features.odata_new_adapter && ieee754 === 'true')) {
|
|
112
|
-
if (cds.env.features.ensure_ieee754) {
|
|
113
|
-
ensureIEEE754(target, this, result)
|
|
93
|
+
result = postProcess(query, result, this)
|
|
114
94
|
}
|
|
115
95
|
|
|
116
96
|
return result
|
|
@@ -36,7 +36,7 @@ module.exports = async function executeCode(code, req) {
|
|
|
36
36
|
const workerId = worker.id
|
|
37
37
|
const contextId = cds.utils.uuid()
|
|
38
38
|
const executePromise = new Promise(function executeCodePromiseExecutor(resolve, reject) {
|
|
39
|
-
queueMicrotask(AsyncResource.bind(onStarted))
|
|
39
|
+
queueMicrotask(AsyncResource.bind(onStarted)) // eslint-disable-line no-undef
|
|
40
40
|
const onMessageReceivedProxy = AsyncResource.bind(onMessageReceived)
|
|
41
41
|
const onErrorProxy = AsyncResource.bind(onError)
|
|
42
42
|
const onExitProxy = AsyncResource.bind(onExit)
|
|
@@ -10,7 +10,6 @@ parentPort.on('message', function onWorkerMessageReceived(message) {
|
|
|
10
10
|
if (kind !== 'start' || workerId !== workerData.id) return
|
|
11
11
|
if (LOG._debug) LOG.debug(`Post message received on worker thread (worker.js) from main thread`, message)
|
|
12
12
|
|
|
13
|
-
// eslint-disable-next-line cds/no-missing-dependencies
|
|
14
13
|
const { VM } = require('vm2')
|
|
15
14
|
const workerReq = new WorkerReq(contextId, reqData)
|
|
16
15
|
|
|
@@ -30,7 +30,6 @@ const _isSameEntityInWhere = (where, target, persistentObj) => {
|
|
|
30
30
|
const val = where[i + 2].val
|
|
31
31
|
const sign = where[i + 1]
|
|
32
32
|
|
|
33
|
-
// eslint-disable-next-line
|
|
34
33
|
if (target.elements[key].key && key in persistentObj && sign === '=' && val !== persistentObj[key]) {
|
|
35
34
|
return false
|
|
36
35
|
}
|