@sap/cds 5.9.7 → 6.0.2
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 +267 -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 +90 -53
- 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 +19 -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 +9 -10
- package/bin/{build → deploy/to-hana}/mtaUtil.js +10 -9
- package/bin/mtx/in-cds.js +19 -7
- package/bin/serve.js +56 -21
- package/bin/utils/log.js +13 -30
- package/bin/version.js +5 -4
- 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 +11 -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 +23 -20
- package/lib/serve/index.js +51 -54
- package/lib/utils/axios.js +8 -12
- package/lib/utils/index.js +3 -3
- 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 +128 -42
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +93 -73
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +10 -45
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -9
- 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 +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -21
- 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 +100 -91
- 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 +77 -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 +15 -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 +6 -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 +3 -7
- package/libx/_runtime/fiori/generic/index.js +31 -0
- package/libx/_runtime/fiori/generic/new.js +2 -4
- package/libx/_runtime/fiori/generic/patch.js +4 -8
- package/libx/_runtime/fiori/generic/prepare.js +2 -4
- package/libx/_runtime/fiori/generic/read.js +137 -162
- package/libx/_runtime/fiori/generic/readOverDraft.js +10 -4
- package/libx/_runtime/fiori/utils/handler.js +10 -5
- 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 +11 -2
- 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 +2 -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 +84 -46
- 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 +261 -157
- 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,7 +1,5 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
|
|
3
|
-
const Differ = require('./utils/differ')
|
|
4
|
-
|
|
5
3
|
const { resolveView, restoreLink, findQueryTarget } = require('../../common/utils/resolveView')
|
|
6
4
|
const { postProcess } = require('../../common/utils/postProcessing')
|
|
7
5
|
|
|
@@ -16,21 +14,7 @@ const CRUD = Object.assign({ READ: 1 }, WRITE_EVENTS)
|
|
|
16
14
|
* Generic Service Event Handler.
|
|
17
15
|
*/
|
|
18
16
|
class ApplicationService extends cds.Service {
|
|
19
|
-
constructor(name, csn, options) {
|
|
20
|
-
// REVISIT: do we still need that -> likely due to legacy test?
|
|
21
|
-
// If not we should remove this legacy constructor
|
|
22
|
-
if (typeof name === 'object') [name, csn, options] = [csn.service, name, csn]
|
|
23
|
-
super(name, csn, options)
|
|
24
|
-
|
|
25
|
-
// REVISIT: umbrella calls srv._calculateDiff
|
|
26
|
-
this._differ = new Differ(this)
|
|
27
|
-
this._calculateDiff = this._differ.calculate
|
|
28
|
-
}
|
|
29
|
-
|
|
30
17
|
init() {
|
|
31
|
-
/*
|
|
32
|
-
* .before handlers (all with _initial === true)
|
|
33
|
-
*/
|
|
34
18
|
require('../../common/generic/auth').call(this, this)
|
|
35
19
|
require('../../common/generic/etag').call(this, this)
|
|
36
20
|
require('../../common/generic/input').call(this, this)
|
|
@@ -38,21 +22,9 @@ class ApplicationService extends cds.Service {
|
|
|
38
22
|
require('../../common/generic/temporal').call(this, this)
|
|
39
23
|
require('../../common/generic/paging').call(this, this) // > paging must be executed before sorting
|
|
40
24
|
require('../../common/generic/sorting').call(this, this)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
//
|
|
44
|
-
this._2fiori = Object.values(this.entities).some(e => e._isDraftEnabled)
|
|
45
|
-
if (this._2fiori) this.registerFioriHandlers()
|
|
46
|
-
|
|
47
|
-
// personal data audit logging
|
|
48
|
-
this._4audit = cds.env.features.audit_personal_data && Object.values(this.entities).some(e => e._hasPersonalData)
|
|
49
|
-
if (this._4audit) this.registerPersonalDataHandlers()
|
|
50
|
-
|
|
51
|
-
/*
|
|
52
|
-
* .on handlers
|
|
53
|
-
*/
|
|
54
|
-
require('../../common/generic/crud').call(this, this)
|
|
55
|
-
|
|
25
|
+
this.registerFioriHandlers(this)
|
|
26
|
+
this.registerPersonalDataHandlers(this)
|
|
27
|
+
this.registerCrudHandlers(this) // default .on handlers, have to go last
|
|
56
28
|
return this
|
|
57
29
|
}
|
|
58
30
|
|
|
@@ -66,7 +38,6 @@ class ApplicationService extends cds.Service {
|
|
|
66
38
|
|
|
67
39
|
/**
|
|
68
40
|
* Registers custom handlers.
|
|
69
|
-
*
|
|
70
41
|
* @param {string | object | Function} serviceImpl - init function to register custom handlers.
|
|
71
42
|
*/
|
|
72
43
|
impl(serviceImpl) {
|
|
@@ -74,43 +45,16 @@ class ApplicationService extends cds.Service {
|
|
|
74
45
|
return this.prepend(serviceImpl)
|
|
75
46
|
}
|
|
76
47
|
|
|
48
|
+
registerPersonalDataHandlers() {
|
|
49
|
+
return cds.env.features.audit_personal_data && require('../../audit/generic/personal').impl.call(this)
|
|
50
|
+
}
|
|
51
|
+
|
|
77
52
|
registerFioriHandlers() {
|
|
78
|
-
|
|
79
|
-
this._draftHandlersRegistered = true
|
|
80
|
-
|
|
81
|
-
/*
|
|
82
|
-
* .before handlers (all with _initial === true)
|
|
83
|
-
*/
|
|
84
|
-
require('../../fiori/generic/before').call(this, this)
|
|
85
|
-
|
|
86
|
-
/*
|
|
87
|
-
* .on handlers
|
|
88
|
-
*/
|
|
89
|
-
require('../../fiori/generic/new').call(this, this) // > NEW
|
|
90
|
-
require('../../fiori/generic/patch').call(this, this) // > PATCH
|
|
91
|
-
require('../../fiori/generic/cancel').call(this, this) // > CANCEL
|
|
92
|
-
require('../../fiori/generic/edit').call(this, this) // > EDIT
|
|
93
|
-
require('../../fiori/generic/prepare').call(this, this) // > draftPrepare (-> should be PREPARE)
|
|
94
|
-
require('../../fiori/generic/activate').call(this, this) // > draftActivate (-> should be ACTIVATE)
|
|
95
|
-
require('../../fiori/generic/readOverDraft').call(this, this) // > READ non-draft via navigation
|
|
96
|
-
require('../../fiori/generic/read').call(this, this) // > READ
|
|
97
|
-
require('../../fiori/generic/delete').call(this, this) // > DELETE
|
|
53
|
+
return require('../../fiori/generic').impl.call(this)
|
|
98
54
|
}
|
|
99
55
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (cds.db && !this._personalDataHandlersRegistered) {
|
|
103
|
-
require('../../audit/generic/personal').call(this, this)
|
|
104
|
-
this._personalDataHandlersRegistered = true
|
|
105
|
-
} else {
|
|
106
|
-
const that = this
|
|
107
|
-
cds.on('connect', srv => {
|
|
108
|
-
if (srv instanceof cds.DatabaseService && !that._personalDataHandlersRegistered) {
|
|
109
|
-
require('../../audit/generic/personal').call(that, that)
|
|
110
|
-
that._personalDataHandlersRegistered = true
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
}
|
|
56
|
+
registerCrudHandlers() {
|
|
57
|
+
return require('../../common/generic/crud').impl.call(this)
|
|
114
58
|
}
|
|
115
59
|
|
|
116
60
|
/**
|
|
@@ -128,18 +72,18 @@ class ApplicationService extends cds.Service {
|
|
|
128
72
|
*/
|
|
129
73
|
getRestrictions(definition, event, user) {
|
|
130
74
|
let restrictions = getNormalizedRestrictions(definition, this.model.definitions, event)
|
|
131
|
-
if (
|
|
75
|
+
if (!restrictions && (event in CRUD || !definition.parent)) {
|
|
132
76
|
// > unrestricted entity or unbound
|
|
133
77
|
return null
|
|
134
78
|
}
|
|
135
|
-
if (event in CRUD && restrictions.every(r => r.grant !== '*' && !(r.grant in CRUD))) {
|
|
79
|
+
if (event in CRUD && restrictions.length && restrictions.every(r => r.grant !== '*' && !(r.grant in CRUD))) {
|
|
136
80
|
// > only bounds are restricted
|
|
137
81
|
return null
|
|
138
82
|
}
|
|
139
|
-
if (!(event in CRUD) &&
|
|
83
|
+
if (!(event in CRUD) && !restrictions && definition.parent) {
|
|
140
84
|
// > bound without own restrictions -> get from parent
|
|
141
85
|
restrictions = getNormalizedRestrictions(definition.parent, this.model.definitions, event)
|
|
142
|
-
if (!restrictions
|
|
86
|
+
if (!restrictions) {
|
|
143
87
|
// > unrestricted bound
|
|
144
88
|
return null
|
|
145
89
|
}
|
|
@@ -152,16 +96,13 @@ class ApplicationService extends cds.Service {
|
|
|
152
96
|
// Result is post processed according to the inverse projection in order to reflect the correct result of the original query.
|
|
153
97
|
async handle(req) {
|
|
154
98
|
// compat mode
|
|
155
|
-
if (req._resolved
|
|
156
|
-
|
|
157
|
-
if (req.target && req.target.name && this.definition && req.target.name.startsWith(this.definition.name + '.')) {
|
|
158
|
-
return super.handle(req)
|
|
159
|
-
}
|
|
99
|
+
if (req._resolved) return super.handle(req)
|
|
100
|
+
if (req.target && req.target.name && req.target.name.startsWith(this.namespace + '.')) return super.handle(req)
|
|
160
101
|
|
|
161
102
|
// req.query can be:
|
|
162
103
|
// - empty object in case of unbound action/function
|
|
163
104
|
// - undefined/null in case of plain string queries
|
|
164
|
-
if (_isSimpleCqnQuery(req.query)
|
|
105
|
+
if (this.model && _isSimpleCqnQuery(req.query)) {
|
|
165
106
|
const q = resolveView(req.query, this.model, this)
|
|
166
107
|
const t = findQueryTarget(q) || req.target
|
|
167
108
|
|
|
@@ -39,7 +39,7 @@ const getColumns = (
|
|
|
39
39
|
return columns
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const
|
|
42
|
+
const _getSearchableColumns = entity => {
|
|
43
43
|
const columnsOptions = { removeIgnore: true, filterVirtual: true }
|
|
44
44
|
const columns = getColumns(entity, columnsOptions)
|
|
45
45
|
const cdsSearchTerm = '@cds.search'
|
|
@@ -121,9 +121,11 @@ const getSearchableColumns = entity => {
|
|
|
121
121
|
/**
|
|
122
122
|
* @returns {import('../../../types/api').ColumnRefs}
|
|
123
123
|
*/
|
|
124
|
-
const computeColumnsToBeSearched = (cqn, entity = {
|
|
124
|
+
const computeColumnsToBeSearched = (cqn, entity = { __searchableColumns: [] }, alias) => {
|
|
125
125
|
// if there is a group by clause, only columns in it may be searched
|
|
126
|
-
let toBeSearched =
|
|
126
|
+
let toBeSearched =
|
|
127
|
+
entity.own('__searchableColumns') || entity.set('__searchableColumns', _getSearchableColumns(entity))
|
|
128
|
+
|
|
127
129
|
if (cqn.SELECT.groupBy) toBeSearched = toBeSearched.filter(tbs => cqn.SELECT.groupBy.some(gb => gb.ref[0] === tbs))
|
|
128
130
|
toBeSearched = toBeSearched.map(c => {
|
|
129
131
|
const col = { ref: [c] }
|
|
@@ -142,6 +144,7 @@ const computeColumnsToBeSearched = (cqn, entity = { _searchableColumns: [] }, al
|
|
|
142
144
|
(column.as === '_counted_' || column.as === '$count')
|
|
143
145
|
)
|
|
144
146
|
return
|
|
147
|
+
|
|
145
148
|
toBeSearched.push(column)
|
|
146
149
|
return
|
|
147
150
|
}
|
|
@@ -162,6 +165,5 @@ const computeColumnsToBeSearched = (cqn, entity = { _searchableColumns: [] }, al
|
|
|
162
165
|
|
|
163
166
|
module.exports = {
|
|
164
167
|
getColumns,
|
|
165
|
-
getSearchableColumns,
|
|
166
168
|
computeColumnsToBeSearched
|
|
167
169
|
}
|
|
@@ -265,58 +265,6 @@ const compareJson = (newValue, oldValue, entity) => {
|
|
|
265
265
|
return Array.isArray(newValue) ? result : result[0]
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
-
const _isObject = item => item && typeof item === 'object' && !Array.isArray(item) && !Buffer.isBuffer(item)
|
|
269
|
-
|
|
270
|
-
const _mergeArrays = (entity, oldValue, newValue) => {
|
|
271
|
-
const merged = []
|
|
272
|
-
const foundIdxNew = []
|
|
273
|
-
const keys = _getKeysOfEntity(entity)
|
|
274
|
-
for (const entry of oldValue) {
|
|
275
|
-
const idxNew = _getIdxCorrespondingEntryWithSameKeys(newValue, entry, keys)
|
|
276
|
-
if (idxNew === -1) merged.push(entry)
|
|
277
|
-
else {
|
|
278
|
-
foundIdxNew.push(idxNew)
|
|
279
|
-
merged.push(mergeJsonDeep(entity, entry, newValue[idxNew]))
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
for (let i = 0; i < newValue.length; i++) {
|
|
283
|
-
if (!foundIdxNew.includes(i)) merged.push(newValue[i])
|
|
284
|
-
}
|
|
285
|
-
return merged
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const mergeJsonDeep = (entity, oldValue, value) => {
|
|
289
|
-
// REVISIT readAfterWrite -> commit -> postProcessing
|
|
290
|
-
// Detach result from req.data
|
|
291
|
-
const newValue = value ? Object.assign({}, value) : oldValue // if newValue === undefined
|
|
292
|
-
if (_isObject(oldValue) && _isObject(newValue)) {
|
|
293
|
-
// append to newValue to keep an order of attributes as might be defined in custom handler
|
|
294
|
-
Object.keys(oldValue).forEach(key => {
|
|
295
|
-
if (!(key in newValue)) {
|
|
296
|
-
Object.assign(newValue, { [key]: oldValue[key] })
|
|
297
|
-
} else {
|
|
298
|
-
const target = entity && entity.elements[key] && entity.elements[key]._target
|
|
299
|
-
if (_isObject(newValue[key])) {
|
|
300
|
-
newValue[key] = mergeJsonDeep(target, oldValue[key], newValue[key])
|
|
301
|
-
} else if (Array.isArray(newValue[key])) {
|
|
302
|
-
if (target) {
|
|
303
|
-
newValue[key] = _mergeArrays(target, oldValue[key], newValue[key])
|
|
304
|
-
}
|
|
305
|
-
// Can't merge items without target
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
})
|
|
309
|
-
}
|
|
310
|
-
return newValue
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Signature similar to Object.assign(oldValue, newValue)
|
|
314
|
-
const mergeJson = (oldValue, newValue, entity) => {
|
|
315
|
-
const result = mergeJsonDeep(entity, oldValue, newValue)
|
|
316
|
-
return result
|
|
317
|
-
}
|
|
318
|
-
|
|
319
268
|
module.exports = {
|
|
320
|
-
compareJson
|
|
321
|
-
mergeJson
|
|
269
|
+
compareJson
|
|
322
270
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
|
-
const LOG = cds.log('app')
|
|
3
2
|
const { SELECT } = cds.ql
|
|
4
3
|
|
|
5
4
|
const { compareJson } = require('./compareJson')
|
|
@@ -11,7 +10,7 @@ const { cqn2cqn4sql, convertPathExpressionToWhere } = require('../../../common/u
|
|
|
11
10
|
const { revertData } = require('../../../common/utils/resolveView')
|
|
12
11
|
const { removeIsActiveEntityRecursively } = require('../../../fiori/utils/where')
|
|
13
12
|
|
|
14
|
-
module.exports = class {
|
|
13
|
+
module.exports = class Differ {
|
|
15
14
|
constructor(srv) {
|
|
16
15
|
this._srv = srv
|
|
17
16
|
}
|
|
@@ -51,16 +50,7 @@ module.exports = class {
|
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
async _diffUpdate(req, providedData) {
|
|
54
|
-
if (cds.db)
|
|
55
|
-
// REVISIT: remove try catch with cds^6
|
|
56
|
-
try {
|
|
57
|
-
await this._addPartialPersistentState(req)
|
|
58
|
-
} catch (e) {
|
|
59
|
-
// NOTE: unofficial compat flag!
|
|
60
|
-
if (cds.env.features.throw_diff_error !== false) throw e
|
|
61
|
-
else LOG.error('Unable to calculate diff due to error: ' + e.message, e)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
53
|
+
if (cds.db) await this._addPartialPersistentState(req)
|
|
64
54
|
const newQuery = cqn2cqn4sql(req.query, this._srv.model)
|
|
65
55
|
const combinedData = providedData || Object.assign({}, req.query.UPDATE.data || {}, req.query.UPDATE.with || {})
|
|
66
56
|
const lastTransition = newQuery.UPDATE._transitions[newQuery.UPDATE._transitions.length - 1]
|
|
@@ -93,13 +83,19 @@ module.exports = class {
|
|
|
93
83
|
}
|
|
94
84
|
|
|
95
85
|
async calculate(req, providedData) {
|
|
96
|
-
|
|
97
|
-
const that = this._differ || this
|
|
98
|
-
|
|
99
|
-
if (req.event === 'CREATE') return that._diffCreate(req, providedData)
|
|
86
|
+
if (req.event === 'CREATE') return this._diffCreate(req, providedData)
|
|
100
87
|
if (req.target._hasPersistenceSkip) return
|
|
101
|
-
if (req.event === 'DELETE') return
|
|
102
|
-
if (req.event === 'UPDATE') return
|
|
103
|
-
if (req.event === 'PATCH') return
|
|
88
|
+
if (req.event === 'DELETE') return this._diffDelete(req)
|
|
89
|
+
if (req.event === 'UPDATE') return this._diffUpdate(req, providedData)
|
|
90
|
+
if (req.event === 'PATCH') return this._diffPatch(req, providedData)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// is used as a req instance method
|
|
94
|
+
static reqDiff(req = this, data) {
|
|
95
|
+
const { _service: d } = req.target
|
|
96
|
+
if (!d) return Promise.resolve([])
|
|
97
|
+
const srv = cds.services[d.name]
|
|
98
|
+
if (!srv) return Promise.resolve([])
|
|
99
|
+
return new Differ(srv).calculate(req, data)
|
|
104
100
|
}
|
|
105
101
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
const cds = require('../../cds')
|
|
2
|
+
const LOG = cds.log('app')
|
|
3
|
+
|
|
1
4
|
// REVISIT: replace with cds.Request
|
|
2
5
|
const getEntry = require('../../common/error/entry')
|
|
3
6
|
|
|
@@ -28,11 +31,13 @@ const _enumValues = element => {
|
|
|
28
31
|
return Object.keys(element).map(enumKey => {
|
|
29
32
|
const enum_ = element[enumKey]
|
|
30
33
|
const enumValue = enum_ && enum_.val
|
|
34
|
+
|
|
31
35
|
if (enumValue !== undefined) {
|
|
32
36
|
if (enumValue['=']) return enumValue['=']
|
|
33
37
|
if (enum_ && enum_.literal && enum_.literal === 'number') return Number(enumValue)
|
|
34
38
|
return enumValue
|
|
35
39
|
}
|
|
40
|
+
|
|
36
41
|
return enumKey
|
|
37
42
|
})
|
|
38
43
|
}
|
|
@@ -40,35 +45,41 @@ const _enumValues = element => {
|
|
|
40
45
|
// REVISIT: this needs a cleanup!
|
|
41
46
|
const assertError = (code, element, value, key, pathSegments = []) => {
|
|
42
47
|
let args
|
|
48
|
+
|
|
43
49
|
if (typeof code === 'object') {
|
|
44
50
|
args = code.args
|
|
45
51
|
code = code.code
|
|
46
52
|
}
|
|
53
|
+
|
|
47
54
|
const { name, type, precision, scale } = element
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
55
|
+
const path = `${pathSegments.join('/')}${pathSegments.length ? '/' : ''}${name || key}`
|
|
56
|
+
|
|
57
|
+
const error = new Error()
|
|
58
|
+
const errorEntry = {
|
|
59
|
+
code,
|
|
60
|
+
message: code,
|
|
61
|
+
target: path,
|
|
62
|
+
args: args || [name || key]
|
|
63
|
+
}
|
|
51
64
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
Object.assign(error, {
|
|
65
|
+
const assertError = Object.assign(error, getEntry(errorEntry))
|
|
66
|
+
Object.assign(assertError, {
|
|
55
67
|
entity: element.parent && element.parent.name,
|
|
56
68
|
element: name, // > REVISIT: when is error.element needed?
|
|
57
69
|
type: element.items ? element.items._type : type,
|
|
58
70
|
value
|
|
59
71
|
})
|
|
60
72
|
|
|
61
|
-
if (element.enum)
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
if (scale) error.scale = scale
|
|
73
|
+
if (element.enum) assertError.enum = _enumValues(element)
|
|
74
|
+
if (precision) assertError.precision = precision
|
|
75
|
+
if (scale) assertError.scale = scale
|
|
65
76
|
|
|
66
77
|
if (element.target) {
|
|
67
78
|
// REVISIT: when does this case apply?
|
|
68
|
-
|
|
79
|
+
assertError.target = element.target
|
|
69
80
|
}
|
|
70
81
|
|
|
71
|
-
return
|
|
82
|
+
return assertError
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
const _checkString = value => {
|
|
@@ -97,7 +108,8 @@ const _checkBoolean = value => {
|
|
|
97
108
|
}
|
|
98
109
|
|
|
99
110
|
const _checkBuffer = value => {
|
|
100
|
-
|
|
111
|
+
// REVISIT: Extension parameter in push is an object with buffer data
|
|
112
|
+
return Buffer.isBuffer(value) || value.type === 'Buffer'
|
|
101
113
|
}
|
|
102
114
|
|
|
103
115
|
const _checkUUID = value => {
|
|
@@ -170,7 +182,7 @@ const checkComplexType = ([key, value], elements, ignoreNonModelledData) => {
|
|
|
170
182
|
return found || ignoreNonModelledData
|
|
171
183
|
}
|
|
172
184
|
|
|
173
|
-
const
|
|
185
|
+
const checkStaticElementByKey = (definition, key, value, result = [], ignoreNonModelledData = true) => {
|
|
174
186
|
const elementsOrParameters = definition.elements || definition.params
|
|
175
187
|
if (!elementsOrParameters) return result
|
|
176
188
|
const elementOrParameter = elementsOrParameters[key]
|
|
@@ -217,11 +229,13 @@ const _getEnumElement = element => {
|
|
|
217
229
|
const _checkEnumElement = (element, value, errors, key, pathSegments) => {
|
|
218
230
|
const enumElements = _getEnumElement(element)
|
|
219
231
|
const enumValues = enumElements && _enumValues(enumElements)
|
|
232
|
+
|
|
220
233
|
if (enumElements && !enumValues.includes(value)) {
|
|
221
234
|
const args =
|
|
222
235
|
typeof value === 'string'
|
|
223
236
|
? ['"' + value + '"', enumValues.map(ele => '"' + ele + '"').join(', ')]
|
|
224
237
|
: [value, enumValues.join(', ')]
|
|
238
|
+
|
|
225
239
|
errors.push(assertError({ code: ASSERT_ENUM, args }, element, value, key, pathSegments))
|
|
226
240
|
}
|
|
227
241
|
}
|
|
@@ -244,6 +258,7 @@ const _checkFormatElement = (element, value, errors, key, pathSegments) => {
|
|
|
244
258
|
// check for forbidden deep operations for association
|
|
245
259
|
const checkIfAssocDeep = (element, value, req) => {
|
|
246
260
|
if (!value) return
|
|
261
|
+
|
|
247
262
|
if (element.on) {
|
|
248
263
|
req.error(
|
|
249
264
|
assertError(
|
|
@@ -254,20 +269,24 @@ const checkIfAssocDeep = (element, value, req) => {
|
|
|
254
269
|
value
|
|
255
270
|
)
|
|
256
271
|
)
|
|
257
|
-
|
|
272
|
+
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (element.is2one) {
|
|
258
277
|
// managed to one
|
|
259
278
|
Object.keys(value).forEach(prop => {
|
|
260
279
|
if (typeof value[prop] !== 'object') {
|
|
261
|
-
const key = element.keys.find(
|
|
262
|
-
if (
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
280
|
+
const key = element.keys.find(element => element.ref[0] === prop)
|
|
281
|
+
if (key) return
|
|
282
|
+
|
|
283
|
+
const err = assertError(
|
|
284
|
+
{ code: ASSERT_DEEP_ASSOCIATION, args: ['managed to-one', element.name] },
|
|
285
|
+
element,
|
|
286
|
+
value
|
|
287
|
+
)
|
|
288
|
+
err.target += `.${prop}`
|
|
289
|
+
req.error(err)
|
|
271
290
|
}
|
|
272
291
|
})
|
|
273
292
|
}
|
|
@@ -276,18 +295,18 @@ const checkIfAssocDeep = (element, value, req) => {
|
|
|
276
295
|
/**
|
|
277
296
|
* @param {import('../../types/api').InputConstraints} constraints
|
|
278
297
|
*/
|
|
279
|
-
const checkInputConstraints = ({ element, value, errors, key,
|
|
298
|
+
const checkInputConstraints = ({ element, value, errors, key, pathSegments }) => {
|
|
280
299
|
if (!element) return errors
|
|
281
300
|
|
|
282
|
-
_checkMandatoryElement(element, value, errors, key,
|
|
301
|
+
_checkMandatoryElement(element, value, errors, key, pathSegments)
|
|
283
302
|
|
|
284
303
|
if (value == null) return errors
|
|
285
304
|
|
|
286
|
-
_checkEnumElement(element, value, errors, key,
|
|
305
|
+
_checkEnumElement(element, value, errors, key, pathSegments)
|
|
287
306
|
|
|
288
|
-
_checkRangeElement(element, value, errors, key,
|
|
307
|
+
_checkRangeElement(element, value, errors, key, pathSegments)
|
|
289
308
|
|
|
290
|
-
_checkFormatElement(element, value, errors, key,
|
|
309
|
+
_checkFormatElement(element, value, errors, key, pathSegments)
|
|
291
310
|
|
|
292
311
|
return errors
|
|
293
312
|
}
|
|
@@ -297,9 +316,9 @@ const checkStatic = (definition, data, ignoreNonModelledData = false) => {
|
|
|
297
316
|
|
|
298
317
|
return data.reduce((result, row) => {
|
|
299
318
|
return Object.entries(row)
|
|
300
|
-
.filter(([
|
|
319
|
+
.filter(([, value]) => value !== null && value !== undefined)
|
|
301
320
|
.reduce((result, [key, value]) => {
|
|
302
|
-
return
|
|
321
|
+
return checkStaticElementByKey(definition, key, value, result, ignoreNonModelledData)
|
|
303
322
|
}, result)
|
|
304
323
|
}, [])
|
|
305
324
|
}
|
|
@@ -315,12 +334,65 @@ const checkKeys = (entity, data) => {
|
|
|
315
334
|
if (row[key] === undefined && !entity.elements[key].isAssociation)
|
|
316
335
|
result.push(assertError(ASSERT_NOT_NULL, entity.elements[key]))
|
|
317
336
|
}
|
|
337
|
+
|
|
318
338
|
return result
|
|
319
339
|
}, [])
|
|
320
340
|
}
|
|
321
341
|
|
|
322
342
|
const assertNotNullError = element => assertError(ASSERT_NOT_NULL, element)
|
|
323
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Check whether the target entity referenced by the association (the reference's target) exists and assert an error if
|
|
346
|
+
* the the reference's target doesn't exist.
|
|
347
|
+
*
|
|
348
|
+
* In other words, use this annotation to check whether a non-null foreign key input in a table has a corresponding
|
|
349
|
+
* primary key (also known as a parent key) in the associated/referenced target table (also known as a parent table).
|
|
350
|
+
*
|
|
351
|
+
* @param {import('../../types/api').assertTargetMap} assertMap
|
|
352
|
+
* @param {array} errors An array to appends the possible errors.
|
|
353
|
+
* @see {@link https://pages.github.tools.sap/cap/docs/guides/providing-services#assert-target @assert.target} for
|
|
354
|
+
* further information.
|
|
355
|
+
*/
|
|
356
|
+
const assertTargets = async (assertMap, errors) => {
|
|
357
|
+
const { targets: targetsMap, allTargets } = assertMap
|
|
358
|
+
if (targetsMap.size === 0) return
|
|
359
|
+
|
|
360
|
+
const targets = Array.from(targetsMap.values())
|
|
361
|
+
const transactions = targets.map(({ keys, entity }) => {
|
|
362
|
+
const where = Object.assign({}, ...keys)
|
|
363
|
+
return cds.db.exists(entity, where).forShareLock()
|
|
364
|
+
})
|
|
365
|
+
const targetsExistsResults = await Promise.allSettled(transactions)
|
|
366
|
+
|
|
367
|
+
targetsExistsResults.forEach((txPromise, index) => {
|
|
368
|
+
const isPromiseRejected = txPromise.status === 'rejected'
|
|
369
|
+
const shouldAssertError = (txPromise.status === 'fulfilled' && txPromise.value === null) || isPromiseRejected
|
|
370
|
+
if (!shouldAssertError) return
|
|
371
|
+
|
|
372
|
+
const target = targets[index]
|
|
373
|
+
const { element } = target.assocInfo
|
|
374
|
+
|
|
375
|
+
if (isPromiseRejected) {
|
|
376
|
+
LOG._debug &&
|
|
377
|
+
LOG.debug(
|
|
378
|
+
`The transaction to check the @assert.target constraint for foreign key "${element.name}" failed`,
|
|
379
|
+
txPromise.reason
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
throw new Error(txPromise.reason.message)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
allTargets
|
|
386
|
+
.filter(t => t.key === target.key)
|
|
387
|
+
.forEach(target => {
|
|
388
|
+
const { row, pathSegments } = target.assocInfo
|
|
389
|
+
const key = target.foreignKey.name
|
|
390
|
+
const error = assertError('ASSERT_TARGET', target.foreignKey, row[key], key, pathSegments)
|
|
391
|
+
errors.push(error)
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
}
|
|
395
|
+
|
|
324
396
|
module.exports = {
|
|
325
397
|
CDS_TYPE_CHECKS,
|
|
326
398
|
checkComplexType,
|
|
@@ -329,6 +401,7 @@ module.exports = {
|
|
|
329
401
|
checkKeys,
|
|
330
402
|
assertError,
|
|
331
403
|
checkIfAssocDeep,
|
|
332
|
-
checkStaticElementByKey
|
|
333
|
-
assertNotNullError
|
|
404
|
+
checkStaticElementByKey,
|
|
405
|
+
assertNotNullError,
|
|
406
|
+
assertTargets
|
|
334
407
|
}
|
package/libx/_runtime/cds.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @type {import('../../lib')} */
|
|
2
|
-
const cds =
|
|
2
|
+
const cds = require('../../lib')
|
|
3
3
|
module.exports = cds
|
|
4
4
|
|
|
5
5
|
/*
|
|
@@ -9,33 +9,3 @@ const { any, entity, Association } = cds.builtin.classes
|
|
|
9
9
|
cds.extend(any).with(require('./common/aspects/any'))
|
|
10
10
|
cds.extend(Association).with(require('./common/aspects/Association'))
|
|
11
11
|
cds.extend(entity).with(require('./common/aspects/entity'))
|
|
12
|
-
|
|
13
|
-
/*
|
|
14
|
-
* mtx?
|
|
15
|
-
*/
|
|
16
|
-
Object.defineProperty(cds, '_mtxEnabled', {
|
|
17
|
-
get: () => cds.mtx && typeof cds.mtx.in === 'function' && !cds.env.features.streamlined_mtx,
|
|
18
|
-
configurable: true
|
|
19
|
-
})
|
|
20
|
-
Object.defineProperty(cds, '_mpsEnabled', {
|
|
21
|
-
get: () =>
|
|
22
|
-
cds.requires.extensibility ||
|
|
23
|
-
cds.requires.toggles ||
|
|
24
|
-
(cds.requires.multitenancy && cds.env.features.streamlined_mtx),
|
|
25
|
-
configurable: true
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
/*
|
|
29
|
-
* (lazy) feature flags
|
|
30
|
-
*/
|
|
31
|
-
// referential integrity
|
|
32
|
-
// REVISIT: why is _db_foreign_key_constraints necessary?
|
|
33
|
-
// REVISIT: Do not access cds.env too early!
|
|
34
|
-
Object.defineProperty(cds.env.features, '_db_foreign_key_constraints', {
|
|
35
|
-
get: () => {
|
|
36
|
-
const { assert_integrity: ai, assert_integrity_type: ait } = cds.env.features
|
|
37
|
-
if ((typeof ai === 'string' && ai.match(/individual/i)) || (ait && ait.match(/db/i))) return true
|
|
38
|
-
return false
|
|
39
|
-
},
|
|
40
|
-
configurable: true
|
|
41
|
-
})
|