@sap/cds-dk 7.9.6 → 8.0.3
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 +2136 -0
- package/bin/add.js +18 -52
- package/bin/bind.js +2 -2
- package/bin/build.js +29 -4
- package/bin/cds.js +31 -14
- package/bin/compile/index.js +7 -6
- package/bin/completion/index.js +70 -46
- package/bin/completion/scripts/cds-bash.sh +4 -1
- package/bin/completion/scripts/cds-fish.fish +13 -0
- package/bin/completion/scripts/cds-ps.ps1 +2 -1
- package/bin/completion/scripts/cds-zsh.sh +2 -1
- package/bin/deploy/index.js +6 -5
- package/bin/deploy/to-sqlite.js +2 -2
- package/bin/extend.js +19 -50
- package/bin/help.js +2 -2
- package/bin/init.js +10 -77
- package/bin/login.js +13 -5
- package/bin/migrate.js +1 -1
- package/bin/pull.js +11 -0
- package/bin/repl.js +3 -0
- package/bin/test.js +5 -0
- package/bin/version.js +7 -7
- package/bin/watch.js +13 -14
- package/lib/bind/KubernetesApiAccessor.js +10 -9
- package/lib/build/buildTaskEngine.js +11 -7
- package/lib/build/buildTaskFactory.js +15 -43
- package/lib/build/buildTaskProviderFactory.js +16 -44
- package/lib/build/constants.js +4 -3
- package/lib/build/index.js +2 -2
- package/lib/build/{buildPlugin.js → plugin.js} +65 -46
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/Chart.yaml +1 -1
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/values.yaml +1 -1
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/service-instance/Chart.yaml +1 -1
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/service-instance/templates/_helpers.tpl +7 -0
- package/lib/build/plugins/helm/files/subcharts/service-instance/templates/servicebinding.yaml +32 -0
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/service-instance/templates/serviceinstance.yaml +3 -0
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/service-instance/values.schema.json +63 -0
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/service-instance/values.yaml +23 -1
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/Chart.yaml +1 -1
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/deployment.yaml +2 -0
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/hpa.yaml +22 -0
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/pod-disruption-budget.yaml +1 -0
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/values.schema.json +49 -0
- package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/values.yaml +8 -2
- package/lib/{init/template/helm/files/chart → build/plugins/helm/files}/templates/_deployment_helpers.tpl +5 -0
- package/lib/build/plugins/helm/files/templates/_helpers.tpl +13 -0
- package/lib/build/plugins/helm/index.js +81 -0
- package/lib/build/plugins.js +12 -15
- package/lib/build/provider/featureToggleBuildPlugin.js +7 -39
- package/lib/build/provider/hana/2migration.js +168 -124
- package/lib/build/provider/hana/index.js +69 -56
- package/lib/build/provider/hana/template/package.json +4 -3
- package/lib/build/provider/internalBuildPlugin.js +32 -97
- package/lib/build/provider/internalBuildTaskProvider.js +12 -48
- package/lib/build/provider/java/index.js +2 -3
- package/lib/build/provider/mtx/index.js +5 -4
- package/lib/build/provider/mtx-extension/index.js +5 -2
- package/lib/build/provider/mtx-sidecar/index.js +2 -2
- package/lib/build/provider/nodejs/index.js +4 -3
- package/lib/build/util.js +83 -12
- package/lib/compile/to-mermaid.js +108 -0
- package/lib/compile/to_asyncapi.js +7 -0
- package/lib/compile/to_openapi.js +7 -0
- package/lib/deploy/to-hana/hana.js +37 -34
- package/lib/deploy/to-hana/hdiDeployUtil.js +8 -6
- package/lib/env/schemas/cds-rc.js +1 -1
- package/lib/import/common.js +2 -2
- package/lib/import/odata/metadataconverter/MetadataConverter.js +4 -4
- package/lib/import/odata/v2parser.js +83 -197
- package/lib/import/odata/v4parser.js +1 -38
- package/lib/import/openapi/importOpenAPI.js +164 -42
- package/lib/index.js +10 -12
- package/lib/init/bas.js +91 -0
- package/lib/init/constants.js +21 -11
- package/lib/init/index.js +72 -150
- package/lib/init/merge.js +12 -20
- package/lib/init/mvn.js +103 -150
- package/lib/init/plugin.js +11 -7
- package/lib/init/projectReader.js +53 -20
- package/lib/init/registries/mta.js +51 -6
- package/lib/init/template/application-logging/files/package.json.hbs +7 -0
- package/lib/init/template/application-logging/index.js +13 -1
- package/lib/init/template/approuter/files/containerize.yaml.hbs +10 -0
- package/lib/init/template/approuter/files/mta.yaml.hbs +1 -2
- package/lib/init/template/approuter/files/values.yaml.hbs +19 -4
- package/lib/init/template/approuter/files/xs-app.json.hbs +12 -3
- package/lib/init/template/approuter/index.js +29 -25
- package/lib/init/template/attachments/files/mta.yaml.hbs +14 -0
- package/lib/init/template/attachments/files/package.json.hbs +5 -0
- package/lib/init/template/attachments/files/values.yaml +7 -0
- package/lib/init/template/attachments/index.js +53 -0
- package/lib/init/template/{redis-messaging → audit-logging}/files/mta.yaml.hbs +4 -4
- package/lib/init/template/audit-logging/files/package.json.hbs +7 -0
- package/lib/init/template/audit-logging/index.js +66 -0
- package/lib/init/template/cf-manifest/index.js +4 -0
- package/lib/init/template/completion/completionSetup.js +54 -33
- package/lib/init/template/completion/index.js +7 -1
- package/lib/init/template/connectivity/index.js +4 -4
- package/lib/init/template/containerize/files/containerize.yaml.hbs +26 -0
- package/lib/init/template/containerize/index.js +24 -0
- package/lib/init/template/data/index.js +4 -0
- package/lib/init/template/destination/files/mta.yaml.hbs +31 -1
- package/lib/init/template/destination/files/package.sidecar.json +7 -0
- package/lib/init/template/destination/index.js +22 -2
- package/lib/init/template/enterprise-messaging/index.js +6 -3
- package/lib/init/template/enterprise-messaging-shared/index.js +5 -1
- package/lib/init/template/extensibility/files/package.json.hbs +1 -1
- package/lib/init/template/extensibility/files/xs-security.json.hbs +2 -8
- package/lib/init/template/extensibility/index.js +3 -1
- package/lib/init/template/file-based-messaging/index.js +4 -0
- package/lib/init/template/h2/index.js +4 -0
- package/lib/init/template/hana/files/containerize.yaml.hbs +10 -0
- package/lib/init/template/hana/files/db/package.json +3 -2
- package/lib/init/template/hana/files/package.json.hbs +4 -7
- package/lib/init/template/hana/files/values.yaml.hbs +1 -2
- package/lib/init/template/hana/index.js +15 -7
- package/lib/init/template/helm/files/Chart.yaml.hbs +2 -3
- package/lib/init/template/helm/files/values.schema.json +2173 -0
- package/lib/init/template/helm/files/values.yaml.hbs +11 -6
- package/lib/init/template/helm/index.js +77 -18
- package/lib/init/template/helm-unified-runtime/index.js +19 -56
- package/lib/init/template/html5-repo/files/app-package.json.hbs +11 -7
- package/lib/init/template/html5-repo/files/manifest.json +13 -0
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +14 -33
- package/lib/init/template/html5-repo/files/package.sidecar.json +7 -0
- package/lib/init/template/html5-repo/files/ui5-deploy.yaml.hbs +21 -0
- package/lib/init/template/html5-repo/files/ui5.yaml.hbs +2 -29
- package/lib/init/template/html5-repo/files/values.yaml.hbs +6 -2
- package/lib/init/template/html5-repo/files/xs-app.json.hbs +6 -7
- package/lib/init/template/html5-repo/index.js +41 -35
- package/lib/init/template/http/index.js +36 -12
- package/lib/init/template/java/index.js +18 -12
- package/lib/init/template/kafka/index.js +4 -0
- package/lib/init/template/lint/index.js +7 -2
- package/lib/init/template/liquibase/index.js +4 -0
- package/lib/init/template/local-messaging/index.js +4 -0
- package/lib/init/template/malware-scanner/files/mta.yaml.hbs +14 -0
- package/lib/init/template/malware-scanner/files/package.json.hbs +17 -0
- package/lib/init/template/malware-scanner/files/values.yaml +7 -0
- package/lib/init/template/malware-scanner/index.js +47 -0
- package/lib/init/template/mta/files/mta.yaml.hbs +3 -3
- package/lib/init/template/mta/files/package.json +1 -1
- package/lib/init/template/mta/index.js +4 -0
- package/lib/init/template/mtx/index.js +4 -0
- package/lib/init/template/multitenancy/files/containerize.yaml.hbs +10 -0
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +0 -1
- package/lib/init/template/multitenancy/files/package.json.hbs +1 -1
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +6 -5
- package/lib/init/template/multitenancy/files/values.yaml.hbs +14 -24
- package/lib/init/template/multitenancy/index.js +50 -28
- package/lib/init/template/nodejs/files/eslint.config.mjs +2 -0
- package/lib/init/template/nodejs/files/package.json.hbs +2 -3
- package/lib/init/template/nodejs/index.js +4 -0
- package/lib/init/template/notifications/files/mta.yaml.hbs +2 -2
- package/lib/init/template/notifications/index.js +4 -0
- package/lib/init/template/pipeline/files/.pipeline/config.yml +1 -1
- package/lib/init/template/pipeline/files/Jenkinsfile +1 -1
- package/lib/init/template/pipeline/index.js +4 -0
- package/lib/init/template/portal/files/mta.yaml.hbs +52 -0
- package/lib/init/template/portal/files/package.json.hbs +11 -0
- package/lib/init/template/portal/files/package.sidecar.json +7 -0
- package/lib/init/template/portal/files/portal-site/CommonDataModel.json.hbs +97 -0
- package/lib/init/template/portal/files/portal-site/i18n/catalog.properties +1 -0
- package/lib/init/template/portal/files/portal-site/i18n/catalog_de.properties +1 -0
- package/lib/init/template/portal/files/portal-site/i18n/group.properties +1 -0
- package/lib/init/template/portal/files/portal-site/i18n/group_de.properties +1 -0
- package/lib/init/template/portal/index.js +84 -0
- package/lib/init/template/postgres/index.js +5 -1
- package/lib/init/template/redis/files/mta.yaml.hbs +25 -0
- package/lib/init/template/redis/files/package.json.hbs +5 -0
- package/lib/init/template/redis/index.js +44 -0
- package/lib/init/template/redis-messaging/files/package.json.hbs +0 -3
- package/lib/init/template/redis-messaging/index.js +8 -18
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n_de.properties +3 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n_en.properties +3 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +13 -1
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n.properties +2 -2
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n_de.properties +3 -0
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n_en.properties +4 -0
- package/lib/init/template/sample/files/app/browse/webapp/manifest.json +3 -3
- package/lib/init/template/sample/files/app/index.html +1 -1
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +5 -5
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +6 -6
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books_texts.csv +5 -5
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +16 -16
- package/lib/init/template/sample/files/nodejs/cat-service.js +2 -2
- package/lib/init/template/sample/files/package.json.hbs +3 -0
- package/lib/init/template/sample/index.js +16 -9
- package/lib/init/template/sqlite/index.js +4 -0
- package/lib/init/template/tiny-sample/files/nodejs/db/data/my.bookshop-Books.csv +3 -3
- package/lib/init/template/tiny-sample/files/nodejs/srv/cat-service.cds.hbs +1 -1
- package/lib/init/template/tiny-sample/index.js +4 -0
- package/lib/init/template/toggles/files/package.json.hbs +1 -1
- package/lib/init/template/toggles/index.js +4 -0
- package/lib/init/template/typer/index.js +4 -0
- package/lib/init/template/typescript/files/package.json +12 -0
- package/lib/init/template/typescript/files/tsconfig.json +13 -0
- package/lib/init/template/typescript/index.js +39 -0
- package/lib/init/template/workzone/index.js +9 -0
- package/lib/init/template/workzone-standard/files/manifest.json.hbs +6 -0
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +59 -0
- package/lib/init/template/workzone-standard/index.js +46 -0
- package/lib/init/template/xsuaa/files/package.json.hbs +1 -1
- package/lib/init/template/xsuaa/files/values.yaml.hbs +3 -2
- package/lib/init/template/xsuaa/index.js +11 -7
- package/lib/init/validate.js +27 -0
- package/lib/lint/generators.js +1 -1
- package/lib/lint/io.js +25 -7
- package/lib/mtx/auth_manager.js +64 -30
- package/lib/mtx/download_legacy.js +2 -2
- package/lib/mtx/index.js +0 -4
- package/lib/mtx/params.js +32 -38
- package/lib/mtx/pull.js +151 -43
- package/lib/mtx/push.js +3 -3
- package/lib/mtx/settings_manager.js +75 -35
- package/lib/mtx/tenant_action.js +1 -1
- package/lib/mtx/util/cf.js +1 -1
- package/lib/mtx/util/fs.js +26 -1
- package/lib/mtx/util/logging.js +7 -3
- package/lib/util/command.js +0 -2
- package/lib/util/fs.js +2 -3
- package/lib/util/question.js +28 -0
- package/lib/util/term.js +5 -3
- package/npm-shrinkwrap.json +225 -1083
- package/package.json +13 -8
- package/bin/activate.js +0 -77
- package/lib/compile/asyncapi/channels.js +0 -22
- package/lib/compile/asyncapi/components/messageTraits/index.js +0 -89
- package/lib/compile/asyncapi/components/messages/index.js +0 -173
- package/lib/compile/asyncapi/components/schemas/annotations.js +0 -33
- package/lib/compile/asyncapi/components/schemas/array.js +0 -8
- package/lib/compile/asyncapi/components/schemas/cache.js +0 -14
- package/lib/compile/asyncapi/components/schemas/definition.js +0 -187
- package/lib/compile/asyncapi/components/schemas/enum.js +0 -16
- package/lib/compile/asyncapi/components/schemas/examples.js +0 -10
- package/lib/compile/asyncapi/components/schemas/index.js +0 -14
- package/lib/compile/asyncapi/components/schemas/localized.js +0 -29
- package/lib/compile/asyncapi/components/schemas/primitiveElement.js +0 -41
- package/lib/compile/asyncapi/components/schemas/ref.js +0 -45
- package/lib/compile/asyncapi/components/schemas/utils.js +0 -108
- package/lib/compile/asyncapi/index.js +0 -247
- package/lib/compile/asyncapi/message.js +0 -13
- package/lib/compile/asyncapi/utils.js +0 -27
- package/lib/compile/openapi/csdl2openapi.js +0 -2448
- package/lib/compile/openapi/index.js +0 -68
- package/lib/init/template/helm/files/chart/templates/NOTES.txt +0 -14
- package/lib/init/template/helm/files/chart/templates/_helpers.tpl +0 -28
- package/lib/init/template/helm/files/chart/values.root.schema.json +0 -61
- package/lib/init/template/helm/files/chart/values.schema.json +0 -366
- package/lib/init/template/helm-unified-runtime/files/Chart.yaml.hbs +0 -10
- package/lib/init/template/helm-unified-runtime/files/templates/_deployment_helpers.tpl +0 -90
- package/lib/init/template/helm-unified-runtime/files/templates/_helpers.tpl +0 -28
- package/lib/init/template/helm-unified-runtime/files/values.root.schema.json +0 -61
- package/lib/init/template/helm-unified-runtime/files/values.schema.json +0 -366
- package/lib/init/template/helm-unified-runtime/files/values.yaml.hbs +0 -26
- package/lib/init/template/helm-unified-runtime/package.json +0 -4
- package/lib/init/template/multitenancy/files/mtxs-configmap-java-approuter.yaml +0 -20
- package/lib/init/template/multitenancy/files/mtxs-configmap-java.yaml +0 -18
- package/lib/init/template/multitenancy/files/mtxs-configmap-nodejs-approuter.yaml +0 -12
- package/lib/init/template/multitenancy/files/mtxs-configmap-nodejs.yaml +0 -12
- package/lib/init/template/multitenancy/files/saas-registry-secret.yaml +0 -9
- package/lib/init/template/nodejs/files/eslint.config.js +0 -13
- package/lib/init/template/notebook/index.js +0 -11
- package/lib/init/template/samples/index.js +0 -9
- package/lib/mtx/activate.js +0 -238
- package/lib/mtx/extend.js +0 -173
- package/lib/util/exec.d.ts +0 -54
- package/lib/util/exec.js +0 -211
- /package/lib/{init/template/approuter/files → build/plugins/helm/files/plugins/approuter}/approuter-configmap.yaml +0 -0
- /package/lib/{init/template/connectivity/files → build/plugins/helm/files/plugins/connectivity}/connectivity-proxy-info.yaml +0 -0
- /package/lib/{init/template/html5-repo/files → build/plugins/helm/files/plugins/html5-repo}/html5-apps-deployer-configmap.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/templates/_helpers.tpl +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/templates/job.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/templates/secret.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/templates/service-account.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/templates/service-binding.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/content-deployment/values.schema.json +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/NOTES.txt +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/_api.tpl +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/_helpers.tpl +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/api-rule.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/network-policy.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/rbac.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/secret.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/service-account.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/service-binding.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/service.yaml +0 -0
- /package/lib/{init/template/helm/files → build/plugins/helm/files/subcharts}/web-application/templates/virtual-service.yaml +0 -0
- /package/lib/{init/template/helm-unified-runtime → build/plugins/helm}/files/templates/NOTES.txt +0 -0
- /package/lib/init/template/{nodejs/files → java}/.cdsrc.json +0 -0
- /package/lib/init/template/tiny-sample/files/nodejs/db/{data-model.cds → schema.cds} +0 -0
|
@@ -23,13 +23,13 @@ module.exports = class Download {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
console.log(`Downloading migrated @sap/mtx extension project(s)`);
|
|
26
|
-
const downloadedTgz = await this.
|
|
26
|
+
const downloadedTgz = await this.pullTgz(params);
|
|
27
27
|
await fs.promises.writeFile(downloadPath, downloadedTgz);
|
|
28
28
|
|
|
29
29
|
console.log(`Finished.`);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
static async
|
|
32
|
+
static async pullTgz(params) {
|
|
33
33
|
const tagRule = params.get('tagRule');
|
|
34
34
|
const defaultTag = params.get('defaultTag');
|
|
35
35
|
const downloadUrl = `${(params.get('appUrl'))}/-/cds/extensibility/getMigratedProjects`;
|
package/lib/mtx/index.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
const Activate = require('./activate');
|
|
2
1
|
const AuthManager = require('./auth_manager');
|
|
3
|
-
const Extend = require('./extend');
|
|
4
2
|
const { SettingsManager } = require('./settings_manager');
|
|
5
3
|
const Question = require('./util/question');
|
|
6
4
|
|
|
7
5
|
module.exports = {
|
|
8
|
-
extend: Extend.run,
|
|
9
|
-
activate: Activate.run,
|
|
10
6
|
login: AuthManager.login,
|
|
11
7
|
logout: AuthManager.logout,
|
|
12
8
|
question: Question,
|
package/lib/mtx/params.js
CHANGED
|
@@ -36,7 +36,7 @@ class Param {
|
|
|
36
36
|
* @param options constructor options
|
|
37
37
|
*/
|
|
38
38
|
constructor(name,
|
|
39
|
-
val,
|
|
39
|
+
val = undefined,
|
|
40
40
|
options = {}) {
|
|
41
41
|
|
|
42
42
|
this.persist = Persistence.none;
|
|
@@ -44,6 +44,11 @@ class Param {
|
|
|
44
44
|
this.abbreviate = false;
|
|
45
45
|
this.internal = false;
|
|
46
46
|
this.allowedValues = null;
|
|
47
|
+
this.type = val === undefined
|
|
48
|
+
? this.allowedValues
|
|
49
|
+
? typeof this.allowedValues[0]
|
|
50
|
+
: 'string' // default
|
|
51
|
+
: typeof val;
|
|
47
52
|
|
|
48
53
|
this.name = name;
|
|
49
54
|
this._val = val;
|
|
@@ -102,12 +107,8 @@ class Param {
|
|
|
102
107
|
if (val === undefined) {
|
|
103
108
|
return; // Allow `undefined` always.
|
|
104
109
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
expectedType = typeof this.allowedValues[0];
|
|
108
|
-
}
|
|
109
|
-
if (typeof val !== expectedType) {
|
|
110
|
-
throw `Failed to set '${(this.name)}' = ${JSON.stringify(val)}: expected value of type ${expectedType}`;
|
|
110
|
+
if (typeof val !== this.type) {
|
|
111
|
+
throw `Failed to set '${(this.name)}' = ${JSON.stringify(val)}: expected value of type ${this.type}`;
|
|
111
112
|
}
|
|
112
113
|
if (this.allowedValues && !(this.allowedValues).includes(val)) {
|
|
113
114
|
throw `Failed to set '${(this.name)}' = ${JSON.stringify(val)}: expected one of ${JSON.stringify(this.allowedValues)}`;
|
|
@@ -125,7 +126,7 @@ class Param {
|
|
|
125
126
|
? undefined
|
|
126
127
|
: this.obfuscate === ObfuscationLevel.none && (!this.abbreviate || process.env.DEBUG)
|
|
127
128
|
? this.val
|
|
128
|
-
: this.obfuscate === ObfuscationLevel.partial && process.env.DEBUG &&
|
|
129
|
+
: this.obfuscate === ObfuscationLevel.partial && process.env.DEBUG && this.type === 'string'
|
|
129
130
|
? this.val.slice(0, DISCLOSURE_LENGTH) + '...' + this.val.slice(-DISCLOSURE_LENGTH)
|
|
130
131
|
: '...';
|
|
131
132
|
}
|
|
@@ -161,48 +162,44 @@ class BasicParams {
|
|
|
161
162
|
constructor() {
|
|
162
163
|
// GENERAL PARAMS
|
|
163
164
|
// - non-persisted
|
|
164
|
-
this.projectFolder = new Param('projectFolder'
|
|
165
|
+
this.projectFolder = new Param('projectFolder');
|
|
165
166
|
this.directory = this.projectFolder.newAlias('directory');
|
|
166
167
|
|
|
167
|
-
this.tagRule = new Param('tagRule', '');
|
|
168
|
-
this.defaultTag = new Param('defaultTag', '');
|
|
169
|
-
|
|
170
|
-
// - non-persisted, internal
|
|
171
|
-
this.reqAuth = new Param('reqAuth', null, { obfuscate: ObfuscationLevel.full, internal: true });
|
|
172
|
-
this.clearOtherTokenStorage = new Param('clearOtherTokenStorage', false, { internal: true });
|
|
173
|
-
|
|
174
168
|
// - persisted
|
|
175
|
-
this.appUrl = new Param('appUrl',
|
|
169
|
+
this.appUrl = new Param('appUrl', undefined, { persist: Persistence.setting }); // any trailing slash (/) is removed
|
|
176
170
|
this.url = this.appUrl.newAlias('url');
|
|
177
171
|
this.from = this.appUrl.newAlias('from');
|
|
178
172
|
this.to = this.appUrl.newAlias('to');
|
|
179
173
|
this.at = this.appUrl.newAlias('at');
|
|
180
|
-
this.subdomain = new Param('subdomain',
|
|
181
|
-
this.passcodeUrl = new Param('passcodeUrl',
|
|
174
|
+
this.subdomain = new Param('subdomain', undefined, { persist: Persistence.setting }); // only needed to fetch token
|
|
175
|
+
this.passcodeUrl = new Param('passcodeUrl', undefined, { persist: Persistence.setting, abbreviate: true });
|
|
182
176
|
this.passcode_url = this.passcodeUrl.newAlias('passcode_url');
|
|
183
|
-
this.tokenUrl = new Param('tokenUrl',
|
|
177
|
+
this.tokenUrl = new Param('tokenUrl', undefined, { persist: Persistence.setting, abbreviate: true })
|
|
184
178
|
|
|
185
179
|
// AUTH PARAMS
|
|
186
180
|
// - non-persisted
|
|
187
|
-
this.passcode = new Param('passcode',
|
|
181
|
+
this.passcode = new Param('passcode', undefined, { obfuscate: ObfuscationLevel.partial });
|
|
182
|
+
this.password = new Param('password', undefined, { obfuscate: ObfuscationLevel.full });
|
|
183
|
+
this.clientid = new Param('clientid', undefined);
|
|
184
|
+
this.clientsecret = new Param('clientsecret', undefined, { obfuscate: ObfuscationLevel.partial });
|
|
185
|
+
this.key = new Param('key', undefined, { obfuscate: ObfuscationLevel.partial }); // private key of client certificate
|
|
188
186
|
this.tokenStorage = new Param('tokenStorage', undefined, { allowedValues: ['plain', 'keyring'] });
|
|
187
|
+
this.clearOtherTokenStorage = new Param('clearOtherTokenStorage', false, { internal: true });
|
|
189
188
|
this.plain = new Param('plain', false, { internal: true }); // for backward compatibility - superseded by tokenStorage
|
|
190
189
|
this.saveData = new Param('saveData', false, { internal: true });
|
|
191
|
-
this.renewLogin = new Param('renewLogin', false);
|
|
192
|
-
this.
|
|
193
|
-
this.clientid = new Param('clientid', '');
|
|
194
|
-
this.clientsecret = new Param('clientsecret', '', { obfuscate: ObfuscationLevel.partial });
|
|
195
|
-
this.key = new Param('key', '', { obfuscate: ObfuscationLevel.partial }); // private key of client certificate
|
|
190
|
+
this.renewLogin = new Param('renewLogin', false, { internal: true });
|
|
191
|
+
this.reqAuth = new Param('reqAuth', undefined, { internal: true, type: 'object', obfuscate: ObfuscationLevel.full });
|
|
196
192
|
|
|
197
193
|
// - persisted
|
|
198
|
-
this.username = new Param('username',
|
|
194
|
+
this.username = new Param('username', undefined, { persist: Persistence.setting }); // only saved against localhost (non-productive); as setting due to ambiguous app URL
|
|
199
195
|
this.isEmptyPassword = new Param('isEmptyPassword', false, { internal: true, persist: Persistence.setting }); // extra param so we can ensure we never save a password
|
|
200
|
-
this.token = new Param('token',
|
|
196
|
+
this.token = new Param('token', undefined, { persist: Persistence.auth, obfuscate: ObfuscationLevel.partial });
|
|
201
197
|
this.tokenExpirationDate = new Param('tokenExpirationDate', Number.MAX_SAFE_INTEGER, { persist: Persistence.auth });
|
|
202
|
-
this.refreshToken = new Param('refreshToken',
|
|
198
|
+
this.refreshToken = new Param('refreshToken', undefined, { persist: Persistence.auth, obfuscate: ObfuscationLevel.partial });
|
|
203
199
|
}
|
|
204
200
|
}
|
|
205
201
|
|
|
202
|
+
// TODO pass these as extra arguments to lib functions
|
|
206
203
|
/**
|
|
207
204
|
* All known params including those needed for specific commands.
|
|
208
205
|
*/
|
|
@@ -211,28 +208,25 @@ class AllParams extends BasicParams {
|
|
|
211
208
|
super();
|
|
212
209
|
|
|
213
210
|
// `extend` PARAMS
|
|
214
|
-
this.
|
|
215
|
-
this.
|
|
216
|
-
this["download-migrated-projects"] = new Param('download-migrated-projects', false)
|
|
211
|
+
this.defaultTag = new Param('defaultTag', undefined);
|
|
212
|
+
this.tagRule = new Param('tagRule', undefined);
|
|
217
213
|
|
|
218
|
-
// `
|
|
219
|
-
this.undeploy = new Param('undeploy', false);
|
|
220
|
-
this.wsdl = new Param('wsdl', false);
|
|
214
|
+
// `push` PARAMS
|
|
221
215
|
this.sync = new Param('sync', false);
|
|
222
216
|
this.async = new Param('async', false);
|
|
223
217
|
|
|
224
218
|
// `subscribe` PARAMS
|
|
225
|
-
this.body = new Param('body',
|
|
219
|
+
this.body = new Param('body', undefined, { internal: true, persist: Persistence.none });
|
|
226
220
|
|
|
227
221
|
// `login` PARAMS
|
|
228
222
|
this.skipToken = new Param('skipToken', false, { internal: true });
|
|
223
|
+
this.saveRefreshToken = new Param('saveRefreshToken', false, { internal: true });
|
|
229
224
|
|
|
230
225
|
// `logout` PARAMS
|
|
231
226
|
this.deleteSettings = new Param('deleteSettings', false);
|
|
232
227
|
this["delete-settings"] = this.deleteSettings.newAlias('delete-settings');
|
|
233
228
|
this.clearInvalid = new Param('clearInvalid', false);
|
|
234
229
|
this["clear-invalid"] = this.clearInvalid.newAlias('clear-invalid');
|
|
235
|
-
|
|
236
230
|
}
|
|
237
231
|
}
|
|
238
232
|
|
|
@@ -411,7 +405,7 @@ class ParamCollection {
|
|
|
411
405
|
}
|
|
412
406
|
|
|
413
407
|
/**
|
|
414
|
-
* Return an object mapping each of the contained params
|
|
408
|
+
* Return an object mapping the names of each of the contained params to their corresponding values.
|
|
415
409
|
* @param persistence the type of persistence to filter for (omit to disable filtering)
|
|
416
410
|
*/
|
|
417
411
|
toEntries(persistence) {
|
package/lib/mtx/pull.js
CHANGED
|
@@ -2,7 +2,7 @@ const cds = require ('../cds')
|
|
|
2
2
|
const { local, tar } = cds.utils;
|
|
3
3
|
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const { join } = require('path');
|
|
5
|
+
const { join, dirname } = require('path');
|
|
6
6
|
const axios = require('axios');
|
|
7
7
|
|
|
8
8
|
const { login } = require('./auth_manager');
|
|
@@ -10,73 +10,181 @@ const { login } = require('./auth_manager');
|
|
|
10
10
|
require('../util/axios').pruneErrors();
|
|
11
11
|
const { getMessage } = require('./util/logging');
|
|
12
12
|
const { handleHttpError } = require('./util/errors');
|
|
13
|
+
const { grepQR } = require('./util/fs');
|
|
14
|
+
const { escapeRegex } = require('./util/strings');
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
function tabSize(jsonString, defaultSize) {
|
|
17
|
+
return /^ +/m.exec(jsonString)?.[0].length ?? defaultSize;
|
|
18
|
+
}
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
function getPackageContentsAndTabSize(pkgPath, defaultContents = undefined, defaultTabSize = 0) {
|
|
21
|
+
try {
|
|
22
|
+
const contents = fs.readFileSync(pkgPath, { encoding: 'utf-8' });
|
|
23
|
+
const tab = tabSize(contents, defaultTabSize);
|
|
24
|
+
return [JSON.parse(contents), tab];
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (defaultContents) {
|
|
27
|
+
return [defaultContents, defaultTabSize];
|
|
19
28
|
}
|
|
29
|
+
throw getMessage('package.json missing or unreadable', { error });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function writeObj(obj, objPath, tabSize) {
|
|
34
|
+
if (!fs.existsSync(dirname(objPath))) {
|
|
35
|
+
fs.mkdirSync(dirname(objPath), { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
fs.writeFileSync(objPath, JSON.stringify(obj, undefined, tabSize), { encoding: 'utf-8' });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const INVALID_BASE_MODEL_NAME = /^[._]/; // See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#name
|
|
20
41
|
|
|
42
|
+
|
|
43
|
+
module.exports = class Pull {
|
|
44
|
+
|
|
45
|
+
static async run(paramValues) {
|
|
21
46
|
const params = await login(paramValues);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
47
|
+
return new Pull(params).run();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
params;
|
|
51
|
+
projectFolder;
|
|
52
|
+
env;
|
|
53
|
+
baseModelName;
|
|
54
|
+
packagePath;
|
|
55
|
+
baseModelFolder;
|
|
56
|
+
#amendPackage = {};
|
|
57
|
+
#baseModelWorkspace;
|
|
58
|
+
#packageContentsAndTabSize;
|
|
59
|
+
|
|
60
|
+
static get DEFAULTS() {
|
|
61
|
+
return {
|
|
62
|
+
tabSize: 2,
|
|
63
|
+
baseModelFolder: '.base',
|
|
64
|
+
baseModelName: 'base-model'
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
constructor(params) {
|
|
69
|
+
this.params = params;
|
|
70
|
+
this.projectFolder = params.get('projectFolder');
|
|
71
|
+
this.env = cds.env.for('cds', this.projectFolder);
|
|
72
|
+
this.baseModelName = this.env.extends;
|
|
73
|
+
this.packagePath = join(this.projectFolder, 'package.json');
|
|
74
|
+
this.baseModelFolder = join(this.projectFolder, this.baseModelWorkspace);
|
|
75
|
+
}
|
|
27
76
|
|
|
28
|
-
|
|
77
|
+
async run() {
|
|
78
|
+
console.log(`Pulling app base model`, {
|
|
79
|
+
from: this.params.get('appUrl'),
|
|
80
|
+
to: local(this.baseModelFolder),
|
|
81
|
+
...(this.params.has('subdomain') && { subdomain: this.params.get('subdomain') })
|
|
82
|
+
});
|
|
29
83
|
|
|
30
|
-
|
|
84
|
+
this.validateBaseModelName();
|
|
31
85
|
|
|
32
|
-
fs.rmSync(
|
|
33
|
-
fs.mkdirSync(
|
|
86
|
+
fs.rmSync(this.baseModelFolder, { force: true, recursive: true });
|
|
87
|
+
fs.mkdirSync(this.baseModelFolder, { recursive: true });
|
|
34
88
|
|
|
35
|
-
const baseModelTgz = await this.
|
|
36
|
-
await tar.xz(baseModelTgz).to(
|
|
89
|
+
const baseModelTgz = await this.pullTgz();
|
|
90
|
+
await tar.xz(baseModelTgz).to(this.baseModelFolder);
|
|
91
|
+
Pull.transformBasePackage(this.baseModelFolder, this.baseModelName);
|
|
92
|
+
this.amendExtPackage();
|
|
37
93
|
|
|
38
|
-
console.log(`Finished. Refer to the base model like so: using from '${this.
|
|
94
|
+
console.log(`Finished. Refer to the base model like so: using from '${this.baseModelName}'`);
|
|
95
|
+
|
|
96
|
+
const baseModelSymlink = join(this.projectFolder, 'node_modules', this.baseModelName);
|
|
97
|
+
if (!fs.statSync(baseModelSymlink, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
98
|
+
console.log(`Note: the base model has been pulled to an NPM workspace in folder '${local(this.baseModelFolder)}'. Run 'npm install' to install it.`);
|
|
99
|
+
}
|
|
39
100
|
}
|
|
40
101
|
|
|
41
|
-
|
|
42
|
-
|
|
102
|
+
get baseModelWorkspace() {
|
|
103
|
+
const defaultFolder = Pull.DEFAULTS.baseModelFolder;
|
|
104
|
+
if (!this.#baseModelWorkspace) {
|
|
105
|
+
if (this.packageContents.workspaces) {
|
|
106
|
+
if (this.packageContents.workspaces.includes(defaultFolder)) {
|
|
107
|
+
this.#baseModelWorkspace = defaultFolder;
|
|
108
|
+
} else {
|
|
109
|
+
this.#baseModelWorkspace = this.packageContents.workspaces
|
|
110
|
+
.map(ws => String(ws))
|
|
111
|
+
.find(ws => {
|
|
112
|
+
try {
|
|
113
|
+
return require(join(this.projectFolder, ws, 'package.json')).name === this.baseModelName;
|
|
114
|
+
} catch (e) { /* ignore */ }
|
|
115
|
+
}) ?? defaultFolder;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
this.#amendPackage.workspaces = [defaultFolder];
|
|
119
|
+
this.#baseModelWorkspace = defaultFolder;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return this.#baseModelWorkspace;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
validateBaseModelName() {
|
|
126
|
+
if (!this.baseModelName) {
|
|
127
|
+
throw getMessage(`Missing configuration 'cds.extends' in package.json`);
|
|
128
|
+
}
|
|
129
|
+
if (this.baseModelName.match(INVALID_BASE_MODEL_NAME)) {
|
|
130
|
+
console.warn(`Invalid base-model name '${this.baseModelName}': must not start with '_' or '.'. ` +
|
|
131
|
+
`Using '${Pull.DEFAULTS.baseModelName}' instead.`);
|
|
132
|
+
const invalidNameInUse = grepQR(this.projectFolder, ['.cds', '.csn'], new RegExp(`\\b${escapeRegex(this.baseModelName)}\\b`));
|
|
133
|
+
if (invalidNameInUse) {
|
|
134
|
+
console.error(`Some model files seem to reference the invalid name. Please update them manually.`);
|
|
135
|
+
}
|
|
136
|
+
this.baseModelName = Pull.DEFAULTS.baseModelName;
|
|
137
|
+
this.#amendPackage.extends = this.baseModelName;
|
|
138
|
+
}
|
|
43
139
|
}
|
|
44
140
|
|
|
45
|
-
|
|
46
|
-
const pullUrl = `${(params.get('appUrl'))}/-/cds/extensibility/pull`;
|
|
47
|
-
const options = { ...params.get('reqAuth'), responseType: 'arraybuffer' };
|
|
141
|
+
async pullTgz() {
|
|
142
|
+
const pullUrl = `${(this.params.get('appUrl'))}/-/cds/extensibility/pull`;
|
|
143
|
+
const options = { ...this.params.get('reqAuth'), responseType: 'arraybuffer' };
|
|
48
144
|
|
|
49
145
|
return axios.post(pullUrl, {}, options)
|
|
50
146
|
.then(response => Buffer.from(response.data))
|
|
51
|
-
.catch(error => handleHttpError(error, params, { url: pullUrl }));
|
|
147
|
+
.catch(error => handleHttpError(error, this.params, { url: pullUrl }));
|
|
52
148
|
}
|
|
53
149
|
|
|
54
|
-
static
|
|
55
|
-
|
|
56
|
-
|
|
150
|
+
static transformBasePackage(baseModelFolder, baseModelName) {
|
|
151
|
+
const baseRcPath = join(baseModelFolder, '.cdsrc.json');
|
|
152
|
+
const baseRc = getPackageContentsAndTabSize(baseRcPath, {}, this.DEFAULTS.tabSize)[0];
|
|
153
|
+
fs.rmSync(baseRcPath, { force: true });
|
|
154
|
+
|
|
155
|
+
const basePkgPath = join(baseModelFolder, 'package.json');
|
|
156
|
+
const basePkg = {
|
|
157
|
+
...getPackageContentsAndTabSize(basePkgPath, {}, this.DEFAULTS.tabSize)[0],
|
|
158
|
+
name: baseModelName,
|
|
159
|
+
cds: baseRc
|
|
160
|
+
};
|
|
57
161
|
|
|
58
|
-
|
|
59
|
-
return JSON.stringify(newObj, undefined, this.getPackageJsonIndentation(oldContents));
|
|
162
|
+
writeObj(basePkg, basePkgPath, this.DEFAULTS.tabSize);
|
|
60
163
|
}
|
|
61
164
|
|
|
62
|
-
|
|
63
|
-
if (
|
|
165
|
+
amendExtPackage() {
|
|
166
|
+
if (Object.keys(this.#amendPackage).length === 0) {
|
|
64
167
|
return;
|
|
65
168
|
}
|
|
66
169
|
console.log(`Amending extension package.json with project configuration`);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
170
|
+
fs.writeFileSync(this.packagePath, JSON.stringify({
|
|
171
|
+
...this.packageContents,
|
|
172
|
+
...this.#amendPackage
|
|
173
|
+
}, undefined, this.tabSize));
|
|
174
|
+
this.#packageContentsAndTabSize = undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get packageContents() {
|
|
178
|
+
if (!this.#packageContentsAndTabSize) {
|
|
179
|
+
this.#packageContentsAndTabSize = getPackageContentsAndTabSize(this.packagePath, undefined, Pull.DEFAULTS.tabSize);
|
|
73
180
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
181
|
+
return this.#packageContentsAndTabSize[0];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get tabSize() {
|
|
185
|
+
if (!this.#packageContentsAndTabSize) {
|
|
186
|
+
this.#packageContentsAndTabSize = getPackageContentsAndTabSize(this.packagePath, undefined, Pull.DEFAULTS.tabSize);
|
|
187
|
+
}
|
|
188
|
+
return this.#packageContentsAndTabSize[1];
|
|
81
189
|
}
|
|
82
190
|
}
|
package/lib/mtx/push.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { utils: { local }} = require ('../cds');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const { readFileSync, existsSync } = require('fs');
|
|
4
4
|
const axios = require('axios');
|
|
@@ -33,7 +33,7 @@ module.exports = class Push {
|
|
|
33
33
|
const { src, content } = await this.readSource(params, pushOptions);
|
|
34
34
|
const url = params.get('appUrl');
|
|
35
35
|
const subdomain = params.get('subdomain');
|
|
36
|
-
const target =
|
|
36
|
+
const target = { url, ...subdomain && { subdomain } };
|
|
37
37
|
|
|
38
38
|
console.log(`\nPushing extension '${extensionName}' from`, { src }, 'to', target);
|
|
39
39
|
const push = await this.pushTgz(params, content, extensionName);
|
|
@@ -51,7 +51,7 @@ module.exports = class Push {
|
|
|
51
51
|
src = local(src);
|
|
52
52
|
} else {
|
|
53
53
|
if (!schemaRegex.test(src)) {
|
|
54
|
-
throw getMessage(`
|
|
54
|
+
throw getMessage(`Non-existent path: ${src}`, { command: 'push' });
|
|
55
55
|
}
|
|
56
56
|
try {
|
|
57
57
|
content = (await axios.get(src, { responseEncoding: 'base64' })).data;
|
|
@@ -8,6 +8,7 @@ const cds = require('../cds');
|
|
|
8
8
|
const { requireGlobal } = require('./util/dependencies');
|
|
9
9
|
const { getAppFromSuggestions, getSubdomain } = require('./util/cf');
|
|
10
10
|
const isBas = require('./util/env');
|
|
11
|
+
const { getMessage } = require('./util/logging');
|
|
11
12
|
const Question = require('./util/question');
|
|
12
13
|
const { httpSchema, httpsSchema, schemaRegex, localhostRegex } = require('./util/urls');
|
|
13
14
|
const { capitalize } = require('./util/strings');
|
|
@@ -34,8 +35,9 @@ const KEYRING_DESC = {
|
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const MTX_FULLY_QUALIFIED = 'com.sap.cds.mtx';
|
|
37
|
-
const
|
|
38
|
-
const
|
|
38
|
+
const OAUTH_PATH_LEGACY = '/mtx/v1/oauth/token';
|
|
39
|
+
const OAUTH_PATH = '/-/cds/login/token';
|
|
40
|
+
const OAUTH_META_PATH = '/-/cds/login/authorization-metadata';
|
|
39
41
|
|
|
40
42
|
const SETTINGS_DIR = path.join(os.homedir(), CONFIG_SUBDIRS[os.platform()] || '', MTX_FULLY_QUALIFIED);
|
|
41
43
|
const SETTINGS_FILE = 'projects.json';
|
|
@@ -92,30 +94,46 @@ async function getSubdomainFromCfAndNotify(appName) {
|
|
|
92
94
|
return subdomain;
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
function appUrlWith(pathname, params) {
|
|
98
|
+
const url = new URL(params.get('appUrl'));
|
|
99
|
+
url.pathname = url.pathname.replace(/\/*$/, pathname);
|
|
100
|
+
return url.toString();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function getTokenUrl(params, renewUrl) {
|
|
96
104
|
if (params.has('tokenUrl') && !renewUrl) {
|
|
97
105
|
return params.get('tokenUrl');
|
|
98
106
|
}
|
|
99
107
|
if (!params.has('appUrl')) {
|
|
100
108
|
throw 'Failed to determine token URL: app URL not given';
|
|
101
109
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
url.pathname = url.pathname.replace(/\/*$/, pathname);
|
|
105
|
-
return url.toString();
|
|
106
|
-
};
|
|
110
|
+
return appUrlWith(OAUTH_PATH, params);
|
|
111
|
+
}
|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
async function fetchPasscodeUrl(params) {
|
|
114
|
+
const url = appUrlWith(OAUTH_META_PATH, params);
|
|
115
|
+
DEBUG?.(`Trying to get passcode URL from GET`, url);
|
|
116
|
+
let responseData;
|
|
109
117
|
try {
|
|
110
|
-
await axios.
|
|
111
|
-
|
|
118
|
+
const response = await axios.get(url /* no auth required */);
|
|
119
|
+
responseData = response.data;
|
|
112
120
|
} catch (error) {
|
|
113
|
-
if (
|
|
114
|
-
|
|
121
|
+
if (error.status === 404) {
|
|
122
|
+
DEBUG?.(`Request unsupported by server, ignoring (${error.message.replace(/ *Details:.*/s, '')})`);
|
|
123
|
+
} else {
|
|
124
|
+
DEBUG?.(getMessage(`Getting passcode URL failed`, { error }));
|
|
115
125
|
}
|
|
116
|
-
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
DEBUG?.(`Received ${JSON.stringify(responseData)}`);
|
|
129
|
+
if (responseData.includes?.('<html')) {
|
|
130
|
+
throw 'HTML response received. Check if route to MTX is configured correctly in App Router.';
|
|
117
131
|
}
|
|
118
|
-
|
|
132
|
+
if (responseData.signed_metadata) {
|
|
133
|
+
DEBUG?.(`Unsupported signed metadata received. Since these should take precedence, ignoring response.`);
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
return responseData.passcode_url;
|
|
119
137
|
}
|
|
120
138
|
|
|
121
139
|
function getKeyringAccountName(params) {
|
|
@@ -135,7 +153,7 @@ function logConfigPaths() {
|
|
|
135
153
|
DEBUG?.(`Authentication data is stored in ${CONFIG.paths.auth} (${TOKEN_STORAGE_DESC.plain}) or ${CONFIG.keyringDesignation} (${TOKEN_STORAGE_DESC.keyring})`);
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
function
|
|
156
|
+
function notifyLogin(params) {
|
|
139
157
|
return params.get('renewLogin')
|
|
140
158
|
? console.log.bind(console)
|
|
141
159
|
: DEBUG;
|
|
@@ -201,8 +219,13 @@ class SettingsManager {
|
|
|
201
219
|
const loadedSettings = await this._loadFromFile(projectFolder);
|
|
202
220
|
DEBUG?.(`Loaded project settings for ${params.get('projectFolder')}: ${loadedSettings.format()}`);
|
|
203
221
|
|
|
222
|
+
const clashing = ['passcode', 'clientid', 'username'].filter(param => params.has(param));
|
|
223
|
+
if (clashing.length > 1) {
|
|
224
|
+
throw `Conflicting parameters: ${clashing.join(', ')}. Please provide only one of them.`;
|
|
225
|
+
}
|
|
226
|
+
|
|
204
227
|
if (params.has('passcode') && loadedSettings.has('username')) {
|
|
205
|
-
console.log(`
|
|
228
|
+
console.log(`Discarding saved username${(loadedSettings.has('isEmptyPassword') ? ' and empty-password hint' : '')}: passcode given`);
|
|
206
229
|
loadedSettings.delete('username');
|
|
207
230
|
loadedSettings.delete('isEmptyPassword');
|
|
208
231
|
}
|
|
@@ -219,6 +242,23 @@ class SettingsManager {
|
|
|
219
242
|
}
|
|
220
243
|
|
|
221
244
|
static async updateUrls(params, logout, loadedSettings) {
|
|
245
|
+
function secure(url, label) {
|
|
246
|
+
if (!url) {
|
|
247
|
+
return url;
|
|
248
|
+
}
|
|
249
|
+
if (url.startsWith(httpSchema) && !localhostRegex.test(url)) {
|
|
250
|
+
url = url.replace(httpSchema, httpsSchema);
|
|
251
|
+
DEBUG?.(`Replaced HTTP with HTTPS in ${label}: ${url}`);
|
|
252
|
+
} else if (!schemaRegex.test(url)) {
|
|
253
|
+
if (localhostRegex.test(url)) {
|
|
254
|
+
url = httpSchema + url;
|
|
255
|
+
} else {
|
|
256
|
+
url = httpsSchema + url;
|
|
257
|
+
}
|
|
258
|
+
DEBUG?.(`Added schema to ${label}: ${url}`);
|
|
259
|
+
}
|
|
260
|
+
return url;
|
|
261
|
+
}
|
|
222
262
|
async function updateAppUrl() {
|
|
223
263
|
if (!logout && !params.has('appUrl')) {
|
|
224
264
|
// Get appUrl from CF
|
|
@@ -231,30 +271,23 @@ class SettingsManager {
|
|
|
231
271
|
}
|
|
232
272
|
|
|
233
273
|
// Prefix URL schema
|
|
234
|
-
let appUrl = params.get('appUrl');
|
|
274
|
+
let appUrl = secure(params.get('appUrl'), 'app URL');
|
|
235
275
|
if (appUrl.endsWith('/')) {
|
|
236
276
|
appUrl = appUrl.replace(/\/+$/, '');
|
|
237
277
|
DEBUG?.(`Removed trailing slash from app URL: ${appUrl}`);
|
|
238
278
|
}
|
|
239
|
-
if (!schemaRegex.test(appUrl)) {
|
|
240
|
-
if (localhostRegex.test(appUrl)) {
|
|
241
|
-
appUrl = httpSchema + appUrl;
|
|
242
|
-
} else {
|
|
243
|
-
appUrl = httpsSchema + appUrl;
|
|
244
|
-
}
|
|
245
|
-
DEBUG?.(`Added schema to app URL: ${appUrl}`);
|
|
246
|
-
}
|
|
247
279
|
params.set('appUrl', appUrl);
|
|
248
280
|
if (params.get('appUrl') !== loadedSettings.get('appUrl')) {
|
|
249
|
-
DEBUG?.(`Updated app URL from '${loadedSettings.get('appUrl')}'
|
|
281
|
+
DEBUG?.(`Updated app URL from loaded value '${loadedSettings.get('appUrl')}'`);
|
|
250
282
|
}
|
|
283
|
+
console.log(`App URL: ${params.get('appUrl')}`);
|
|
251
284
|
}
|
|
252
285
|
async function updateTokenUrl() {
|
|
253
|
-
const tokenUrl = params.get('tokenUrl');
|
|
286
|
+
const tokenUrl = secure(params.get('tokenUrl'), 'token URL');
|
|
254
287
|
const renewUrl = !logout && !params.get('skipToken')
|
|
255
|
-
&& (!tokenUrl || tokenUrl.includes('//-/cds') || tokenUrl.includes(
|
|
288
|
+
&& (!tokenUrl || tokenUrl.includes('//-/cds') || tokenUrl.includes(OAUTH_PATH_LEGACY) || params.get('appUrl') !== loadedSettings.get('appUrl'));
|
|
256
289
|
if (renewUrl) {
|
|
257
|
-
const tokenUrl = await
|
|
290
|
+
const tokenUrl = await getTokenUrl(params, renewUrl);
|
|
258
291
|
params.set('tokenUrl', tokenUrl);
|
|
259
292
|
DEBUG?.(`Updated token URL from '${loadedSettings.get('tokenUrl')}' (loaded) to '${tokenUrl}'`);
|
|
260
293
|
}
|
|
@@ -317,7 +350,13 @@ class SettingsManager {
|
|
|
317
350
|
}
|
|
318
351
|
}
|
|
319
352
|
async function addPasscode() {
|
|
320
|
-
|
|
353
|
+
if (!params.has('passcodeUrl')) {
|
|
354
|
+
const passcodeUrl = await fetchPasscodeUrl(params);
|
|
355
|
+
if (passcodeUrl) {
|
|
356
|
+
params.set('passcodeUrl', passcodeUrl);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const prompt = `Passcode${params.has('passcodeUrl') ? ' (visit ' + params.get('passcodeUrl') + ' to generate)' : ''}: `;
|
|
321
360
|
params.set('passcode', (await Question.askQuestion(prompt, undefined, true)).trim());
|
|
322
361
|
console.log();
|
|
323
362
|
if (params.get('passcode') === '') {
|
|
@@ -515,7 +554,7 @@ class SettingsManager {
|
|
|
515
554
|
(allAuthValues[appUrl] || (allAuthValues[appUrl] = {}))[params.get('subdomain')] = authValues;
|
|
516
555
|
await fs.promises.mkdir(path.dirname(CONFIG.paths.auth), { recursive: true })
|
|
517
556
|
await fs.promises.writeFile(CONFIG.paths.auth, JSON.stringify(allAuthValues, null, 2));
|
|
518
|
-
|
|
557
|
+
notifyLogin(params)?.(`Saved authentication data to ${location}`);
|
|
519
558
|
} else if (allAuthValues[appUrl]) {
|
|
520
559
|
delete allAuthValues[appUrl][params.get('subdomain')];
|
|
521
560
|
if (Object.keys(allAuthValues[appUrl]).length === 0) {
|
|
@@ -525,7 +564,7 @@ class SettingsManager {
|
|
|
525
564
|
await fs.promises.writeFile(CONFIG.paths.auth, JSON.stringify(allAuthValues, null, 2));
|
|
526
565
|
console.log('Deleted authentication data from', location);
|
|
527
566
|
} else {
|
|
528
|
-
|
|
567
|
+
notifyLogin(params)?.(`No authentication data to delete from ${location}`);
|
|
529
568
|
}
|
|
530
569
|
}
|
|
531
570
|
|
|
@@ -538,7 +577,7 @@ class SettingsManager {
|
|
|
538
577
|
|
|
539
578
|
if (auth !== null) {
|
|
540
579
|
await keytar.setPassword(MTX_FULLY_QUALIFIED, getKeyringAccountName(params), JSON.stringify(auth));
|
|
541
|
-
|
|
580
|
+
notifyLogin(params)?.(`Saved authentication data to ${location}`);
|
|
542
581
|
} else {
|
|
543
582
|
await keytar.deletePassword(MTX_FULLY_QUALIFIED, getKeyringAccountName(params));
|
|
544
583
|
console.log('Deleted authentication data from', location);
|
|
@@ -663,5 +702,6 @@ class SettingsManager {
|
|
|
663
702
|
|
|
664
703
|
module.exports = {
|
|
665
704
|
SettingsManager,
|
|
666
|
-
other
|
|
705
|
+
other,
|
|
706
|
+
notifyLogin
|
|
667
707
|
};
|