@sap/cds 5.9.8 → 6.0.1
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 +252 -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 +80 -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 +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 +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 +70 -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 +127 -41
- 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
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,234 @@
|
|
|
4
4
|
- The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
5
5
|
- This project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
|
|
7
|
+
## Version 6.0.1 - 2022-07-05
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Config option `cds.env.server.port` allows to configure the port to use (in addition to `process.env.PORT` and CLI option `--port`)
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Removed debug log about shutdown from `cds serve`
|
|
15
|
+
- Hiding timeout error in production mode
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Plugins cannot be loaded as ES modules, but need to remain CommonJS modules
|
|
20
|
+
|
|
21
|
+
## Version 6.0.0 - 2022-06-30
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Listeners for `commit` events on the request object are now awaited
|
|
26
|
+
- Experimental support for ECMAScript modules (ESM): You can now write your custom code, i.e.,
|
|
27
|
+
service implementations, `server.js`, `db/init.js` using ES6 `import` statements.
|
|
28
|
+
**Note though** that this is _experimental_ for now. Known limitation: _jest_ doesn't
|
|
29
|
+
support dynamic imports, which are required for that.
|
|
30
|
+
|
|
31
|
+
- Improved `cds.error` to allow these using variants:
|
|
32
|
+
```js
|
|
33
|
+
cds.error `Message with formatted: ${{foo:'bar'}}`
|
|
34
|
+
cds.error ({ message, code, ... })
|
|
35
|
+
cds.error (message, { code, ... })
|
|
36
|
+
let e = new cds.error(...) //> will not throw
|
|
37
|
+
```
|
|
38
|
+
> Calling `cds.error()` with `new` returns the newly created Error,
|
|
39
|
+
> while calling it without `new` it throws immediately. The latter is
|
|
40
|
+
> useful for usages like that:
|
|
41
|
+
|
|
42
|
+
- Improved `req.error` to always turn each recorded error in to an instance of `Error` with own stack trace.
|
|
43
|
+
Multiple errors are finally thrown as an array of these errors with `.message = 'MULTIPLE_ERRORS'`
|
|
44
|
+
and `.details = this` (the latter is for compatibility to former releases).
|
|
45
|
+
|
|
46
|
+
- Public API for `cds.User.roles`: For example, this allows to construct new instances of `cds.User` like so:
|
|
47
|
+
```js
|
|
48
|
+
let user = new cds.User ({ id:'me', roles:['admin'] })
|
|
49
|
+
user.is('admin') //> true
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- Public API for `cds.context.tx`: This provides access to the current global root `tx`, if any.
|
|
53
|
+
(This replaces the former undocumented `req._tx`)
|
|
54
|
+
|
|
55
|
+
- Public API `cds.User.anonymous` and `cds.User.privileged` which are sealed instances you can use directly
|
|
56
|
+
instead of always passing `new cds.UserPrivileged`.
|
|
57
|
+
|
|
58
|
+
- Public API `cds.context.http` to reliably access inbound http `req` and `res` objects.
|
|
59
|
+
|
|
60
|
+
- Persistent outbox now contains last error and timestamp of last attempt
|
|
61
|
+
- Enable PUT requests for UPDATE queries with CQN for remote services
|
|
62
|
+
- Support for new major version 2 of SAP Cloud SDK
|
|
63
|
+
- Support for the `@assert.target` annotation for managed-to-one associations
|
|
64
|
+
- Support for `FOR SHARE LOCK` on SAP HANA to acquire shared locks on the queried records so that the locked records
|
|
65
|
+
stay intact until the transaction is committed or rolled back.
|
|
66
|
+
- Consistent error information for remote batch requests
|
|
67
|
+
- `cds.env` now supports expanding scalar `cds.requires` entries from `cds.requires.kinds`as follows:
|
|
68
|
+
```jsonc
|
|
69
|
+
{ "cds": {
|
|
70
|
+
"requires": {
|
|
71
|
+
"mtx-sidecar": true,
|
|
72
|
+
"db": "sql",
|
|
73
|
+
"kinds": {
|
|
74
|
+
"sql": {/* detailed config for sql */},
|
|
75
|
+
"mtx-sidecar": {/* detailed config */},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}}
|
|
79
|
+
```
|
|
80
|
+
- Support for mTLS in `enterprise-messaging-shared` and `message-queuing`
|
|
81
|
+
- Allow empty publish and subscribe prefixes for SAP Event Mesh when using the format `cloudevents`
|
|
82
|
+
- Custom type `sap.common.Locale` in common.cds
|
|
83
|
+
- Ordering by aggregated value for draft-enabled active entity
|
|
84
|
+
- `cds build` support for model provider service-based resource deployment.
|
|
85
|
+
- Remote service:
|
|
86
|
+
- Conversion of OData V2 (`"kind": "odata-v2"`) function and action results to OData V4 format
|
|
87
|
+
- Conversion of binary data in CQN queries to `base64url` in URL and payload
|
|
88
|
+
- Key predicate is omitted for single-key entities in resulting URL (e.g. `GET /Foo(1)` instead of `GET /Foo(ID=1)`)
|
|
89
|
+
- Support of views with parameters
|
|
90
|
+
- Add `@odata.mediaContentType` if selecting stream property
|
|
91
|
+
- Kubernetes service bindings: Support for servicebinding.io and SAP BTP Service Operator based bindings
|
|
92
|
+
- `cds build` copies an existing `.npmrc` file located in the root or srv folder of your project into the deployment folder (usually `gen/srv`). This allows for dedicated npm configuration in cloud environments. Can be switched off by cds build option `contentNpmrc`.
|
|
93
|
+
- `cds build` copies an existing `.cdsrc.json` file located in the root or srv folder of your project into the deployment folder (usually `gen/srv`). The effective CDS configuration is created from the `.cdsrc.json` and CDS configuration defined in the `package.json` file. Can be switched off by cds build option `contentCdsrcJson`.
|
|
94
|
+
- Beta OData URL to CQN parser (`cds.env.features.odata_new_parser = true`):
|
|
95
|
+
- `@odata.context` is derived without using okra, not yet supported:
|
|
96
|
+
- `$expand=*` query option
|
|
97
|
+
- Support for actions and functions
|
|
98
|
+
- Further `$apply` transformations supported
|
|
99
|
+
- (nested) `concat` transformations
|
|
100
|
+
- `orderBy` transformation
|
|
101
|
+
- `top` & `skip` transformation
|
|
102
|
+
- `identity` transformation
|
|
103
|
+
- Log `BEGIN`/`COMMIT`/`ROLLBACK` commands when using SAP HANA as the underlying database
|
|
104
|
+
- Binary data in payload is validated to be RFC-4648 and OData ABNF conformed
|
|
105
|
+
- Support multiple media (streaming) properties in one entity
|
|
106
|
+
- Support for annotation `@protocol:'none'` to mark services as internal
|
|
107
|
+
- New build task aliases `java` and `nodejs` deprecating `java-cf`and `node-cf`, which are still supported for compatibility reasons.
|
|
108
|
+
- New shutdown event sent by `cds serve` (beta)
|
|
109
|
+
- $filter in $expand for remote services
|
|
110
|
+
- Mapping of aliases in $expand for remote services
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
|
|
115
|
+
- `@sap/cds` can now be loaded from different install locations like any other module, i.e. `@require('@sap/cds')` will no longer return the same singleton instance.
|
|
116
|
+
- SAP Cloud SDK is now only an optional dependency and must be installed manually
|
|
117
|
+
- Improved `cds.context` implementation to use `AsyncLocalStorage` instead of plain `async_hooks` (-> [see Node.js docs](https://nodejs.org/api/async_context.html)); APIs stay the same.
|
|
118
|
+
- Improved `cds.tx(tx=>{ ... })`: The new `tx` will be set as `cds.context.tx` for the function body's continuation,
|
|
119
|
+
so all nested service or database operations will be executed within this transaction automatically.
|
|
120
|
+
- Node.js 14.15 is now the minimum required Node.js version. Version 12 is no longer supported.
|
|
121
|
+
- Node.js 14.15 is now enforced on loading of `@sap/cds`, for example, on server startup.
|
|
122
|
+
- Improve error messages in messaging management
|
|
123
|
+
- `cds.env.requires` formerly inherited from `cds.env.requires.kinds`. This is not the case anymore; hence things like this worked before but don't anymore:
|
|
124
|
+
```js
|
|
125
|
+
let sql = cds.requires.sql //> is undefined now
|
|
126
|
+
let sql = cds.requires.kinds.sql //> use this instead
|
|
127
|
+
```
|
|
128
|
+
Alternatively you can add this to your cds config:
|
|
129
|
+
```json
|
|
130
|
+
{ "cds": { "requires": { "sql": true } }}
|
|
131
|
+
```
|
|
132
|
+
- Details of errors from remote services are now in property `reason` (before it was `innererror`)
|
|
133
|
+
- `innererror` is not removed from OData error response
|
|
134
|
+
- The `file` option of file-based messaging is now on top level (before it was in `credentials`)
|
|
135
|
+
- Optimized Search: `cds.env.features.optimized_search=true` is now the default behavior.
|
|
136
|
+
- `cds build` no longer generates CF manifest files for Nodejs and HANA db deployer modules.
|
|
137
|
+
- `cds build` no longer supports WebIDE Fullstack compatibility mode. Consequently HANA artifacts and service EDMX files for Fiori modules might no longer be correctly generated.
|
|
138
|
+
- Remote services: Batched `GET` requests will not fetch CSRF tokens
|
|
139
|
+
- CQN now uses `xpr` correctly instead of brackets in `where`
|
|
140
|
+
- `process.exit` is called again by `cds run/serve` and `watch`, to gain a reliable `exit` event for cleanup tasks. Before, this would be spoiled by apps that do not shut down the event loop properly.
|
|
141
|
+
- `cds build` no longer filters `./` file dependencies from package.json in the build output.
|
|
142
|
+
- Fiori preview no longer supports URL pattern with `service` and `entity` query parameters, e.g. `$fiori-preview?service=...&entity=...`. These URLs were created back in `@sap/cds` 3.x.
|
|
143
|
+
- `cds build` no longer copies the `node_modules` folder into the deployment folder (usually `gen/db/**` and `gen/srv/**`).
|
|
144
|
+
- Set default tenant to `undefined` in single-tenant mode
|
|
145
|
+
- Handle foreign keys of to-one associations which should be set to `null` on db layer
|
|
146
|
+
- `cds build` uses the native `fs` functions instead of `fs-extra`.
|
|
147
|
+
- `cds build` supports initial data in CSV files that are located in any 'csv' or 'data' subfolder of some CDS model file. This also implies CSV files stored in reuse modules. Now, this behaviour is consistent with SQLite deployment. If the location of some CSV file has changed, a deployment error might be returned. In that case previously deployed `hdbtabledata` files have to be undeployed.
|
|
148
|
+
- `cds deploy` reads Cloud Foundry file `config.json` to get org and space information.
|
|
149
|
+
- New REST adapter replaced old (limited) implementation
|
|
150
|
+
- Default behaviour for runtime integrity checks. From now on no integrity checks will be done by default.
|
|
151
|
+
Note that this is a breaking change for appliations that rely on automatic integrity checks by runtime. We recommend to use `cds.env.features.assert_integrity`: `db` to switch on database integrity constraints. The value `app` can be used as fallback to previous behaviour.
|
|
152
|
+
- `cds build` no longer copies `.env` or `default-env.json` files into the deployment folder.
|
|
153
|
+
- OData `POST`, `PATCH` and `PUT` requests as well as draft-related `draftEdit` and `draftActivate` actions are now followed by an additional `READ` request to the application service. Consequently affected functionality:
|
|
154
|
+
+ It is now sufficient to have a custom `READ` handler in order to adjust the response (e.g. to handle virtual properties) of the modification request.
|
|
155
|
+
+ A user is now required to be authorized to read updated data e.g. a user having a role restricted with "INSERT-only" annotation pattern will get empty results in response to `POST` request.
|
|
156
|
+
+ For compatibility reasons, `req._` of the modification request is uplinked to `req._` of the follow-up `READ` request so that one still can access original `req._.req/res` request objects of the modification request within the corresponding `READ` handlers.
|
|
157
|
+
+ Modification logs are now followed by corresponding access logs.
|
|
158
|
+
+ More details can be found in cds v6.0.0 release notes.
|
|
159
|
+
- Message for PreconditionFailedError is now configurable in messages.properties
|
|
160
|
+
- Remove circular references in Kibana logging
|
|
161
|
+
- Error sanitization in production is skipped for custom errors with HTTP code `5xx`. From now on, it's possible for an app developer to return any error message to the client.
|
|
162
|
+
Note that this is a breaking change for appliations that rely on error sanitization for custom errors in production. The behaviour of errors thrown by CAP framework is unchanged.
|
|
163
|
+
|
|
164
|
+
### Fixed
|
|
165
|
+
|
|
166
|
+
- Improved shutdown for AMQP connections and file listeners
|
|
167
|
+
- Using `CQL` with a tagged template string `SELECT from Foo { null as boo }` throwed an exception.
|
|
168
|
+
- In case of `MULTIPLE_ERRORS` throw an `Error` instead of an object
|
|
169
|
+
- `cds build` ensures correct precedence of feature annotations. Fixes `Duplicate assignment` compilation errors.
|
|
170
|
+
- Compatibility with former support to find service `@impl: 'relative/to/cdw'`.
|
|
171
|
+
- Views on views with parameters where erroneously inherited params through `cds.linked()`.
|
|
172
|
+
- Authentication: Return HTTP `404 Not Found` rather than `204 No Content` status code for invalid requests.
|
|
173
|
+
For example, given the following request `/ReqAdmin(1)/toIntermediate/toa` and assuming that the `toIntermediate` instance does not exist,
|
|
174
|
+
the runtime returned an HTTP `204 No Content` success status response code indicating that the request has succeeded.
|
|
175
|
+
In such scenarios, now the HTTP `404 Not Found` status code is returned rather than `204 No Content`.
|
|
176
|
+
- Errors from HTTP requests sent via `cds.test.axios` now are the original Axios errors, i.e. including properties like `request` and `response`, with stack traces from caller.
|
|
177
|
+
- Errors constructed and thrown by `req.reject()` now have a stack starting at the code calling `req.reject()`.
|
|
178
|
+
- Auth annotations `@restrict` and `@requires` with empty array do not allow access anymore
|
|
179
|
+
- Delete on restricted singleton caused request to fail
|
|
180
|
+
- Add workaround of typescript not complete literal unions, specially when union strings.
|
|
181
|
+
- Accidental handling of non-proxy entities as they would have been proxies (`cds.env.odata.proxies`) in expands
|
|
182
|
+
- Boolean keys are properly parsed into JS boolean values
|
|
183
|
+
- Navigation path segments with aliased keys in structured mode (OData flavors `w4` and `x4`) when using beta OData URL to CQN parser (`cds.env.features.odata_new_parser`)
|
|
184
|
+
- All entities in `@sap/cds/common` have now proper CDS doc comments
|
|
185
|
+
- `cds build` uses `package.json` and `package-lock.json` files located in `srv` folder for deployment if existing. Before, `package.json` and `package-lock.json` files of the project root folder have always been taken.
|
|
186
|
+
- Pass options from `cds.parse.expr` to `cdsc.parse.expr`.
|
|
187
|
+
- Avoid error that is caused e.g. in a streaming scenario when there is an issue while processing the stream. Trying to change/send the response object could cause a crash because the response was sent already.
|
|
188
|
+
- Correct URL generation for `Integer64` and `Decimal` for remote services
|
|
189
|
+
- Operation parameters from structured type and annotated with @open are not filtered from the input query
|
|
190
|
+
- Services are secured by default in production. Can be disabled via feature flag `cds.env.auth.restrict_all_services: false` or by using `mocked-auth`.
|
|
191
|
+
- Optimized Search: Exception when searching on views using built-in SQL SAP HANA functions
|
|
192
|
+
- In some cases, custom error handlers were not called for rest
|
|
193
|
+
- `cds build` adds newline at EOF for `hdbmigrationtable` files
|
|
194
|
+
- Static values in on condition were ignored when inserting on navigation
|
|
195
|
+
- Removed entity key validation by POST request in rest
|
|
196
|
+
- `$count=false` returned count
|
|
197
|
+
- `odata_new_parser`: `format=json` allowed as query parameter, other formats not supported and returning 501, trailing `?` allowed e.g. `/Employees?`
|
|
198
|
+
- `odata_new_parser`: Piped use of same transformations is now supported, like `/Students?$apply=filter(BIRTHYEAR ge 2000)/groupby((UNIVERSITY),aggregate(SUBJECT with countdistinct as distinctSubjects))/filter(UNIVERSITY eq 'Hamburg')`
|
|
199
|
+
- `odata_new_parser`: Behavior of piped transformations while using `topcount` or `bottomcount` is now correct
|
|
200
|
+
- Better error message for missing `exists` predicate in `@restrict.where`
|
|
201
|
+
- Reading raw Binary data provided as a `base64` (standard or url-safe) string by means of a `$value` query option
|
|
202
|
+
- Selecting a navigation with `$select` ended up in database error
|
|
203
|
+
- `cds.compile` no longer fails for cds sources that contain the `file:` pattern
|
|
204
|
+
- $select=IsActiveEntity did not work on draft enabled entity, when requesting active data via navigation
|
|
205
|
+
- not equal operator `<>` treated the same way as `!=`
|
|
206
|
+
- `cds.localize` now respects custom i18n file names (which is not recommended though)
|
|
207
|
+
- `cds version` now handles array-valued entries for `folders.db`and `folders.srv` gracefully when looking for MTX sidecar
|
|
208
|
+
- OData access of entities named `get` and `set`
|
|
209
|
+
- missing brackets for OR condition in `.where()` when requesting by navigation
|
|
210
|
+
- `cds build` now correctly supports nodejs apps that do not have a service module defined. In these cases the build task's _src_ folder has to be configured as "."
|
|
211
|
+
- `cds build <dir>` is now correctly executed if called by npm script or mta build.
|
|
212
|
+
- `cds deploy` now shows a better error message on INSERT errors (on SQLite).
|
|
213
|
+
|
|
214
|
+
### Removed
|
|
215
|
+
|
|
216
|
+
- Deprecated option to send synchronous requests via `srv.emit()` -> use `srv.send()` for that
|
|
217
|
+
- Deprecated feature flag `cds.env.features.implicit_sorting`
|
|
218
|
+
- Deprecated feature flag `cds.env.features.update_managed_properties`
|
|
219
|
+
- Deprecated feature flag `cds.env.features.resolve_views`
|
|
220
|
+
- Deprecated feature flag `cds.env.features.spaced_columns`
|
|
221
|
+
- Deprecated feature flag `cds.env.features.throw_diff_error`
|
|
222
|
+
- Deprecated feature flag `cds.env.features.delay_assert_deep_assoc`
|
|
223
|
+
- Deprecated feature flag `cds.env.features.auto_fetch_expand_keys`
|
|
224
|
+
- Deprecation warning for query parameters `sap-valid-from` and `sap-valid-to`
|
|
225
|
+
- Built-in graphql support → moved to new `@sap/cds-graphql`
|
|
226
|
+
- Deprecated feature flag `cds.env.features.extract_vals`
|
|
227
|
+
- Support for CQN `where in` syntax `{ val: [1, 2, 3] }` without `list`. Use `{ list: [{ val: 1 }, { val: 2 }, { val: 3 }] }` instead.
|
|
228
|
+
- Support for selects in restrict entries, e.g. `where : 'exists (select 1 from MyTable where a = b)'` is not allowed anymore
|
|
229
|
+
- Input validation for deep `INSERT`/`UPDATE` for associations in the service layer
|
|
230
|
+
- Support for `@odata.contained` annotation. Use Compositions instead.
|
|
231
|
+
- Support for `@odata.on.insert/update` annotation. Use `cds.on.insert/update` instead.
|
|
232
|
+
- Support for expressions in references, for example: `ref: ['foo as bar']`).
|
|
233
|
+
- Generic support of `$expand` and `$select` OData query options for custom actions and functions
|
|
234
|
+
|
|
7
235
|
## Version 5.9.8 - 2022-06-24
|
|
8
236
|
|
|
9
237
|
### Fixed
|
|
@@ -71,11 +299,10 @@
|
|
|
71
299
|
|
|
72
300
|
- Since 5.8.2 `req.target` for requests like `srv.put('/MyService.entity')` is defined, but `req.query` undefined (before `req.target` was also undefined). This was leading to accessing undefined, which has been fixed.
|
|
73
301
|
- Custom actions with names conflicting with methods from service base classes, e.g. `run()`, could lead to hard-to-detect errors. This is now detected and avoided with a warning.
|
|
74
|
-
- Typed methods for custom actions were erroneously applied to `cds.db` service, which led to server crashes,
|
|
302
|
+
- Typed methods for custom actions were erroneously applied to `cds.db` service, which led to server crashes, for example, when the action was named `deploy()`.
|
|
75
303
|
- Invalid batch requests were further processed after error response was already sent to client, leading to an InternalServerError
|
|
76
304
|
- Full support of `SELECT` queries with operator expressions (`xpr`)
|
|
77
305
|
|
|
78
|
-
|
|
79
306
|
## Version 5.9.2 - 2022-04-07
|
|
80
307
|
|
|
81
308
|
### Fixed
|
|
@@ -94,11 +321,11 @@
|
|
|
94
321
|
|
|
95
322
|
- Function arguments might be escaped too often
|
|
96
323
|
- URL encoding for remote services for CQN queries
|
|
97
|
-
- `cds serve` during development again redirects URLs
|
|
324
|
+
- `cds serve` during development again redirects URLs for UI apps in a folder with the same name as a service, so `/foo/webapp` would redirect to `/foo` again. This got broken in 5.8.3.
|
|
98
325
|
- Endless loop in localization handling
|
|
99
326
|
- Ensure service impl while extending entity from the service
|
|
100
327
|
- Post-processing of custom draft queries
|
|
101
|
-
-
|
|
328
|
+
- `cds build` no longer omits unused CDS type definitions, leading to Java compiler errors
|
|
102
329
|
|
|
103
330
|
## Version 5.9.0 - 2022-03-25
|
|
104
331
|
|
|
@@ -116,13 +343,14 @@
|
|
|
116
343
|
+ `[{ grant: '...', to: ['...'], where: '...' }, ...]`: applicable restrictions with grant normalized to strings
|
|
117
344
|
+ That is, `grant: ['CREATE', 'UPDATE']` in model becomes `[{ grant: 'CREATE' }, { grant: 'UPDATE' }]`
|
|
118
345
|
+ Promise resolving to any of the above (needed for CAS override)
|
|
119
|
-
- Internal model provider service can be used for obtaining dynamic csn including features and key user extensions
|
|
346
|
+
- Internal model provider service can be used for obtaining dynamic csn, including features and key user extensions
|
|
120
347
|
- Support insert of SQL snippets for HANA migration tables using @sql.append and @sql.prepend annotations.
|
|
121
348
|
- Support for the `@odata.draft.enclosed` annotation on associations targeted via navigation — previously only supported for `$expand`
|
|
122
349
|
- Pseudo role `internal-user` for technical user tokens acquired from own XSUAA instance
|
|
123
350
|
- Include globally-installed cds-dk version in output of `cds version`.
|
|
124
351
|
- Include version of cds-mtx in output of `cds version`, if available.
|
|
125
352
|
- Feature toggle support in `cds build` for cloud deployments. Create language bundles and parsed CSN for all features.
|
|
353
|
+
- Support for `@Aggregation.default` in new OData parser (`cds.env.features.odata_new_parser = true`)
|
|
126
354
|
|
|
127
355
|
### Changed
|
|
128
356
|
|
|
@@ -155,7 +383,7 @@
|
|
|
155
383
|
- 'Preview' links in generic index.html page no longer get the word _preview_ appended automatically, allowing for more flexible naming. Link providers should make sure to add the _preview_ word if necessary.
|
|
156
384
|
- Don't throw error in GraphQL adapter if update mutation filter does not match any entries (to be consistent with delete mutations)
|
|
157
385
|
- Remote call of unbound action/function returns octet-stream instead of string by default
|
|
158
|
-
- Default pool's
|
|
386
|
+
- Default pool's behavior has been changed from `FIFO` (queue) to `LIFO` (stack). Can be changed in pool configuration.
|
|
159
387
|
- `cds run/serve` now gracefully shuts down the HTTP server before exiting. Custom handlers for signals like `SIGTERM` or `SIGINT` can now be processed.
|
|
160
388
|
- `cds build` no longer creates `COMMENT` statements for HANA if doc comments are present in CDS models. The statements caused superfluous table migrations during HANA deployments.
|
|
161
389
|
|
|
@@ -190,7 +418,8 @@
|
|
|
190
418
|
- `cds.compile` correctly supports reserved namespaces like `cds.foundation`.
|
|
191
419
|
- `cds.compile.to.serviceinfo` now uses the correct configuration for the base URL paths for Java services
|
|
192
420
|
- `cds deploy --to sqlite` correctly localizes texts in deployed views. Before not all localized texts have been correctly resolved.
|
|
193
|
-
- `cds deploy --to hana` reports missing org or space info with better message.
|
|
421
|
+
- `cds deploy --to hana` reports missing org or space info with a better message.
|
|
422
|
+
- Using combinations of `.` and `_` in CSN definition names
|
|
194
423
|
|
|
195
424
|
### Removed
|
|
196
425
|
|
|
@@ -207,17 +436,18 @@
|
|
|
207
436
|
|
|
208
437
|
### Fixed
|
|
209
438
|
|
|
210
|
-
- `queries` property for application
|
|
439
|
+
- `queries` property for application-defined destinations of remote services
|
|
211
440
|
- `cds serve --watch` no longer fails if `@sap/cds-dk` is installed only globally
|
|
212
441
|
- `cds serve` during development longer redirects URLs with similar path segments from different services, like `/service/one` and `/service`
|
|
213
442
|
- `cds deploy --to sqlite` now ignores a `_texts.csv` file again if there is a language-specific file like `_texts_en.csv` present
|
|
214
443
|
- Using logical blocks (surrounded with `(` and `)`) in ON-conditions of unmanaged associations and compositions
|
|
215
|
-
- Skip "with parameters" clause if no order by clause or all columns in the order by clause are not strings when using parametrized views on
|
|
444
|
+
- Skip "with parameters" clause if no order by clause or all columns in the order by clause are not strings when using parametrized views on SAP HANA
|
|
216
445
|
- Limited support for binary data in OData
|
|
217
|
-
|
|
218
|
-
|
|
446
|
+
- Using of `base64` encoded string values in `WHERE IN` on SAP HANA
|
|
447
|
+
- `base64url` values in `@odata.context` annotation
|
|
219
448
|
- `cds.context` is set in GraphQL adapter
|
|
220
|
-
- Using payloads with `@odata.type` annotating primitive properties no longer crashes the application. `#` in type value may be
|
|
449
|
+
- Using payloads with `@odata.type` annotating primitive properties no longer crashes the application. `#` in type value may be omitted. Example:
|
|
450
|
+
|
|
221
451
|
```json
|
|
222
452
|
{
|
|
223
453
|
"ID": 201,
|
|
@@ -227,13 +457,14 @@
|
|
|
227
457
|
"stock": 12
|
|
228
458
|
}
|
|
229
459
|
```
|
|
460
|
+
|
|
230
461
|
- Unicode support for i18n bundles
|
|
231
462
|
|
|
232
463
|
## Version 5.8.2 - 2022-02-22
|
|
233
464
|
|
|
234
465
|
### Fixed
|
|
235
466
|
|
|
236
|
-
- Crash if error does not have a stack in
|
|
467
|
+
- Crash if error does not have a stack in Kibana logging
|
|
237
468
|
- Allow short names for bound operations in odata-server
|
|
238
469
|
- Performance issue during deep operations
|
|
239
470
|
- Resolving views with parameters
|
|
@@ -273,17 +504,18 @@
|
|
|
273
504
|
- Draft (Access control for bound actions): Only the user that is the owner of the draft can execute its bound actions.
|
|
274
505
|
- Check that all keys are provided in REST adapter
|
|
275
506
|
- Restrict access to all services via `cds.env.requires.auth.restrict_all_services = true`
|
|
276
|
-
|
|
507
|
+
- That is, all unrestricted services (i.e., w/o own `@requires`) are treated as having `@requires: 'authenticated-user'`
|
|
277
508
|
- Threshold for automatically sending GET requests as `$batch` (beta, cf. @sap/cds@5.6.0) can be configured per remote service via `cds.env.requires.<srv>.max_get_url_length` (if not configured on service, the global config applies)
|
|
278
509
|
- Limited support for binary data in OData
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
510
|
+
- In payloads, the binary data must be a base64 encoded string
|
|
511
|
+
- In URLs, the binary data must have the following format: `binary'<url-safe base64 encoded>'`, e.g., `$filter=ID eq binary'Q0FQIE5vZGUuanM='`
|
|
512
|
+
- The use of binary data in some advanced constructs like `$apply` and `/any()` may be limited
|
|
513
|
+
- On SQLite, the base64 encoded string is stored in the database
|
|
514
|
+
- It’s strongly discouraged to use binary data as keys. See "Primary Keys — Best Practices" in the documentation.
|
|
284
515
|
- Support for OData annotation `@Core.ContentDisposition.Type` with `attachment` as the default value
|
|
285
516
|
- Support for returning custom stream objects in custom handlers (beta):
|
|
286
|
-
|
|
517
|
+
- Example:
|
|
518
|
+
|
|
287
519
|
```js
|
|
288
520
|
return {
|
|
289
521
|
value: instanceof Readable || null,
|
package/apis/services.d.ts
CHANGED
|
@@ -317,7 +317,7 @@ interface EventContext {
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
type Events = Event | Event[]
|
|
320
|
-
type Event = ( CRUD | TX | HTTP | DRAFT ) |
|
|
320
|
+
type Event = ( CRUD | TX | HTTP | DRAFT ) | (CustomOp & {})
|
|
321
321
|
type CRUD = 'CREATE' | 'READ' | 'UPDATE' | 'DELETE'
|
|
322
322
|
type DRAFT = 'NEW' | 'EDIT' | 'PATCH' | 'SAVE'
|
|
323
323
|
type HTTP = 'GET' | 'PUT' | 'POST' | 'PATCH' | 'DELETE'
|
package/app/fiori/preview.js
CHANGED
|
@@ -233,7 +233,7 @@ cds.on('served', ()=>{
|
|
|
233
233
|
|
|
234
234
|
// fetch and instrument all OData providers
|
|
235
235
|
const any = providers.filter (srv =>
|
|
236
|
-
srv._adapters [Object.keys(srv._adapters) .find (a => a.startsWith ('odata'))]
|
|
236
|
+
srv._adapters && srv._adapters [Object.keys(srv._adapters) .find (a => a.startsWith ('odata'))]
|
|
237
237
|
)
|
|
238
238
|
.map(srv => {
|
|
239
239
|
// called from ../index.js to provide the data for the HTML link
|
|
@@ -251,11 +251,7 @@ cds.on('served', ()=>{
|
|
|
251
251
|
router.get ('/:service/:entity/app/Component.js', ({ params }, resp) => resp.send(_componentJs(params.service, params.entity)))
|
|
252
252
|
// html
|
|
253
253
|
router.get ('/:service/:entity', ({ params }, resp) => resp.send(_html(params.service, params.entity)))
|
|
254
|
-
|
|
255
|
-
router.get ('/', ({ query }, resp, next) => {
|
|
256
|
-
if (query.service && query.entity) resp.redirect (308, _appURL(query.service, query.entity))
|
|
257
|
-
else next()
|
|
258
|
-
})
|
|
254
|
+
|
|
259
255
|
app.use(mountPoint.replace('$','\\$'), router)
|
|
260
256
|
}
|
|
261
257
|
|
package/app/index.js
CHANGED
|
@@ -3,7 +3,7 @@ const { find, path, fs } = cds.utils
|
|
|
3
3
|
|
|
4
4
|
module.exports = { get html(){
|
|
5
5
|
|
|
6
|
-
const odata = srv => Object.keys(srv._adapters).find (a => a.startsWith ('odata'))
|
|
6
|
+
const odata = srv => srv._adapters && Object.keys(srv._adapters).find (a => a.startsWith ('odata'))
|
|
7
7
|
const metadata = srv => odata(srv) ? ` / <a href="${srv.path}/$metadata">$metadata</a>` : ``
|
|
8
8
|
|
|
9
9
|
let html = fs.readFileSync(path.join(__dirname,'index.html'),'utf-8')
|
|
@@ -14,7 +14,7 @@ module.exports = { get html(){
|
|
|
14
14
|
html => `\n<li><a href="${html}">/${html.replace(/^[/]/,'')}</a></li>`
|
|
15
15
|
).join('\n') || '— none —'
|
|
16
16
|
)
|
|
17
|
-
.replace ('{{services}}', cds.service.providers.map (srv => `
|
|
17
|
+
.replace ('{{services}}', cds.service.providers.map (srv => srv._is_dark ? '' : `
|
|
18
18
|
<h3>
|
|
19
19
|
<a href="${srv.path}">${srv.path}</a>${metadata(srv)} ${_moreLinks(srv)}
|
|
20
20
|
</h3>
|
|
@@ -73,7 +73,7 @@ function _moreLinks (srv, entity) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function _project(){
|
|
76
|
-
const cwd =
|
|
76
|
+
const cwd = cds.root
|
|
77
77
|
try {
|
|
78
78
|
const pj = require(cwd+'/package.json')
|
|
79
79
|
return `${pj.name} ${pj.version}`
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const _cds = require('./cds'), { log } = _cds.exec
|
|
4
4
|
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
5
5
|
const { sortMessagesSeverityAware, deduplicateMessages, CompilationError } = require('@sap/cds-compiler')
|
|
6
|
-
const {
|
|
6
|
+
const { relativePaths, BuildError, BuildMessage } = require('./util')
|
|
7
7
|
const { OUTPUT_MODE_DEFAULT, SEVERITIES, LOG_LEVELS, LOG_MODULE_NAMES } = require('./constants')
|
|
8
8
|
const BuildTaskHandlerInternal = require('./provider/buildTaskHandlerInternal')
|
|
9
9
|
|
|
@@ -43,7 +43,7 @@ class BuildTaskEngine {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
this.logger.log(`building project [${buildOptions.root}], clean [${clean}]`)
|
|
46
|
-
this.logger.log(`cds [${_cds.version}], compiler [${
|
|
46
|
+
this.logger.log(`cds [${_cds.version}], compiler [${_cds.compiler.version()}], home [${_cds.home}]\n`)
|
|
47
47
|
|
|
48
48
|
if (!buildOptions.target) {
|
|
49
49
|
buildOptions.target = path.resolve(buildOptions.root, this.env.build.target)
|
|
@@ -108,7 +108,7 @@ class BuildTaskEngine {
|
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
110
|
* @deprecated
|
|
111
|
-
* @param {*} handlerGroup
|
|
111
|
+
* @param {*} handlerGroup
|
|
112
112
|
*/
|
|
113
113
|
async _doPrepare(handlerGroup, buildOptions) {
|
|
114
114
|
for (let handler of handlerGroup) {
|
|
@@ -128,10 +128,10 @@ class BuildTaskEngine {
|
|
|
128
128
|
// clean entire build staging folder once
|
|
129
129
|
if (buildOptions.target !== buildOptions.root) {
|
|
130
130
|
this.logger._debug && this.logger.debug(`cleaning staging folder ${buildOptions.target}`)
|
|
131
|
-
await fs.
|
|
131
|
+
await fs.promises.rm(buildOptions.target, {force: true, recursive: true})
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
const results = await allSettled(handlers.map((handler) => {
|
|
134
|
+
const results = await Promise.allSettled(handlers.map((handler) => {
|
|
135
135
|
this.logger._debug && this.logger.debug(`cleaning, handler [${handler.constructor.name}], src [${relativePaths(buildOptions.root, handler.task.src)}]`)
|
|
136
136
|
return handler.clean()
|
|
137
137
|
}))
|
|
@@ -169,7 +169,7 @@ class BuildTaskEngine {
|
|
|
169
169
|
async _executePipeline(buildOptions, pipeline) {
|
|
170
170
|
let allResults = []
|
|
171
171
|
for (const group of pipeline) {
|
|
172
|
-
const results = await allSettled(group.map((handler) => {
|
|
172
|
+
const results = await Promise.allSettled(group.map((handler) => {
|
|
173
173
|
this.logger._debug && this.logger.debug(`building, handler [${handler.constructor.name}], src [${relativePaths(buildOptions.root, handler.task.src)}]`)
|
|
174
174
|
return handler.build()
|
|
175
175
|
.then(handlerResult => {
|
|
@@ -188,10 +188,10 @@ class BuildTaskEngine {
|
|
|
188
188
|
_resolveHandlerResponse(results, buildOptions, handlerMessages = []) {
|
|
189
189
|
const errors = []
|
|
190
190
|
const resolvedResults = results.reduce((acc, r) => {
|
|
191
|
-
if (r.
|
|
191
|
+
if (r.status === 'fulfilled') {
|
|
192
192
|
acc.push(r.value)
|
|
193
193
|
}
|
|
194
|
-
if (r.
|
|
194
|
+
if (r.status === 'rejected' && r.reason) {
|
|
195
195
|
errors.push(r.reason)
|
|
196
196
|
}
|
|
197
197
|
return acc
|
|
@@ -262,12 +262,13 @@ class BuildTaskEngine {
|
|
|
262
262
|
const outputFile = this.env.build.outputfile || process.env.GENERATION_LOG
|
|
263
263
|
if (outputFile) {
|
|
264
264
|
this.logger.log(`writing generation log to [${outputFile}]\n`)
|
|
265
|
-
await fs.
|
|
266
|
-
.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
265
|
+
await fs.promises.mkdir(path.dirname(outputFile), {recursive: true}).then(() =>
|
|
266
|
+
fs.promises.writeFile(outputFile, files.join('\n'))
|
|
267
|
+
).catch((error) => {
|
|
268
|
+
this.logger.error(`failed to write generation log`)
|
|
269
|
+
this.logger.error(error.stack || error)
|
|
270
|
+
return Promise.resolve()
|
|
271
|
+
})
|
|
271
272
|
}
|
|
272
273
|
}
|
|
273
274
|
}
|
|
@@ -287,6 +288,7 @@ class BuildTaskEngine {
|
|
|
287
288
|
log: this.logger.log,
|
|
288
289
|
"log-level": this._getLogLevel(buildOptions) // ensures that for tests the correct cds.env is used
|
|
289
290
|
}
|
|
291
|
+
deduplicateMessages(messages)
|
|
290
292
|
log(messages, options)
|
|
291
293
|
}
|
|
292
294
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const _cds = require('./cds'), { log } = _cds.exec
|
|
4
4
|
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
5
5
|
const { hasJavaNature, getProperty, redactCredentials } = require('./util')
|
|
6
|
-
const { FILE_EXT_CDS,
|
|
6
|
+
const { FILE_EXT_CDS, BUILD_TASK_JAVA_CF, LOG_MODULE_NAMES, BUILD_TASK_JAVA } = require("./constants")
|
|
7
7
|
|
|
8
8
|
class BuildTaskFactory {
|
|
9
9
|
constructor(logger, cds) {
|
|
@@ -65,24 +65,35 @@ class BuildTaskFactory {
|
|
|
65
65
|
const buildOptions = providerFactory.buildOptions
|
|
66
66
|
this.logger.log(`determining build tasks for project [${buildOptions.root}].`)
|
|
67
67
|
|
|
68
|
+
// clear model cache - see https://github.tools.sap/cap/cds/pull/181
|
|
69
|
+
// Required as cds.serve is invoking cds.resolve('*') which caused cds to cache the current model state
|
|
70
|
+
// which in turn screwed-up all subsequent tests - see ./lib/compile/resolve.js#L67 and ./lib/compile/resolve.js#L58
|
|
71
|
+
this.cds.resolve.cache = {}
|
|
72
|
+
|
|
68
73
|
let tasks = this._getExistingTasks()
|
|
69
74
|
if (tasks.length === 0) {
|
|
70
75
|
tasks = await providerFactory.lookupTasks()
|
|
76
|
+
await providerFactory.applyTaskDefaults(tasks)
|
|
71
77
|
} else {
|
|
72
78
|
// 1. apply default values including task.for and task.use and ensure that for all tasks a provider exists - throwing error otherwise
|
|
73
79
|
await providerFactory.applyTaskDefaults(tasks)
|
|
80
|
+
await providerFactory.lookupTasks(tasks)
|
|
74
81
|
}
|
|
75
82
|
|
|
83
|
+
// 3. filters the list of build tasks and adapts according to given CLI options
|
|
76
84
|
const existingTasks = tasks
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
tasks = await this._applyCliTaskOptions(providerFactory, tasks)
|
|
86
|
+
|
|
87
|
+
// 2. add dependencies
|
|
88
|
+
await providerFactory.lookupTasks(tasks)
|
|
89
|
+
|
|
79
90
|
if (tasks !== existingTasks && tasks.some(task => !existingTasks.find(existingTask => existingTask === task))) {
|
|
80
91
|
// a different task shall be executed
|
|
81
92
|
await providerFactory.applyTaskDefaults(tasks)
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
// obligatory task defaults shared by all tasks
|
|
85
|
-
this.
|
|
96
|
+
this._applyCommonTaskDefaults(tasks, buildOptions)
|
|
86
97
|
|
|
87
98
|
// ensure correct values for optional build task properties, error for missing mandatory properties
|
|
88
99
|
this._validateBuildTasks(tasks)
|
|
@@ -95,7 +106,7 @@ class BuildTaskFactory {
|
|
|
95
106
|
return Array.isArray(getProperty(this.env, 'build.tasks')) ? JSON.parse(JSON.stringify(this.env.build.tasks)) : []
|
|
96
107
|
}
|
|
97
108
|
|
|
98
|
-
|
|
109
|
+
_applyCommonTaskDefaults(tasks, buildOptions) {
|
|
99
110
|
tasks.forEach(task => {
|
|
100
111
|
this._setTaskOptions(task, buildOptions.root)
|
|
101
112
|
if (!task.src) {
|
|
@@ -113,7 +124,7 @@ class BuildTaskFactory {
|
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
_setDefaultBuildTargetFolder(tasks, buildOptions) {
|
|
116
|
-
const task = tasks.find(task => task.for ===
|
|
127
|
+
const task = tasks.find(task => task.for === BUILD_TASK_JAVA_CF || task.for === BUILD_TASK_JAVA)
|
|
117
128
|
const srv = task ? task.src : BuildTaskFactory._getModuleFolder(buildOptions.root, BuildTaskFactory._flatten([this.env.folders.srv])) || "srv"
|
|
118
129
|
|
|
119
130
|
// Java projects use "." as the default build target folder
|
|
@@ -124,10 +135,6 @@ class BuildTaskFactory {
|
|
|
124
135
|
}
|
|
125
136
|
|
|
126
137
|
_getDefaultModelOptions(projectPath) {
|
|
127
|
-
// clear model cache - see https://github.tools.sap/cap/cds/pull/181
|
|
128
|
-
// Required as cds.serve is invoking cds.resolve('*') which caused cds to cache the current model state
|
|
129
|
-
// which in turn screwed-up all subsequent tests - see ./lib/compile/resolve.js#L67 and ./lib/compile/resolve.js#L58
|
|
130
|
-
this.cds.resolve.cache = {}
|
|
131
138
|
const fts = this.env.features.folders
|
|
132
139
|
const modelPaths = this.cds.resolve(!fts ? '*' : ['*', fts], false)
|
|
133
140
|
return this._pushModelPaths(projectPath, [], modelPaths)
|
|
@@ -161,26 +168,29 @@ class BuildTaskFactory {
|
|
|
161
168
|
return false
|
|
162
169
|
}
|
|
163
170
|
|
|
164
|
-
_applyCliTaskOptions(
|
|
171
|
+
async _applyCliTaskOptions(providerFactory, tasks) {
|
|
172
|
+
const { buildOptions } = providerFactory
|
|
165
173
|
if (buildOptions.cmdOptions) {
|
|
166
174
|
const options = buildOptions.cmdOptions
|
|
167
175
|
|
|
168
176
|
// filter tasks using either option for, use, src
|
|
169
177
|
tasks = tasks.filter(task => {
|
|
170
|
-
return (!options.use || options.use === task.use)
|
|
178
|
+
return (!options.use || options.use === task.use)
|
|
179
|
+
&& (!options.for || options.for === task.for)
|
|
180
|
+
&& (!options.src || options.src === task.src)
|
|
171
181
|
})
|
|
172
|
-
|
|
173
182
|
if (tasks.length === 0 && (options.for || options.use)) {
|
|
174
|
-
|
|
183
|
+
const task = {}
|
|
175
184
|
if ((options.for)) {
|
|
176
|
-
|
|
185
|
+
task.for = options.for
|
|
177
186
|
}
|
|
178
187
|
if ((options.use)) {
|
|
179
|
-
|
|
188
|
+
task.use = options.use
|
|
180
189
|
}
|
|
181
190
|
if (options.src) {
|
|
182
|
-
|
|
191
|
+
task.src = options.src
|
|
183
192
|
}
|
|
193
|
+
tasks.push(task)
|
|
184
194
|
}
|
|
185
195
|
// apply remaining cli options to filtered tasks
|
|
186
196
|
tasks.forEach(task => {
|
|
@@ -217,7 +227,7 @@ class BuildTaskFactory {
|
|
|
217
227
|
|
|
218
228
|
return keys.reduce((acc, key, idx) => {
|
|
219
229
|
// render either "for" OR "use" value
|
|
220
|
-
return acc + (key !== "use" || keys[idx - 1] !== "for" ? (acc !== "{" ? ", " : "") + JSON.stringify(key) + ":" + JSON.stringify(task[key]) : "")
|
|
230
|
+
return acc + (!key.match("^_") ? (key !== "use" || keys[idx - 1] !== "for" ? (acc !== "{" ? ", " : "") + JSON.stringify(key) + ":" + JSON.stringify(task[key]) : "") : "")
|
|
221
231
|
}, "{") + "}"
|
|
222
232
|
}
|
|
223
233
|
|