@sap/cds-dk 10.0.7 → 10.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +106 -0
- package/bin/add.js +7 -23
- package/bin/bind.js +14 -0
- package/bin/build.js +21 -34
- package/bin/cds.js +1 -1
- package/bin/compile/index.js +16 -41
- package/bin/completion/completionFs.js +11 -8
- package/bin/completion/index.js +603 -80
- package/bin/completion/scripts/cds.fish +620 -0
- package/bin/completion/scripts/cds.ps1 +403 -0
- package/bin/completion/scripts/cds.sh +327 -0
- package/bin/completion/scripts/cds.zsh +296 -0
- package/bin/completion/templates/cds-tmpl.fish +65 -0
- package/bin/completion/templates/cds-tmpl.ps1 +217 -0
- package/bin/completion/templates/cds-tmpl.sh +93 -0
- package/bin/completion/templates/cds-tmpl.zsh +74 -0
- package/bin/deploy/index.js +11 -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/env.js +4 -1
- package/bin/export.js +44 -6
- package/bin/help/export.md +3 -0
- package/bin/help.js +1 -5
- package/bin/import.js +9 -0
- package/bin/init.js +6 -24
- package/bin/inspect.js +8 -0
- package/bin/lint.js +5 -3
- package/bin/login.js +26 -20
- package/bin/minify.js +6 -1
- package/bin/pull.js +19 -6
- package/bin/push.js +19 -6
- package/bin/repl.js +11 -2
- package/bin/run.js +12 -1
- package/bin/serve.js +13 -2
- package/bin/up.js +17 -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 +10 -4
- package/bin/version.js +10 -1
- package/{lib → bin}/watch/hot-reload.js +1 -1
- package/bin/{watch.js → watch/index.js} +24 -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/build/util.js +2 -4
- 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 +117 -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/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/db-service/CHANGELOG.md +17 -0
- package/node_modules/@cap-js/db-service/lib/common/generic-pool.js +4 -7
- package/node_modules/@cap-js/db-service/lib/cqn2pql.js +1 -1
- package/node_modules/@cap-js/db-service/lib/cqn2sql.js +15 -11
- package/node_modules/@cap-js/db-service/lib/cqn4sql.js +119 -19
- package/node_modules/@cap-js/db-service/lib/infer/index.js +27 -16
- package/node_modules/@cap-js/db-service/lib/recursion-guard.js +40 -0
- package/node_modules/@cap-js/db-service/lib/search.js +1 -1
- package/node_modules/@cap-js/db-service/package.json +1 -1
- package/node_modules/@cap-js/sqlite/CHANGELOG.md +19 -0
- package/node_modules/@cap-js/sqlite/lib/SQLiteService.js +110 -14
- package/node_modules/@cap-js/sqlite/package.json +3 -3
- package/node_modules/@sap/cds/CHANGELOG.md +57 -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/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/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 +75 -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 +48 -18
- 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 +4 -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 +15 -0
- package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +10 -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/db/flattening.js +4 -3
- package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +40 -0
- package/node_modules/@sap/cds-compiler/lib/transform/effective/flattening.js +17 -1
- package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +20 -0
- package/node_modules/@sap/cds-compiler/lib/transform/fioriTreeViews.js +12 -1
- package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +7 -2
- package/node_modules/@sap/cds-compiler/lib/transform/odata/adaptAnnotationRefs.js +11 -5
- package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +48 -10
- package/node_modules/@sap/cds-compiler/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/CHANGELOG.md +49 -0
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx-migrate.js +26 -5
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +37 -16
- package/node_modules/@sap/cds-mtxs/lib/utils.js +23 -7
- package/node_modules/@sap/cds-mtxs/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +63 -8
- package/node_modules/@sap/cds-mtxs/srv/cf/saas-provisioning-service.js +1 -1
- package/node_modules/@sap/cds-mtxs/srv/cf/sms-provisioning-service.js +23 -3
- package/node_modules/@sap/cds-mtxs/srv/extensibility/compat/update.js +15 -0
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/annotations.js +2 -2
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/config.js +2 -0
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/index.js +2 -0
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/protected-namespace.js +45 -0
- package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +30 -16
- package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +49 -10
- package/node_modules/@sap/cds-mtxs/srv/model-provider.js +28 -4
- package/node_modules/@sap/cds-mtxs/srv/plugins/common.js +19 -12
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +1 -1
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi-ctnr-mgr.js +6 -3
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/serverless.js +271 -0
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +7 -10
- package/node_modules/@sap/cds-mtxs/srv/worker/job-worker-pool.js +212 -0
- package/node_modules/@sap/cds-mtxs/srv/worker/job-worker.js +61 -0
- 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/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 +2 -2
- 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 -454
- package/lib/import/asyncapi/utils.js +0 -49
- package/node_modules/@sap/cds/libx/_runtime/ucl/queries.js +0 -61
- 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
- /package/node_modules/@sap/cds-mtxs/srv/worker/{pool.js → model-worker-pool.js} +0 -0
- /package/node_modules/@sap/cds-mtxs/srv/worker/{load.js → model-worker.js} +0 -0
package/lib/lint/eslintHelp.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "10.
|
|
2
|
+
"version": "10.8.0",
|
|
3
3
|
"help": "\n# SYNOPSIS\n\n *cds lint* [options] file.js [file.js] [dir]\n\n Runs environment checks and/or checks the specified models\n based on the ESLint framework\n\n# OPTIONS\n \n Basic configuration:\n --no-config-lookup Disable look up for eslint.config.js\n -c, --config path::String Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs\n --inspect-config Open the config inspector with the current configuration\n --ext [String] Specify additional file extensions to lint\n --global [String] Define global variables\n --parser String Specify the parser to be used\n --parser-options Object Specify parser options\n \n Specify Rules and Plugins:\n --plugin [String] Specify plugins\n --rule Object Specify rules\n \n Fix Problems:\n --fix Automatically fix problems\n --fix-dry-run Automatically fix problems without saving the changes to the file system\n --fix-type Array Specify the types of fixes to apply (directive, problem, suggestion, layout)\n \n Ignore Files:\n --no-ignore Disable use of ignore files and patterns\n --ignore-pattern [String] Patterns of files to ignore\n \n Use stdin:\n --stdin Lint code provided on <STDIN> - default: false\n --stdin-filename String Specify filename to process STDIN as\n \n Handle Warnings:\n --quiet Report errors only - default: false\n --max-warnings Int Number of warnings to trigger nonzero exit code - default: -1\n \n Output:\n -o, --output-file path::String Specify file to write report to\n -f, --format String Use a specific output format - default: stylish\n --color, --no-color Force enabling/disabling of color\n \n Inline configuration comments:\n --no-inline-config Prevent comments from changing config or rules\n --report-unused-disable-directives Adds reported errors for unused eslint-disable and eslint-enable directives\n --report-unused-disable-directives-severity String Chooses severity level for reporting unused eslint-disable and eslint-enable directives - either: off, warn, error, 0, 1, or 2\n --report-unused-inline-configs String Adds reported errors for unused eslint inline config comments - either: off, warn, error, 0, 1, or 2\n \n Caching:\n --cache Only check changed files - default: false\n --cache-file path::String Path to the cache file. Deprecated: use --cache-location - default: .eslintcache\n --cache-location path::String Path to the cache file or directory\n --cache-strategy String Strategy to use for detecting changed files in the cache - either: metadata or content - default: metadata\n \n Suppressing Violations:\n --suppress-all Suppress all violations - default: false\n --suppress-rule [String] Suppress specific rules\n --suppressions-location path::String Specify the location of the suppressions file\n --prune-suppressions Prune unused suppressions - default: false\n --pass-on-unpruned-suppressions Ignore unused suppressions - default: false\n \n Miscellaneous:\n --init Run config initialization wizard - default: false\n --env-info Output execution environment information - default: false\n --no-error-on-unmatched-pattern Prevent errors when pattern is unmatched\n --exit-on-fatal-error Exit with exit code 2 in case of fatal error - default: false\n --no-warn-ignored Suppress warnings when the file list includes ignored files\n --pass-on-no-patterns Exit with exit code 0 in case no file patterns are passed\n --debug Output debugging information\n -h, --help Show help\n -v, --version Output the version number\n --print-config path::String Print the configuration for the given file\n --stats Add statistics to the lint report - default: false\n --flag [String] Enable a feature flag\n --mcp Start the ESLint MCP server\n --concurrency Int|String Number of linting threads, auto to choose automatically, off for no multithreading - default: off\n \n",
|
|
4
4
|
"options": [
|
|
5
5
|
"--config",
|
package/lib/mtx/auth_manager.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const cds = require('../cds');
|
|
2
|
-
const { SettingsManager } = require('./settings_manager');
|
|
2
|
+
const { SettingsManager, OAUTH_PATH, OAUTH_PATH_LEGACY_TOKEN } = require('./settings_manager');
|
|
3
3
|
const { ParamCollection } = require('./params');
|
|
4
4
|
const { getMessage } = require('./util/logging');
|
|
5
5
|
const { buildResponseError, buildNetworkError, parseResponseBody } = require('./util/request');
|
|
@@ -39,28 +39,107 @@ function reqParams(method, params) {
|
|
|
39
39
|
const url = params.get('tokenUrl');
|
|
40
40
|
const d = {};
|
|
41
41
|
const ignored = {};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
d.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
const headers = { 'content-type': 'application/x-www-form-urlencoded' };
|
|
43
|
+
const tls = {};
|
|
44
|
+
if (params.get('directUaa')) {
|
|
45
|
+
d.grant_type = 'client_credentials';
|
|
46
|
+
d.client_id = params.get('clientid');
|
|
47
|
+
if (params.has('key')) {
|
|
48
|
+
tls.cert = params.get('certificate');
|
|
49
|
+
tls.key = params.get('key');
|
|
50
|
+
} else {
|
|
51
|
+
const encoded = Buffer.from(`${params.get('clientid')}:${params.get('clientsecret')}`).toString('base64');
|
|
52
|
+
headers.Authorization = `Basic ${encoded}`;
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
if (params.has('subdomain')) {
|
|
56
|
+
d.subdomain = params.get('subdomain');
|
|
57
|
+
}
|
|
58
|
+
if (params.has('refreshToken')) {
|
|
59
|
+
d.refresh_token = params.get('refreshToken');
|
|
60
|
+
const param = ['passcode', 'clientid'].find(param => params.has(param));
|
|
61
|
+
if (param) {
|
|
62
|
+
ignored[param] = 'refresh token is present';
|
|
63
|
+
}
|
|
64
|
+
} else if (params.has('passcode')) {
|
|
65
|
+
d.passcode = params.get('passcode');
|
|
66
|
+
} else if (params.has('clientsecret')) {
|
|
67
|
+
d.clientid = params.get('clientid');
|
|
68
|
+
d.clientsecret = params.get('clientsecret');
|
|
50
69
|
}
|
|
51
|
-
} else if (params.has('passcode')) {
|
|
52
|
-
d.passcode = params.get('passcode');
|
|
53
|
-
} else if (params.has('clientsecret')) {
|
|
54
|
-
d.clientid = params.get('clientid');
|
|
55
|
-
d.clientsecret = params.get('clientsecret');
|
|
56
|
-
} else if (params.has('key')) {
|
|
57
|
-
d.clientid = params.get('clientid');
|
|
58
|
-
d.key = params.get('key');
|
|
59
70
|
}
|
|
60
71
|
const data = new URLSearchParams(d).toString();
|
|
61
|
-
|
|
62
|
-
? { url, data,
|
|
63
|
-
: { url: `${url}?${data}`, data: undefined,
|
|
72
|
+
const req = method === 'post'
|
|
73
|
+
? { url, data, method, headers, ...tls }
|
|
74
|
+
: { url: `${url}?${data}`, data: undefined, method, headers, ...tls };
|
|
75
|
+
return { req, ignored };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toResponse(res, body) {
|
|
79
|
+
const status = res.statusCode;
|
|
80
|
+
return {
|
|
81
|
+
ok: status >= 200 && status < 300,
|
|
82
|
+
status,
|
|
83
|
+
statusText: res.statusMessage ?? '',
|
|
84
|
+
headers: { get: name => res.headers[name.toLowerCase()] },
|
|
85
|
+
json: async () => JSON.parse(body),
|
|
86
|
+
text: async () => body
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function postTokenViaMtls(url, data, headers, { cert, key }) {
|
|
91
|
+
const https = require('node:https');
|
|
92
|
+
const u = new URL(url);
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
const request = https.request({
|
|
95
|
+
hostname: u.hostname,
|
|
96
|
+
port: u.port || 443,
|
|
97
|
+
path: `${u.pathname}${u.search}`,
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers,
|
|
100
|
+
cert,
|
|
101
|
+
key
|
|
102
|
+
}, res => {
|
|
103
|
+
let body = '';
|
|
104
|
+
res.setEncoding('utf8');
|
|
105
|
+
res.on('data', chunk => { body += chunk; });
|
|
106
|
+
res.on('end', () => resolve(toResponse(res, body)));
|
|
107
|
+
});
|
|
108
|
+
request.on('error', reject);
|
|
109
|
+
if (data) {
|
|
110
|
+
request.write(data);
|
|
111
|
+
}
|
|
112
|
+
request.end();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function postTokenTo(req, params) {
|
|
117
|
+
const { url, data, method, headers, cert, key } = req;
|
|
118
|
+
DEBUG?.(`Getting authentication token from ${method.toUpperCase()} ${params.obfuscateQueryParams(url)}`);
|
|
119
|
+
const response = cert
|
|
120
|
+
? await postTokenViaMtls(url, data, headers, { cert, key })
|
|
121
|
+
: await fetch(url, {
|
|
122
|
+
method: method.toUpperCase(),
|
|
123
|
+
body: data,
|
|
124
|
+
headers
|
|
125
|
+
});
|
|
126
|
+
if (!response.ok) {
|
|
127
|
+
throw await buildResponseError(method, url, response);
|
|
128
|
+
}
|
|
129
|
+
return parseResponseBody(response);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function postToken(req, params) {
|
|
133
|
+
try {
|
|
134
|
+
return await postTokenTo(req, params);
|
|
135
|
+
} catch (e) {
|
|
136
|
+
if (e.status !== 404 || !req.url.includes(OAUTH_PATH)) {
|
|
137
|
+
throw e;
|
|
138
|
+
}
|
|
139
|
+
req.url = req.url.replace(OAUTH_PATH, OAUTH_PATH_LEGACY_TOKEN);
|
|
140
|
+
DEBUG?.(`Token endpoint not found, retrying against legacy path ${params.obfuscateQueryParams(req.url)}`);
|
|
141
|
+
return postTokenTo(req, params);
|
|
142
|
+
}
|
|
64
143
|
}
|
|
65
144
|
|
|
66
145
|
async function fetchToken(params) {
|
|
@@ -71,29 +150,16 @@ async function fetchToken(params) {
|
|
|
71
150
|
let responseData, error;
|
|
72
151
|
const method = 'post';
|
|
73
152
|
do {
|
|
74
|
-
const {
|
|
153
|
+
const { req, ignored } = reqParams(method, params);
|
|
75
154
|
if (Object.keys(ignored).length) {
|
|
76
155
|
console.log(`Ignoring parameters for fetching token: ${Object.entries(ignored).map(([param, reason]) => `${param} (${reason})`).join(', ')}.`);
|
|
77
156
|
}
|
|
78
|
-
DEBUG?.(`Getting authentication token from ${method.toUpperCase()} ${params.obfuscateQueryParams(url)}`);
|
|
79
157
|
error = undefined;
|
|
80
158
|
try {
|
|
81
|
-
|
|
82
|
-
method: method.toUpperCase(),
|
|
83
|
-
body: data,
|
|
84
|
-
headers: { 'content-type': 'application/x-www-form-urlencoded' }
|
|
85
|
-
});
|
|
86
|
-
if (!response.ok) {
|
|
87
|
-
throw await buildResponseError(method, url, response);
|
|
88
|
-
}
|
|
89
|
-
responseData = await parseResponseBody(response);
|
|
159
|
+
responseData = await postToken(req, params);
|
|
90
160
|
break;
|
|
91
161
|
} catch (e) {
|
|
92
|
-
|
|
93
|
-
error = e;
|
|
94
|
-
} else {
|
|
95
|
-
error = buildNetworkError(method, url, e);
|
|
96
|
-
}
|
|
162
|
+
error = e.status ? e : buildNetworkError(method, req.url, e);
|
|
97
163
|
DEBUG?.(`HTTP status ${error.status}`);
|
|
98
164
|
if (params.has('refreshToken')) {
|
|
99
165
|
DEBUG?.('Discarding invalid refresh token');
|
|
@@ -122,7 +188,7 @@ async function fetchToken(params) {
|
|
|
122
188
|
message += `. Ensure the client credentials are correct`;
|
|
123
189
|
}
|
|
124
190
|
} else {
|
|
125
|
-
message = '
|
|
191
|
+
message = 'token request failed';
|
|
126
192
|
}
|
|
127
193
|
throw new Error(message + '.', { cause: error });
|
|
128
194
|
}
|
package/lib/mtx/params.js
CHANGED
|
@@ -178,7 +178,8 @@ class BasicParams {
|
|
|
178
178
|
this.password = new Param('password', undefined, { obfuscate: ObfuscationLevel.full });
|
|
179
179
|
this.clientid = new Param('clientid', undefined);
|
|
180
180
|
this.clientsecret = new Param('clientsecret', undefined, { obfuscate: ObfuscationLevel.partial });
|
|
181
|
-
this.
|
|
181
|
+
this.certificate = new Param('certificate', undefined, { obfuscate: ObfuscationLevel.partial }); // client certificate for mTLS
|
|
182
|
+
this.key = new Param('key', undefined, { obfuscate: ObfuscationLevel.partial }); // private key of the client certificate
|
|
182
183
|
this.tokenStorage = new Param('tokenStorage', undefined, { allowedValues: ['plain', 'keyring'] });
|
|
183
184
|
this.clearOtherTokenStorage = new Param('clearOtherTokenStorage', false, { internal: true });
|
|
184
185
|
this.plain = new Param('plain', false, { internal: true }); // for backward compatibility - superseded by tokenStorage
|
|
@@ -195,7 +196,6 @@ class BasicParams {
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
|
|
198
|
-
// TODO pass these as extra arguments to lib functions
|
|
199
199
|
/**
|
|
200
200
|
* All known params including those needed for specific commands.
|
|
201
201
|
*/
|
|
@@ -216,6 +216,7 @@ class AllParams extends BasicParams {
|
|
|
216
216
|
|
|
217
217
|
// `login` PARAMS
|
|
218
218
|
this.skipToken = new Param('skipToken', false, { internal: true });
|
|
219
|
+
this.directUaa = new Param('directUaa', false, { internal: true }); // client-credentials login goes directly to the authorization server
|
|
219
220
|
this.saveRefreshToken = new Param('saveRefreshToken', false, { internal: true });
|
|
220
221
|
|
|
221
222
|
// `logout` PARAMS
|
|
@@ -34,9 +34,10 @@ const KEYRING_DESC = {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
const MTX_FULLY_QUALIFIED = 'com.sap.cds.mtx';
|
|
37
|
-
const
|
|
38
|
-
const OAUTH_PATH = '/-/cds/login/
|
|
39
|
-
const OAUTH_META_PATH = '/-/cds/login/
|
|
37
|
+
const OAUTH_PATH_LEGACY_TOKEN = '/-/cds/login/token';
|
|
38
|
+
const OAUTH_PATH = '/-/cds/login/grant';
|
|
39
|
+
const OAUTH_META_PATH = '/-/cds/login/grant-metadata';
|
|
40
|
+
const OAUTH_UAA_PATH = '/oauth/token';
|
|
40
41
|
|
|
41
42
|
const SETTINGS_DIR = path.join(os.homedir(), CONFIG_SUBDIRS[os.platform()] || '', MTX_FULLY_QUALIFIED);
|
|
42
43
|
const SETTINGS_FILE = 'projects.json';
|
|
@@ -102,12 +103,40 @@ async function getTokenUrl(params, renewUrl) {
|
|
|
102
103
|
if (!params.has('appUrl')) {
|
|
103
104
|
throw 'Failed to determine token URL: app URL not given';
|
|
104
105
|
}
|
|
106
|
+
if (params.has('clientid')) {
|
|
107
|
+
return deriveUaaTokenUrl(params);
|
|
108
|
+
}
|
|
105
109
|
return appUrlWith(OAUTH_PATH, params);
|
|
106
110
|
}
|
|
107
111
|
|
|
108
|
-
|
|
112
|
+
function uaaTokenUrl(passcodeUrl, { mtls } = {}) {
|
|
113
|
+
const url = new URL(passcodeUrl);
|
|
114
|
+
url.pathname = url.pathname.replace(/\/passcode\/*$/, '').replace(/\/+$/, '') + OAUTH_UAA_PATH;
|
|
115
|
+
url.search = '';
|
|
116
|
+
if (mtls) {
|
|
117
|
+
url.hostname = url.hostname.replace(/\.authentication\./, '.authentication.cert.');
|
|
118
|
+
}
|
|
119
|
+
return url.toString();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function deriveUaaTokenUrl(params) {
|
|
123
|
+
const mtls = params.has('key');
|
|
124
|
+
const metadata = await fetchAuthMetadata(params);
|
|
125
|
+
const announced = mtls ? metadata?.cert_token_url : metadata?.token_url;
|
|
126
|
+
const passcodeUrl = metadata?.passcode_url;
|
|
127
|
+
const tokenUrl = announced ?? (passcodeUrl && uaaTokenUrl(passcodeUrl, { mtls }));
|
|
128
|
+
if (!tokenUrl) {
|
|
129
|
+
throw 'Cannot determine the authorization server for client-credentials login. ' +
|
|
130
|
+
'Ensure MTX is running with extensibility enabled and up to date.';
|
|
131
|
+
}
|
|
132
|
+
params.set('directUaa', true);
|
|
133
|
+
DEBUG?.(`Derived authorization-server token URL for ${mtls ? 'mTLS' : 'client-credentials'} login: ${tokenUrl}`);
|
|
134
|
+
return tokenUrl;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function fetchAuthMetadata(params) {
|
|
109
138
|
let fetchUrl = appUrlWith(OAUTH_META_PATH, params);
|
|
110
|
-
DEBUG?.(`Trying to get
|
|
139
|
+
DEBUG?.(`Trying to get authorization metadata from GET`, fetchUrl);
|
|
111
140
|
if (params.has('subdomain')) {
|
|
112
141
|
const u = new URL(fetchUrl);
|
|
113
142
|
u.searchParams.set('subdomain', params.get('subdomain'));
|
|
@@ -124,10 +153,10 @@ async function fetchPasscodeUrl(params) {
|
|
|
124
153
|
if (error.status === 404) {
|
|
125
154
|
DEBUG?.(`Request unsupported by server, ignoring (${error.message.replace(/ *Details:.*/s, '')})`);
|
|
126
155
|
} else if (error.status) {
|
|
127
|
-
DEBUG?.(getMessage(`Getting
|
|
156
|
+
DEBUG?.(getMessage(`Getting authorization metadata failed`, { error }));
|
|
128
157
|
} else {
|
|
129
158
|
const netError = buildNetworkError('GET', fetchUrl, error);
|
|
130
|
-
DEBUG?.(getMessage(`Getting
|
|
159
|
+
DEBUG?.(getMessage(`Getting authorization metadata failed`, { error: netError }));
|
|
131
160
|
}
|
|
132
161
|
return undefined;
|
|
133
162
|
}
|
|
@@ -139,7 +168,7 @@ async function fetchPasscodeUrl(params) {
|
|
|
139
168
|
DEBUG?.(`Unsupported signed metadata received. Since these should take precedence, ignoring response.`);
|
|
140
169
|
return undefined;
|
|
141
170
|
}
|
|
142
|
-
return responseData
|
|
171
|
+
return responseData;
|
|
143
172
|
}
|
|
144
173
|
|
|
145
174
|
function getKeyringAccountName(params) {
|
|
@@ -289,8 +318,9 @@ class SettingsManager {
|
|
|
289
318
|
}
|
|
290
319
|
async function updateTokenUrl() {
|
|
291
320
|
const tokenUrl = secure(params.get('tokenUrl'), 'token URL');
|
|
321
|
+
const machineLogin = params.has('clientid');
|
|
292
322
|
const renewUrl = !logout && !params.get('skipToken')
|
|
293
|
-
&& (!tokenUrl || tokenUrl.includes('//-/cds') || tokenUrl.includes(
|
|
323
|
+
&& (machineLogin || !tokenUrl || tokenUrl.includes('//-/cds') || !tokenUrl.includes(OAUTH_PATH)
|
|
294
324
|
|| params.get('appUrl') !== loadedSettings.get('appUrl')
|
|
295
325
|
|| params.get('subdomain') !== loadedSettings.get('subdomain'));
|
|
296
326
|
if (renewUrl) {
|
|
@@ -303,7 +333,6 @@ class SettingsManager {
|
|
|
303
333
|
}
|
|
304
334
|
}
|
|
305
335
|
}
|
|
306
|
-
|
|
307
336
|
await updateAppUrl();
|
|
308
337
|
await updateTokenUrl();
|
|
309
338
|
}
|
|
@@ -353,16 +382,9 @@ class SettingsManager {
|
|
|
353
382
|
throw 'Clientsecret cannot be empty';
|
|
354
383
|
}
|
|
355
384
|
}
|
|
356
|
-
async function addKey() {
|
|
357
|
-
params.set('key', await Question.askQuestion('key: ', undefined, true));
|
|
358
|
-
console.log();
|
|
359
|
-
if (params.get('key') === '') {
|
|
360
|
-
throw 'Key cannot be empty';
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
385
|
async function addPasscode() {
|
|
364
386
|
if (!params.has('passcodeUrl')) {
|
|
365
|
-
const passcodeUrl = await
|
|
387
|
+
const passcodeUrl = (await fetchAuthMetadata(params))?.passcode_url;
|
|
366
388
|
if (passcodeUrl) {
|
|
367
389
|
params.set('passcodeUrl', passcodeUrl);
|
|
368
390
|
}
|
|
@@ -440,15 +462,8 @@ class SettingsManager {
|
|
|
440
462
|
return;
|
|
441
463
|
}
|
|
442
464
|
|
|
443
|
-
if (params.get('clientid') && !logout) {
|
|
444
|
-
|
|
445
|
-
if (params.get('key') === 'ask') {
|
|
446
|
-
params.delete('key');
|
|
447
|
-
await addKey();
|
|
448
|
-
}
|
|
449
|
-
} else if (!params.has('clientsecret')) {
|
|
450
|
-
await addClientSecret();
|
|
451
|
-
}
|
|
465
|
+
if (params.get('clientid') && !logout && !params.has('clientsecret') && !params.has('key')) {
|
|
466
|
+
await addClientSecret();
|
|
452
467
|
}
|
|
453
468
|
|
|
454
469
|
await addAuthSettings();
|
|
@@ -714,5 +729,7 @@ class SettingsManager {
|
|
|
714
729
|
module.exports = {
|
|
715
730
|
SettingsManager,
|
|
716
731
|
other,
|
|
717
|
-
notifyLogin
|
|
732
|
+
notifyLogin,
|
|
733
|
+
OAUTH_PATH,
|
|
734
|
+
OAUTH_PATH_LEGACY_TOKEN
|
|
718
735
|
};
|
package/lib/mtx/tenant_action.js
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const CLIENT_ID_ENV = 'CDS_LOGIN_CLIENT_ID';
|
|
2
|
+
const CLIENT_SECRET_ENV = 'CDS_LOGIN_CLIENT_SECRET';
|
|
3
|
+
const CLIENT_CERT_ENV = 'CDS_LOGIN_CLIENT_CERT';
|
|
4
|
+
const CLIENT_KEY_ENV = 'CDS_LOGIN_CLIENT_KEY';
|
|
5
|
+
|
|
6
|
+
function clientId(inlineId) {
|
|
7
|
+
const clientid = inlineId ?? process.env[CLIENT_ID_ENV];
|
|
8
|
+
if (!clientid) {
|
|
9
|
+
throw `Client ID required: pass it as --client <id> or via the ${CLIENT_ID_ENV} environment variable.`;
|
|
10
|
+
}
|
|
11
|
+
return clientid;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function splitFirst(value, separator) {
|
|
15
|
+
const i = value.indexOf(separator);
|
|
16
|
+
return i === -1 ? [value, undefined] : [value.slice(0, i), value.slice(i + separator.length)];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve `--client` credentials, each part falling back to the environment
|
|
21
|
+
* (`CDS_LOGIN_CLIENT_ID`/`CDS_LOGIN_CLIENT_SECRET`). Splits on the first colon only;
|
|
22
|
+
* an empty client ID (`:secret`) is rejected.
|
|
23
|
+
* @returns {{ clientid?: string, clientsecret?: string }}
|
|
24
|
+
*/
|
|
25
|
+
function clientCredentials(clientOption) {
|
|
26
|
+
if (!clientOption) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
const [id, secret] = typeof clientOption === 'string' ? splitFirst(clientOption, ':') : [];
|
|
30
|
+
return { clientid: clientId(id), clientsecret: secret ?? process.env[CLIENT_SECRET_ENV] };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Resolve `--mtls` credentials: client ID inline or from `CDS_LOGIN_CLIENT_ID`,
|
|
35
|
+
* certificate and key only from `CDS_LOGIN_CLIENT_CERT`/`CDS_LOGIN_CLIENT_KEY`.
|
|
36
|
+
* An inline `:key` is rejected.
|
|
37
|
+
* @returns {{ clientid?: string, certificate?: string, key?: string }}
|
|
38
|
+
*/
|
|
39
|
+
function clientCertificate(mtlsOption) {
|
|
40
|
+
if (!mtlsOption) {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
if (typeof mtlsOption === 'string' && mtlsOption.includes(':')) {
|
|
44
|
+
throw `The client key cannot be passed on the command line. Pass only the client ID as --mtls <id>, and provide the certificate and key via the ${CLIENT_CERT_ENV} and ${CLIENT_KEY_ENV} environment variables.`;
|
|
45
|
+
}
|
|
46
|
+
const id = typeof mtlsOption === 'string' ? mtlsOption : undefined;
|
|
47
|
+
const certificate = process.env[CLIENT_CERT_ENV];
|
|
48
|
+
const key = process.env[CLIENT_KEY_ENV];
|
|
49
|
+
if (!certificate || !key) {
|
|
50
|
+
throw `Client certificate and key required: set the ${CLIENT_CERT_ENV} and ${CLIENT_KEY_ENV} environment variables.`;
|
|
51
|
+
}
|
|
52
|
+
return { clientid: clientId(id), certificate, key };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
clientCredentials,
|
|
57
|
+
clientCertificate,
|
|
58
|
+
CLIENT_ID_ENV,
|
|
59
|
+
CLIENT_SECRET_ENV,
|
|
60
|
+
CLIENT_CERT_ENV,
|
|
61
|
+
CLIENT_KEY_ENV
|
|
62
|
+
};
|
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
- The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
5
5
|
- This project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [3.1.0](https://github.com/cap-js/cds-dbs/compare/db-service-v3.0.1...db-service-v3.1.0) (2026-09-07)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
* rank $search results by relevance ([#1725](https://github.com/cap-js/cds-dbs/issues/1725)) ([bc93160](https://github.com/cap-js/cds-dbs/commit/bc931601a721f7c9e00b89e6844ba064352b541d))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
* **cqn4sql:** reject overly nested query expressions instead of crashing ([#1712](https://github.com/cap-js/cds-dbs/issues/1712)) ([29a45b7](https://github.com/cap-js/cds-dbs/commit/29a45b7daadbc77433b882148700d73c00efae62))
|
|
18
|
+
* don't throw when releasing/destroying a resource that's no longer in the pool ([#1696](https://github.com/cap-js/cds-dbs/issues/1696)) ([5d3b277](https://github.com/cap-js/cds-dbs/commit/5d3b277a1cf7cac02e41f2f24975a8e9473e5b5e))
|
|
19
|
+
* exclude cds.Vector from wildcard select expansion ([#1716](https://github.com/cap-js/cds-dbs/issues/1716)) ([398bacc](https://github.com/cap-js/cds-dbs/commit/398bacc2a74883dcd93acba288deae362570a4c1))
|
|
20
|
+
* INSERT.from(SELECT) used non-existent `value` ([#1565](https://github.com/cap-js/cds-dbs/issues/1565)) ([fd98844](https://github.com/cap-js/cds-dbs/commit/fd98844c83a78d6cf2b0b71344d3ee1d88528106))
|
|
21
|
+
* **pool:** recover lost connection after stale acquire timeout ([#1724](https://github.com/cap-js/cds-dbs/issues/1724)) ([cf6af99](https://github.com/cap-js/cds-dbs/commit/cf6af991d02be7cf5f861e2a424d4d733b8f9238))
|
|
22
|
+
* pql groupby path expression ([#1700](https://github.com/cap-js/cds-dbs/issues/1700)) ([82b5e03](https://github.com/cap-js/cds-dbs/commit/82b5e0385e680321f30c352f0f78ade6d25259a6))
|
|
23
|
+
|
|
7
24
|
## [3.0.1](https://github.com/cap-js/cds-dbs/compare/db-service-v3.0.0...db-service-v3.0.1) (2026-06-29)
|
|
8
25
|
|
|
9
26
|
|
|
@@ -150,7 +150,7 @@ constructor (factory, options = {}) {
|
|
|
150
150
|
return
|
|
151
151
|
}
|
|
152
152
|
const loan = this._loans.get(resource)
|
|
153
|
-
if (!loan)
|
|
153
|
+
if (!loan) return
|
|
154
154
|
this._loans.delete(resource)
|
|
155
155
|
const pooledResource = loan.pooledResource
|
|
156
156
|
pooledResource.idle()
|
|
@@ -164,7 +164,7 @@ constructor (factory, options = {}) {
|
|
|
164
164
|
return
|
|
165
165
|
}
|
|
166
166
|
const loan = this._loans.get(resource)
|
|
167
|
-
if (!loan)
|
|
167
|
+
if (!loan) return
|
|
168
168
|
this._loans.delete(resource)
|
|
169
169
|
const pooledResource = loan.pooledResource
|
|
170
170
|
await this.#destroy(pooledResource)
|
|
@@ -212,16 +212,13 @@ constructor (factory, options = {}) {
|
|
|
212
212
|
for (let i = 0; i < needed; i++) this.#createResource()
|
|
213
213
|
}
|
|
214
214
|
const dispense = async resource => {
|
|
215
|
-
|
|
215
|
+
let request = this._queue.shift()
|
|
216
|
+
while (request && request.state !== RequestState.PENDING) request = this._queue.shift()
|
|
216
217
|
if (!request) {
|
|
217
218
|
resource.idle()
|
|
218
219
|
this._available.add(resource)
|
|
219
220
|
return false
|
|
220
221
|
}
|
|
221
|
-
if (request.state !== RequestState.PENDING) {
|
|
222
|
-
this.#dispense()
|
|
223
|
-
return false
|
|
224
|
-
}
|
|
225
222
|
this._loans.set(resource.obj, { pooledResource: resource })
|
|
226
223
|
resource.update(ResourceState.ALLOCATED)
|
|
227
224
|
request.resolve(resource.obj)
|
|
@@ -18,7 +18,7 @@ class CQN2PQLRenderer extends CQN2SQL {
|
|
|
18
18
|
|
|
19
19
|
column_expr(x, q) {
|
|
20
20
|
// omit alias when target is a single source
|
|
21
|
-
if (q.SELECT.from
|
|
21
|
+
if (q.SELECT.from?.ref && x?.ref) x.ref = x.ref.slice(-1)
|
|
22
22
|
return super.column_expr(x, q)
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -1088,7 +1088,7 @@ class CQN2SQLRenderer {
|
|
|
1088
1088
|
|
|
1089
1089
|
const extractions = this._managed = this.managed(columns.map(c => ({ name: c, sql: `NEW.${this.quote(c)}` })), elements)
|
|
1090
1090
|
const sql = extractions.length > columns.length
|
|
1091
|
-
? `SELECT ${extractions.map(c => `${c.insert} AS ${this.quote(c.name)}`)} FROM (${this.SELECT(src)}) AS NEW`
|
|
1091
|
+
? `SELECT ${extractions.map((c, i) => `${i < columns.length ? c.insert : c.onInsert} AS ${this.quote(c.name)}`)} FROM (${this.SELECT(src)}) AS NEW`
|
|
1092
1092
|
: this.SELECT(src)
|
|
1093
1093
|
if (extractions.length > columns.length) columns = this.columns = extractions.map(c => c.name)
|
|
1094
1094
|
this.sql = `INSERT INTO ${this.quote(entity)}${alias ? ' as ' + this.quote(alias) : ''} (${columns.map(c => this.quote(transitions.mapping.get(c)?.ref?.[0] || c))}) ${sql}`
|
|
@@ -1161,12 +1161,12 @@ class CQN2SQLRenderer {
|
|
|
1161
1161
|
const extractions = this._managed
|
|
1162
1162
|
if (this.values) this.values = [] // Clear previously computed values
|
|
1163
1163
|
const src = this.cqn4sql(UPSERT.from || UPSERT.as)
|
|
1164
|
-
const aliasedQuery =
|
|
1165
|
-
.columns(
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
sql = `SELECT ${extractions.map(c =>
|
|
1164
|
+
const aliasedQuery = `SELECT ${[
|
|
1165
|
+
...src.SELECT.columns.map((c, i) => this.column_expr({ ref: [this.column_name(c)], as: this.columns[i] })),
|
|
1166
|
+
...extractions.slice(src.SELECT.columns.length).map(c => `${elements[c.name].key ? c.onInsert : 'NULL'} AS ${this.quote(c.name)}`), // fill in missing default values
|
|
1167
|
+
]} FROM (${this.SELECT(src)})`
|
|
1168
|
+
|
|
1169
|
+
sql = `SELECT ${extractions.map(c => elements[c.name].key ? `NEW.${this.quote(c.name)}` : c.upsert)} FROM(${aliasedQuery}) AS NEW LEFT JOIN ${this.quote(entity)} AS OLD ON ${keyCompare} `
|
|
1170
1170
|
if (extractions.length > columns.length) columns = this.columns = extractions.map(c => c.name)
|
|
1171
1171
|
this.entries = [this.values]
|
|
1172
1172
|
}
|
|
@@ -1574,9 +1574,11 @@ class CQN2SQLRenderer {
|
|
|
1574
1574
|
|
|
1575
1575
|
managed_extract(name, element, converter) {
|
|
1576
1576
|
const { UPSERT, INSERT } = this.cqn
|
|
1577
|
-
const extract =
|
|
1578
|
-
? `value->>${this.string(
|
|
1579
|
-
:
|
|
1577
|
+
const extract = (INSERT?.entries || UPSERT?.entries)
|
|
1578
|
+
? `value->>${this.string(`$.${JSON.stringify(name)}`)}`
|
|
1579
|
+
: (INSERT?.rows || UPSERT?.rows)
|
|
1580
|
+
? `value->>${this.string(`$[${this.columns.indexOf(name)}]`)}`
|
|
1581
|
+
: `NEW.${this.quote(name)}` // in case of (INSERT?.from || UPSERT?.from)
|
|
1580
1582
|
const sql = converter?.(extract) || extract
|
|
1581
1583
|
return { extract, sql }
|
|
1582
1584
|
}
|
|
@@ -1587,7 +1589,9 @@ class CQN2SQLRenderer {
|
|
|
1587
1589
|
}
|
|
1588
1590
|
|
|
1589
1591
|
managed_default(name, managed, src) {
|
|
1590
|
-
|
|
1592
|
+
const { UPSERT, INSERT } = this.cqn
|
|
1593
|
+
const isJson = INSERT?.entries || UPSERT?.entries || INSERT?.rows || UPSERT?.rows
|
|
1594
|
+
return `(CASE WHEN ${isJson ? `json_type(value,${this.managed_extract(name).extract.slice(8)})` : `NEW.${this.quote(name)}`} IS NULL THEN ${managed} ELSE ${src} END)`
|
|
1591
1595
|
}
|
|
1592
1596
|
}
|
|
1593
1597
|
|