@sap/cds-dk 10.0.6 → 10.1.0
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 +107 -0
- package/bin/add.js +7 -23
- package/bin/bind.js +10 -0
- package/bin/build.js +20 -34
- package/bin/cds.js +1 -1
- package/bin/compile/index.js +15 -41
- package/bin/completion/completionFs.js +11 -8
- package/bin/completion/index.js +592 -80
- package/bin/completion/scripts/cds.fish +568 -0
- package/bin/completion/scripts/cds.ps1 +329 -0
- package/bin/completion/scripts/cds.sh +261 -0
- package/bin/completion/scripts/cds.zsh +230 -0
- package/bin/completion/templates/cds-tmpl.fish +65 -0
- package/bin/completion/templates/cds-tmpl.ps1 +208 -0
- package/bin/completion/templates/cds-tmpl.sh +93 -0
- package/bin/completion/templates/cds-tmpl.zsh +74 -0
- package/bin/deploy/index.js +7 -1
- package/bin/deploy/options.js +25 -0
- package/{lib → bin}/deploy/to-hana/hana.js +8 -8
- package/{lib → bin}/deploy/to-hana/hdiDeployUtil.js +1 -1
- package/bin/deploy/{to-hana.js → to-hana/index.js} +1 -1
- package/{lib → bin}/deploy/to-hana/mtaUtil.js +1 -1
- package/bin/deploy/to-sql.js +0 -2
- package/bin/export.js +35 -5
- package/bin/help/export.md +3 -0
- package/bin/help.js +1 -5
- package/bin/import.js +6 -0
- package/bin/init.js +5 -24
- package/bin/inspect.js +6 -0
- package/bin/login.js +26 -20
- package/bin/pull.js +19 -6
- package/bin/push.js +19 -6
- package/bin/up.js +14 -11
- package/{lib → bin}/upgrade/constants.js +1 -1
- package/bin/{upgrade.js → upgrade/index.js} +2 -2
- package/{lib → bin}/upgrade/preflight/consistency.js +1 -1
- package/{lib → bin}/upgrade/preflight/index.js +1 -1
- package/{lib → bin}/upgrade/steps/analyze/index.js +1 -1
- package/{lib → bin}/upgrade/steps/install.js +1 -1
- package/{lib → bin}/upgrade/steps/openrewrite.js +1 -1
- package/{lib → bin}/upgrade/steps/removals.js +1 -1
- package/{lib → bin}/upgrade/steps/rewrite.js +1 -1
- package/{lib → bin}/upgrade/steps/verify.js +1 -1
- package/{lib/upgrade/index.js → bin/upgrade/upgrade.js} +2 -2
- package/{lib → bin}/upgrade/util/pom.js +2 -2
- package/{lib → bin}/upgrade/util/prompt.js +1 -1
- package/bin/util/containerize.js +8 -4
- package/bin/version.js +10 -1
- package/{lib → bin}/watch/hot-reload.js +1 -1
- package/bin/{watch.js → watch/index.js} +17 -9
- package/{lib → bin}/watch/livereload-connect.js +1 -1
- package/{lib → bin}/watch/vite-watch.js +1 -1
- package/{lib → bin}/watch/watched.js +2 -2
- package/lib/build/constants.js +1 -1
- package/lib/build/plugins/fiori/index.js +31 -2
- package/lib/build/plugins/internal.js +4 -2
- package/lib/build/plugins/mtx-sidecar/index.js +7 -8
- package/lib/build/plugins/nodejs/index.js +64 -7
- package/lib/compile/to_asyncapi.js +1 -1
- package/lib/env/schema.js +16 -0
- package/lib/env/schemas/cds-rc.js +1 -76
- package/lib/import/importapi.js +2 -3
- package/lib/import/message.js +0 -2
- package/lib/init/constants.js +2 -1
- package/lib/init/index.js +2 -2
- package/lib/init/merge.js +123 -280
- package/lib/init/plugin.js +3 -1
- package/lib/init/projectReader.js +22 -6
- package/lib/init/registries/xs-app.js +3 -5
- package/lib/init/template/ai/files/mta.yaml.hbs +1 -1
- package/lib/init/template/ai/index.js +14 -2
- package/lib/init/template/ams/index.js +2 -2
- package/lib/init/template/app-frontend/files/containerize.yaml.hbs +2 -2
- package/lib/init/template/app-frontend/index.js +4 -4
- package/lib/init/template/application-logging/index.js +2 -2
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/approuter/index.js +8 -3
- package/lib/init/template/attachments/files/package.json.hbs +1 -1
- package/lib/init/template/attachments/index.js +2 -2
- package/lib/init/template/audit-logging/index.js +2 -2
- package/lib/init/template/cloud-logging/files/package.json.hbs +4 -4
- package/lib/init/template/cloud-logging/index.js +2 -2
- package/lib/init/template/completion/completionSetup.js +36 -39
- package/lib/init/template/connectivity/index.js +2 -2
- package/lib/init/template/data/as-csv.js +15 -5
- package/lib/init/template/data/as-json.js +114 -42
- package/lib/init/template/data/index.js +16 -2
- package/lib/init/template/destination/index.js +2 -2
- package/lib/init/template/dynatrace/files/package.json.hbs +3 -3
- package/lib/init/template/dynatrace/index.js +2 -2
- package/lib/init/template/enterprise-messaging/index.js +2 -2
- package/lib/init/template/enterprise-messaging-shared/index.js +2 -2
- package/lib/init/template/extensibility/files/mta.yaml.hbs +11 -0
- package/lib/init/template/extensibility/files/xs-security.json.hbs +1 -1
- package/lib/init/template/extensibility/index.js +3 -3
- package/lib/init/template/github-actions/index.js +2 -2
- package/lib/init/template/hana/index.js +3 -2
- package/lib/init/template/hana-serverless/files/db/package.json +14 -0
- package/lib/init/template/hana-serverless/files/identity.values.yaml.hbs +10 -0
- package/lib/init/template/hana-serverless/files/mta.yaml.hbs +64 -0
- package/lib/init/template/hana-serverless/files/package.json.hbs +35 -0
- package/lib/init/template/hana-serverless/files/src/.hdiconfig +139 -0
- package/lib/init/template/hana-serverless/files/undeploy.json +7 -0
- package/lib/init/template/hana-serverless/files/values.yaml.hbs +18 -0
- package/lib/init/template/hana-serverless/index.js +184 -0
- package/lib/init/template/html5-repo/files/containerize.yaml.hbs +2 -2
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +5 -0
- package/lib/init/template/html5-repo/index.js +18 -14
- package/lib/init/template/http/index.js +123 -26
- package/lib/init/template/ias/index.js +2 -2
- package/lib/init/template/kafka/index.js +2 -2
- package/lib/init/template/kyma/index.js +7 -5
- package/lib/init/template/malware-scanner/index.js +2 -2
- package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
- package/lib/init/template/multitenancy/index.js +18 -3
- package/lib/init/template/nodejs/index.js +4 -2
- package/lib/init/template/notifications/index.js +2 -2
- package/lib/init/template/portal/files/mta.yaml.hbs +4 -0
- package/lib/init/template/portal/index.js +13 -8
- package/lib/init/template/postgres/index.js +2 -2
- package/lib/init/template/redis/index.js +2 -2
- package/lib/init/template/sample/files/db/currencies.cds +2 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +1 -1
- package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +2 -2
- package/lib/init/template/workzone-standard/index.js +5 -5
- package/lib/init/template/xsuaa/index.js +20 -2
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/mtx/auth_manager.js +103 -37
- package/lib/mtx/params.js +3 -2
- package/lib/mtx/settings_manager.js +45 -28
- package/lib/mtx/tenant_action.js +0 -1
- package/lib/mtx/util/credentials.js +62 -0
- package/node_modules/@cap-js/openapi/lib/compile/csdl.js +3 -3
- package/node_modules/@cap-js/openapi/lib/compile/csdl2openapi.js +111 -103
- package/node_modules/@cap-js/openapi/lib/compile/diagram.js +4 -4
- package/node_modules/@cap-js/openapi/lib/compile/types.d.ts +3 -1
- package/node_modules/@cap-js/openapi/package.json +3 -3
- package/node_modules/@sap/cds/CHANGELOG.md +64 -0
- package/node_modules/@sap/cds/app/index.js +5 -4
- package/node_modules/@sap/cds/eslint.config.mjs +1 -0
- package/node_modules/@sap/cds/lib/compile/for/nodejs.js +1 -0
- package/node_modules/@sap/cds/lib/compile/minify.js +14 -10
- package/node_modules/@sap/cds/lib/env/cds-env.js +1 -1
- package/node_modules/@sap/cds/lib/env/cds-requires.js +22 -11
- package/node_modules/@sap/cds/lib/env/defaults.js +4 -1
- package/node_modules/@sap/cds/lib/env/schemas/cds-rc.js +5 -2
- package/node_modules/@sap/cds/lib/plugins.js +9 -5
- package/node_modules/@sap/cds/lib/req/spawn.js +1 -1
- package/node_modules/@sap/cds/lib/srv/srv-dispatch.js +1 -1
- package/node_modules/@sap/cds/lib/srv/srv-models.js +1 -1
- package/node_modules/@sap/cds/lib/utils/cds-utils.js +2 -1
- package/node_modules/@sap/cds/libx/_runtime/common/generic/assert.js +2 -3
- package/node_modules/@sap/cds/libx/_runtime/common/generic/auth/restrict.js +8 -1
- package/node_modules/@sap/cds/libx/_runtime/common/generic/crud.js +18 -8
- package/node_modules/@sap/cds/libx/_runtime/fiori/lean-draft.js +25 -17
- package/node_modules/@sap/cds/libx/_runtime/messaging/common-utils/authorizedRequest.js +3 -2
- package/node_modules/@sap/cds/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +9 -3
- package/node_modules/@sap/cds/libx/_runtime/remote/Service.js +4 -19
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/LruCache.js +42 -0
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js +14 -4
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/cloudSdkProvider.js +2 -9
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/destinationClient.js +150 -0
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/error.js +13 -0
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/fetchClient.js +26 -18
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/query.js +34 -23
- package/node_modules/@sap/cds/libx/_runtime/remote/utils/token.js +82 -0
- package/node_modules/@sap/cds/libx/_runtime/ucl/Service.js +36 -189
- package/node_modules/@sap/cds/libx/common/utils/streaming.js +16 -16
- package/node_modules/@sap/cds/libx/http/location.js +3 -3
- package/node_modules/@sap/cds/libx/odata/middleware/batch.js +16 -10
- package/node_modules/@sap/cds/libx/odata/middleware/metadata.js +9 -6
- package/node_modules/@sap/cds/libx/odata/middleware/service-document.js +1 -1
- package/node_modules/@sap/cds/libx/odata/parse/afterburner.js +19 -3
- package/node_modules/@sap/cds/libx/odata/parse/cqn2odata.js +83 -86
- package/node_modules/@sap/cds/libx/queue/SchedulingService.js +17 -2
- package/node_modules/@sap/cds/libx/queue/processing.js +1 -3
- package/node_modules/@sap/cds/libx/rest/RestAdapter.js +3 -7
- package/node_modules/@sap/cds/libx/rest/middleware/delete.js +3 -3
- package/node_modules/@sap/cds/libx/rest/middleware/parse.js +13 -8
- package/node_modules/@sap/cds/libx/rest/middleware/read.js +3 -3
- package/node_modules/@sap/cds/libx/rest/middleware/upsert.js +2 -2
- package/node_modules/@sap/cds/package.json +1 -1
- package/node_modules/@sap/cds-compiler/CHANGELOG.md +60 -8
- package/node_modules/@sap/cds-compiler/bin/cdsc.js +2 -2
- package/node_modules/@sap/cds-compiler/doc/IncompatibleChanges_v7.md +46 -19
- package/node_modules/@sap/cds-compiler/lib/api/main.js +10 -7
- package/node_modules/@sap/cds-compiler/lib/api/options.js +8 -2
- package/node_modules/@sap/cds-compiler/lib/base/csnRefs.js +5 -2
- package/node_modules/@sap/cds-compiler/lib/base/message-registry.js +4 -0
- package/node_modules/@sap/cds-compiler/lib/base/optionProcessor.js +12 -0
- package/node_modules/@sap/cds-compiler/lib/checks/enricher.js +1 -0
- package/node_modules/@sap/cds-compiler/lib/compiler/assert-consistency.js +8 -7
- package/node_modules/@sap/cds-compiler/lib/compiler/checks.js +3 -3
- package/node_modules/@sap/cds-compiler/lib/compiler/define.js +301 -75
- package/node_modules/@sap/cds-compiler/lib/compiler/dictionaries.js +2 -0
- package/node_modules/@sap/cds-compiler/lib/compiler/extend.js +40 -26
- package/node_modules/@sap/cds-compiler/lib/compiler/populate.js +45 -60
- package/node_modules/@sap/cds-compiler/lib/compiler/propagator.js +16 -7
- package/node_modules/@sap/cds-compiler/lib/compiler/resolve.js +41 -15
- package/node_modules/@sap/cds-compiler/lib/compiler/shared.js +7 -6
- package/node_modules/@sap/cds-compiler/lib/compiler/tweak-assocs.js +62 -50
- package/node_modules/@sap/cds-compiler/lib/compiler/utils.js +29 -14
- package/node_modules/@sap/cds-compiler/lib/edm/edmAnnoPreprocessor.js +6 -5
- package/node_modules/@sap/cds-compiler/lib/gen/CdlGrammar.checksum +1 -1
- package/node_modules/@sap/cds-compiler/lib/gen/CdlParser.js +1119 -1109
- package/node_modules/@sap/cds-compiler/lib/gen/Dictionary.json +19 -3
- package/node_modules/@sap/cds-compiler/lib/json/from-csn.js +10 -16
- package/node_modules/@sap/cds-compiler/lib/json/to-csn.js +58 -39
- package/node_modules/@sap/cds-compiler/lib/main.d.ts +8 -0
- package/node_modules/@sap/cds-compiler/lib/main.js +1 -0
- package/node_modules/@sap/cds-compiler/lib/model/csnUtils.js +2 -0
- package/node_modules/@sap/cds-compiler/lib/parsers/AstBuildingParser.js +2 -1
- package/node_modules/@sap/cds-compiler/lib/parsers/XprTree.js +8 -0
- package/node_modules/@sap/cds-compiler/lib/render/toCdl.js +22 -1
- package/node_modules/@sap/cds-compiler/lib/render/toSql.js +17 -2
- package/node_modules/@sap/cds-compiler/lib/render/utils/common.js +6 -1
- package/node_modules/@sap/cds-compiler/lib/render/utils/operators.js +27 -0
- package/node_modules/@sap/cds-compiler/lib/render/utils/standardDatabaseFunctions.js +125 -3
- package/node_modules/@sap/cds-compiler/lib/tool-lib/revealInternalProperties.js +2 -1
- package/node_modules/@sap/cds-compiler/lib/transform/db/applyTransformations.js +3 -0
- package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +8 -2
- package/node_modules/@sap/cds-compiler/lib/transform/db/backlinks.js +22 -6
- package/node_modules/@sap/cds-compiler/lib/transform/db/constraints.js +62 -1
- package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +40 -0
- package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +1 -0
- package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +6 -1
- package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +19 -8
- package/node_modules/@sap/cds-compiler/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/CHANGELOG.md +51 -0
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx-migrate.js +32 -48
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +35 -16
- package/node_modules/@sap/cds-mtxs/cds-plugin.js +18 -0
- package/node_modules/@sap/cds-mtxs/lib/migration/migration.js +3 -408
- package/node_modules/@sap/cds-mtxs/lib/utils.js +19 -4
- package/node_modules/@sap/cds-mtxs/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +6 -7
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/annotations.js +5 -2
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/index.js +6 -5
- package/node_modules/@sap/cds-mtxs/srv/extensibility-service.cds +0 -11
- package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +34 -35
- package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +30 -24
- package/node_modules/@sap/cds-mtxs/srv/model-provider.js +19 -4
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +6 -3
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi.js +5 -3
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/srv-mgr.js +3 -2
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/tms.js +17 -0
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +18 -21
- package/node_modules/@sap/xsenv/CHANGELOG.md +7 -0
- package/node_modules/@sap/xsenv/package.json +10 -7
- package/node_modules/body-parser/node_modules/content-type/README.md +2 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/body-parser/node_modules/content-type/package.json +1 -1
- package/node_modules/hdb/cfg/VERSION +1 -1
- package/node_modules/hdb/lib/protocol/ClientInfo.js +16 -3
- package/node_modules/hdb/lib/protocol/Connection.js +1 -0
- package/node_modules/hdb/package.json +3 -2
- package/node_modules/negotiator/lib/accept.js +54 -0
- package/node_modules/negotiator/lib/charset.js +10 -34
- package/node_modules/negotiator/lib/encoding.js +9 -30
- package/node_modules/negotiator/lib/language.js +15 -36
- package/node_modules/negotiator/lib/mediaType.js +16 -134
- package/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
- package/node_modules/negotiator/node_modules/content-type/README.md +71 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/negotiator/node_modules/content-type/package.json +52 -0
- package/node_modules/negotiator/package.json +16 -10
- package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
- package/node_modules/qs/CHANGELOG.md +15 -0
- package/node_modules/qs/README.md +19 -1
- package/node_modules/qs/dist/qs.js +21 -21
- package/node_modules/qs/eslint.config.mjs +1 -1
- package/node_modules/qs/lib/parse.js +3 -4
- package/node_modules/qs/lib/stringify.js +23 -8
- package/node_modules/qs/lib/utils.js +10 -3
- package/node_modules/qs/package.json +4 -4
- package/node_modules/qs/test/parse.js +192 -3
- package/node_modules/qs/test/stringify.js +317 -0
- package/node_modules/qs/test/utils.js +12 -0
- package/node_modules/sax/lib/sax.js +27 -9
- package/node_modules/sax/package.json +1 -1
- package/node_modules/type-is/node_modules/content-type/README.md +2 -0
- package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/type-is/node_modules/content-type/package.json +1 -1
- package/node_modules/ws/lib/permessage-deflate.js +3 -1
- package/node_modules/ws/package.json +1 -1
- package/package.json +5 -5
- package/bin/completion/scripts/cds-bash.sh +0 -20
- package/bin/completion/scripts/cds-fish.fish +0 -13
- package/bin/completion/scripts/cds-ps.ps1 +0 -19
- package/bin/completion/scripts/cds-zsh.sh +0 -13
- package/lib/deploy/index.js +0 -25
- package/lib/import/asyncapi/importAsyncAPI.js +0 -33
- package/lib/import/asyncapi/index.js +0 -18
- package/lib/import/asyncapi/parserContext.js +0 -372
- package/lib/import/asyncapi/utils.js +0 -49
- package/lib/init/template/nodejs/files/.gitignore.hbs +0 -34
- package/node_modules/@sap/cds/libx/_runtime/ucl/queries.js +0 -61
- package/node_modules/@sap/cds-mtxs/lib/migration/extension-project-builder.js +0 -129
- package/node_modules/@sap/cds-mtxs/lib/migration/extension-project.js +0 -89
- package/node_modules/@sap/cds-mtxs/lib/migration/mtx-adapter.js +0 -230
- package/node_modules/negotiator/HISTORY.md +0 -114
- /package/{lib → bin}/upgrade/context.js +0 -0
- /package/{lib → bin}/upgrade/migrations/cds10/migrations.json +0 -0
- /package/{lib → bin}/upgrade/preflight/cds-version.js +0 -0
- /package/{lib → bin}/upgrade/preflight/project-type.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/classification.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/detector.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/evaluator.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/reporter.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/setup.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/detection.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/files.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/grep.js +0 -0
- /package/{lib → bin}/upgrade/steps/analyze/utils/yaml.js +0 -0
- /package/{lib → bin}/upgrade/util/workspaces.js +0 -0
- /package/{lib → bin}/watch/esm-resolve-registration.js +0 -0
- /package/{lib → bin}/watch/livereload-server.js +0 -0
- /package/{lib → bin}/watch/node-watch.js +0 -0
- /package/{lib → bin}/watch/open.js +0 -0
- /package/{lib → bin}/watch/watcher.js +0 -0
|
@@ -2,9 +2,9 @@ const express = require('express')
|
|
|
2
2
|
const cds = require('@sap/cds/lib')
|
|
3
3
|
const { SELECT, DELETE } = cds.ql
|
|
4
4
|
const { fs, path, tar, rimraf, read, readdir, mkdirp, write } = cds.utils
|
|
5
|
-
const { token: authToken } = require('../lib/utils')
|
|
5
|
+
const { token: authToken, authUrl } = require('../lib/utils')
|
|
6
|
+
const main = require('./config')
|
|
6
7
|
const linter = require('./extensibility/linter')
|
|
7
|
-
const { getMigratedProjects } = require('../lib/migration/migration')
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
const BUILT_IN_NAMESPACES = ['cds.core', 'cds.outbox', 'cds.xt'] // REVISIT: move to a more central place to be consumed also by linter
|
|
@@ -20,12 +20,14 @@ const ACTIVE = 2, DRAFT = 1, INACTIVE = 0
|
|
|
20
20
|
//const packageJson = require(main.root + '/package.json');
|
|
21
21
|
const APPID = require('../lib/utils').getAppId()
|
|
22
22
|
|
|
23
|
+
const conf = () => ({ ...main.env.requires.extensibility, ...cds.env.requires['cds.xt.ExtensibilityService'] })
|
|
24
|
+
|
|
23
25
|
const _async = () => {
|
|
24
26
|
return cds.context.http?.req?.headers?.prefer === 'respond-async'
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
const _includeExt = () => {
|
|
28
|
-
return (
|
|
30
|
+
return conf()['check-existing-extensions'] !== false
|
|
29
31
|
}
|
|
30
32
|
class DbAdapter {
|
|
31
33
|
|
|
@@ -64,7 +66,7 @@ class DbAdapter {
|
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
if (ext.csvs && Object.keys(ext.csvs).length > 0 &&
|
|
69
|
+
if (ext.csvs && Object.keys(ext.csvs).length > 0 && conf().activate?.['skip-csv']) throw Error('CSV deployment is disabled')
|
|
68
70
|
|
|
69
71
|
// insert extension
|
|
70
72
|
const tenant = ext.tenant
|
|
@@ -74,14 +76,9 @@ class DbAdapter {
|
|
|
74
76
|
const tag = ext.ID
|
|
75
77
|
await cds.tx({ tenant, user: new cds.User.Privileged() }, async tx => {
|
|
76
78
|
// remove current inactive extension with tag
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
await tx.run(INSERT.into('cds_xt_Extensions').entries({ ID, csn, i18n, sources: ext.archive ?? null, activated: this.activated(ext.status), tag, appid: ext.appid ?? APPID, timestamp: new Date().toISOString() }))
|
|
81
|
-
} catch (error) {
|
|
82
|
-
DEBUG?.('Trying legacy request without appid', error)
|
|
83
|
-
await tx.run(INSERT.into('cds_xt_Extensions').entries({ ID, csn, i18n, sources: ext.archive ?? null, activated: this.activated(ext.status), tag, timestamp: new Date().toISOString() }))
|
|
84
|
-
}
|
|
79
|
+
if (tag) await tx.run(DELETE.from('cds.xt.Extensions').where({ tag, activated: { '!=': this.activated(ACTIVE) } }))
|
|
80
|
+
// will break with missing appid
|
|
81
|
+
await tx.run(INSERT.into('cds.xt.Extensions').entries({ ID, csn, i18n, sources: ext.archive ?? null, activated: this.activated(ext.status), tag, appid: ext.appid ?? APPID, timestamp: new Date().toISOString() }))
|
|
85
82
|
})
|
|
86
83
|
return ID
|
|
87
84
|
}
|
|
@@ -213,7 +210,7 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
|
|
|
213
210
|
if (async) { // 202 is set by the job service
|
|
214
211
|
return
|
|
215
212
|
}
|
|
216
|
-
const res = await _fetchExtensions(req.data.ID)
|
|
213
|
+
const res = await _fetchExtensions(req.data.ID, status)
|
|
217
214
|
req.results = { ID: res?.tag, csn: res?.csn, i18n: res?.i18n !== '{}' ? res?.i18n : undefined, timestamp: res?.timestamp, appid: res?.appid, status: DbAdapter.status(res?.activated) } // REVISIT: return csvs?
|
|
218
215
|
})
|
|
219
216
|
|
|
@@ -379,9 +376,9 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
|
|
|
379
376
|
}
|
|
380
377
|
})
|
|
381
378
|
|
|
382
|
-
async function _fetchExtensions(ID) {
|
|
379
|
+
async function _fetchExtensions(ID, status) {
|
|
383
380
|
try {
|
|
384
|
-
return !ID ? await SELECT.from('cds.xt.Extensions') : await SELECT.one.from('cds.xt.Extensions').where({ tag: ID })
|
|
381
|
+
return !ID ? await SELECT.from('cds.xt.Extensions') : await SELECT.one.from('cds.xt.Extensions').where(status != undefined ? { tag: ID, activated: DbAdapter.activated(status) } : { tag: ID })
|
|
385
382
|
} catch (error) {
|
|
386
383
|
DEBUG?.('Trying legacy request without appid', error)
|
|
387
384
|
const fields = ['ID', 'csn', 'tag', 'activated', 'timestamp', 'i18n']
|
|
@@ -401,25 +398,22 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
|
|
|
401
398
|
|
|
402
399
|
})
|
|
403
400
|
|
|
404
|
-
this.on('getMigratedProjects', req => {
|
|
405
|
-
const { tagRule, defaultTag } = req.data
|
|
406
|
-
const tenant = req.tenant // REVISIT: check if access for arbitrary tenants needed
|
|
407
|
-
if (!tenant) req.reject(401, 'User not assigned to any tenant')
|
|
408
|
-
return getMigratedProjects(req, tagRule || undefined, defaultTag || undefined, tenant)
|
|
409
|
-
})
|
|
410
|
-
|
|
411
401
|
cds.on('served', () => {
|
|
412
|
-
cds.app?.post('/-/cds/login/
|
|
402
|
+
cds.app?.post('/-/cds/login/grant', express.urlencoded({ extended: false }), async (req, res) => {
|
|
413
403
|
try {
|
|
414
|
-
if (req.method === 'HEAD') return res.status(204).send()
|
|
415
|
-
|
|
416
404
|
const cred = cds.env.requires.auth.credentials || {}
|
|
417
405
|
if (!cred.clientid) throw cds.error('missing authentication service binding', { status: 500 })
|
|
418
406
|
|
|
419
|
-
const query = req.
|
|
407
|
+
const query = req.body || {}
|
|
408
|
+
|
|
409
|
+
// Endpoint accepts only passcode and refresh_token grant requests.
|
|
410
|
+
const refresh_token = typeof query.refresh_token === 'string' ? query.refresh_token : undefined
|
|
411
|
+
const passcode = typeof query.passcode === 'string' ? query.passcode : undefined
|
|
412
|
+
if (!refresh_token && !passcode)
|
|
413
|
+
throw cds.error('missing passcode or refresh_token', { status: 400 })
|
|
420
414
|
|
|
421
|
-
const form =
|
|
422
|
-
|
|
415
|
+
const form = refresh_token ? { grant_type: 'refresh_token', refresh_token } :
|
|
416
|
+
{ grant_type: 'password', passcode }
|
|
423
417
|
form.scope = `${cred.xsappname}.cds.ExtensionDeveloper`
|
|
424
418
|
const raw = await authToken(cred, { form, subdomain: query.subdomain })
|
|
425
419
|
const data = JSON.parse(raw)
|
|
@@ -434,7 +428,11 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
|
|
|
434
428
|
}
|
|
435
429
|
})
|
|
436
430
|
|
|
437
|
-
cds.app?.get('/-/cds/login/
|
|
431
|
+
cds.app?.get('/-/cds/login/grant-metadata', authMeta)
|
|
432
|
+
|
|
433
|
+
const redirectTo = to => (req, res) => res.redirect(308, to + req.url.slice(req.path.length))
|
|
434
|
+
cds.app?.post('/-/cds/login/token', redirectTo('/-/cds/login/grant'))
|
|
435
|
+
cds.app?.get('/-/cds/login/authorization-metadata', redirectTo('/-/cds/login/grant-metadata'))
|
|
438
436
|
})
|
|
439
437
|
|
|
440
438
|
const _tenant = function (req) {
|
|
@@ -483,7 +481,7 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
|
|
|
483
481
|
else await UPDATE('cds.xt.Extensions', { tag, ID: extEntry.ID }).with({ activated: DbAdapter.activated(status) }) // update status
|
|
484
482
|
|
|
485
483
|
// really activate extension
|
|
486
|
-
if (status === ACTIVE && !(
|
|
484
|
+
if (status === ACTIVE && !(conf().activate?.['skip-db'] === true)) {
|
|
487
485
|
const { 'cds.xt.DeploymentService': ds } = cds.services
|
|
488
486
|
if (!ds) {
|
|
489
487
|
LOG.info('database activation skipped for extension', tag, '- no deployment service')
|
|
@@ -503,15 +501,16 @@ module.exports = class ExtensibilityService extends cds.ApplicationService {
|
|
|
503
501
|
}
|
|
504
502
|
|
|
505
503
|
function _passcodeUrl(c, sub) {
|
|
506
|
-
|
|
507
|
-
if (sub) u.hostname = u.hostname.replace(/^[^.]+/, sub)
|
|
508
|
-
u.pathname = '/passcode'
|
|
509
|
-
return u.toString()
|
|
504
|
+
return authUrl(c.url, sub, '/passcode').toString()
|
|
510
505
|
}
|
|
511
506
|
|
|
512
507
|
function authMeta(req, res) {
|
|
513
508
|
const cred = cds.env.requires?.auth?.credentials || {}
|
|
514
|
-
|
|
509
|
+
try {
|
|
510
|
+
res.send({ passcode_url: _passcodeUrl(cred, req.query?.subdomain) })
|
|
511
|
+
} catch (err) {
|
|
512
|
+
res.status(err.status || err.statusCode || 500).json({ error: err.message })
|
|
513
|
+
}
|
|
515
514
|
}
|
|
516
515
|
|
|
517
516
|
const _getCompilerError = messages => {
|
|
@@ -7,14 +7,6 @@ const Jobs = 'cds.xt.Jobs', Tasks = 'cds.xt.Tasks'
|
|
|
7
7
|
|
|
8
8
|
const { t0_ } = require('../lib/utils')
|
|
9
9
|
|
|
10
|
-
const {
|
|
11
|
-
queueSize = 100, clusterSize = 3, workerSize = 4, poolSize = 1
|
|
12
|
-
} = {
|
|
13
|
-
...(cds.env.requires.multitenancy?.jobs ?? {}),
|
|
14
|
-
...(cds.env.requires['cds.xt.SaasProvisioningService']?.jobs ?? {}),
|
|
15
|
-
...(cds.env.requires['cds.xt.SmsProvisioningService']?.jobs ?? {})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
10
|
const RUNNING = 'RUNNING', FINISHED = 'FINISHED', FAILED = 'FAILED', QUEUED = 'QUEUED', TIMEOUT = 'TIMEOUT'
|
|
19
11
|
|
|
20
12
|
// A queue, implemented as a circular buffer for O(1) insert + delete
|
|
@@ -41,12 +33,15 @@ class Queue {
|
|
|
41
33
|
return value
|
|
42
34
|
}
|
|
43
35
|
}
|
|
44
|
-
const jobQueue = new Queue(queueSize)
|
|
45
|
-
let runningJobs = new Map()
|
|
46
36
|
|
|
47
37
|
module.exports = class JobsService extends cds.ApplicationService {
|
|
48
38
|
|
|
49
39
|
async init() {
|
|
40
|
+
|
|
41
|
+
this._conf = this._config()
|
|
42
|
+
this.jobQueue = new Queue(this._conf.queueSize)
|
|
43
|
+
this.runningJobs = new Map()
|
|
44
|
+
|
|
50
45
|
if (cds.requires.multitenancy?.diagnostics) _diagnostics4(this)
|
|
51
46
|
cds.on('listening', () => _scheduled(this))
|
|
52
47
|
|
|
@@ -57,16 +52,16 @@ module.exports = class JobsService extends cds.ApplicationService {
|
|
|
57
52
|
return jobs.map(job => ({ ...job, tasks: job.tasks.sort((a, b) => a.tenant.localeCompare(b.tenant))}))
|
|
58
53
|
})
|
|
59
54
|
this.on('config', () => {
|
|
60
|
-
const conf = main.requires.
|
|
55
|
+
const conf = main.requires['cds.xt.ExtensibilityService'], ext = main.requires.extensibility
|
|
61
56
|
const allowlist = 'extension-allowlist', blocklist = 'namespace-blocklist'
|
|
62
57
|
return {
|
|
63
58
|
pool: main.requires.db.pool,
|
|
64
59
|
poolMtx: cds.requires.db.pool,
|
|
65
60
|
jobs: cds.requires.multitenancy.jobs,
|
|
66
61
|
extensibility: {
|
|
67
|
-
tenantCheckInterval: conf?.tenantCheckInterval,
|
|
68
|
-
[allowlist]: conf?.[allowlist] ??
|
|
69
|
-
[blocklist]: conf?.[blocklist] ??
|
|
62
|
+
tenantCheckInterval: conf?.tenantCheckInterval ?? ext?.tenantCheckInterval,
|
|
63
|
+
[allowlist]: conf?.[allowlist] ?? ext?.[allowlist],
|
|
64
|
+
[blocklist]: conf?.[blocklist] ?? ext?.[blocklist]
|
|
70
65
|
}
|
|
71
66
|
}
|
|
72
67
|
})
|
|
@@ -74,6 +69,17 @@ module.exports = class JobsService extends cds.ApplicationService {
|
|
|
74
69
|
return super.init()
|
|
75
70
|
}
|
|
76
71
|
|
|
72
|
+
_config() {
|
|
73
|
+
const {
|
|
74
|
+
queueSize = 100, clusterSize = 3, workerSize = 4, poolSize = 1
|
|
75
|
+
} = {
|
|
76
|
+
...(cds.env.requires.multitenancy?.jobs ?? {}),
|
|
77
|
+
...(cds.env.requires['cds.xt.SaasProvisioningService']?.jobs ?? {}),
|
|
78
|
+
...(cds.env.requires['cds.xt.SmsProvisioningService']?.jobs ?? {})
|
|
79
|
+
}
|
|
80
|
+
return { queueSize, clusterSize, workerSize, poolSize }
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
async enqueue(service, op, clusters, args, onJobDone) {
|
|
78
84
|
const _inspect = obj => obj && Object.values(obj).filter(Boolean).length > 0 ? inspect(obj, { depth: 5, colors: cds.utils.colors.enabled }) : []
|
|
79
85
|
const inspected = Object.entries(args).reduce((acc, [k, v]) => {
|
|
@@ -112,9 +118,9 @@ module.exports = class JobsService extends cds.ApplicationService {
|
|
|
112
118
|
if (tasks.length) {
|
|
113
119
|
if (cds.services[service]) {
|
|
114
120
|
const fn = task => cds.services[service].tx({ tenant: task.tenant }, tx => tx[op](task.tenant, ...Object.values(args)))
|
|
115
|
-
jobQueue.enqueue({ job_ID, clusters: clustered, fn, onJobDone })
|
|
121
|
+
this.jobQueue.enqueue({ job_ID, clusters: clustered, fn, onJobDone })
|
|
116
122
|
} else {
|
|
117
|
-
jobQueue.enqueue({ job_ID, clusters: clustered, fn: () => {
|
|
123
|
+
this.jobQueue.enqueue({ job_ID, clusters: clustered, fn: () => {
|
|
118
124
|
LOG.warn('service', service, 'is not available, skipping job')
|
|
119
125
|
}, onJobDone })
|
|
120
126
|
}
|
|
@@ -186,16 +192,16 @@ module.exports = class JobsService extends cds.ApplicationService {
|
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
async pickJob() {
|
|
189
|
-
if (jobQueue.size === 0) return
|
|
195
|
+
if (this.jobQueue.size === 0) return
|
|
190
196
|
|
|
191
|
-
const next = new Set(jobQueue.peek().clusters.flat().map(t => t.tenant).flat())
|
|
192
|
-
const running = [...runningJobs.values()].flatMap(j => j.clusters.flat().map(t => t.tenant))
|
|
197
|
+
const next = new Set(this.jobQueue.peek().clusters.flat().map(t => t.tenant).flat())
|
|
198
|
+
const running = [...this.runningJobs.values()].flatMap(j => j.clusters.flat().map(t => t.tenant))
|
|
193
199
|
if (running.some(t => next.has(t))) return
|
|
194
200
|
|
|
195
|
-
const job = jobQueue.dequeue()
|
|
201
|
+
const job = this.jobQueue.dequeue()
|
|
196
202
|
const { job_ID, clusters, fn, onJobDone } = job
|
|
197
203
|
try {
|
|
198
|
-
runningJobs.set(job_ID, job)
|
|
204
|
+
this.runningJobs.set(job_ID, job)
|
|
199
205
|
await t0_(async () => {
|
|
200
206
|
await UPDATE(Jobs, { ID: job_ID }).with({ status: RUNNING })
|
|
201
207
|
await this.emit('jobUpdate', { job: { ID: job_ID, status: RUNNING }})
|
|
@@ -207,16 +213,16 @@ module.exports = class JobsService extends cds.ApplicationService {
|
|
|
207
213
|
await this.emit('jobUpdate', { job: { ID: job_ID, status: FAILED, error: _errorMessage(e) }})
|
|
208
214
|
})
|
|
209
215
|
} finally {
|
|
210
|
-
runningJobs.delete(job_ID)
|
|
216
|
+
this.runningJobs.delete(job_ID)
|
|
211
217
|
}
|
|
212
218
|
setImmediate(() => this.pickJob())
|
|
213
219
|
}
|
|
214
220
|
|
|
215
221
|
async _nextJob(clusters, fn, onJobDone) {
|
|
216
222
|
if (clusters.length > 1) {
|
|
217
|
-
await this.limiter(clusterSize, clusters, cluster => this.limiter(workerSize ?? poolSize, Array.from(cluster), fn, true))
|
|
223
|
+
await this.limiter(this._conf.clusterSize, clusters, cluster => this.limiter(this._conf.workerSize ?? this._conf.poolSize, Array.from(cluster), fn, true))
|
|
218
224
|
} else {
|
|
219
|
-
await this.limiter(workerSize ?? poolSize, Array.from(clusters[0]), fn, true)
|
|
225
|
+
await this.limiter(this._conf.workerSize ?? this._conf.poolSize, Array.from(clusters[0]), fn, true)
|
|
220
226
|
}
|
|
221
227
|
|
|
222
228
|
const { job_ID } = clusters[0][0] // all tasks have the same job ID -> just take the first
|
|
@@ -208,8 +208,14 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
|
|
|
208
208
|
if (extensions) {
|
|
209
209
|
const key = crypto.createHash('sha256').update(JSON.stringify({ extensions, models, javaornode })).digest('hex')
|
|
210
210
|
csn = lru4(extensionCache, key, () => {
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
try {
|
|
212
|
+
const result = cds.extend(csn).with(extensions)
|
|
213
|
+
return _delayMinify ? cds.minify(result) : result
|
|
214
|
+
} catch (e) {
|
|
215
|
+
if (!activated || e.code !== 'ERR_CDS_COMPILATION_FAILURE') throw e
|
|
216
|
+
const message = _getCompilerError(e.messages)
|
|
217
|
+
throw cds.error(`Extensions of tenant '${tenant}' are incompatible with the base model: ${message}`, { code: 'ERR_CDS_COMPILATION_FAILURE', status: 422, tenant, messages: e.messages })
|
|
218
|
+
}
|
|
213
219
|
})
|
|
214
220
|
}
|
|
215
221
|
|
|
@@ -334,7 +340,7 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
|
|
|
334
340
|
async function _getETag(tenant, activated = true) {
|
|
335
341
|
if (!main.requires.extensibility || main.requires.multitenancy && !tenant) return BASE_MODEL_ETAG
|
|
336
342
|
try {
|
|
337
|
-
const query = SELECT('max(timestamp) as TS').from('
|
|
343
|
+
const query = SELECT('max(timestamp) as TS').from('cds.xt.Extensions')
|
|
338
344
|
if (activated) query.where('activated=', 'database')
|
|
339
345
|
const exts = await cds.db.run(query)
|
|
340
346
|
if (!exts.length || !exts[0].TS) return BASE_MODEL_ETAG
|
|
@@ -377,7 +383,7 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
|
|
|
377
383
|
}
|
|
378
384
|
|
|
379
385
|
async function getExtCsvs(req) {
|
|
380
|
-
if (cds.env.requires['cds.xt.ExtensibilityService']?.activate?.['skip-csv']) return {}
|
|
386
|
+
if (cds.env.requires['cds.xt.ExtensibilityService']?.activate?.['skip-csv'] ?? main.env.requires.extensibility?.activate?.['skip-csv']) return {}
|
|
381
387
|
|
|
382
388
|
const tenant = req.data.tenant || req.tenant
|
|
383
389
|
if (tenant) cds.context = { tenant }
|
|
@@ -410,3 +416,12 @@ module.exports = class ModelProviderService extends cds.ApplicationService {
|
|
|
410
416
|
}
|
|
411
417
|
|
|
412
418
|
module.exports.prototype._add_stub_methods = true
|
|
419
|
+
|
|
420
|
+
const _getCompilerError = messages => {
|
|
421
|
+
const defaultMsg = 'Error while compiling extension'
|
|
422
|
+
if (!messages) return defaultMsg
|
|
423
|
+
for (const msg of messages) {
|
|
424
|
+
if (msg.severity === 'Error') return msg.message
|
|
425
|
+
}
|
|
426
|
+
return defaultMsg
|
|
427
|
+
}
|
|
@@ -48,7 +48,7 @@ class AbstractContainerManagerClient {
|
|
|
48
48
|
if (this.cachedToken && this.cachedToken.expiry >= Date.now() + 30_000) {
|
|
49
49
|
return `Bearer ${this.cachedToken.access_token}`
|
|
50
50
|
}
|
|
51
|
-
const raw = await token(this)
|
|
51
|
+
const raw = await token(this, { form: { grant_type: 'client_credentials' } })
|
|
52
52
|
const { access_token, expires_in } = JSON.parse(raw)
|
|
53
53
|
this.cachedToken = { access_token, expiry: Date.now() + expires_in * 1000 }
|
|
54
54
|
return `Bearer ${access_token}`
|
|
@@ -68,7 +68,7 @@ class AbstractContainerManagerClient {
|
|
|
68
68
|
conf.baseURL ??= url.startsWith('http') ? '' : this.sm_url + '/v1/'
|
|
69
69
|
|
|
70
70
|
const { retries, maxRetryAfter } = cds.requires?.multitenancy?.serviceManager ?? cds.requires?.multitenancy?.containerManager ?? {}
|
|
71
|
-
return fetchResiliently(conf.baseURL + url, conf, {
|
|
71
|
+
return fetchResiliently(conf.baseURL + url, conf, { retriesLeft: retries ?? 10, maxRetryAfter: maxRetryAfter ?? 5000, retryUntil, failures })
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
_poll = async (location, conf = {}) => {
|
|
@@ -89,9 +89,12 @@ class AbstractContainerManagerClient {
|
|
|
89
89
|
return new Promise(_next)
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// base implementation used by srv-mgr
|
|
92
93
|
_succeeded = (response) => response.data?.state === 'succeeded'
|
|
93
94
|
_failed = (response) => response.data?.state === 'failed'
|
|
94
|
-
_pollError = (response) =>
|
|
95
|
+
_pollError = (response) =>
|
|
96
|
+
response.data?.errors?.[0] ?? response.data.errors
|
|
97
|
+
?? { error: 'Unknown Error', description: `Polling failed with state ${response.data?.state ?? 'unknown'}. Last operation ${response.data?.id}` }
|
|
95
98
|
|
|
96
99
|
static _errorMessage = (e, action, tenant) => {
|
|
97
100
|
const msg = `Error ${action} tenant ${tenant}: ${e.response?.data?.error ?? e.code ?? e.message ?? 'unknown error'}`
|
|
@@ -13,7 +13,7 @@ exports._logDirectory = async () => {
|
|
|
13
13
|
await mkdirp(defaultDir)
|
|
14
14
|
return defaultDir
|
|
15
15
|
} catch (e) {
|
|
16
|
-
if (e.code !== 'EACCES') throw e
|
|
16
|
+
if (e.code !== 'EACCES' && e.code !== 'EROFS' && e.code !== 'ENOENT') throw e
|
|
17
17
|
LOG?.(`using temporary directory ${TEMP_DIR} for deployment logs`)
|
|
18
18
|
return join(TEMP_DIR, 'logs')
|
|
19
19
|
}
|
|
@@ -86,9 +86,10 @@ exports.deploy = async (hana, tenant, cwd, options, deployEnv) => {
|
|
|
86
86
|
*/
|
|
87
87
|
exports._hdi_env4 = async (t,container,options,deployEnv)=>{
|
|
88
88
|
|
|
89
|
+
let vcapFromFile
|
|
89
90
|
if (process.env.VCAP_SERVICES_FILE_PATH) {
|
|
90
91
|
try {
|
|
91
|
-
|
|
92
|
+
vcapFromFile = await fs.read(process.env.VCAP_SERVICES_FILE_PATH, 'utf-8')
|
|
92
93
|
} catch (e) {
|
|
93
94
|
LOG.warn(`Could not read or parse VCAP_SERVICES_FILE_PATH at ${process.env.VCAP_SERVICES_FILE_PATH}: ${e.message}`)
|
|
94
95
|
}
|
|
@@ -104,7 +105,8 @@ exports._hdi_env4 = async (t,container,options,deployEnv)=>{
|
|
|
104
105
|
...deployEnv // Although VCAP is in here, it will be overwritten
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
const
|
|
108
|
+
const vcapEnv = vcapFromFile ? { VCAP_SERVICES: vcapFromFile } : process.env
|
|
109
|
+
const { hana=[], 'user-provided':up=[] } = _parse_env (vcapEnv, 'VCAP_SERVICES')
|
|
108
110
|
const { hana: customEnvHana=[], 'user-provided':customEnvUp=[] } = _parse_env(deployEnv ?? {}, 'VCAP_SERVICES')
|
|
109
111
|
|
|
110
112
|
const vcapFromEnv = {
|
|
@@ -126,6 +126,7 @@ class ServiceManagerClient extends AbstractContainerManagerClient {
|
|
|
126
126
|
|
|
127
127
|
get = async (tenant, options = {}) => {
|
|
128
128
|
const { invalidCredentials, retryUntil } = options
|
|
129
|
+
if (invalidCredentials && cacheBindings) delete this._bindingsCache[tenant]
|
|
129
130
|
try {
|
|
130
131
|
const previousFailures = this.failures.has(tenant) ? this.failures.get(tenant).count : 0
|
|
131
132
|
const [binding] = await this._bindings4([tenant], { ...options, tenant, failures: previousFailures, retryUntil })
|
|
@@ -292,9 +293,9 @@ class ServiceManagerClient extends AbstractContainerManagerClient {
|
|
|
292
293
|
}
|
|
293
294
|
fetched.push(...directMatches)
|
|
294
295
|
}
|
|
295
|
-
const cacheMisses = Object.fromEntries(fetched.filter(b => b.labels?.tenant_id).map(b => [b.labels.tenant_id[0], b]))
|
|
296
|
-
Object.assign(this._bindingsCache, cacheMisses)
|
|
297
296
|
if (useCache) {
|
|
297
|
+
const cacheMisses = Object.fromEntries(fetched.filter(b => b.labels?.tenant_id).map(b => [b.labels.tenant_id[0], b]))
|
|
298
|
+
Object.assign(this._bindingsCache, cacheMisses)
|
|
298
299
|
return tenants.map(t => this._bindingsCache[t])
|
|
299
300
|
}
|
|
300
301
|
return fetched
|
|
@@ -17,6 +17,23 @@ class TMSClient extends AbstractContainerManagerClient {
|
|
|
17
17
|
this.tmsHost = credentials.baseurl
|
|
18
18
|
|
|
19
19
|
this.credentialCache = {}
|
|
20
|
+
|
|
21
|
+
// clusterSize > 1 not supported yet for TMS
|
|
22
|
+
const {
|
|
23
|
+
clusterSize
|
|
24
|
+
} = {
|
|
25
|
+
...(cds.env.requires.multitenancy?.jobs ?? {}),
|
|
26
|
+
...(cds.env.requires['cds.xt.SaasProvisioningService']?.jobs ?? {}),
|
|
27
|
+
...(cds.env.requires['cds.xt.SmsProvisioningService']?.jobs ?? {})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (clusterSize && clusterSize > 1) {
|
|
31
|
+
LOG.warn(`Cluster size of ${clusterSize} is not supported for TMS. Defaulting to 1.`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
cds.utils.merge(cds.env.requires, { multitenancy: { jobs: { clusterSize: 1 } } })
|
|
35
|
+
cds.utils.merge(cds.env.requires, { 'cds.xt.SaasProvisioningService': { jobs: { clusterSize: 1 } } })
|
|
36
|
+
cds.utils.merge(cds.env.requires, { 'cds.xt.SmsProvisioningService': { jobs: { clusterSize: 1 } } })
|
|
20
37
|
}
|
|
21
38
|
|
|
22
39
|
static defaultInstance() {
|
|
@@ -15,8 +15,6 @@ const resources = new Map()
|
|
|
15
15
|
|
|
16
16
|
const { deepMerge } = require('../../lib/utils')
|
|
17
17
|
|
|
18
|
-
const migration = require('../../lib/migration/migration')
|
|
19
|
-
|
|
20
18
|
if (db?.kind === 'hana') {
|
|
21
19
|
if (!db.credentials?.sm_url && !db.credentials?.baseurl) cds.error('No Service Manager credentials found. Make sure the application is bound to a BTP Service Manager instance.')
|
|
22
20
|
|
|
@@ -89,20 +87,24 @@ if (db?.kind === 'hana') {
|
|
|
89
87
|
})
|
|
90
88
|
ds.on ('tenantsByDb', async req => {
|
|
91
89
|
const tenantsInT0 = await ds.getTenants()
|
|
92
|
-
const
|
|
93
|
-
const tenants = req.data.tenants ?? [...tenantsInT0, ...mtxTenants]
|
|
90
|
+
const tenants = req.data.tenants ?? [...tenantsInT0]
|
|
94
91
|
const hana = require('./hana/hdi-ctnr-mgr').defaultInstance() // TODO tms more generic handling -> new functions hana.toTenantId + hana.toDbId
|
|
95
92
|
const toTenantId = t => t.tenant_id ?? t.labels.tenant_id[0]
|
|
96
93
|
const smTenants = (await hana.getAll(tenants.length > 0 ? tenants : '*')).filter(Boolean).filter(t => toTenantId(t) !== t0)
|
|
94
|
+
const byDb = {}
|
|
97
95
|
if (tenants.length !== smTenants.length) {
|
|
98
96
|
const smSet = new Set(smTenants.map(toTenantId))
|
|
99
97
|
const inconsistent = tenants.filter(t => !smSet.has(t))
|
|
100
98
|
if (!inconsistent.length)
|
|
101
99
|
LOG.warn('Tenants', smTenants.map(toTenantId).join(', '), 'are subscribed in Service Manager but not in t0. Make sure to re-subscribe the tenants.')
|
|
102
|
-
else if (inconsistent.length === 1)
|
|
100
|
+
else if (inconsistent.length === 1) {
|
|
103
101
|
LOG.warn('Warning: Tenant', inconsistent[0], 'does not exist in Service Manager any more and is therefore ignored. Make sure to unsubscribe the tenant.')
|
|
104
|
-
|
|
102
|
+
byDb['no-db'] = inconsistent
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
105
|
LOG.warn('Warning: Tenants', inconsistent.join(', '), 'do not exist in Service Manager any more and are therefore ignored. Make sure to unsubscribe the tenants.')
|
|
106
|
+
byDb['no-db'] = inconsistent
|
|
107
|
+
}
|
|
106
108
|
}
|
|
107
109
|
const tenantToDbUrl = smTenants.reduce((res, t) => {
|
|
108
110
|
const id = toTenantId(t)
|
|
@@ -110,7 +112,7 @@ if (db?.kind === 'hana') {
|
|
|
110
112
|
return { ...res, [id]: `${t.credentials.host}:${t.credentials.port}` }
|
|
111
113
|
}
|
|
112
114
|
, {})
|
|
113
|
-
|
|
115
|
+
|
|
114
116
|
for (const tenant of Object.keys(tenantToDbUrl)) {
|
|
115
117
|
const dbUrl = tenantToDbUrl[tenant]
|
|
116
118
|
if (!byDb[dbUrl]) byDb[dbUrl] = new Set
|
|
@@ -129,11 +131,6 @@ if (db?.kind === 'hana') {
|
|
|
129
131
|
}
|
|
130
132
|
return byDb
|
|
131
133
|
})
|
|
132
|
-
|
|
133
|
-
// check migration before upgrade
|
|
134
|
-
ds.before('upgrade', async (req) => {
|
|
135
|
-
await migration.checkMigration(req)
|
|
136
|
-
})
|
|
137
134
|
})
|
|
138
135
|
})
|
|
139
136
|
|
|
@@ -178,7 +175,11 @@ async function resources4(out) {
|
|
|
178
175
|
throw error
|
|
179
176
|
}
|
|
180
177
|
}
|
|
181
|
-
if (cache)
|
|
178
|
+
if (cache) {
|
|
179
|
+
const p = _resources4(out).catch(e => { resources.delete(out); throw e })
|
|
180
|
+
resources.set(out, p)
|
|
181
|
+
return p
|
|
182
|
+
}
|
|
182
183
|
return _resources4(out)
|
|
183
184
|
}
|
|
184
185
|
module.exports.resources4 = resources4 // required in abstract provisioning service to prepare shared deployment directory
|
|
@@ -323,14 +324,10 @@ async function _deploy (req, _container, { skipExt = false, skipResources = fals
|
|
|
323
324
|
if (cacheBindings) {
|
|
324
325
|
// health-check credentials for DB connection, get uncached if stale
|
|
325
326
|
|
|
326
|
-
let driver
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
...(process.env.NODE_ENV !== 'production' && projectPackage.devDependencies),
|
|
331
|
-
}
|
|
332
|
-
if (dependencies.hdb) driver = 'hdb'
|
|
333
|
-
if (dependencies['@sap/hana-client']) driver = '@sap/hana-client'
|
|
327
|
+
let driver
|
|
328
|
+
try { require.resolve('hdb'); driver = 'hdb' } catch { /* continue */ }
|
|
329
|
+
if (!driver) try { require.resolve('@sap/hana-client'); driver = '@sap/hana-client' } catch { /* continue */ }
|
|
330
|
+
if (!driver) cds.error('No HANA client driver found. Add hdb or @sap/hana-client to your sidecar dependencies.')
|
|
334
331
|
|
|
335
332
|
const client = require(driver).createClient(container.credentials)
|
|
336
333
|
const connect = promisify(client.connect.bind(client))
|
|
@@ -5,6 +5,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
5
5
|
|
|
6
6
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
7
7
|
|
|
8
|
+
## 6.2.2 - 2026-08-11
|
|
9
|
+
|
|
10
|
+
### Updated
|
|
11
|
+
- Updated `filter-node-package` dependency to 6.2.2
|
|
12
|
+
- Updated `mocha` dependency to 11.8.0
|
|
13
|
+
- Updated `diff` dependency to 9
|
|
14
|
+
|
|
8
15
|
## 6.2.1 - 2026-05-13
|
|
9
16
|
|
|
10
17
|
### Updated
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/xsenv",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.2",
|
|
4
4
|
"description": "Utility for easy setup and access of SAP HANA XS Advanced environment variables",
|
|
5
5
|
"repository": {},
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"prepareRelease": "clean-packages -i"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@eslint/js": "9.39.
|
|
26
|
+
"@eslint/js": "9.39.5",
|
|
27
27
|
"@eslint/eslintrc": "3.3.5",
|
|
28
|
-
"@babel/eslint-parser": "7.
|
|
28
|
+
"@babel/eslint-parser": "7.29.7",
|
|
29
29
|
"c8": "11.0.0",
|
|
30
|
-
"filter-node-package": "6.2.
|
|
30
|
+
"filter-node-package": "6.2.2",
|
|
31
31
|
"lodash": "4.18.1",
|
|
32
|
-
"mocha": "11.
|
|
32
|
+
"mocha": "11.8.0",
|
|
33
33
|
"mock-fs": "5.5.0",
|
|
34
34
|
"node-build": "^3.0.0",
|
|
35
35
|
"node-style": "2.0.0",
|
|
@@ -43,7 +43,10 @@
|
|
|
43
43
|
},
|
|
44
44
|
"overrides": {
|
|
45
45
|
"mocha": {
|
|
46
|
-
"glob": "^13.0.0"
|
|
47
|
-
|
|
46
|
+
"glob": "^13.0.0",
|
|
47
|
+
"serialize-javascript": "^7.0.0"
|
|
48
|
+
},
|
|
49
|
+
"diff": "^9.0.0",
|
|
50
|
+
"lodash": "4.18.1"
|
|
48
51
|
}
|
|
49
52
|
}
|
|
@@ -36,6 +36,8 @@ The parser is lenient and does not error. You should validate `type` and `parame
|
|
|
36
36
|
#### Options
|
|
37
37
|
|
|
38
38
|
- `parameters` (default: `true`): Set to `false` to skip parameters.
|
|
39
|
+
- `comma` (default: `false`): Set to `true` to stop on a comma. This can be used to parse the media range in an `Accept` header.
|
|
40
|
+
- `start` (default: `0`): Set index to start parsing from.
|
|
39
41
|
|
|
40
42
|
### contentType.format(obj)
|
|
41
43
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export interface ContentType {
|
|
10
10
|
type: string;
|
|
11
|
+
index: number;
|
|
11
12
|
parameters: Record<string, string>;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
@@ -18,7 +19,26 @@ export declare function format(obj: Partial<ContentType>): string;
|
|
|
18
19
|
* Options for parsing a `Content-Type` header.
|
|
19
20
|
*/
|
|
20
21
|
export interface ParseOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Exit early on the first semicolon, returning only the type.
|
|
24
|
+
* This is useful for parsing the MIME from `Content-Type` headers.
|
|
25
|
+
*
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
21
28
|
parameters?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Exits early on a comma, returning the first value and parameters.
|
|
31
|
+
* This is useful for parsing `Accept` headers.
|
|
32
|
+
*
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
comma?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The index to start parsing from.
|
|
38
|
+
*
|
|
39
|
+
* @default 0
|
|
40
|
+
*/
|
|
41
|
+
start?: number;
|
|
22
42
|
}
|
|
23
43
|
/**
|
|
24
44
|
* Parse a `Content-Type` header.
|