@sap/cds 5.9.8 → 6.0.3
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 +277 -20
- package/apis/services.d.ts +1 -1
- package/app/fiori/preview.js +2 -6
- package/app/index.js +3 -3
- package/bin/build/buildTaskEngine.js +17 -15
- package/bin/build/buildTaskFactory.js +29 -19
- package/bin/build/buildTaskHandler.js +27 -11
- package/bin/build/buildTaskProvider.js +2 -4
- package/bin/build/buildTaskProviderFactory.js +11 -16
- package/bin/build/constants.js +14 -6
- package/bin/build/csv-reader.js +2 -1
- package/bin/build/index.js +12 -18
- package/bin/build/provider/buildTaskHandlerEdmx.js +3 -39
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +149 -0
- package/bin/build/provider/buildTaskHandlerInternal.js +2 -3
- package/bin/build/provider/buildTaskProviderInternal.js +108 -239
- package/bin/build/provider/fiori/index.js +2 -2
- package/bin/build/provider/hana/2migration.js +11 -11
- package/bin/build/provider/hana/2tabledata.js +3 -3
- package/bin/build/provider/hana/index.js +89 -99
- package/bin/build/provider/hana/migrationtable.js +4 -3
- package/bin/build/provider/java/index.js +101 -0
- package/bin/build/provider/java-cf/index.js +1 -101
- package/bin/build/provider/mtx/index.js +83 -41
- package/bin/build/provider/mtx/resourcesTarBuilder.js +68 -0
- package/bin/build/provider/mtx-sidecar/index.js +110 -0
- package/bin/build/provider/node-cf/index.js +1 -308
- package/bin/build/provider/nodejs/index.js +189 -0
- package/bin/build/util.js +21 -31
- package/bin/cds.js +5 -3
- package/bin/deploy/to-hana/cfUtil.js +31 -6
- package/bin/deploy/to-hana/gitUtil.js +5 -3
- package/bin/deploy/to-hana/hana.js +15 -13
- package/bin/{build → deploy/to-hana}/mtaUtil.js +10 -9
- package/bin/mtx/in-cds.js +19 -7
- package/bin/serve.js +49 -22
- package/bin/utils/log.js +13 -30
- package/bin/version.js +4 -3
- package/common.cds +61 -16
- package/lib/compile/cdsc.js +3 -2
- package/lib/compile/etc/_localized.js +15 -14
- package/lib/compile/for/drafts.js +3 -4
- package/lib/compile/for/java.js +13 -10
- package/lib/compile/for/nodejs.js +8 -8
- package/lib/compile/for/odata.js +7 -12
- package/lib/compile/for/sql.js +5 -6
- package/lib/compile/index.js +5 -4
- package/lib/compile/load.js +9 -11
- package/lib/compile/minify.js +8 -5
- package/lib/compile/parse.js +4 -2
- package/lib/compile/resolve.js +18 -15
- package/lib/compile/to/edm.js +0 -1
- package/lib/compile/to/gql.js +3 -2
- package/lib/compile/to/json.js +24 -17
- package/lib/connect/bindings.js +3 -2
- package/lib/connect/index.js +5 -5
- package/lib/core/classes.js +74 -2
- package/lib/core/entities.js +52 -3
- package/lib/core/reflect.js +2 -1
- package/lib/deploy.js +10 -8
- package/lib/env/defaults.js +4 -3
- package/lib/env/index.js +71 -31
- package/lib/env/presets.js +1 -14
- package/lib/env/requires.js +71 -20
- package/lib/env/serviceBindings.js +147 -0
- package/lib/i18n/localize.js +22 -23
- package/lib/index.js +148 -144
- package/lib/log/errors.js +55 -12
- package/lib/log/format/kibana.js +1 -1
- package/lib/log/index.js +4 -0
- package/lib/ql/SELECT.js +7 -2
- package/lib/ql/Whereable.js +8 -2
- package/lib/ql/index.js +2 -2
- package/lib/req/assert.js +71 -0
- package/lib/req/cds-context.js +38 -70
- package/lib/req/context.js +34 -21
- package/lib/req/request.js +12 -18
- package/lib/req/response.js +6 -2
- package/lib/req/user.js +30 -22
- package/lib/serve/Service-api.js +17 -12
- package/lib/serve/Service-dispatch.js +5 -9
- package/lib/serve/Service-methods.js +4 -3
- package/lib/serve/Transaction.js +24 -21
- package/lib/serve/adapters.js +15 -5
- package/lib/serve/factory.js +22 -20
- package/lib/serve/index.js +51 -54
- package/lib/utils/axios.js +8 -12
- package/lib/utils/index.js +13 -4
- package/lib/utils/resources/index.js +1 -44
- package/lib/utils/resources/tar.js +2 -1
- package/lib/utils/tests.js +13 -15
- package/libx/_runtime/.eslintrc +1 -1
- package/libx/_runtime/audit/Service.js +6 -4
- package/libx/_runtime/audit/generic/personal/access.js +19 -43
- package/libx/_runtime/audit/generic/personal/index.js +40 -34
- package/libx/_runtime/audit/generic/personal/modification.js +11 -9
- package/libx/_runtime/audit/generic/personal/utils.js +13 -6
- package/libx/_runtime/audit/utils/v2.js +6 -3
- package/libx/_runtime/auth/index.js +71 -66
- package/libx/_runtime/auth/strategies/JWT.js +3 -2
- package/libx/_runtime/auth/strategies/mock.js +54 -53
- package/libx/_runtime/auth/strategies/xssecUtils.js +3 -4
- package/libx/_runtime/auth/strategies/xsuaa.js +3 -2
- package/libx/_runtime/auth/utils.js +2 -15
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +127 -41
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +9 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +93 -73
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +25 -45
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +10 -14
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +9 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +60 -53
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +21 -26
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +8 -15
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +29 -41
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -13
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectToCQN.js +0 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +24 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityContainer.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriHelper.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +4 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/validator/ValueValidator.js +5 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/ResponseHeaderSetter.js +2 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DebugSerializingCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/PresetResponseHeadersCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SerializingCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/SetResponseHeadersCommand.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +3 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ErrorJsonSerializer.js +3 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +3 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +36 -25
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +97 -92
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +382 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/oDataConfiguration.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +5 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +82 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +3 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +91 -69
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +27 -6
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +7 -17
- package/libx/_runtime/cds-services/services/Service.js +17 -76
- package/libx/_runtime/cds-services/services/utils/columns.js +6 -4
- package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -53
- package/libx/_runtime/cds-services/services/utils/differ.js +15 -19
- package/libx/_runtime/cds-services/util/assert.js +107 -34
- package/libx/_runtime/cds.js +1 -31
- package/libx/_runtime/common/aspects/Association.js +40 -54
- package/libx/_runtime/common/aspects/any.js +61 -6
- package/libx/_runtime/common/aspects/entity.js +19 -79
- package/libx/_runtime/common/composition/data.js +2 -2
- package/libx/_runtime/common/composition/delete.js +8 -7
- package/libx/_runtime/common/composition/tree.js +10 -10
- package/libx/_runtime/common/composition/update.js +3 -2
- package/libx/_runtime/common/constants/events.js +13 -0
- package/libx/_runtime/common/error/entry.js +9 -3
- package/libx/_runtime/common/error/frontend.js +13 -19
- package/libx/_runtime/common/error/index.js +8 -3
- package/libx/_runtime/common/generic/auth/capabilities.js +2 -1
- package/libx/_runtime/common/generic/auth/constants.js +1 -4
- package/libx/_runtime/common/generic/auth/requires.js +1 -1
- package/libx/_runtime/common/generic/auth/restrict.js +12 -28
- package/libx/_runtime/common/generic/auth/restrictions.js +12 -4
- package/libx/_runtime/common/generic/auth/utils.js +2 -1
- package/libx/_runtime/common/generic/crud.js +9 -60
- package/libx/_runtime/common/generic/etag.js +41 -7
- package/libx/_runtime/common/generic/input.js +128 -66
- package/libx/_runtime/common/generic/paging.js +9 -3
- package/libx/_runtime/common/generic/put.js +2 -2
- package/libx/_runtime/common/generic/sorting.js +7 -3
- package/libx/_runtime/common/generic/temporal.js +0 -5
- package/libx/_runtime/common/i18n/messages.properties +2 -1
- package/libx/_runtime/common/utils/binary.js +69 -0
- package/libx/_runtime/common/utils/cqn.js +39 -14
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +93 -59
- package/libx/_runtime/common/utils/csn.js +87 -85
- package/libx/_runtime/common/utils/dollar.js +8 -7
- package/libx/_runtime/common/utils/draft.js +1 -1
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +23 -7
- package/libx/_runtime/common/utils/generateOnCond.js +2 -1
- package/libx/_runtime/common/utils/keys.js +30 -13
- package/libx/_runtime/common/utils/postProcessing.js +6 -1
- package/libx/_runtime/common/utils/quotingStyles.js +0 -23
- package/libx/_runtime/common/utils/resolveStructured.js +23 -26
- package/libx/_runtime/common/utils/resolveView.js +4 -1
- package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -0
- package/libx/_runtime/common/utils/search2cqn4sql.js +4 -13
- package/libx/_runtime/common/utils/searchToLike.js +9 -13
- package/libx/_runtime/common/utils/streamProp.js +35 -0
- package/libx/_runtime/common/utils/structured.js +12 -18
- package/libx/_runtime/common/utils/template.js +3 -5
- package/libx/_runtime/common/utils/templateProcessor.js +22 -14
- package/libx/_runtime/common/utils/unionCqnTemplate.js +4 -14
- package/libx/_runtime/db/Service.js +2 -1
- package/libx/_runtime/db/expand/expand-v2.js +2 -2
- package/libx/_runtime/db/expand/expandCQNToJoin.js +7 -6
- package/libx/_runtime/db/generic/input.js +14 -17
- package/libx/_runtime/db/generic/integrity.js +1 -2
- package/libx/_runtime/db/generic/update.js +14 -1
- package/libx/_runtime/db/query/read.js +0 -1
- package/libx/_runtime/db/query/update.js +1 -1
- package/libx/_runtime/db/sql-builder/BaseBuilder.js +1 -1
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +5 -31
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
- package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +0 -9
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +11 -10
- package/libx/_runtime/db/sql-builder/UpdateBuilder.js +2 -2
- package/libx/_runtime/db/sql-builder/annotations.js +1 -2
- package/libx/_runtime/db/utils/coloredTxCommands.js +5 -0
- package/libx/_runtime/db/utils/columns.js +1 -1
- package/libx/_runtime/db/utils/propagateForeignKeys.js +10 -2
- package/libx/_runtime/extensibility/activate.js +69 -0
- package/libx/_runtime/extensibility/add.js +41 -0
- package/libx/_runtime/extensibility/addExtension.js +68 -0
- package/libx/_runtime/extensibility/defaults.js +39 -0
- package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformREAD.js +0 -0
- package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformRESULT.js +2 -2
- package/libx/_runtime/extensibility/{uiflex/handler → handler}/transformWRITE.js +2 -2
- package/libx/_runtime/extensibility/push.js +61 -0
- package/libx/_runtime/extensibility/service.js +21 -0
- package/libx/_runtime/extensibility/{uiflex/utils.js → utils.js} +39 -3
- package/libx/_runtime/extensibility/validation.js +53 -0
- package/libx/_runtime/extensibility/views.js +12 -0
- package/libx/_runtime/fiori/generic/activate.js +2 -4
- package/libx/_runtime/fiori/generic/before.js +17 -29
- package/libx/_runtime/fiori/generic/cancel.js +2 -4
- package/libx/_runtime/fiori/generic/delete.js +2 -4
- package/libx/_runtime/fiori/generic/edit.js +4 -16
- package/libx/_runtime/fiori/generic/index.js +31 -0
- package/libx/_runtime/fiori/generic/new.js +5 -21
- package/libx/_runtime/fiori/generic/patch.js +10 -15
- package/libx/_runtime/fiori/generic/prepare.js +13 -22
- package/libx/_runtime/fiori/generic/read.js +148 -163
- package/libx/_runtime/fiori/generic/readOverDraft.js +10 -4
- package/libx/_runtime/fiori/utils/handler.js +10 -22
- package/libx/_runtime/fiori/utils/where.js +1 -4
- package/libx/_runtime/hana/Service.js +14 -7
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
- package/libx/_runtime/hana/dynatrace.js +2 -2
- package/libx/_runtime/hana/localized.js +7 -6
- package/libx/_runtime/hana/pool.js +9 -6
- package/libx/_runtime/hana/search.js +2 -3
- package/libx/_runtime/hana/{searchToContains.js → search2Contains.js} +5 -2
- package/libx/_runtime/hana/search2cqn4sql.js +20 -17
- package/libx/_runtime/index.js +2 -6
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +30 -22
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -3
- package/libx/_runtime/messaging/common-utils/appId.js +9 -0
- package/libx/_runtime/messaging/common-utils/authorizedRequest.js +2 -18
- package/libx/_runtime/messaging/common-utils/connections.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +305 -231
- package/libx/_runtime/messaging/enterprise-messaging-utils/cloudEvents.js +2 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/options-management.js +15 -8
- package/libx/_runtime/messaging/enterprise-messaging-utils/options-messaging.js +57 -14
- package/libx/_runtime/messaging/enterprise-messaging.js +14 -19
- package/libx/_runtime/messaging/file-based.js +3 -1
- package/libx/_runtime/messaging/http-utils/token.js +18 -6
- package/libx/_runtime/messaging/message-queuing-utils/options-management.js +22 -12
- package/libx/_runtime/messaging/message-queuing-utils/options-messaging.js +27 -14
- package/libx/_runtime/messaging/message-queuing.js +138 -85
- package/libx/_runtime/messaging/outbox/utils.js +13 -7
- package/libx/_runtime/messaging/redis-messaging.js +0 -1
- package/libx/_runtime/messaging/service.js +4 -1
- package/libx/_runtime/remote/Service.js +24 -18
- package/libx/_runtime/remote/utils/client.js +90 -48
- package/libx/_runtime/remote/utils/data.js +23 -6
- package/libx/_runtime/sqlite/Service.js +14 -13
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +2 -0
- package/libx/_runtime/sqlite/customBuilder/CustomSelectBuilder.js +1 -0
- package/libx/_runtime/sqlite/execute.js +3 -9
- package/libx/_runtime/types/api.js +23 -11
- package/libx/common/utils/ucsn.js +15 -9
- package/libx/odata/afterburner.js +109 -29
- package/libx/odata/cqn2odata.js +48 -9
- package/libx/odata/grammar.pegjs +263 -156
- package/libx/odata/index.js +21 -9
- package/libx/odata/parseToCqn.js +8 -5
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +13 -3
- package/libx/rest/RestAdapter.js +173 -113
- package/libx/rest/RestRequest.js +3 -2
- package/libx/rest/middleware/create.js +8 -6
- package/libx/rest/middleware/delete.js +6 -13
- package/libx/rest/middleware/error.js +1 -1
- package/libx/rest/middleware/input.js +6 -6
- package/libx/rest/middleware/operation.js +8 -3
- package/libx/rest/middleware/parse.js +3 -3
- package/libx/rest/middleware/payload.js +12 -0
- package/libx/rest/middleware/read.js +12 -2
- package/libx/rest/middleware/update.js +3 -3
- package/package.json +4 -6
- package/server.js +3 -44
- package/srv/extensibility-service.cds +56 -0
- package/srv/extensibility-service.js +1 -0
- package/srv/extensions.cds +8 -0
- package/srv/model-provider.cds +59 -0
- package/srv/model-provider.js +163 -0
- package/srv/mtx.cds +2 -0
- package/srv/mtx.js +22 -0
- package/srv/outbox.cds +2 -0
- package/tasks/enterprise-messaging-deploy.js +19 -12
- package/lib/serve/Service-compat.js +0 -36
- package/libx/_runtime/audit/generic/personal/constants.js +0 -4
- package/libx/_runtime/auth/strategies/dwc.js +0 -45
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +0 -56
- package/libx/_runtime/cds-services/adapter/rest/Rest.js +0 -183
- package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +0 -67
- package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -82
- package/libx/_runtime/cds-services/adapter/rest/handlers/delete.js +0 -39
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +0 -63
- package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +0 -52
- package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +0 -81
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +0 -56
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +0 -33
- package/libx/_runtime/cds-services/adapter/rest/to.js +0 -8
- package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +0 -50
- package/libx/_runtime/cds-services/adapter/rest/utils/data.js +0 -117
- package/libx/_runtime/cds-services/adapter/rest/utils/header-checks.js +0 -14
- package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +0 -30
- package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +0 -250
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +0 -26
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +0 -200
- package/libx/_runtime/common/aspects/utils.js +0 -152
- package/libx/_runtime/common/toggles/handler.js +0 -21
- package/libx/_runtime/common/utils/extensibilityUtils.js +0 -18
- package/libx/_runtime/extensibility/mps/index.js +0 -5
- package/libx/_runtime/extensibility/mps/service.js +0 -111
- package/libx/_runtime/extensibility/mps/tar.js +0 -42
- package/libx/_runtime/extensibility/mps/utils.js +0 -11
- package/libx/_runtime/extensibility/uiflex/index.js +0 -54
- package/libx/_runtime/extensibility/uiflex/service.js +0 -276
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +0 -20
- package/libx/_runtime/remote/utils/client-types.d.ts +0 -7
- package/libx/gql/GraphQLAdapter.js +0 -33
- package/libx/gql/constants/adapter.js +0 -69
- package/libx/gql/constants/cds.js +0 -18
- package/libx/gql/constants/graphql.js +0 -33
- package/libx/gql/readme.md +0 -1
- package/libx/gql/resolvers/crud/create.js +0 -20
- package/libx/gql/resolvers/crud/delete.js +0 -29
- package/libx/gql/resolvers/crud/index.js +0 -6
- package/libx/gql/resolvers/crud/read.js +0 -30
- package/libx/gql/resolvers/crud/update.js +0 -42
- package/libx/gql/resolvers/crud/utils/index.js +0 -36
- package/libx/gql/resolvers/field.js +0 -5
- package/libx/gql/resolvers/index.js +0 -7
- package/libx/gql/resolvers/mutation.js +0 -23
- package/libx/gql/resolvers/parse/ast/enrich.js +0 -52
- package/libx/gql/resolvers/parse/ast/fragment.js +0 -11
- package/libx/gql/resolvers/parse/ast/fromObject.js +0 -39
- package/libx/gql/resolvers/parse/ast/index.js +0 -3
- package/libx/gql/resolvers/parse/ast/meta.js +0 -4
- package/libx/gql/resolvers/parse/ast/variable.js +0 -7
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +0 -44
- package/libx/gql/resolvers/parse/ast2cqn/entries.js +0 -31
- package/libx/gql/resolvers/parse/ast2cqn/index.js +0 -8
- package/libx/gql/resolvers/parse/ast2cqn/limit.js +0 -6
- package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +0 -24
- package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +0 -3
- package/libx/gql/resolvers/parse/ast2cqn/where.js +0 -70
- package/libx/gql/resolvers/parse/utils/index.js +0 -8
- package/libx/gql/resolvers/query.js +0 -13
- package/libx/gql/resolvers/root.js +0 -34
- package/libx/gql/schema/generate.js +0 -18
- package/libx/gql/schema/index.js +0 -5
- package/libx/gql/schema/mutation.js +0 -76
- package/libx/gql/schema/query.js +0 -108
- package/libx/gql/schema/typeDefMap.js +0 -45
- package/libx/gql/schema/utils/index.js +0 -54
- package/libx/gql/utils/index.js +0 -12
- package/libx/rest/middleware/auth.js +0 -20
- package/libx/rest/middleware/content.js +0 -19
- package/srv/flex.cds +0 -21
- package/srv/flex.js +0 -1
- package/srv/mps.cds +0 -23
- package/srv/mps.js +0 -1
- package/srv/outbox.js +0 -0
|
@@ -1,57 +1,14 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
-
|
|
3
2
|
const CHALLENGE = 'Basic realm="Users"'
|
|
4
3
|
|
|
5
|
-
const _getUser = (users, id) => {
|
|
6
|
-
let user
|
|
7
|
-
|
|
8
|
-
for (const k in users) {
|
|
9
|
-
if (k === id || users[k].ID === id) {
|
|
10
|
-
user = users[k]
|
|
11
|
-
break
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (!user && users['*']) user = { id }
|
|
16
|
-
|
|
17
|
-
return user
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const _getRoles = user => {
|
|
21
|
-
const _roles = ['any', 'identified-user', 'authenticated-user']
|
|
22
|
-
|
|
23
|
-
if (user.roles) {
|
|
24
|
-
_roles.push(...user.roles)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (user.jwt) {
|
|
28
|
-
const scopes = user.jwt.scope || user.jwt.scopes || []
|
|
29
|
-
const aud = user.jwt.aud || []
|
|
30
|
-
_roles.push(
|
|
31
|
-
...scopes.map(s => {
|
|
32
|
-
for (const each of aud) {
|
|
33
|
-
s = s.replace(`${each}.`, '')
|
|
34
|
-
}
|
|
35
|
-
return s
|
|
36
|
-
})
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (user.jwt && (user.jwt.grant_type === 'client_credentials' || user.jwt.grant_type === 'client_x509')) {
|
|
41
|
-
_roles.push('system-user')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return _roles
|
|
45
|
-
}
|
|
46
|
-
|
|
47
4
|
class MockStrategy {
|
|
48
|
-
constructor(users, name = 'mock') {
|
|
5
|
+
constructor({ users, tenants }, name = 'mock') {
|
|
49
6
|
this.name = name
|
|
50
|
-
this.users = users || cds.env.requires.auth.users || {}
|
|
7
|
+
this.users = _init_users(users || cds.env.requires.auth.users || {}, tenants)
|
|
51
8
|
}
|
|
52
9
|
|
|
53
10
|
authenticate(req) {
|
|
54
|
-
const authorization = req.headers
|
|
11
|
+
const { authorization } = req.headers
|
|
55
12
|
if (!authorization) return this.fail(CHALLENGE)
|
|
56
13
|
|
|
57
14
|
const [scheme, base64] = authorization.split(' ')
|
|
@@ -59,18 +16,62 @@ class MockStrategy {
|
|
|
59
16
|
if (!base64) return this.fail(CHALLENGE)
|
|
60
17
|
|
|
61
18
|
const [id, password] = Buffer.from(base64, 'base64').toString().split(':')
|
|
62
|
-
|
|
63
|
-
let user = _getUser(this.users, id)
|
|
19
|
+
const user = this.users[id] || ('*' in this.users && { id })
|
|
64
20
|
if (!user) return this.fail(CHALLENGE)
|
|
65
21
|
if (user.password && user.password !== password) return this.fail(CHALLENGE)
|
|
66
22
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
23
|
+
const { features } = req.headers
|
|
24
|
+
this.success(new cds.User(features ? { ...user, features } : user))
|
|
25
|
+
}
|
|
26
|
+
}
|
|
70
27
|
|
|
71
|
-
|
|
72
|
-
|
|
28
|
+
// eslint-disable-next-line complexity
|
|
29
|
+
const _init_users = (users, tenants = {}) => {
|
|
30
|
+
if (!users._initialized) {
|
|
31
|
+
Object.defineProperty(users, '_initialized', { value: true })
|
|
32
|
+
for (let [id, user] of Object.entries(users)) {
|
|
33
|
+
if (id !== '*') user.id = user.ID || user.id || id // fill in user ids
|
|
34
|
+
if (id !== user.id) users[user.id] = user
|
|
35
|
+
if (user.jwt) {
|
|
36
|
+
let scopes = user.jwt.scope || user.jwt.scopes
|
|
37
|
+
if (scopes) {
|
|
38
|
+
const aud = user.jwt.aud
|
|
39
|
+
if (aud)
|
|
40
|
+
scopes = scopes.map(s => {
|
|
41
|
+
for (const each of aud) s = s.replace(`${each}.`, '')
|
|
42
|
+
return s
|
|
43
|
+
})
|
|
44
|
+
Array.isArray(user.roles) ? user.roles.push(...scopes) : (user.roles = scopes)
|
|
45
|
+
}
|
|
46
|
+
if (user.jwt.grant_type === 'client_credentials' || user.jwt.grant_type === 'client_x509') {
|
|
47
|
+
user.roles.push('system-user')
|
|
48
|
+
}
|
|
49
|
+
if (!user.tenant && user.jwt.zid) user.tenant = user.jwt.zid
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// optimization:
|
|
53
|
+
if (user.roles)
|
|
54
|
+
user.roles = user.roles.reduce((p, n) => {
|
|
55
|
+
p[n] = 1
|
|
56
|
+
return p
|
|
57
|
+
}, {})
|
|
58
|
+
|
|
59
|
+
// apply tenant info if any
|
|
60
|
+
if (!user.features) {
|
|
61
|
+
const features = tenants[user.tenant]?.features
|
|
62
|
+
if (features) user.features = features
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const attr = Object.assign(
|
|
66
|
+
{},
|
|
67
|
+
user.userAttributes,
|
|
68
|
+
user.jwt && user.jwt.userInfo,
|
|
69
|
+
user.jwt && user.jwt.attributes
|
|
70
|
+
)
|
|
71
|
+
if (Object.keys(attr).length > 0) user.attr = attr
|
|
72
|
+
}
|
|
73
73
|
}
|
|
74
|
+
return users
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
module.exports = MockStrategy
|
|
@@ -25,10 +25,9 @@ const getRoles = (roles, info, credentials) => {
|
|
|
25
25
|
|
|
26
26
|
if (info && info.checkLocalScope && typeof info.checkLocalScope === 'function') {
|
|
27
27
|
// > xssec v3
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return role in _roles ? _roles[role] : info.checkLocalScope(role)
|
|
28
|
+
roles = new Proxy(roles, {
|
|
29
|
+
get: function (t, role) {
|
|
30
|
+
return role in t ? t[role] : info.checkLocalScope(role)
|
|
32
31
|
}
|
|
33
32
|
})
|
|
34
33
|
}
|
|
@@ -22,10 +22,11 @@ class XSUAAStrategy extends JS {
|
|
|
22
22
|
// create cds.User
|
|
23
23
|
user = new cds.User({
|
|
24
24
|
id: xssecUtils.getUserId(user, info),
|
|
25
|
-
|
|
26
|
-
_roles: xssecUtils.getRoles(['any', 'identified-user'], info, credentials),
|
|
25
|
+
roles: xssecUtils.getRoles(['any', 'identified-user'], info, credentials),
|
|
27
26
|
attr: xssecUtils.getAttrForXSSEC(info)
|
|
28
27
|
})
|
|
28
|
+
const tenant = xssecUtils.getTenant(info)
|
|
29
|
+
if (tenant) user.tenant = tenant
|
|
29
30
|
// call "super.success"
|
|
30
31
|
_success(user, info)
|
|
31
32
|
}
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
const cds = require('../cds')
|
|
2
|
-
|
|
3
1
|
const UNAUTHORIZED = { statusCode: 401, code: '401', message: 'Unauthorized' }
|
|
4
2
|
const FORBIDDEN = { statusCode: 403, code: '403', message: 'Forbidden' }
|
|
5
3
|
|
|
6
4
|
const getRequiresAsArray = definition => {
|
|
7
|
-
const requires = []
|
|
8
|
-
|
|
9
|
-
if (definition['@requires']) {
|
|
10
|
-
if (Array.isArray(definition['@requires'])) requires.push(...definition['@requires'])
|
|
11
|
-
else requires.push(definition['@requires'])
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const { restrict_all_services: restrictAllServices } = cds.env.requires.auth || {}
|
|
15
|
-
if (!requires.length && definition.kind === 'service' && restrictAllServices) requires.push('authenticated-user')
|
|
16
|
-
|
|
17
|
-
return requires
|
|
5
|
+
const requires = definition['@requires']
|
|
6
|
+
if (requires) return Array.isArray(requires) ? requires : [requires]
|
|
18
7
|
}
|
|
19
8
|
|
|
20
9
|
const isRestricted = srv => {
|
|
21
|
-
const envAuth = cds.env.requires.auth
|
|
22
|
-
if (envAuth && envAuth.restrict_all_services) return true
|
|
23
10
|
if (srv.definition['@requires']) return true
|
|
24
11
|
|
|
25
12
|
const entities = srv.entities
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
2
|
const LOG = cds.log('odata')
|
|
3
|
-
const { BASE_TENANT, channelName } = require('../../../common/utils/extensibilityUtils')
|
|
4
|
-
|
|
5
|
-
const { SYSTEM_SERVICES, createOdataService, createNewService, getModelHash } = require('./utils/dispatcherUtils')
|
|
6
3
|
|
|
7
4
|
const { normalizeError } = require('../../../common/error/frontend')
|
|
8
5
|
|
|
9
|
-
|
|
6
|
+
const _run4 = (tenant, query) => (tenant ? cds.tx({ tenant }, tx => tx.run(query)) : query)
|
|
7
|
+
const getError = require('../../../common/error')
|
|
8
|
+
|
|
9
|
+
// REVISIT: this is always active, even without mtx -> do that better
|
|
10
|
+
module.exports = class Dispatcher {
|
|
10
11
|
/**
|
|
11
12
|
* Constructs an Dispatcher for cds service.
|
|
12
13
|
* New OData services will be created.
|
|
@@ -18,25 +19,44 @@ class Dispatcher {
|
|
|
18
19
|
this._options = service.options
|
|
19
20
|
|
|
20
21
|
this._extMap = new Map()
|
|
21
|
-
this._extMap.set(getModelHash(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
cds.services['mtx-messaging'].on(channelName(), async msg => {
|
|
25
|
-
const tenant = msg.data.tenant
|
|
26
|
-
const hash = getModelHash(tenant, [])
|
|
27
|
-
for (const entry of this._extMap.entries()) {
|
|
28
|
-
if (entry[0].startsWith(hash)) {
|
|
29
|
-
this._extMap.delete(entry[0])
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
}
|
|
22
|
+
this._extMap.set(getModelHash(), createOdataService(service))
|
|
23
|
+
this._intervalMap = new Map()
|
|
24
|
+
this._intervalMap.set(undefined, Date.now())
|
|
34
25
|
|
|
35
|
-
if (cds.
|
|
26
|
+
if (cds.mtx) {
|
|
27
|
+
cds.mtx._nodejs_models = {}
|
|
36
28
|
cds.mtx.eventEmitter.on(cds.mtx.events.TENANT_UPDATED, async tenant => {
|
|
37
29
|
this._extMap.delete(getModelHash(tenant))
|
|
30
|
+
delete cds.mtx._nodejs_models[tenant]
|
|
38
31
|
})
|
|
39
32
|
}
|
|
33
|
+
|
|
34
|
+
this._tenantCheckInterval = cds.requires.extensibility && cds.requires.extensibility.tenantCheckInterval
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_deleteService(tenant) {
|
|
38
|
+
const hash = getModelHash(tenant)
|
|
39
|
+
for (const entry of this._extMap.entries()) {
|
|
40
|
+
if (entry[0].startsWith(hash)) {
|
|
41
|
+
this._extMap.delete(entry[0])
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
this._intervalMap.delete(tenant)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async _checkTenantExt(tenant, last) {
|
|
48
|
+
try {
|
|
49
|
+
const rs = await _run4(tenant, SELECT(1).from('cds.xt.Extensions').where('timestamp >=', last))
|
|
50
|
+
if (!this._mps) this._mps = await cds.connect.to('cds.xt.ModelProviderService')
|
|
51
|
+
if (rs.length) {
|
|
52
|
+
this._deleteService(tenant)
|
|
53
|
+
this._mps.invalidateCache(tenant)
|
|
54
|
+
} else {
|
|
55
|
+
this._intervalMap.set(tenant, Date.now())
|
|
56
|
+
}
|
|
57
|
+
} catch (_) {
|
|
58
|
+
this._deleteService(tenant)
|
|
59
|
+
}
|
|
40
60
|
}
|
|
41
61
|
|
|
42
62
|
async _getService4Tenant(req) {
|
|
@@ -45,42 +65,46 @@ class Dispatcher {
|
|
|
45
65
|
const isExtended = await cds.mtx.isExtended(tenant) // REVISIT: avoid await
|
|
46
66
|
if (!isExtended) return false
|
|
47
67
|
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
let model = cds.mtx._nodejs_models[tenant]
|
|
69
|
+
if (!model) {
|
|
70
|
+
const raw = await cds.mtx.getCsn(tenant)
|
|
71
|
+
model = cds.mtx._nodejs_models[tenant] = cds.compile.for.nodejs(raw)
|
|
72
|
+
}
|
|
73
|
+
|
|
50
74
|
const service = await createNewService(this._serviceName, model, this._options)
|
|
51
75
|
service._cdsService._isExtended = true
|
|
52
76
|
return service
|
|
53
77
|
}
|
|
54
78
|
|
|
55
79
|
async _getService4(tenant, features) {
|
|
56
|
-
const
|
|
57
|
-
const model = cds.compile.for.nodejs(csn)
|
|
80
|
+
const model = await this._mps.getCsn(tenant, features || [], 'nodejs')
|
|
58
81
|
return createNewService(this._serviceName, model, this._options)
|
|
59
82
|
}
|
|
60
83
|
|
|
61
84
|
async _getService(tenant, features, hash, req) {
|
|
62
|
-
if (cds.
|
|
85
|
+
if (cds.mtx) {
|
|
63
86
|
const service = await this._getService4Tenant(req)
|
|
64
87
|
|
|
65
88
|
if (service) return service
|
|
66
89
|
|
|
67
|
-
return this._extMap.get(getModelHash(
|
|
90
|
+
return this._extMap.get(getModelHash())
|
|
68
91
|
}
|
|
69
92
|
|
|
70
|
-
if (!this._mps) this._mps = await cds.connect.to('
|
|
71
|
-
const hashBase = getModelHash(
|
|
72
|
-
if (tenant && tenant !==
|
|
93
|
+
if (!this._mps) this._mps = await cds.connect.to('cds.xt.ModelProviderService')
|
|
94
|
+
const hashBase = getModelHash(undefined, features)
|
|
95
|
+
if (tenant && tenant !== undefined && hash !== hashBase) {
|
|
73
96
|
const isExtended = cds.requires.extensibility && (await this._mps.isExtended(tenant))
|
|
74
97
|
if (isExtended) {
|
|
75
98
|
return this._getService4(tenant, features)
|
|
76
99
|
} else {
|
|
77
100
|
if (!this._extMap.has(hashBase)) {
|
|
78
|
-
this._extMap.set(hashBase, this._getService4(
|
|
101
|
+
this._extMap.set(hashBase, this._getService4(undefined, features))
|
|
102
|
+
this._intervalMap.set(tenant, Date.now())
|
|
79
103
|
}
|
|
80
104
|
return this._extMap.get(hashBase)
|
|
81
105
|
}
|
|
82
106
|
} else {
|
|
83
|
-
return this._getService4(
|
|
107
|
+
return this._getService4(undefined, features)
|
|
84
108
|
}
|
|
85
109
|
}
|
|
86
110
|
|
|
@@ -92,11 +116,16 @@ class Dispatcher {
|
|
|
92
116
|
// clear map entry
|
|
93
117
|
this._extMap.delete(hash)
|
|
94
118
|
// return 503 to client
|
|
95
|
-
|
|
119
|
+
err = getError(Object.assign(err, { statusCode: 503 }))
|
|
120
|
+
const { error } = normalizeError(err, req)
|
|
96
121
|
|
|
97
122
|
return res.status(503).send({ error })
|
|
98
123
|
}
|
|
99
124
|
|
|
125
|
+
_hasModelProvider() {
|
|
126
|
+
return 'cds.xt.ModelProviderService' in cds.services || 'cds.xt.ModelProviderService' in cds.requires
|
|
127
|
+
}
|
|
128
|
+
|
|
100
129
|
/**
|
|
101
130
|
* Dispatch request in case of extensibility to other odata adapters.
|
|
102
131
|
*
|
|
@@ -107,26 +136,34 @@ class Dispatcher {
|
|
|
107
136
|
*/
|
|
108
137
|
async dispatch(req, res) {
|
|
109
138
|
// here, req is express' req -> req.tenant not available
|
|
139
|
+
// REVISIT: rethink authentication
|
|
110
140
|
const tenant = req.user && req.user.tenant
|
|
111
141
|
|
|
112
|
-
|
|
113
|
-
|
|
142
|
+
// single tenant w/o features
|
|
143
|
+
if (!cds.mtx && !this._hasModelProvider()) {
|
|
144
|
+
const service = this._extMap.get(getModelHash())
|
|
114
145
|
return service.process(req, res)
|
|
115
146
|
}
|
|
116
147
|
|
|
117
|
-
//
|
|
118
|
-
const features = req.features
|
|
119
|
-
? Array.isArray(req.features)
|
|
120
|
-
? req.features
|
|
121
|
-
: Object.keys(req.features)
|
|
122
|
-
.filter(k => req.features[k])
|
|
123
|
-
.sort()
|
|
124
|
-
: []
|
|
148
|
+
// old mtx does not support feature toggles
|
|
149
|
+
const features = cds.mtx ? [] : _features4(req.features || req.user.features)
|
|
125
150
|
const hash = getModelHash(tenant, features)
|
|
126
151
|
|
|
152
|
+
// check for extensions
|
|
153
|
+
if (cds.requires.extensibility && !this._inCheckTenant) {
|
|
154
|
+
this._inCheckTenant = true
|
|
155
|
+
if (this._intervalMap.has(tenant)) {
|
|
156
|
+
const last = this._intervalMap.get(tenant)
|
|
157
|
+
if (Date.now() - last > this._tenantCheckInterval)
|
|
158
|
+
await this._checkTenantExt(tenant, new Date(last).toISOString())
|
|
159
|
+
}
|
|
160
|
+
this._inCheckTenant = false
|
|
161
|
+
}
|
|
162
|
+
|
|
127
163
|
// set promise into the map to avoid conflicts
|
|
128
164
|
if (!this._extMap.has(hash)) {
|
|
129
165
|
this._extMap.set(hash, this._getService(tenant, features, hash, req))
|
|
166
|
+
this._intervalMap.set(tenant, Date.now())
|
|
130
167
|
}
|
|
131
168
|
|
|
132
169
|
let service
|
|
@@ -151,4 +188,53 @@ class Dispatcher {
|
|
|
151
188
|
}
|
|
152
189
|
}
|
|
153
190
|
|
|
154
|
-
|
|
191
|
+
// -----------------------------------------------------
|
|
192
|
+
// Private utils...
|
|
193
|
+
|
|
194
|
+
const OData = require('./OData')
|
|
195
|
+
const DEBUG = cds.debug('extensibility')
|
|
196
|
+
|
|
197
|
+
const { alias2ref } = require('../../../common/utils/csn')
|
|
198
|
+
|
|
199
|
+
function createOdataService(service) {
|
|
200
|
+
const name = (service.definition && service.definition.name) || service.name
|
|
201
|
+
const edm = cds.compile.to.edm(service.model, { service: name })
|
|
202
|
+
alias2ref(service, edm)
|
|
203
|
+
|
|
204
|
+
const odataService = new OData(edm, service.model, service.options)
|
|
205
|
+
odataService.addCDSServiceToChannel(service)
|
|
206
|
+
|
|
207
|
+
return odataService
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async function createNewService(name, model, options) {
|
|
211
|
+
const { constructor: Service, path } = cds.services[name]
|
|
212
|
+
const service = new Service(name, model, { ...options }) // cloning options to be safe
|
|
213
|
+
if (service.init) await service.prepend(service.init)
|
|
214
|
+
if (options.impl) await service.prepend(options.impl)
|
|
215
|
+
if (path) service.path = path
|
|
216
|
+
DEBUG &&
|
|
217
|
+
DEBUG('Created tenant-specific service:', service.name, '= new', Service.name, {
|
|
218
|
+
_handlers: {
|
|
219
|
+
on: service._handlers.on.map(h => ({ on: h.on, handler: () => {} }))
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
return createOdataService(service)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const getModelHash = (tenant, features) => {
|
|
226
|
+
// ignore tenant in single tenant mode - use default (undefined) hash
|
|
227
|
+
const hash = cds.requires.multitenancy ? `${tenant}:` : 'undefined:'
|
|
228
|
+
return !features ? hash : hash + features.join(';')
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const _features4 = features => {
|
|
232
|
+
// ensure features is an array
|
|
233
|
+
if (!features) return []
|
|
234
|
+
if (Array.isArray(features)) return features
|
|
235
|
+
if (typeof features === 'string') return features.split(',')
|
|
236
|
+
if (typeof features === 'object')
|
|
237
|
+
return Object.keys(features)
|
|
238
|
+
.filter(k => features[k])
|
|
239
|
+
.sort()
|
|
240
|
+
}
|
|
@@ -27,7 +27,6 @@ const _delete = require('./handlers/delete')
|
|
|
27
27
|
const _read = require('./handlers/read')
|
|
28
28
|
const _action = require('./handlers/action')
|
|
29
29
|
const { normalizeError, isClientError } = require('../../../common/error/frontend')
|
|
30
|
-
|
|
31
30
|
const { getErrorMessage } = require('../../../common/error/utils')
|
|
32
31
|
|
|
33
32
|
function _log(level, arg) {
|
|
@@ -51,7 +50,6 @@ function _log(level, arg) {
|
|
|
51
50
|
// reduce 4xx to warning
|
|
52
51
|
if (isClientError(obj)) {
|
|
53
52
|
if (!LOG._warn) {
|
|
54
|
-
// restore
|
|
55
53
|
return
|
|
56
54
|
}
|
|
57
55
|
level = 'warn'
|
|
@@ -164,10 +162,11 @@ class OData {
|
|
|
164
162
|
const txs = (data.txs = data.txs || {})
|
|
165
163
|
const {
|
|
166
164
|
req: { user },
|
|
167
|
-
req
|
|
165
|
+
req,
|
|
166
|
+
res
|
|
168
167
|
} = data
|
|
169
168
|
// REVISIT: _model should not be necessary
|
|
170
|
-
const tx = (txs[odataContext.id] = cdsService.tx({ user, req, _model: cdsService.model }))
|
|
169
|
+
const tx = (txs[odataContext.id] = cdsService.tx({ user, req, res, _model: cdsService.model }))
|
|
171
170
|
cds.context = tx.context
|
|
172
171
|
// for collecting results and errors
|
|
173
172
|
data.results = data.results || {}
|
|
@@ -264,8 +263,13 @@ class OData {
|
|
|
264
263
|
|
|
265
264
|
// this._startPerfMeasurementOData(req)
|
|
266
265
|
this._odataService.process(req, res).catch(err => {
|
|
266
|
+
LOG.warn(err)
|
|
267
267
|
// REVISIT: use i18n
|
|
268
|
-
|
|
268
|
+
//do not reply with error, if response already processed (streaming)
|
|
269
|
+
if (!res.headersSent) {
|
|
270
|
+
const { error, statusCode } = normalizeError(err, req)
|
|
271
|
+
res.status(statusCode).send({ error })
|
|
272
|
+
}
|
|
269
273
|
})
|
|
270
274
|
}
|
|
271
275
|
}
|
|
@@ -11,11 +11,10 @@ const {
|
|
|
11
11
|
} = require('./okra/odata-server')
|
|
12
12
|
|
|
13
13
|
const { findCsnTargetFor } = require('../../../common/utils/csn')
|
|
14
|
-
|
|
14
|
+
const metaInfo = require('./utils/metaInfo')
|
|
15
15
|
const odataToCQN = require('./odata-to-cqn')
|
|
16
16
|
const { getData, getParams } = require('./utils/data')
|
|
17
17
|
const { isCustomOperation } = require('./utils/request')
|
|
18
|
-
const { flattenDeepToOneAssociations } = require('../../services/utils/handlerUtils')
|
|
19
18
|
|
|
20
19
|
function _isCorrectCallToViewWithParams(csdlStructuredType) {
|
|
21
20
|
return (
|
|
@@ -55,6 +54,12 @@ function _getTarget(service, segments) {
|
|
|
55
54
|
return _getTarget(service, segments)
|
|
56
55
|
}
|
|
57
56
|
|
|
57
|
+
function _add4Odata(query) {
|
|
58
|
+
if (Array.isArray(query))
|
|
59
|
+
for (let i = 0; i < query.length; i++) Object.defineProperty(query[i].SELECT, '_4odata', { value: true })
|
|
60
|
+
else Object.defineProperty(query.SELECT, '_4odata', { value: true })
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
/**
|
|
59
64
|
* Class representing an OData request.
|
|
60
65
|
* @extends cds.Request
|
|
@@ -71,86 +76,101 @@ class ODataRequest extends cds.Request {
|
|
|
71
76
|
: odataReq.getIncomingRequest()
|
|
72
77
|
const res = req.res
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
?
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
79
|
+
if (cds.env.features.odata_new_parser) {
|
|
80
|
+
// REVISIT need to resolve target after replacing okra <= maybe just take one from afterburner?
|
|
81
|
+
const target = _getTarget(service, [...odataReq.getUriInfo().getPathSegments()])
|
|
82
|
+
// REVISIT payload after replacing okra
|
|
83
|
+
const data = getData(type, odataReq, service, target)
|
|
84
|
+
const query = odataToCQN(type, service, target, data, odataReq, upsert)
|
|
85
|
+
const headers = Object.assign({}, req.headers, odataReq.getHeaders())
|
|
86
|
+
// REVISIT needed in case of $batch, replace after removing okra
|
|
87
|
+
const method = odataReq.getIncomingRequest().method
|
|
88
|
+
const { user } = req
|
|
89
|
+
const info = metaInfo(query, type, service, data, req, upsert)
|
|
90
|
+
const { event, unbound } = info
|
|
91
|
+
if (event === 'READ') _add4Odata(query)
|
|
92
|
+
const _queryOptions = odataReq.getQueryOptions()
|
|
93
|
+
super({ event, target, data, query: unbound ? {} : query, user, method, headers, req, res, _queryOptions })
|
|
94
|
+
this._metaInfo = info.metadata
|
|
95
|
+
} else {
|
|
96
|
+
/*
|
|
97
|
+
* target
|
|
98
|
+
*/
|
|
99
|
+
const target = _getTarget(service, [...odataReq.getUriInfo().getPathSegments()])
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* data
|
|
103
|
+
*/
|
|
104
|
+
const data = getData(type, odataReq, service, target)
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* query
|
|
108
|
+
*/
|
|
109
|
+
const operation = isCustomOperation(odataReq.getUriInfo().getPathSegments())
|
|
110
|
+
? odataReq.getUriInfo().getLastSegment().getKind()
|
|
111
|
+
: type
|
|
112
|
+
const query = odataToCQN(operation, service, target, data, odataReq, upsert)
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* event
|
|
116
|
+
*/
|
|
117
|
+
let event = type
|
|
118
|
+
|
|
119
|
+
// actions & functions
|
|
120
|
+
const uriInfoLastSegment = odataReq.getUriInfo().getLastSegment()
|
|
121
|
+
|
|
122
|
+
switch (uriInfoLastSegment && uriInfoLastSegment.getKind()) {
|
|
123
|
+
case 'BOUND.ACTION':
|
|
124
|
+
event = uriInfoLastSegment.getAction().getName()
|
|
125
|
+
break
|
|
126
|
+
|
|
127
|
+
case 'ACTION.IMPORT':
|
|
128
|
+
event = uriInfoLastSegment.getActionImport().getName()
|
|
129
|
+
break
|
|
130
|
+
|
|
131
|
+
case 'BOUND.FUNCTION':
|
|
132
|
+
event = uriInfoLastSegment.getFunction().getName()
|
|
133
|
+
break
|
|
134
|
+
|
|
135
|
+
case 'FUNCTION.IMPORT':
|
|
136
|
+
event = uriInfoLastSegment.getFunctionImport().getName()
|
|
137
|
+
break
|
|
138
|
+
|
|
139
|
+
// no default
|
|
140
|
+
}
|
|
96
141
|
|
|
97
|
-
|
|
98
|
-
|
|
142
|
+
// draft
|
|
143
|
+
if (target && target._isDraftEnabled) {
|
|
144
|
+
if (type === 'CREATE') event = 'NEW'
|
|
145
|
+
else if (event === 'draftEdit') event = 'EDIT'
|
|
146
|
+
else if (type === 'UPDATE') event = 'PATCH'
|
|
147
|
+
else if (type === 'DELETE' && data.IsActiveEntity !== true) event = 'CANCEL'
|
|
148
|
+
}
|
|
99
149
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
event = uriInfoLastSegment.getAction().getName()
|
|
103
|
-
break
|
|
150
|
+
// mark query as for an OData READ
|
|
151
|
+
if (event === 'READ') Object.defineProperty(query.SELECT, '_4odata', { value: true })
|
|
104
152
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
153
|
+
/*
|
|
154
|
+
* method, headers
|
|
155
|
+
*/
|
|
156
|
+
const method = odataReq.getMethod()
|
|
108
157
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
break
|
|
158
|
+
// REVISIT: Why do we mix headers of $batch and batched request headers??
|
|
159
|
+
const headers = Object.assign({}, req.headers, odataReq.getHeaders())
|
|
112
160
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
161
|
+
/*
|
|
162
|
+
* super
|
|
163
|
+
*/
|
|
164
|
+
const { user } = req
|
|
116
165
|
|
|
117
|
-
//
|
|
118
|
-
|
|
166
|
+
// REVISIT: _model should not be necessary
|
|
167
|
+
const _model = service.model
|
|
119
168
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
else if (event === 'draftEdit') event = 'EDIT'
|
|
124
|
-
else if (type === 'UPDATE') event = 'PATCH'
|
|
125
|
-
else if (type === 'DELETE' && data.IsActiveEntity !== 'true') event = 'CANCEL'
|
|
169
|
+
// REVISIT: public API for query options (express style req.query already in use)?
|
|
170
|
+
const _queryOptions = odataReq.getQueryOptions()
|
|
171
|
+
super({ event, target, data, query, user, method, headers, req, res, _model, _queryOptions })
|
|
126
172
|
}
|
|
127
173
|
|
|
128
|
-
// mark query as for an OData READ
|
|
129
|
-
if (event === 'READ') Object.defineProperty(query.SELECT, '_4odata', { value: true })
|
|
130
|
-
|
|
131
|
-
/*
|
|
132
|
-
* method, headers
|
|
133
|
-
*/
|
|
134
|
-
const method = odataReq.getMethod()
|
|
135
|
-
|
|
136
|
-
// REVISIT: Why do we mix headers of $batch and batched request headers??
|
|
137
|
-
const headers = Object.assign({}, req.headers, odataReq.getHeaders())
|
|
138
|
-
|
|
139
|
-
/*
|
|
140
|
-
* super
|
|
141
|
-
*/
|
|
142
|
-
const { user } = req
|
|
143
|
-
|
|
144
|
-
// REVISIT: _model should not be necessary
|
|
145
|
-
const _model = service.model
|
|
146
|
-
|
|
147
|
-
// REVISIT: public API for query options (express style req.query already in use)?
|
|
148
|
-
const _queryOptions = odataReq.getQueryOptions()
|
|
149
|
-
super({ event, target, data, query, user, method, headers, req, res, _model, _queryOptions })
|
|
150
|
-
|
|
151
|
-
// REVISIT: validate associations for deep insert
|
|
152
|
-
flattenDeepToOneAssociations(this, this.model)
|
|
153
|
-
|
|
154
174
|
/*
|
|
155
175
|
* req.run
|
|
156
176
|
*/
|