@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
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const mtxAdapter = require('./mtx-adapter')
|
|
3
|
-
const { createProjects } = require('./extension-project')
|
|
4
1
|
const cds = require('@sap/cds')
|
|
5
|
-
const LOG = cds.log('mtx')
|
|
6
|
-
const { mkdirp, rimraf, tar, exists, readdir, read, write, isdir, isfile } = cds.utils
|
|
7
|
-
const fs = cds.utils.fs.promises
|
|
2
|
+
const LOG = cds.log('mtx')
|
|
8
3
|
|
|
9
|
-
const linter = require('../../srv/extensibility/linter')
|
|
10
4
|
const { t0_ } = require('../utils')
|
|
11
5
|
const Tenants = 'cds.xt.Tenants'
|
|
12
6
|
|
|
@@ -14,14 +8,6 @@ const Tenants = 'cds.xt.Tenants'
|
|
|
14
8
|
module.exports._hasMtEnv = () => cds.requires.multitenancy || (cds.env.requires['cds.xt.DeploymentService'] && cds.env.requires['cds.xt.ModelProviderService'])
|
|
15
9
|
module.exports._hasExtensibilityEnv = () => cds.requires.extensibility || cds.env.requires['cds.xt.ExtensibilityService']
|
|
16
10
|
|
|
17
|
-
module.exports._getExtensionProjectDirectory = function(dir) {
|
|
18
|
-
if (dir) {
|
|
19
|
-
LOG.log('Project directory', dir, 'does not exist.', dir, 'has been created.')
|
|
20
|
-
return mkdirp(dir)
|
|
21
|
-
}
|
|
22
|
-
return mtxAdapter.mkdirTemp()
|
|
23
|
-
}
|
|
24
|
-
|
|
25
11
|
class MigrationResult {
|
|
26
12
|
constructor() {
|
|
27
13
|
this.connectedTenants = []
|
|
@@ -29,9 +15,8 @@ class MigrationResult {
|
|
|
29
15
|
this.hasError = false
|
|
30
16
|
}
|
|
31
17
|
|
|
32
|
-
addTenant(tenant
|
|
18
|
+
addTenant(tenant) {
|
|
33
19
|
this.connectedTenants.push(tenant)
|
|
34
|
-
if (meta) this.connectedTenants.push(mtxAdapter.getMetaTenantName(tenant))
|
|
35
20
|
}
|
|
36
21
|
|
|
37
22
|
log(tenant, message) {
|
|
@@ -59,17 +44,13 @@ function getT0() {
|
|
|
59
44
|
return cds.env.requires.multitenancy?.t0 ?? 't0'
|
|
60
45
|
}
|
|
61
46
|
|
|
62
|
-
module.exports.getDbId = async function () {
|
|
63
|
-
return mtxAdapter.getDbId()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
47
|
module.exports.syncTenantList = async function syncTenantList(tenants, options, deleteEntries = false) {
|
|
67
48
|
const EXCLUDED_TENANTS = /^MT_LIB_TENANT-.*/
|
|
68
49
|
|
|
69
50
|
const migrationResult = new MigrationResult()
|
|
70
51
|
const { dry, force } = options
|
|
71
52
|
const t0 = getT0()
|
|
72
|
-
migrationResult.addTenant(t0
|
|
53
|
+
migrationResult.addTenant(t0) // adds tenant for disconnect
|
|
73
54
|
|
|
74
55
|
// get all containers + create metadata in t0
|
|
75
56
|
const ds = await cds.connect.to('cds.xt.DeploymentService')
|
|
@@ -96,390 +77,4 @@ module.exports.syncTenantList = async function syncTenantList(tenants, options,
|
|
|
96
77
|
}
|
|
97
78
|
migrationResult.log(t0, `Tenant list created for ${JSON.stringify(tenantContainers)} ${dry ? '(dry run only)' : ''}.`)
|
|
98
79
|
return migrationResult
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
module.exports.cleanupMetatenants = async function cleanup(tenants, options) {
|
|
102
|
-
const migrationResult = new MigrationResult()
|
|
103
|
-
const { dry } = options
|
|
104
|
-
|
|
105
|
-
let tenantsToCleanup = tenants
|
|
106
|
-
// handle tenant "*" -> retrieve all tenants
|
|
107
|
-
if (tenants.includes('*')) {
|
|
108
|
-
tenantsToCleanup = await mtxAdapter.getAllTenantIds()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const t0 = getT0()
|
|
112
|
-
migrationResult.addTenant(t0, false) // adds tenant for disconnect
|
|
113
|
-
|
|
114
|
-
const metatenantsToCleanup = {}
|
|
115
|
-
for (const tenant of tenantsToCleanup) {
|
|
116
|
-
if (tenant === t0) continue
|
|
117
|
-
const metatenant = mtxAdapter.getMetaTenantName(tenant)
|
|
118
|
-
metatenantsToCleanup[tenant] = metatenant
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
for (const [tenant, metatenant] of Object.entries(metatenantsToCleanup)) {
|
|
122
|
-
migrationResult.addTenant(metatenant, false)
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
// check if tenant was already migrated
|
|
126
|
-
try {
|
|
127
|
-
const migrated = tenant !== '__META__' ? await mtxAdapter.isMigrated(tenant) : { timestamp: true }
|
|
128
|
-
if (!migrated.timestamp) {
|
|
129
|
-
migrationResult.error(tenant, `Tenant ${tenant} was not migrated. Skipping cleanup.`, new Error(`Tenant ${tenant} was not migrated`))
|
|
130
|
-
continue
|
|
131
|
-
}
|
|
132
|
-
} catch (e) {
|
|
133
|
-
if (e.status === 404) {
|
|
134
|
-
migrationResult.log(tenant, `No @sap/cds-mtx meta-tenant found for ${tenant}. Skipping cleanup.`)
|
|
135
|
-
continue
|
|
136
|
-
} else throw e
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// do the cleanup
|
|
140
|
-
if (!dry) {
|
|
141
|
-
const ds = await cds.connect.to('cds.xt.DeploymentService')
|
|
142
|
-
await ds.unsubscribe(metatenant)
|
|
143
|
-
}
|
|
144
|
-
migrationResult.log(metatenant, `Metatenant ${metatenant} successfully deleted.`)
|
|
145
|
-
} catch (error) {
|
|
146
|
-
migrationResult.error(metatenant, `Cleanup of tenant ${metatenant} failed.`, error)
|
|
147
|
-
continue
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// only cleanup __META__ if all other meta tenants have been cleaned up successfully
|
|
152
|
-
if (!dry && tenants.includes('*') && !migrationResult.hasError) {
|
|
153
|
-
const ds = await cds.connect.to('cds.xt.DeploymentService')
|
|
154
|
-
const commonMetaTenant = '__META__'
|
|
155
|
-
await ds.unsubscribe(commonMetaTenant)
|
|
156
|
-
migrationResult.log(commonMetaTenant, `Common metatenant ${commonMetaTenant} successfully deleted.`)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
LOG.log('Cleanup done')
|
|
160
|
-
return migrationResult
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
module.exports.checkMigration = async function checkMigration(req) {
|
|
164
|
-
const { tenant } = req.data
|
|
165
|
-
if (await mtxAdapter.hasExtensions(tenant)) {
|
|
166
|
-
if (module.exports._hasExtensibilityEnv()) {
|
|
167
|
-
if (!await mtxAdapter.isMigrated(tenant))
|
|
168
|
-
req.reject(422, `Upgrade of tenant ${tenant} aborted. Extensions have not been migrated yet`)
|
|
169
|
-
} else {
|
|
170
|
-
req.reject(422, `Upgrade of tenant ${tenant} aborted. Old MTX Extensions exist but extensibility is not configured (cds.requires.extensibility is false)`)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
module.exports.getMissingMtxTenants = async (existingTenants) => {
|
|
176
|
-
if (await mtxAdapter.wasOldMtx()) {
|
|
177
|
-
// TODO do this only once
|
|
178
|
-
// get all mtx tenants
|
|
179
|
-
const mtxTenants = await mtxAdapter.getAllTenantIds()
|
|
180
|
-
// add metadata for non-existing entries
|
|
181
|
-
return await Promise.all(mtxTenants.filter( mtxTenant => !existingTenants.includes(mtxTenant)).map( async mtxTenant => {
|
|
182
|
-
await module.exports.addMetadata(mtxTenant, {
|
|
183
|
-
subscribedTenantId: mtxTenant
|
|
184
|
-
})
|
|
185
|
-
return mtxTenant
|
|
186
|
-
}))
|
|
187
|
-
}
|
|
188
|
-
return []
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
module.exports.migrate = async function migrate(tenants, options) {
|
|
192
|
-
|
|
193
|
-
const { directory, dry, force, tagRule, tag: defaultTag, "skip-verification": skipVerification} = options
|
|
194
|
-
|
|
195
|
-
const migrationResult = new MigrationResult()
|
|
196
|
-
let tenantsToMigrate = tenants
|
|
197
|
-
|
|
198
|
-
// handle tenant "*" -> retrieve all tenants
|
|
199
|
-
if (tenants.includes('*')) {
|
|
200
|
-
tenantsToMigrate = await mtxAdapter.getAllTenantIds()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const t0 = getT0()
|
|
204
|
-
migrationResult.addTenant(t0, false) // adds tenant for disconnect
|
|
205
|
-
|
|
206
|
-
const extensibility = module.exports._hasExtensibilityEnv()
|
|
207
|
-
let projectsDir
|
|
208
|
-
|
|
209
|
-
for (const tenant of tenantsToMigrate) {
|
|
210
|
-
|
|
211
|
-
migrationResult.addTenant(tenant)
|
|
212
|
-
|
|
213
|
-
// skip migration of t0
|
|
214
|
-
if (tenant === t0) {
|
|
215
|
-
migrationResult.log(tenant, `Skipping internal tenant ${tenant}.`)
|
|
216
|
-
continue
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
// check if tenant was already migrated
|
|
221
|
-
try {
|
|
222
|
-
const migrated = await mtxAdapter.isMigrated(tenant)
|
|
223
|
-
if (migrated?.timestamp && !force) {
|
|
224
|
-
migrationResult.log(tenant, `Tenant ${tenant} is already migrated. Skipping migration.`)
|
|
225
|
-
continue
|
|
226
|
-
}
|
|
227
|
-
} catch (e) {
|
|
228
|
-
if (e.status === 404) {
|
|
229
|
-
migrationResult.log(tenant, `No @sap/cds-mtx meta-tenant found for ${tenant}. Skipping migration.`)
|
|
230
|
-
continue
|
|
231
|
-
} else throw e
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Get from old mtx
|
|
235
|
-
const metadata = await mtxAdapter.getMetadata(tenant)
|
|
236
|
-
|
|
237
|
-
if (extensibility) {
|
|
238
|
-
|
|
239
|
-
// update tenant metadata + extension tables
|
|
240
|
-
// add extension tables - TODO could also be done on-the-fly with push
|
|
241
|
-
const extTables = await cds.load(`${__dirname}/../../db/extensions.cds`)
|
|
242
|
-
cds.model = cds.db.model = cds.compile.for.nodejs(extTables)
|
|
243
|
-
if (!dry) {
|
|
244
|
-
// disable extension deployment to avoid lengthy redeployments when doing the push()
|
|
245
|
-
const ds = await cds.connect.to('cds.xt.DeploymentService')
|
|
246
|
-
ds.prepend (srv => srv.on ('extend', () => { }))
|
|
247
|
-
|
|
248
|
-
try {
|
|
249
|
-
await cds.tx({ tenant}, tx => tx.run(SELECT.one(1).from('cds.xt.Extensions')))
|
|
250
|
-
// add metadata in case it had not been added before
|
|
251
|
-
await module.exports.addMetadata(tenant, metadata)
|
|
252
|
-
} catch (error) {
|
|
253
|
-
LOG.log('cds.xt.Extensions not yet deployed, deploying ...')
|
|
254
|
-
DEBUG && DEBUG(error)
|
|
255
|
-
await ds.subscribe({ tenant, metadata, options: { csn: extTables } }) // also creates metadata ...
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// run extend -> into memory?
|
|
260
|
-
const mtxExtension = await mtxAdapter.getExtension(tenant)
|
|
261
|
-
|
|
262
|
-
if (mtxExtension) {
|
|
263
|
-
// allow different folder from command line to preserve results
|
|
264
|
-
projectsDir = projectsDir || await module.exports._getExtensionProjectDirectory(directory)
|
|
265
|
-
const tenantProjectFolder = path.join(projectsDir, tenant)
|
|
266
|
-
|
|
267
|
-
const tags = await createProjects(mtxExtension, tenantProjectFolder, tagRule, defaultTag)
|
|
268
|
-
|
|
269
|
-
// upload and verify extensions
|
|
270
|
-
// iterate all tags
|
|
271
|
-
migrationResult.log(tenant, `Created projects for tags "${tags}"`)
|
|
272
|
-
|
|
273
|
-
// Verify migrated extension
|
|
274
|
-
if (!skipVerification) {
|
|
275
|
-
try {
|
|
276
|
-
// check diff and abort if necessary
|
|
277
|
-
const existingCsn = await mtxAdapter.getCsn(tenant)
|
|
278
|
-
|
|
279
|
-
await fs.mkdir(path.join(tenantProjectFolder, 'mtx_original_csn'), { recursive: true })
|
|
280
|
-
await fs.writeFile(path.join(tenantProjectFolder, 'mtx_original_csn', 'csn.json'), JSON.stringify(existingCsn, null, 2))
|
|
281
|
-
|
|
282
|
-
await _verifyExtension(migrationResult, tenantProjectFolder, tenant, tags, existingCsn, options)
|
|
283
|
-
migrationResult.log(tenant, `Extension verification successful for tenant ${tenant} [${tenantProjectFolder}]`)
|
|
284
|
-
} catch (error) {
|
|
285
|
-
migrationResult.error(tenant, `Extension verification failed for tenant ${tenant} [${tenantProjectFolder}]), skipping migration.`, error)
|
|
286
|
-
continue
|
|
287
|
-
}
|
|
288
|
-
} else {
|
|
289
|
-
migrationResult.log(tenant, `Extension verification skipped for tenant ${tenant}`)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (!dry && force) {
|
|
293
|
-
// cleanup in case extension ids have changed
|
|
294
|
-
if (tenant) cds.context = { tenant }
|
|
295
|
-
await DELETE.from('cds.xt.Extensions')
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
for (const tag of tags) {
|
|
299
|
-
const projectFolder = path.join(tenantProjectFolder, tag)
|
|
300
|
-
|
|
301
|
-
if (!dry) {
|
|
302
|
-
try {
|
|
303
|
-
const extensionTgz = await fs.readFile(path.join(projectFolder, 'gen', 'extension.tgz'))
|
|
304
|
-
const es = await cds.connect.to('cds.xt.ExtensibilityService')
|
|
305
|
-
await es.tx({ tenant, user: new cds.User.Privileged }, tx =>
|
|
306
|
-
tx.push(extensionTgz.toString('base64'), tag)
|
|
307
|
-
)
|
|
308
|
-
migrationResult.log(tenant, `Extension for tenant ${tenant} and tag ${tag} pushed.`)
|
|
309
|
-
} catch (error) {
|
|
310
|
-
migrationResult.error(tenant, `Error pushing extension for tenant ${tenant} and tag ${tag}`, error)
|
|
311
|
-
continue
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
} else {
|
|
317
|
-
// check if extensions exist -> abort if yes
|
|
318
|
-
if (await mtxAdapter.hasExtensions(tenant)) throw new Error(`Extensions exist but extensibility is not configured (cds.requires.extensibilty is false)`)
|
|
319
|
-
|
|
320
|
-
if (!dry) {
|
|
321
|
-
await module.exports.addMetadata(tenant, metadata)
|
|
322
|
-
migrationResult.log(tenant, `Metadata for tenant ${tenant} added.`)
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (!dry) await mtxAdapter.setMigrated(tenant, tagRule, defaultTag, !!force /* ensure it is not undefined so that a record is written */)
|
|
327
|
-
migrationResult.log(tenant, `Migration of tenant ${tenant} done.`)
|
|
328
|
-
} catch (error) {
|
|
329
|
-
migrationResult.error(tenant, `Migration of tenant ${tenant} failed.`, error)
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// cleanup tmpdir, keep directory if it was set externally
|
|
334
|
-
if (!directory && projectsDir) await fs.rm(projectsDir, { recursive: true, force: true })
|
|
335
|
-
|
|
336
|
-
LOG.log('Extension migration done')
|
|
337
|
-
return migrationResult
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
module.exports.addMetadata = async function addMetadata(tenant, metadata) {
|
|
341
|
-
try {
|
|
342
|
-
// can't use UPSERT here so @cds.on.insert still works for createdAt
|
|
343
|
-
await t0_(INSERT.into('cds.xt.Tenants', { ID: tenant, metadata: JSON.stringify(metadata) }))
|
|
344
|
-
} catch (e) {
|
|
345
|
-
if (e.message === 'ENTITY_ALREADY_EXISTS' || e.code === 301 || e.message.match(/unique constraint/i)) {
|
|
346
|
-
await t0_(UPSERT.into('cds.xt.Tenants', { ID: tenant, metadata: JSON.stringify(metadata) }))
|
|
347
|
-
} else throw e
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
async function _verifyExtension(migrationResult, tenantProjectFolder, tenant, tags, existingCsn, options) {
|
|
352
|
-
|
|
353
|
-
const { "ignore-migrations": ignoreMigrations } = options
|
|
354
|
-
|
|
355
|
-
const projectFolders = tags
|
|
356
|
-
|
|
357
|
-
const mp = await cds.connect.to('cds.xt.ModelProviderService')
|
|
358
|
-
const mainCsn = await mp.getCsn({ tenant, flavor: 'inferred', activated: true, base: true, options: { skipMinify: true } })
|
|
359
|
-
|
|
360
|
-
if (!mainCsn) throw new Error(`Verification error for tenant ${tenant}: Empty base model`)
|
|
361
|
-
|
|
362
|
-
let previewCsn = mainCsn
|
|
363
|
-
|
|
364
|
-
// calculate model with extensions to be pushed later
|
|
365
|
-
for (const projectFolder of projectFolders) {
|
|
366
|
-
const extensionCsnString = await fs.readFile(path.join(tenantProjectFolder, projectFolder, 'gen', 'ext', 'extension.csn'))
|
|
367
|
-
const extensionCsn = JSON.parse(extensionCsnString)
|
|
368
|
-
previewCsn = cds.extend(previewCsn).with(extensionCsn)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// ensure flavor
|
|
372
|
-
const inferredExistingCsn = cds.compile({inferred: existingCsn}, {flavor: 'inferred'})
|
|
373
|
-
|
|
374
|
-
const existingHana = cds.compiler.to.hdi.migration(inferredExistingCsn)
|
|
375
|
-
const newHana = cds.compiler.to.hdi.migration(previewCsn)
|
|
376
|
-
|
|
377
|
-
const diffMessages = []
|
|
378
|
-
|
|
379
|
-
// are artifacts lost?
|
|
380
|
-
const hanaDiffNewToOld = cds.compiler.to.hdi.migration(cds.minify(previewCsn), {}, cds.minify(existingHana.afterImage))
|
|
381
|
-
if (hanaDiffNewToOld.deletions.length) {
|
|
382
|
-
diffMessages.push(`Migrated model is missing artifacts:\n ${hanaDiffNewToOld.deletions.map( ({ name, suffix }) => `${name}${suffix}\n`)}`)
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
if (hanaDiffNewToOld.migrations.length) {
|
|
386
|
-
const ignore = ignoreMigrations ?? '^sap.common'
|
|
387
|
-
const relevantMigrations = hanaDiffNewToOld.migrations.filter( m => !new RegExp(ignore).test(m.name))
|
|
388
|
-
migrationResult.log(tenant, `Table migrations found but ignored for /${ignore}/`)
|
|
389
|
-
|
|
390
|
-
if (relevantMigrations.length) diffMessages.push(`Table migrations found\n` +
|
|
391
|
-
`${relevantMigrations.map( ({ name, suffix, changeset }) => ` ${name}${suffix}: ${changeset.map(({sql}) => sql)}\n`)}`)
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// does the new model contain more artifacts?
|
|
395
|
-
const MTXS_ENTITIES = ['cds.xt.Extensions']
|
|
396
|
-
const hanaDiffOldToNew = cds.compiler.to.hdi.migration(cds.minify(inferredExistingCsn), {}, cds.minify(newHana.afterImage)) // cds.xt.Extensions is allowed
|
|
397
|
-
const filteredDeletions = hanaDiffOldToNew.deletions.filter( ({name}) => !MTXS_ENTITIES.includes(name))
|
|
398
|
-
if (filteredDeletions.length) {
|
|
399
|
-
diffMessages.push(`Migrated model has additional artifacts:\n ${hanaDiffOldToNew.deletions.map( ({ name, suffix }) => `${name}${suffix}\n`)}`)
|
|
400
|
-
throw new Error(`Verification error for tenant ${tenant}: migrated model has additional artifacts:\n ${hanaDiffOldToNew.deletions.map( ({ name, suffix }) => `${name}${suffix}\n`)}`)
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (diffMessages.length) throw new Error(`Verification error for tenant ${tenant}:\n${diffMessages.join('\n')}`)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
module.exports.getMigratedProjects = async (req, tagRule, defaultTag, tenant) => {
|
|
407
|
-
const temp = await mtxAdapter.mkdirTemp()
|
|
408
|
-
|
|
409
|
-
let parameters = { tagRule, defaultTag }
|
|
410
|
-
if (!(tagRule || defaultTag)) {
|
|
411
|
-
try {
|
|
412
|
-
const storedParameters = await mtxAdapter.getMigrationParameters(tenant) ?? {}
|
|
413
|
-
parameters = { ...parameters, ...storedParameters }
|
|
414
|
-
} catch (e) {
|
|
415
|
-
req.reject(404, `No migrated projects found for tenant ${tenant}: ${e.message}`)
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// run dry migration with force + own temp directory
|
|
420
|
-
// { directory, dry, force, tagRule: tagRegex, tag: defaultTag, "skip-verification": skipVerification, "ignore-migrations": ignoreMigrations }
|
|
421
|
-
await module.exports.migrate([tenant], { directory: temp, dry: true, skipVerification: true, tagRule: parameters.tagRule, tag: parameters.defaultTag, force: true})
|
|
422
|
-
|
|
423
|
-
const projectsLocation = path.join(temp, tenant)
|
|
424
|
-
if (!exists(projectsLocation)) req.reject(404, `No migrated projects found for tenant ${tenant}`)
|
|
425
|
-
|
|
426
|
-
// postprocessing: remove cds-based base model, adjust references
|
|
427
|
-
await module.exports.fixBaseModelReferences(projectsLocation)
|
|
428
|
-
|
|
429
|
-
try {
|
|
430
|
-
return await tar.cz(projectsLocation)
|
|
431
|
-
} finally {
|
|
432
|
-
rimraf(temp)
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
module.exports.fixBaseModelReferences = async (directory) => {
|
|
437
|
-
|
|
438
|
-
await traverse(directory, async (file) => {
|
|
439
|
-
// remove base cds files
|
|
440
|
-
if (/.*\/node_modules\/_base\//.test(file)) {
|
|
441
|
-
await rimraf(file)
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// remove gen folder
|
|
445
|
-
if (new RegExp(`${directory}/.*/gen$`).test(file)) {
|
|
446
|
-
await rimraf(file)
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// fix using statements
|
|
450
|
-
if (/.*\.cds$/.test(file) && isfile(file)) {
|
|
451
|
-
const content = await read(file, 'utf-8')
|
|
452
|
-
const fixedContent = content.replace(/'_base\/.*'/g, '\'_base\'')
|
|
453
|
-
await write(file, fixedContent, 'utf-8')
|
|
454
|
-
}
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
// add index.csn and .cdsrc.json
|
|
458
|
-
await traverse(directory, async (file) => {
|
|
459
|
-
if (/.*\/node_modules\/_base$/.test(file)) {
|
|
460
|
-
await addBaseAndConfig(file)
|
|
461
|
-
}
|
|
462
|
-
})
|
|
463
|
-
|
|
464
|
-
async function traverse(dir, visitor) {
|
|
465
|
-
const list = await readdir(dir)
|
|
466
|
-
for (const entry of list) {
|
|
467
|
-
const fullPath = path.join(dir, entry)
|
|
468
|
-
await visitor(fullPath)
|
|
469
|
-
if (await isdir(fullPath)) {
|
|
470
|
-
await traverse(fullPath, visitor)
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const addBaseAndConfig = async function (directory) {
|
|
477
|
-
const { 'cds.xt.ModelProviderService': mps } = cds.services
|
|
478
|
-
const csn = await mps.getCsn({
|
|
479
|
-
base: true, // without any custom extensions
|
|
480
|
-
flavor: 'xtended'
|
|
481
|
-
})
|
|
482
|
-
await write(path.join(directory, 'index.csn'), cds.compile.to.json(csn))
|
|
483
|
-
const config = linter.configCopyFrom(cds.env)
|
|
484
|
-
await write(path.join(directory, '.cdsrc.json'), JSON.stringify(config, null, 2))
|
|
485
80
|
}
|
|
@@ -89,13 +89,27 @@ const t0_ = async (query) => retry(async () => {
|
|
|
89
89
|
return cds.tx({ tenant: t0 }, tx => { tx.model = _t0Csn; return tx.run(query) })
|
|
90
90
|
})
|
|
91
91
|
|
|
92
|
+
const SUBDOMAIN_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i
|
|
93
|
+
|
|
94
|
+
function authUrl(baseUrl, subdomain, pathname) {
|
|
95
|
+
const u = new URL(baseUrl)
|
|
96
|
+
if (subdomain) {
|
|
97
|
+
if (typeof subdomain !== 'string' || !SUBDOMAIN_RE.test(subdomain)) {
|
|
98
|
+
throw cds.error('invalid subdomain', { status: 400 })
|
|
99
|
+
}
|
|
100
|
+
const dot = u.hostname.indexOf('.')
|
|
101
|
+
u.hostname = subdomain + (dot >= 0 ? u.hostname.slice(dot) : '')
|
|
102
|
+
}
|
|
103
|
+
u.pathname = pathname
|
|
104
|
+
return u
|
|
105
|
+
}
|
|
106
|
+
|
|
92
107
|
async function token(credentials, { query = {}, form = {}, subdomain } = {}) {
|
|
93
108
|
const { clientid, clientsecret, certurl, url, certificate, key } = credentials ?? {}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
u.pathname = '/oauth/token'
|
|
109
|
+
if (!form.grant_type) throw cds.error('grant_type is required', { status: 400 })
|
|
110
|
+
const u = authUrl(certurl || url, subdomain, '/oauth/token')
|
|
97
111
|
Object.entries(query).forEach(([k, v]) => u.searchParams.append(k, v))
|
|
98
|
-
const body = new URLSearchParams({
|
|
112
|
+
const body = new URLSearchParams({ client_id: clientid, ...form })
|
|
99
113
|
const headers = { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' }
|
|
100
114
|
let raw
|
|
101
115
|
if (certificate) {
|
|
@@ -249,6 +263,7 @@ module.exports = {
|
|
|
249
263
|
readData,
|
|
250
264
|
readDataCsv,
|
|
251
265
|
token,
|
|
266
|
+
authUrl,
|
|
252
267
|
fetchResiliently,
|
|
253
268
|
getAppId,
|
|
254
269
|
deepMerge
|
|
@@ -2,7 +2,6 @@ const cds = require('@sap/cds/lib')
|
|
|
2
2
|
const LOG = cds.log('mtx'), DEBUG = cds.debug('mtx')
|
|
3
3
|
const main = require('../config')
|
|
4
4
|
const { fetchResiliently, token } = require('../../lib/utils')
|
|
5
|
-
const migration = require('../../lib/migration/migration')
|
|
6
5
|
const DeploymentService = 'cds.xt.DeploymentService'
|
|
7
6
|
const JobsService = 'cds.xt.JobsService'
|
|
8
7
|
const Tenants = 'cds.xt.Tenants'
|
|
@@ -89,6 +88,7 @@ module.exports = class ProvisioningService extends cds.ApplicationService {
|
|
|
89
88
|
|
|
90
89
|
|
|
91
90
|
_toMetadataJson(metadata, subscribedTenantId) {
|
|
91
|
+
if (!metadata) return { subscribedTenantId };
|
|
92
92
|
try {
|
|
93
93
|
return JSON.parse(metadata);
|
|
94
94
|
} catch (error) {
|
|
@@ -114,9 +114,7 @@ module.exports = class ProvisioningService extends cds.ApplicationService {
|
|
|
114
114
|
|
|
115
115
|
async _getTenants() {
|
|
116
116
|
const ds = await cds.connect.to(DeploymentService)
|
|
117
|
-
const
|
|
118
|
-
const mtxTenants = await migration.getMissingMtxTenants(tenants)
|
|
119
|
-
const all = [...tenants, ...mtxTenants]
|
|
117
|
+
const all = await ds.getTenants()
|
|
120
118
|
if (cds.env.requires[this.name]?.upgrade?.ignoreNonExistingContainers) {
|
|
121
119
|
const containers = await ds.getContainers()
|
|
122
120
|
return all.filter(t => containers.includes(t))
|
|
@@ -140,12 +138,13 @@ module.exports = class ProvisioningService extends cds.ApplicationService {
|
|
|
140
138
|
await resources4(out)
|
|
141
139
|
await csvs4('base', out)
|
|
142
140
|
}
|
|
143
|
-
const { clusterSize = 1 } = cds.env.requires.multitenancy.jobs ?? cds.env.requires[this.name]?.jobs ?? {}
|
|
144
141
|
const { 'cds.xt.DeploymentService': ds } = cds.services
|
|
142
|
+
const js = await cds.connect.to(JobsService)
|
|
143
|
+
const { clusterSize = 3 } = js._config()
|
|
145
144
|
const dbToTenants = (clusterSize > 1 && ds) ? await ds.tenantsByDb(tenants) : [new Set(tenants)]
|
|
146
145
|
LOG.info('upgrading', { tenants })
|
|
147
146
|
|
|
148
|
-
|
|
147
|
+
|
|
149
148
|
return await new Promise((resolve, reject) => {
|
|
150
149
|
const tx = js.tx({ tenant: cds.context.tenant, user: new cds.User.Privileged() })
|
|
151
150
|
const job = tx.enqueue(DeploymentService, 'upgrade', dbToTenants, { options }, async error => {
|
|
@@ -292,7 +291,7 @@ module.exports = class ProvisioningService extends cds.ApplicationService {
|
|
|
292
291
|
async _token() {
|
|
293
292
|
const serviceName = 'cds.xt.' + this.constructor.name
|
|
294
293
|
const cred = this._getCredentials()
|
|
295
|
-
const raw = await token(cred, { query: { response_type: 'token' } })
|
|
294
|
+
const raw = await token(cred, { query: { response_type: 'token' }, form: { grant_type: 'client_credentials' } })
|
|
296
295
|
const { access_token } = JSON.parse(raw)
|
|
297
296
|
if (!access_token) cds.error(`could not get token for ${serviceName}: token is empty`)
|
|
298
297
|
return access_token
|
|
@@ -8,6 +8,7 @@ const checkedExtensionAnnotations = new Map([
|
|
|
8
8
|
['@cds.persistence.journal', _createJournalAnnotationWarning],
|
|
9
9
|
['@mandatory', _createMandatoryAnnotationWarning],
|
|
10
10
|
['@readonly', _createMandatoryAnnotationWarning],
|
|
11
|
+
['@Common.FieldControl', _createMandatoryAnnotationWarning],
|
|
11
12
|
['@assert.notNull', _createMandatoryAnnotationWarning],
|
|
12
13
|
['@assert.range', _createMandatoryAnnotationWarning]
|
|
13
14
|
])
|
|
@@ -18,6 +19,7 @@ const criticalExtensionAnnotations = new RegExp('^@(?:'
|
|
|
18
19
|
+ '|restrict'
|
|
19
20
|
+ '|readonly'
|
|
20
21
|
+ '|mandatory'
|
|
22
|
+
+ '|Common\\.FieldControl'
|
|
21
23
|
+ '|assert.*'
|
|
22
24
|
+ '|cds.persistence.*'
|
|
23
25
|
+ '|sql.append'
|
|
@@ -31,7 +33,8 @@ const criticalExtensionAnnotations = new RegExp('^@(?:'
|
|
|
31
33
|
+ '|cds.query.limit'
|
|
32
34
|
+ '|cds.localized'
|
|
33
35
|
+ '|cds.valid.*'
|
|
34
|
-
+ '|cds.search
|
|
36
|
+
+ '|cds.search'
|
|
37
|
+
+ '|Capabilities.*)'
|
|
35
38
|
);
|
|
36
39
|
|
|
37
40
|
function locationString(element) {
|
|
@@ -52,7 +55,7 @@ function _createMandatoryAnnotationWarning(annotationName, { element, parent })
|
|
|
52
55
|
if (element.default || element[annotationName] === false) return
|
|
53
56
|
const message = `Annotation '${annotationName}' in '${
|
|
54
57
|
element.annotate || element.name || parent.extend || parent.annotate
|
|
55
|
-
}' is not supported in extensions
|
|
58
|
+
}' is not supported in extensions`
|
|
56
59
|
return new LinterMessage(locationString(element) + message, element)
|
|
57
60
|
}
|
|
58
61
|
|
|
@@ -27,7 +27,7 @@ module.exports.legacyCheck = (env = cds.env) => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
module.exports.lint = (extCsn, fullCsn, env = cds.env, cloneExt = false) => {
|
|
30
|
-
const conf = env.requires[EXT_SERVICE_NAME] || env.mtx || {}
|
|
30
|
+
const conf = env.requires[EXT_SERVICE_NAME] || env.requires.extensibility || env.mtx || {}
|
|
31
31
|
const linter_options = {}
|
|
32
32
|
let x
|
|
33
33
|
for (let p of LINTER_OPTIONS) if ((x = conf[p])) {
|
|
@@ -62,13 +62,14 @@ module.exports.ERR_CDS_VALIDATION_FAILURE = 'ERR_CDS_VALIDATION_FAILURE'
|
|
|
62
62
|
* Sparsely copies the linter-relevant config from the given env into the given target
|
|
63
63
|
*/
|
|
64
64
|
module.exports.configCopyFrom = (env, target = {}) => {
|
|
65
|
-
|
|
65
|
+
const source = env.requires?.[EXT_SERVICE_NAME] ?? env.requires?.extensibility
|
|
66
|
+
if (!source) return target
|
|
66
67
|
|
|
67
68
|
const config = {}
|
|
68
|
-
Object.keys(
|
|
69
|
+
Object.keys(source)
|
|
69
70
|
.filter(key => LINTER_OPTIONS.includes(key)) // only let some keys pass, to not compromise security
|
|
70
|
-
.filter(key => !!
|
|
71
|
-
.forEach(key => (config[key] =
|
|
71
|
+
.filter(key => !!source[key])
|
|
72
|
+
.forEach(key => (config[key] = source[key]))
|
|
72
73
|
|
|
73
74
|
target.requires = target.requires || {}
|
|
74
75
|
target.requires[EXT_SERVICE_NAME] = config // overwrite ext.service key, though
|
|
@@ -69,14 +69,3 @@ extend service cds.xt.ExtensibilityService with @private {
|
|
|
69
69
|
);
|
|
70
70
|
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
// Access to legacy content
|
|
74
|
-
extend service cds.xt.ExtensibilityService {
|
|
75
|
-
|
|
76
|
-
@requires: ['cds.ExtensionDeveloper']
|
|
77
|
-
@private action getMigratedProjects(
|
|
78
|
-
tagRule: String, // optional
|
|
79
|
-
defaultTag: String, // optional
|
|
80
|
-
tenant: String // optional
|
|
81
|
-
) returns LargeBinary;
|
|
82
|
-
}
|