@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,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
2
|
+
* Input handler on application service layer
|
|
3
3
|
*
|
|
4
4
|
* - remove readonly fields
|
|
5
5
|
* - remove immutable fields on update
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const cds = require('../../cds')
|
|
11
|
+
const LOG = cds.log('app')
|
|
11
12
|
const { enrichDataWithKeysFromWhere } = require('../utils/keys')
|
|
12
13
|
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
13
|
-
const { checkInputConstraints,
|
|
14
|
+
const { checkInputConstraints, assertTargets } = require('../../cds-services/util/assert')
|
|
14
15
|
const getTemplate = require('../utils/template')
|
|
15
16
|
const templateProcessor = require('../utils/templateProcessor')
|
|
16
17
|
const { getDataFromCQN, setDataFromCQN } = require('../utils/data')
|
|
17
|
-
const { isMandatory, isReadOnly } = require('../aspects/utils')
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const _shouldSuppressErrorPropagation = (event, value) => {
|
|
20
20
|
return (
|
|
21
21
|
event === 'NEW' ||
|
|
22
22
|
event === 'PATCH' ||
|
|
@@ -25,7 +25,7 @@ const shouldSuppressErrorPropagation = ({ event, value }) => {
|
|
|
25
25
|
)
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const
|
|
28
|
+
const _getSimpleCategory = category => {
|
|
29
29
|
if (typeof category === 'object') {
|
|
30
30
|
category = category.category
|
|
31
31
|
}
|
|
@@ -33,7 +33,7 @@ const getSimpleCategory = category => {
|
|
|
33
33
|
return category
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const
|
|
36
|
+
const _rowKeysGenerator = eventName => {
|
|
37
37
|
if (eventName === 'UPDATE') return
|
|
38
38
|
return (keyNames, row, template) => {
|
|
39
39
|
for (const keyName of keyNames) {
|
|
@@ -69,8 +69,62 @@ const _getMediaTypeValue = req =>
|
|
|
69
69
|
!req._.req.headers['content-type'].match(/json|multipart/i) &&
|
|
70
70
|
req._.req.headers['content-type']
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
|
|
72
|
+
const _preProcessAssertTarget = (assocInfo, assertMap) => {
|
|
73
|
+
const { element: assoc, row } = assocInfo
|
|
74
|
+
const assocTarget = assoc._target
|
|
75
|
+
|
|
76
|
+
// it is expected that the associated entities be defined in the same service
|
|
77
|
+
if (assoc.parent._service !== assocTarget._service) {
|
|
78
|
+
LOG._warn && LOG.warn('Cross-service checks for the @assert.target constraint are not supported.')
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const foreignKeys = assoc._foreignKeys
|
|
83
|
+
let mapKey = `${assocTarget.name}(`
|
|
84
|
+
const hasOwn = Object.prototype.hasOwnProperty
|
|
85
|
+
const parentKeys = []
|
|
86
|
+
|
|
87
|
+
foreignKeys.forEach(keyMap => {
|
|
88
|
+
const { childElement, parentElement } = keyMap
|
|
89
|
+
|
|
90
|
+
// don't assert target if the foreign key isn't in the payload
|
|
91
|
+
if (!hasOwn.call(row, parentElement.name)) return
|
|
92
|
+
|
|
93
|
+
const foreignKeyValue = row[parentElement.name]
|
|
94
|
+
|
|
95
|
+
// don't assert target if the foreign key value is null
|
|
96
|
+
if (foreignKeyValue === null) return
|
|
97
|
+
|
|
98
|
+
mapKey += `${childElement.name}=${foreignKeyValue},`
|
|
99
|
+
parentKeys.push({
|
|
100
|
+
[childElement.name]: foreignKeyValue
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
mapKey += `)`
|
|
104
|
+
|
|
105
|
+
if (parentKeys.length === 0) return
|
|
106
|
+
|
|
107
|
+
foreignKeys.forEach(keyMap => {
|
|
108
|
+
const clonedAssocInfo = Object.assign({}, assocInfo, { pathSegments: assocInfo.pathSegments.slice(0) })
|
|
109
|
+
const target = {
|
|
110
|
+
key: mapKey,
|
|
111
|
+
entity: assocTarget,
|
|
112
|
+
keys: parentKeys,
|
|
113
|
+
assocInfo: clonedAssocInfo,
|
|
114
|
+
foreignKey: keyMap.parentElement
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!assertMap.targets.has(mapKey)) {
|
|
118
|
+
assertMap.targets.set(mapKey, target)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
assertMap.allTargets.push(target)
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const _processCategory = (req, category, value, elementInfo, assertMap) => {
|
|
126
|
+
const { row, key, element, isRoot } = elementInfo
|
|
127
|
+
category = _getSimpleCategory(category)
|
|
74
128
|
|
|
75
129
|
// remember mandatory
|
|
76
130
|
if (category === 'mandatory') {
|
|
@@ -78,6 +132,8 @@ const _processCategory = ({ row, key, category, isRoot, event, value, req, eleme
|
|
|
78
132
|
return
|
|
79
133
|
}
|
|
80
134
|
|
|
135
|
+
const event = req.event
|
|
136
|
+
|
|
81
137
|
// remove readonly & immutable (can also be complex, so do first)
|
|
82
138
|
if (category === 'readonly' || (category === 'immutable' && event === 'UPDATE')) {
|
|
83
139
|
if (_isDraftCoreComputed(req, element, event)) {
|
|
@@ -95,11 +151,9 @@ const _processCategory = ({ row, key, category, isRoot, event, value, req, eleme
|
|
|
95
151
|
value.val = row[key] = cds.utils.uuid()
|
|
96
152
|
}
|
|
97
153
|
|
|
98
|
-
//
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
// REVISIT: remove delay_assert_deep_assoc with cds^6
|
|
102
|
-
if (!cds.env.features.delay_assert_deep_assoc) checkIfAssocDeep(element, value.val, req)
|
|
154
|
+
// @assert.target
|
|
155
|
+
if ((event === 'UPDATE' || event === 'CREATE') && category === '@assert.target') {
|
|
156
|
+
_preProcessAssertTarget(elementInfo, assertMap)
|
|
103
157
|
}
|
|
104
158
|
|
|
105
159
|
// set media type from content-type header if streaming
|
|
@@ -108,28 +162,26 @@ const _processCategory = ({ row, key, category, isRoot, event, value, req, eleme
|
|
|
108
162
|
if (category === 'stream' && isStreaming && mtValue) row[key] = mtValue
|
|
109
163
|
}
|
|
110
164
|
|
|
111
|
-
const
|
|
112
|
-
const
|
|
165
|
+
const _getProcessorFn = (req, errors, assertMap) => {
|
|
166
|
+
const event = req.event
|
|
113
167
|
|
|
114
|
-
return
|
|
115
|
-
const
|
|
168
|
+
return elementInfo => {
|
|
169
|
+
const { row, key, element, plain, pathSegments } = elementInfo
|
|
116
170
|
// ugly pointer passing for sonar
|
|
117
171
|
const value = { mandatory: false, val: row && row[key] }
|
|
118
172
|
|
|
119
|
-
for (const category of categories) {
|
|
120
|
-
_processCategory(
|
|
173
|
+
for (const category of plain.categories) {
|
|
174
|
+
_processCategory(req, category, value, elementInfo, assertMap)
|
|
121
175
|
}
|
|
122
176
|
|
|
123
|
-
if (
|
|
124
|
-
return
|
|
125
|
-
}
|
|
177
|
+
if (_shouldSuppressErrorPropagation(event, value)) return
|
|
126
178
|
|
|
127
179
|
// REVISIT: Convert checkInputConstraints to template mechanism
|
|
128
|
-
checkInputConstraints({ element, value: value.val, errors,
|
|
180
|
+
checkInputConstraints({ element, value: value.val, errors, pathSegments, event })
|
|
129
181
|
}
|
|
130
182
|
}
|
|
131
183
|
|
|
132
|
-
// params: element, target, parent
|
|
184
|
+
// params: element, target, parent
|
|
133
185
|
const _pick = element => {
|
|
134
186
|
// collect actions to apply
|
|
135
187
|
const categories = []
|
|
@@ -151,25 +203,27 @@ const _pick = element => {
|
|
|
151
203
|
categories.push('immutable')
|
|
152
204
|
}
|
|
153
205
|
|
|
154
|
-
if (element._isAssociationEffective && !element._target._hasPersistenceSkip) {
|
|
155
|
-
categories.push('associationEffective')
|
|
156
|
-
}
|
|
157
|
-
|
|
158
206
|
if (element.key && !DRAFT_COLUMNS_MAP[element.name] && element.isUUID) {
|
|
159
207
|
categories.push('uuid')
|
|
160
208
|
}
|
|
161
209
|
|
|
162
210
|
if (element['@Core.IsMediaType']) categories.push('stream')
|
|
163
211
|
|
|
212
|
+
if (
|
|
213
|
+
element._isAssociationStrict &&
|
|
214
|
+
!element.on && // managed assoc
|
|
215
|
+
element.is2one &&
|
|
216
|
+
element['@assert.target'] === true
|
|
217
|
+
) {
|
|
218
|
+
categories.push('@assert.target')
|
|
219
|
+
}
|
|
220
|
+
|
|
164
221
|
if (categories.length) return { categories }
|
|
165
222
|
}
|
|
166
223
|
|
|
167
224
|
const _callError = (req, errors) => {
|
|
168
|
-
if (errors.length
|
|
169
|
-
|
|
170
|
-
req.error(error)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
225
|
+
if (errors.length === 0) return
|
|
226
|
+
for (const error of errors) req.error(error)
|
|
173
227
|
}
|
|
174
228
|
|
|
175
229
|
const _isBoundAction = req => !!(req.getUriInfo && req.getUriInfo().getLastSegment().getKind() === 'BOUND.ACTION')
|
|
@@ -183,7 +237,7 @@ const _getBoundActionBindingParameter = req => {
|
|
|
183
237
|
return (actions && actions[action] && actions[action]['@cds.odata.bindingparameter.name']) || 'in'
|
|
184
238
|
}
|
|
185
239
|
|
|
186
|
-
function _handler(req) {
|
|
240
|
+
async function _handler(req) {
|
|
187
241
|
if (!req.query) return // FIXME: the code below expects req.query to be defined
|
|
188
242
|
if (!req.target) return
|
|
189
243
|
|
|
@@ -191,41 +245,44 @@ function _handler(req) {
|
|
|
191
245
|
if (template.elements.size === 0) return
|
|
192
246
|
|
|
193
247
|
const errors = []
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
248
|
+
const assertMap = {
|
|
249
|
+
targets: new Map(),
|
|
250
|
+
allTargets: []
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const pathOptions = {
|
|
254
|
+
rowKeysGenerator: _rowKeysGenerator(req.event),
|
|
255
|
+
includeKeyValues: true,
|
|
256
|
+
pathSegments: []
|
|
202
257
|
}
|
|
258
|
+
|
|
203
259
|
if (_isBoundAction(req)) {
|
|
204
260
|
const pathSegment = _getBoundActionBindingParameter(req)
|
|
205
261
|
const keys = req._ && req._.params && req._.params[0]
|
|
206
|
-
if (pathSegment)
|
|
207
|
-
args.pathOptions.path.push({ key: pathSegment, url: pathSegment })
|
|
208
|
-
}
|
|
262
|
+
if (pathSegment) pathOptions.pathSegments.push(pathSegment)
|
|
209
263
|
|
|
210
264
|
if (keys && 'IsActiveEntity' in keys) {
|
|
211
|
-
|
|
265
|
+
pathOptions.extraKeys = { IsActiveEntity: keys.IsActiveEntity }
|
|
212
266
|
}
|
|
213
267
|
}
|
|
214
268
|
|
|
215
269
|
const data = getDataFromCQN(req.query) // REVISIT: req.data should point into req.query
|
|
216
|
-
|
|
217
270
|
enrichDataWithKeysFromWhere(data, req, this)
|
|
218
|
-
|
|
219
271
|
const arrayData = Array.isArray(data) ? data : [data]
|
|
272
|
+
|
|
220
273
|
for (const row of arrayData) {
|
|
221
|
-
templateProcessor(
|
|
274
|
+
templateProcessor({ processFn: _getProcessorFn(req, errors, assertMap), row, template, pathOptions })
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (assertMap.targets.size > 0) {
|
|
278
|
+
await assertTargets(assertMap, errors)
|
|
222
279
|
}
|
|
223
280
|
|
|
224
281
|
setDataFromCQN(req) // REVISIT: req.data should point into req.query
|
|
225
282
|
_callError(req, errors)
|
|
226
283
|
}
|
|
227
284
|
|
|
228
|
-
const
|
|
285
|
+
const _getProcessorFnForActionsFunctions =
|
|
229
286
|
(errors, opName) =>
|
|
230
287
|
({ row, key, element }) => {
|
|
231
288
|
const value = row && row[key]
|
|
@@ -236,6 +293,7 @@ const processorFnForActionsFunctions =
|
|
|
236
293
|
|
|
237
294
|
const _processActionFunctionRow = (row, param, key, errors, event, service) => {
|
|
238
295
|
const values = Array.isArray(row[key]) ? row[key] : [row[key]]
|
|
296
|
+
|
|
239
297
|
// unstructured
|
|
240
298
|
for (const value of values) {
|
|
241
299
|
checkInputConstraints({ element: param, value, errors, key })
|
|
@@ -245,9 +303,10 @@ const _processActionFunctionRow = (row, param, key, errors, event, service) => {
|
|
|
245
303
|
const template = getTemplate('app-input-operation', service, param, {
|
|
246
304
|
pick: _pick
|
|
247
305
|
})
|
|
306
|
+
|
|
248
307
|
if (template && template.elements.size) {
|
|
249
308
|
for (const value of values) {
|
|
250
|
-
const args = { processFn:
|
|
309
|
+
const args = { processFn: _getProcessorFnForActionsFunctions(errors, key), row: value, template }
|
|
251
310
|
templateProcessor(args)
|
|
252
311
|
}
|
|
253
312
|
}
|
|
@@ -256,6 +315,7 @@ const _processActionFunctionRow = (row, param, key, errors, event, service) => {
|
|
|
256
315
|
const _processActionFunction = (row, eventParams, errors, event, service) => {
|
|
257
316
|
for (const key in eventParams) {
|
|
258
317
|
let param = eventParams[key]
|
|
318
|
+
|
|
259
319
|
// .type of action/function behaves different to .type of other csn elements
|
|
260
320
|
const _type = param.type
|
|
261
321
|
if (!_type && param.items) param = param.items
|
|
@@ -281,27 +341,29 @@ function _actionFunctionHandler(req) {
|
|
|
281
341
|
const eventParams = _getEventParameters(req, this)
|
|
282
342
|
if (!eventParams) return
|
|
283
343
|
|
|
284
|
-
// REVISIT: find better solution
|
|
344
|
+
// REVISIT: find better solution -> this obviously was because params were not linked in the past
|
|
285
345
|
// attach aspects, if not yet done
|
|
286
|
-
for (const param of Object.values(eventParams)) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
346
|
+
// for (const param of Object.values(eventParams)) {
|
|
347
|
+
// if ('_isMandatory' in param) continue
|
|
348
|
+
// param._isMandatory = isMandatory(param)
|
|
349
|
+
// param._isReadOnly = isReadOnly(param)
|
|
350
|
+
// }
|
|
291
351
|
|
|
292
|
-
// REVISIT: find better solution, maybe compiler?
|
|
352
|
+
// REVISIT: find better solution, maybe compiler? -> this obviously was because params were not linked in the past
|
|
293
353
|
// resolve enums like format, range, etc.
|
|
294
|
-
for (const param of Object.values(eventParams)) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
354
|
+
// for (const param of Object.values(eventParams)) {
|
|
355
|
+
// // .type of action/function behaves different to .type of other csn elements
|
|
356
|
+
// const _type = param.type && this.model && this.model.definitions[param.type]
|
|
357
|
+
//
|
|
358
|
+
// if (_type) {
|
|
359
|
+
// param.enum = _type.enum
|
|
360
|
+
// }
|
|
361
|
+
// }
|
|
301
362
|
|
|
302
363
|
const errors = []
|
|
303
364
|
const data = req.data
|
|
304
365
|
const arrayData = Array.isArray(data) ? data : [data]
|
|
366
|
+
|
|
305
367
|
for (const row of arrayData) {
|
|
306
368
|
_processActionFunction(row, eventParams, errors, req.event, this)
|
|
307
369
|
}
|
|
@@ -314,8 +376,8 @@ _actionFunctionHandler._initial = true
|
|
|
314
376
|
|
|
315
377
|
module.exports = cds.service.impl(function () {
|
|
316
378
|
this.before(['CREATE', 'UPDATE', 'NEW', 'PATCH'], '*', _handler)
|
|
317
|
-
|
|
318
379
|
const operationNames = []
|
|
380
|
+
|
|
319
381
|
for (const operation of this.operations) {
|
|
320
382
|
operationNames.push(operation.name.substring(this.name.length + 1))
|
|
321
383
|
}
|
|
@@ -8,10 +8,16 @@ const _handler = function (req) {
|
|
|
8
8
|
// target === null if view with parameters
|
|
9
9
|
if (!req.target || !req.query.SELECT || req.query.SELECT.one) return
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
_addPaging(req.query, req.target)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const _addPaging = function (query, target) {
|
|
15
|
+
let { rows, offset } = query.SELECT.limit || {}
|
|
16
|
+
rows = rows && 'val' in rows ? rows.val : getDefaultPageSize(target)
|
|
13
17
|
offset = offset && 'val' in offset ? offset.val : 0
|
|
14
|
-
|
|
18
|
+
query.limit(...[Math.min(rows, getMaxPageSize(target)), offset])
|
|
19
|
+
//Handle nested limits
|
|
20
|
+
if (query.SELECT.from.SELECT) _addPaging(query.SELECT.from, target)
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
/**
|
|
@@ -23,7 +23,7 @@ const _fillStructure = (row, parts, element, category, args) => {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const _getProcessorFn = req => {
|
|
27
27
|
const REST = req.constructor.name === 'RestRequest'
|
|
28
28
|
|
|
29
29
|
return ({ row, key, element, plain }) => {
|
|
@@ -73,7 +73,7 @@ function _handler(req) {
|
|
|
73
73
|
const arrayData = Array.isArray(data) ? data : [data]
|
|
74
74
|
for (const row of arrayData) {
|
|
75
75
|
const args = {
|
|
76
|
-
processFn:
|
|
76
|
+
processFn: _getProcessorFn(req),
|
|
77
77
|
row,
|
|
78
78
|
template
|
|
79
79
|
}
|
|
@@ -15,8 +15,7 @@ const _getStaticOrders = req => {
|
|
|
15
15
|
|
|
16
16
|
const ordersFromKeys = []
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
if (cds.env.features.implicit_sorting !== false && (req.target._isSingleton || query.SELECT.limit)) {
|
|
18
|
+
if (req.target._isSingleton || query.SELECT.limit) {
|
|
20
19
|
const keys = getAllKeys(entity, true)
|
|
21
20
|
for (const key of keys) {
|
|
22
21
|
if (!(key in DRAFT_COLUMNS_MAP) && !defaultOrders.some(o => o.by['='] === key)) {
|
|
@@ -47,13 +46,18 @@ const _getStaticOrders = req => {
|
|
|
47
46
|
const _handler = function (req) {
|
|
48
47
|
if (!req.query || !req.query.SELECT || req.query.SELECT.one) return
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
let select = req.query.SELECT
|
|
51
50
|
|
|
52
51
|
// do not sort for /$count queries or queries only using aggregations
|
|
53
52
|
if (select.columns && select.columns.length && select.columns.every(col => col.func)) {
|
|
54
53
|
return
|
|
55
54
|
}
|
|
56
55
|
|
|
56
|
+
// apply default sort to bottom-most sub-query
|
|
57
|
+
if (select.from && select.from.SELECT) {
|
|
58
|
+
while (select.from.SELECT) select = select.from.SELECT
|
|
59
|
+
}
|
|
60
|
+
|
|
57
61
|
// "static orders" = the orders not from the query options
|
|
58
62
|
let staticOrders = _getStaticOrders(req)
|
|
59
63
|
|
|
@@ -48,11 +48,6 @@ const _handler = function (req) {
|
|
|
48
48
|
// REVISIT: stable access
|
|
49
49
|
const _ = (req.context && req.context._) || req._
|
|
50
50
|
|
|
51
|
-
if (_isWarningRequired(cds._deprecationWarningForTemporal, _queryOptions)) {
|
|
52
|
-
LOG._warn && LOG.warn('query options "sap-valid-from" and "sap-valid-to" are deprecated and will be removed.')
|
|
53
|
-
cds._deprecationWarningForTemporal = true
|
|
54
|
-
}
|
|
55
|
-
|
|
56
51
|
// make sure the env vars are reset
|
|
57
52
|
_['VALID-FROM'] = null
|
|
58
53
|
_['VALID-TO'] = null
|
|
@@ -46,6 +46,7 @@ ASSERT_DATA_TYPE=Value {0} is invalid according to type definition "{1}"
|
|
|
46
46
|
ASSERT_ENUM=Value {0} is invalid according to enum declaration {{1}}
|
|
47
47
|
ASSERT_NOT_NULL=Value is required
|
|
48
48
|
ASSERT_REFERENCE_INTEGRITY=Reference integrity is violated for association "{0}"
|
|
49
|
+
ASSERT_TARGET="Value doesn't exist"
|
|
49
50
|
ASSERT_DEEP_ASSOCIATION=It is not allowed to modify sub documents in {0} Association "{1}"
|
|
50
51
|
|
|
51
52
|
# persistence
|
|
@@ -70,7 +71,7 @@ DELETABLE=deletable
|
|
|
70
71
|
ENTITY_IS_INSERT_ONLY=Entity "{0}" is insert-only
|
|
71
72
|
ENTITY_IS_READ_ONLY=Entity "{0}" is read-only
|
|
72
73
|
ENTITY_IS_NOT_CRUD=Entity "{0}" is not {1}
|
|
73
|
-
ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via
|
|
74
|
+
ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via navigation "{2}"
|
|
74
75
|
ENTITY_IS_AUTOEXPOSED=Entity "{0}" is not explicitly exposed as part of the service
|
|
75
76
|
EXPAND_IS_RESTRICTED=Navigation property "{0}" is not allowed for expand operation
|
|
76
77
|
EXPAND_COUNT_UNSUPPORTED="$count" is not supported for expand operation
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const getTemplate = require('./template')
|
|
2
|
+
const templateProcessor = require('./templateProcessor')
|
|
3
|
+
|
|
4
|
+
const BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}={0,1}|[A-Za-z0-9+/]{2}={0,2})$/
|
|
5
|
+
|
|
6
|
+
// convert the standard base64 encoding to the URL-safe variant
|
|
7
|
+
const toBase64url = value =>
|
|
8
|
+
(Buffer.isBuffer(value) ? value.toString('base64') : value).replace(/\//g, '_').replace(/\+/g, '-')
|
|
9
|
+
|
|
10
|
+
const normalizeBase64string = value => {
|
|
11
|
+
if (typeof value !== 'string') return value
|
|
12
|
+
// add last byte(s) and '=' padding in case of shortend base64
|
|
13
|
+
return Buffer.from(value, 'base64').toString('base64')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const isInvalidBase64string = value => {
|
|
17
|
+
if (Buffer.isBuffer(value)) return // ok
|
|
18
|
+
|
|
19
|
+
// convert to standard base64 string; let it crash if typeof value !== 'string'
|
|
20
|
+
const base64 = value.replace(/_/g, '/').replace(/-/g, '+')
|
|
21
|
+
const normalized = normalizeBase64string(value)
|
|
22
|
+
|
|
23
|
+
// example of invalid base64 string --> 'WTGTdDsD/k21LnFRb+uNcAi=' <-- '...i=' must be '...g='
|
|
24
|
+
// see https://datatracker.ietf.org/doc/html/rfc4648#section-4
|
|
25
|
+
return !base64.match(BASE64) || base64.replace(/=/g, '') !== normalized.replace(/=/g, '')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const _picker = element => {
|
|
29
|
+
const categories = {}
|
|
30
|
+
if (Array.isArray(element)) return
|
|
31
|
+
if (element.type !== 'cds.Binary' && element.type !== 'cds.LargeBinary') return
|
|
32
|
+
categories['convert_binary'] = true
|
|
33
|
+
return categories
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const _processorFn =
|
|
37
|
+
toBuffer =>
|
|
38
|
+
({ row, key, plain: categories }) => {
|
|
39
|
+
if (categories['convert_binary'] && row[key] != null) {
|
|
40
|
+
if (toBuffer && typeof row[key] === 'string') row[key] = Buffer.from(row[key], 'base64')
|
|
41
|
+
if (!toBuffer && Buffer.isBuffer(row[key])) row[key] = row[key].toString('base64')
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const _processBinaryData = (data, srv, definition, toBuffer) => {
|
|
46
|
+
const template = getTemplate('rest-payload', srv, definition, { pick: _picker })
|
|
47
|
+
if (template && template.elements.size) {
|
|
48
|
+
const rows = Array.isArray(data) ? data : [data]
|
|
49
|
+
for (const row of rows) {
|
|
50
|
+
templateProcessor({ processFn: _processorFn(toBuffer), row, template })
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const base64ToBuffer = (data, srv, definition) => {
|
|
56
|
+
_processBinaryData(data, srv, definition, true)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const bufferToBase64 = (data, srv, definition) => {
|
|
60
|
+
_processBinaryData(data, srv, definition, false)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = {
|
|
64
|
+
normalizeBase64string,
|
|
65
|
+
isInvalidBase64string,
|
|
66
|
+
toBase64url,
|
|
67
|
+
base64ToBuffer,
|
|
68
|
+
bufferToBase64
|
|
69
|
+
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
const cds = require('../../cds')
|
|
2
|
+
const { SELECT } = cds.ql
|
|
3
|
+
const { setEntityContained } = require('./csn')
|
|
4
|
+
|
|
1
5
|
const getEntityNameFromDeleteCQN = cqn => {
|
|
2
6
|
let from
|
|
3
7
|
if (cqn && cqn.DELETE && cqn.DELETE.from) {
|
|
@@ -17,8 +21,7 @@ const getEntityNameFromUpdateCQN = cqn => {
|
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
// scope: simple wheres à la "[{ ref: ['foo'] }, '=', { val: 'bar' }, 'and', ... ]"
|
|
20
|
-
function where2obj(where, target = null) {
|
|
21
|
-
const data = {}
|
|
24
|
+
function where2obj(where, target = null, data = {}) {
|
|
22
25
|
for (let i = 0; i < where.length; i++) {
|
|
23
26
|
const whereEl = where[i]
|
|
24
27
|
|
|
@@ -39,20 +42,34 @@ function where2obj(where, target = null) {
|
|
|
39
42
|
return data
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
function targetFromPath(
|
|
43
|
-
const
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
function targetFromPath(from, model) {
|
|
46
|
+
const fromRef = from ? from.ref || [from] : []
|
|
47
|
+
let last = fromRef.length ? model.definitions : {}
|
|
48
|
+
const path = []
|
|
49
|
+
let target
|
|
50
|
+
let isContained
|
|
51
|
+
for (let r of fromRef) {
|
|
52
|
+
isContained = undefined
|
|
53
|
+
path.push(r.operation || r)
|
|
54
|
+
r = (r.id && r.id.replace(/_drafts$/, '')) || r
|
|
55
|
+
if (r.operation) {
|
|
56
|
+
if (last && last.actions) last = last.actions[r.operation]
|
|
57
|
+
else last = last[r.operation]
|
|
58
|
+
} else if (last.elements) {
|
|
59
|
+
last = last.elements[r]
|
|
60
|
+
if (last.isAssociation) {
|
|
61
|
+
isContained = last._isContained && last.target !== last.parent.name
|
|
62
|
+
last = model.definitions[last.target]
|
|
63
|
+
}
|
|
50
64
|
} else {
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
last = last[r]
|
|
66
|
+
}
|
|
67
|
+
if (last.kind === 'entity') {
|
|
68
|
+
target = last
|
|
69
|
+
setEntityContained(target, model, isContained)
|
|
53
70
|
}
|
|
54
71
|
}
|
|
55
|
-
return
|
|
72
|
+
return { last, path, target, isTargetComposition: isContained }
|
|
56
73
|
}
|
|
57
74
|
|
|
58
75
|
function isPathToDraft(path, model) {
|
|
@@ -80,10 +97,18 @@ function isPathToDraft(path, model) {
|
|
|
80
97
|
return draft
|
|
81
98
|
}
|
|
82
99
|
|
|
100
|
+
const resolveFromSelect = query => {
|
|
101
|
+
const __protoSelect = Object.getPrototypeOf(SELECT())
|
|
102
|
+
if (!(query instanceof __protoSelect.constructor)) Object.setPrototypeOf(query, __protoSelect)
|
|
103
|
+
const { from } = query.SELECT
|
|
104
|
+
return from.SELECT ? resolveFromSelect(from) : from
|
|
105
|
+
}
|
|
106
|
+
|
|
83
107
|
module.exports = {
|
|
84
108
|
getEntityNameFromDeleteCQN,
|
|
85
109
|
getEntityNameFromUpdateCQN,
|
|
86
110
|
where2obj,
|
|
87
111
|
targetFromPath,
|
|
88
|
-
isPathToDraft
|
|
112
|
+
isPathToDraft,
|
|
113
|
+
resolveFromSelect
|
|
89
114
|
}
|