@sap/cds-dk 7.9.4 → 8.0.2
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 +2116 -0
- package/bin/add.js +18 -52
- package/bin/bind.js +2 -2
- package/bin/build.js +29 -4
- package/bin/cds.js +23 -11
- 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 +2 -11
- 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 +3 -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 +20 -25
- package/lib/build/provider/hana/template/.hdiconfig-all +3 -0
- package/lib/build/provider/hana/template/.hdiconfig-cloud +3 -0
- package/lib/build/provider/hana/template/package.json +4 -3
- package/lib/build/provider/internalBuildPlugin.js +32 -97
- package/lib/build/provider/internalBuildTaskProvider.js +10 -46
- 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/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 +16 -10
- package/lib/init/index.js +74 -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 -19
- 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/audit-logging/files/mta.yaml.hbs +14 -0
- 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 +25 -1
- package/lib/init/template/destination/index.js +12 -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/src/.hdiconfig +3 -0
- 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 +41 -8
- 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 +21 -8
- package/lib/init/template/html5-repo/index.js +33 -30
- 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-messaging/index.js +4 -0
- 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 +5 -0
- package/lib/init/template/workzone-standard/files/manifest.json.hbs +6 -0
- package/lib/init/template/workzone-standard/index.js +30 -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 +231 -1089
- 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
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
|
};
|
package/lib/mtx/tenant_action.js
CHANGED
|
@@ -23,7 +23,7 @@ module.exports = class TenantAction {
|
|
|
23
23
|
*/
|
|
24
24
|
constructor(command) {
|
|
25
25
|
if (!(command in COMMANDS)) {
|
|
26
|
-
throw
|
|
26
|
+
throw `invalid command: ${command}`;
|
|
27
27
|
}
|
|
28
28
|
this.command = command;
|
|
29
29
|
this.gerund = command.replace(/e$/, 'ing');
|
package/lib/mtx/util/cf.js
CHANGED
|
@@ -9,7 +9,7 @@ const { schemaRegex } = require('./urls');
|
|
|
9
9
|
const DEBUG = cds.debug('cli');
|
|
10
10
|
|
|
11
11
|
function runCf(args, callback) {
|
|
12
|
-
const env =
|
|
12
|
+
const env = { ...process.env, LC_ALL: 'en_US.UTF-8' }; // enforce English headings
|
|
13
13
|
return execFile('cf', args, { env }, callback);
|
|
14
14
|
}
|
|
15
15
|
|
package/lib/mtx/util/fs.js
CHANGED
|
@@ -72,11 +72,36 @@ function isParent(maybeParent, maybeChild) {
|
|
|
72
72
|
return ! path.relative(maybeParent, maybeChild).startsWith('..');
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Searches for a regular expression in a directory tree
|
|
77
|
+
* @param folder directory to search in
|
|
78
|
+
* @param extensions file extensions to search for (use lower-case strings)
|
|
79
|
+
* @param regex regular expression to search for
|
|
80
|
+
* @return {boolean} true if the regular expression was found in a file
|
|
81
|
+
*/
|
|
82
|
+
function grepQR(folder, extensions, regex) {
|
|
83
|
+
for (const dirent of fs.readdirSync(folder, { withFileTypes: true })) {
|
|
84
|
+
if (dirent.isFile() &&
|
|
85
|
+
extensions.some(x => dirent.name.toLowerCase().endsWith(x))) {
|
|
86
|
+
try {
|
|
87
|
+
if (regex.test(fs.readFileSync(path.join(folder, dirent.name), { encoding: 'utf-8' }))) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
} catch (error) { /* ignore */ }
|
|
91
|
+
}
|
|
92
|
+
if (dirent.isDirectory() && grepQR(path.join(folder, dirent.name), extensions, regex)) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
75
99
|
|
|
76
100
|
module.exports = {
|
|
77
101
|
collectFileContent,
|
|
78
102
|
collectFiles,
|
|
79
103
|
toUnixPath,
|
|
80
104
|
normalizePath,
|
|
81
|
-
isParent
|
|
105
|
+
isParent,
|
|
106
|
+
grepQR
|
|
82
107
|
};
|
package/lib/mtx/util/logging.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
|
|
3
3
|
function getMessage(errorText, { error, command, help = command && getCommandHelp(command) } = {}) {
|
|
4
4
|
let message = errorText ? errorText.trim() : '';
|
|
@@ -16,8 +16,12 @@ function getMessage(errorText, { error, command, help = command && getCommandHel
|
|
|
16
16
|
if (includeStack) {
|
|
17
17
|
message += (oriMsg ? '\n' : '') + error.stack;
|
|
18
18
|
}
|
|
19
|
-
if (
|
|
20
|
-
|
|
19
|
+
if (error.cause) {
|
|
20
|
+
if (debug) {
|
|
21
|
+
message += '\nCaused by: ' + getMessage('', { error: error.cause }).replace(/^(?= *at)/gm, ' ');
|
|
22
|
+
} else if (error.cause.status) {
|
|
23
|
+
message += `\nHTTP status: ${error.cause.status}`;
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
}
|
|
23
27
|
if (typeof help === 'string') {
|
package/lib/util/command.js
CHANGED
package/lib/util/fs.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
const { yaml: YAML } = require('
|
|
1
|
+
const { read, write, yaml: YAML } = require('../cds').utils
|
|
2
2
|
const JSONC = require('./jsonc');
|
|
3
|
-
const { read, write } = require('../cds').utils;
|
|
4
3
|
|
|
5
4
|
// REVISIT: Consider merging with template util
|
|
6
5
|
|
|
@@ -28,7 +27,7 @@ module.exports = new class FsUtil {
|
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
async writeYAML(dst, yaml) {
|
|
31
|
-
const content = YAML.stringify(yaml, { collectionStyle: 'block', lineWidth:
|
|
30
|
+
const content = YAML.stringify(yaml, { collectionStyle: 'block', lineWidth: 150 })
|
|
32
31
|
await write(content).to(dst)
|
|
33
32
|
}
|
|
34
33
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const readline = require('readline')
|
|
2
|
+
async function ask4(...args) {
|
|
3
|
+
const answers = []
|
|
4
|
+
const rl = readline.createInterface({
|
|
5
|
+
input: process.stdin,
|
|
6
|
+
output: process.stdout
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
async function askQuestion(questionParam) {
|
|
10
|
+
return new Promise(function (resolve) {
|
|
11
|
+
rl.question(`${questionParam}`, function (answer) {
|
|
12
|
+
answers.push(answer);
|
|
13
|
+
resolve();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
for (const idx in args) {
|
|
19
|
+
await askQuestion(args[idx])
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
rl.close()
|
|
23
|
+
return answers
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
ask4
|
|
28
|
+
}
|
package/lib/util/term.js
CHANGED
|
@@ -9,13 +9,15 @@ const t = module.exports.codes = {
|
|
|
9
9
|
red: '\x1b[91m', // Bright Foreground Red
|
|
10
10
|
green: '\x1b[32m', // Foreground Green
|
|
11
11
|
blue: '\x1b[34m', // Foreground Blue
|
|
12
|
+
yellow:'\x1b[33m', // Foreground Yellow
|
|
12
13
|
orange: '\x1b[38;2;255;140;0m' // darker orange, works with bright and dark background
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
Object.defineProperty(module.exports, 'isTTY', { get: () => process.
|
|
16
|
-
|
|
16
|
+
Object.defineProperty(module.exports, 'isTTY', { get: () => process.stdout.isTTY && process.stderr.isTTY })
|
|
17
|
+
const useColor = module.exports.isTTY && process.env.NO_COLOR !== 'true' || (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== 'false')
|
|
18
|
+
module.exports.colors = useColor
|
|
17
19
|
const as = module.exports.as = (codes, o) => {
|
|
18
|
-
return
|
|
20
|
+
return useColor ? (codes + o + t.reset) : ('' + o)
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const asErr = module.exports.error = o => DEBUG ? o : as(t.red + t.bold, o)
|