@sap/cds-dk 6.8.3 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/activate.js +15 -7
- package/bin/add.js +29 -15
- package/bin/bind.js +49 -116
- package/bin/build.js +114 -0
- package/bin/cds.js +67 -24
- package/bin/compile/index.js +2 -2
- package/bin/deploy/index.js +46 -39
- package/bin/deploy/to-hana.js +11 -8
- package/bin/deploy/to-postgres.js +8 -2
- package/bin/deploy/to-sqlite.js +0 -1
- package/bin/env.js +75 -41
- package/bin/eval.js +3 -3
- package/bin/extend.js +17 -10
- package/bin/help.js +22 -21
- package/bin/import.js +10 -7
- package/bin/init.js +38 -17
- package/bin/login.js +69 -55
- package/bin/logout.js +12 -9
- package/bin/migrate.js +10 -4
- package/bin/pull.js +12 -5
- package/bin/push.js +24 -13
- package/bin/repl.js +1 -0
- package/bin/run.js +25 -0
- package/bin/subscribe.js +13 -8
- package/bin/unsubscribe.js +15 -8
- package/bin/upgrade.js +15 -9
- package/bin/util/log.js +24 -0
- package/bin/version.js +124 -0
- package/bin/watch.js +1 -35
- package/bin/watched.js +39 -0
- package/lib/bind/KubernetesApiAccessor.js +2 -2
- package/lib/bind/bindingManager.js +1 -1
- package/lib/bind/bindingUtil.js +0 -9
- package/lib/bind/cfKeyProvider.js +10 -72
- package/lib/bind/index.js +114 -0
- package/lib/bind/kubernetesCredentialsProvider.js +2 -2
- package/lib/bind/userCdsrcJsonStorageProvider.js +7 -44
- package/lib/build/buildTaskEngine.js +355 -0
- package/lib/build/buildTaskFactory.js +284 -0
- package/lib/build/buildTaskHandler.js +240 -0
- package/lib/build/buildTaskProvider.js +22 -0
- package/lib/build/buildTaskProviderFactory.js +182 -0
- package/lib/build/constants.js +56 -0
- package/lib/build/index.js +21 -0
- package/lib/build/provider/buildTaskHandlerEdmx.js +83 -0
- package/lib/build/provider/buildTaskHandlerFeatureToggles.js +132 -0
- package/lib/build/provider/buildTaskHandlerInternal.js +228 -0
- package/lib/build/provider/buildTaskProviderInternal.js +370 -0
- package/lib/build/provider/fiori/index.js +167 -0
- package/lib/build/provider/hana/2migration.js +179 -0
- package/lib/build/provider/hana/index.js +522 -0
- package/lib/build/provider/hana/migrationtable.js +472 -0
- package/lib/build/provider/hana/template/.hdiconfig-all +163 -0
- package/lib/build/provider/hana/template/.hdiconfig-cloud +137 -0
- package/lib/build/provider/hana/template/.hdinamespace +4 -0
- package/lib/build/provider/hana/template/package.json +12 -0
- package/lib/build/provider/hana/template/undeploy.json +5 -0
- package/lib/build/provider/java/index.js +93 -0
- package/lib/build/provider/java-cf/index.js +1 -0
- package/lib/build/provider/mtx/index.js +37 -0
- package/lib/build/provider/mtx/resourcesTarBuilder.js +94 -0
- package/lib/build/provider/mtx-extension/index.js +131 -0
- package/lib/build/provider/mtx-sidecar/index.js +138 -0
- package/lib/build/provider/node-cf/index.js +1 -0
- package/lib/build/provider/nodejs/index.js +178 -0
- package/lib/build/util.js +263 -0
- package/lib/cds.js +9 -21
- package/lib/client/auth_manager.js +39 -16
- package/lib/client/helper/dependency_helper.js +7 -6
- package/lib/client/push.js +2 -1
- package/lib/client/settings_manager.js +10 -39
- package/lib/deploy/to-hana/hana.js +273 -0
- package/lib/deploy/to-hana/hdiDeployUtil.js +68 -0
- package/lib/deploy/to-hana/mtaUtil.js +171 -0
- package/lib/import/asyncapi/importAsyncAPI.js +3 -2
- package/lib/import/asyncapi/index.js +5 -2
- package/lib/import/asyncapi/parserContext.js +67 -26
- package/lib/import/asyncapi/utils.js +34 -3
- package/lib/import/common.js +40 -30
- package/lib/import/importapi.js +36 -35
- package/lib/index.js +12 -17
- package/lib/init/constants.js +36 -71
- package/lib/init/index.js +18 -52
- package/lib/init/template/_merging/registry-mta.js +21 -3
- package/lib/init/template/approuter/files/mta.yaml.hbs +29 -29
- package/lib/init/template/approuter/files/values.yaml.hbs +5 -5
- package/lib/init/template/approuter/files/xs-app.json.hbs +8 -2
- package/lib/init/template/approuter/index.js +7 -8
- package/lib/init/template/auditlog/files/mta.yaml.hbs +5 -5
- package/lib/init/template/auditlog/files/package.json.hbs +13 -13
- package/lib/init/template/auditlog/index.js +3 -3
- package/lib/init/template/cf-manifest/files/manifest.yml.hbs +22 -22
- package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +3 -3
- package/lib/init/template/connectivity/files/mta.yaml.hbs +14 -0
- package/lib/init/template/connectivity/files/package.json.hbs +17 -0
- package/lib/init/template/connectivity/index.js +21 -4
- package/lib/init/template/data/index.js +5 -1
- package/lib/init/template/destination/files/mta.yaml.hbs +14 -0
- package/lib/init/template/destination/files/package.json.hbs +17 -0
- package/lib/init/template/{destinations → destination}/index.js +19 -13
- package/lib/init/template/enterprise-messaging/files/event-mesh.json.hbs +3 -3
- package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/enterprise-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/enterprise-messaging/files/xs-security.json.hbs +19 -0
- package/lib/init/template/enterprise-messaging/index.js +27 -6
- package/lib/init/template/enterprise-messaging-shared/files/event-mesh.json.hbs +3 -3
- package/lib/init/template/enterprise-messaging-shared/files/mta.yaml.hbs +5 -5
- package/lib/init/template/enterprise-messaging-shared/files/package.json.hbs +9 -9
- package/lib/init/template/enterprise-messaging-shared/index.js +4 -5
- package/lib/init/template/extensibility/files/package.json.hbs +10 -10
- package/lib/init/template/extensibility/index.js +8 -9
- package/lib/init/template/file-based-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/file-based-messaging/index.js +3 -4
- package/lib/init/template/hana/files/db/package.json +1 -1
- package/lib/init/template/hana/files/mta.yaml.hbs +21 -21
- package/lib/init/template/hana/files/package.json.hbs +16 -22
- package/lib/init/template/hana/files/values.yaml.hbs +1 -1
- package/lib/init/template/hana/index.js +5 -15
- package/lib/init/template/helm/files/Chart.yaml.hbs +4 -4
- package/lib/init/template/helm/files/values.yaml.hbs +6 -6
- package/lib/init/template/helm/index.js +5 -10
- package/lib/init/template/helm/subcharts/content-deployment/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +37 -31
- package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +13 -14
- package/lib/init/template/helm/subcharts/content-deployment/templates/secret.yaml +2 -2
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-account.yaml +1 -1
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/content-deployment/values.md +116 -116
- package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/service-instance/templates/_helpers.tpl +9 -9
- package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +2 -2
- package/lib/init/template/helm/subcharts/service-instance/values.md +15 -15
- package/lib/init/template/helm/subcharts/web-application/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/web-application/templates/NOTES.txt +15 -0
- package/lib/init/template/helm/subcharts/web-application/templates/_helpers.tpl +23 -23
- package/lib/init/template/helm/subcharts/web-application/templates/api-rule.yaml +4 -4
- package/lib/init/template/helm/subcharts/web-application/templates/deployment.yaml +17 -17
- package/lib/init/template/helm/subcharts/web-application/templates/network-policy.yaml +24 -3
- package/lib/init/template/helm/subcharts/web-application/templates/pod-disruption-budget.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/templates/secret.yaml +2 -2
- package/lib/init/template/helm/subcharts/web-application/templates/service-account.yaml +1 -1
- package/lib/init/template/helm/subcharts/web-application/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/templates/service.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/values.md +141 -123
- package/lib/init/template/helm/subcharts/web-application/values.schema.json +7 -0
- package/lib/init/template/helm/subcharts/web-application/values.yaml +1 -0
- package/lib/init/template/html5-repo/index.js +4 -5
- package/lib/init/template/java/index.js +5 -5
- package/lib/init/template/kibana-logging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/kibana-logging/files/package.json.hbs +9 -9
- package/lib/init/template/kibana-logging/index.js +3 -4
- package/lib/init/template/lint/index.js +3 -3
- package/lib/init/template/mta/files/mta.yaml.hbs +14 -14
- package/lib/init/template/mta/files/package.json +5 -0
- package/lib/init/template/mta/index.js +12 -13
- package/lib/init/template/mtx/index.js +2 -2
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +29 -27
- package/lib/init/template/multitenancy/files/package.json.hbs +17 -14
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -7
- package/lib/init/template/multitenancy/files/values.yaml.hbs +19 -19
- package/lib/init/template/multitenancy/index.js +14 -16
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/template/nodejs/index.js +5 -8
- package/lib/init/template/redis-messaging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/redis-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/redis-messaging/index.js +4 -5
- package/lib/init/template/sample/files/app/_i18n/i18n.properties +43 -0
- package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +14 -0
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +114 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +8 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +11 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +129 -0
- package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +57 -0
- package/lib/init/template/sample/files/app/common.cds +263 -0
- package/lib/init/template/sample/files/app/index.html +30 -0
- package/lib/init/template/sample/files/app/services.cds +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +6 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books_texts.csv +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +16 -0
- package/lib/init/template/sample/files/db/schema.cds +31 -0
- package/lib/init/template/sample/files/nodejs/admin-service.js +12 -0
- package/lib/init/template/sample/files/nodejs/cat-service.js +26 -0
- package/lib/init/template/sample/files/srv/admin-service.cds +5 -0
- package/lib/init/template/sample/files/srv/cat-service.cds +16 -0
- package/lib/init/template/sample/index.js +24 -0
- package/lib/init/template/sample-tiny/index.js +39 -0
- package/lib/init/template/samples/index.js +5 -56
- package/lib/init/template/sqlite/files/package.json.hbs +13 -13
- package/lib/init/template/sqlite/index.js +2 -2
- package/lib/init/template/templateBase.js +24 -1
- package/lib/init/template/toggles/files/package.json.hbs +10 -10
- package/lib/init/template/toggles/index.js +3 -3
- package/lib/init/template/typer/files/gitignore +1 -0
- package/lib/init/template/typer/files/package.json +8 -0
- package/lib/init/template/typer/files/xsconfig.json +9 -0
- package/lib/init/template/typer/index.js +36 -0
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +12 -12
- package/lib/init/template/xsuaa/files/package.json.hbs +13 -13
- package/lib/init/template/xsuaa/files/values.yaml.hbs +8 -8
- package/lib/init/template/xsuaa/index.js +8 -19
- package/lib/init/util/merge.js +73 -59
- package/lib/init/util/mvn.js +21 -17
- package/lib/init/util/projectReader.js +49 -87
- package/lib/init/util/xml.js +14 -23
- package/lib/util/cfUtil.js +366 -0
- package/lib/util/command.js +3 -3
- package/lib/util/gitUtil.js +55 -0
- package/lib/util/version.js +27 -0
- package/npm-shrinkwrap.json +337 -275
- package/package.json +6 -6
- package/CHANGELOG.md +0 -1460
- package/bin/build/all.js +0 -88
- package/bin/build/index.js +0 -82
- package/lib/compile/index.js +0 -14
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data/my.bookshop-Books.csv +0 -0
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data-model.cds +0 -0
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/srv/cat-service.cds.hbs +0 -0
package/bin/version.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
const { join, resolve } = require ('path')
|
|
3
|
+
const { execSync } = require('child_process')
|
|
4
|
+
module.exports = Object.assign(list_versions, {
|
|
5
|
+
flags: [ '--info', '--markdown', '--all', '--npm-list', '--npm-tree', '--no-colors'],
|
|
6
|
+
shortcuts: [ '-i', '-m','-a', '-ls', '-ll' ],
|
|
7
|
+
info,
|
|
8
|
+
help: `
|
|
9
|
+
# SYNOPSIS
|
|
10
|
+
|
|
11
|
+
*cds version* <options>
|
|
12
|
+
*cds -v* <option>
|
|
13
|
+
|
|
14
|
+
Prints the versions of all @sap/cds packages in your package dependencies.
|
|
15
|
+
|
|
16
|
+
# OPTIONS
|
|
17
|
+
|
|
18
|
+
*-i | --info*
|
|
19
|
+
|
|
20
|
+
Prints version information in a tabular markdown format, which you
|
|
21
|
+
can embed into your bug reports.
|
|
22
|
+
|
|
23
|
+
*-a | --all*
|
|
24
|
+
|
|
25
|
+
Also lists sub-packages and optional dependencies.
|
|
26
|
+
|
|
27
|
+
*-ls | --npm-list* <pattern>
|
|
28
|
+
*-ll | --npm-tree* <pattern>
|
|
29
|
+
|
|
30
|
+
Prints an npm ls tree filtered to the specified pattern.
|
|
31
|
+
(default: '@sap/cds')
|
|
32
|
+
|
|
33
|
+
`})
|
|
34
|
+
|
|
35
|
+
const MISSING = '-- missing --'
|
|
36
|
+
|
|
37
|
+
function list_versions(args, options) { //NOSONAR
|
|
38
|
+
if (options['npm-list'] || options['npm-tree']) {
|
|
39
|
+
let [pattern] = args, re = pattern ? RegExp(pattern) : /@sap\/cd[rs]|@sap\/eslint-plugin-cds/
|
|
40
|
+
let cmd = 'npm ls --depth ' + (options['npm-tree'] ? 11 : 0)
|
|
41
|
+
console.log (cmd,'| grep', pattern)
|
|
42
|
+
return require('child_process').exec(cmd, (e,stdout)=>{
|
|
43
|
+
// if (e) console.error(e)
|
|
44
|
+
const replacement = (options['no-colors'] ? '$1 $2$3$4' : '\x1b[91m$1 \x1b[32m$2\x1b[0m\x1b[2m$3\x1b[32m$4\x1b[0m');
|
|
45
|
+
for (let line of stdout.split(/\n/)) if (line.match(re)) console.log(
|
|
46
|
+
line.replace(/(@sap[^@]*)@([\S]+)( -> [\S]+)?(deduped)?/,replacement)
|
|
47
|
+
)
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
const versions = info ()
|
|
51
|
+
if (options.markdown) return _markdown (versions)
|
|
52
|
+
if (options.info) return _markdown (versions)
|
|
53
|
+
const mark = options['no-colors'] ? s => s : require('../lib/util/term').info
|
|
54
|
+
for (let each of Object.keys(versions).sort()) console.log(`${mark(each)}: ${versions[each]}`)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function info() {
|
|
58
|
+
const cwd = process.cwd()
|
|
59
|
+
const npmRoot = execSync('npm root -g').toString().trim()
|
|
60
|
+
return {
|
|
61
|
+
..._versions_from(_pkg_path('@sap/cds-dk', __dirname), '@sap/cds-dk (global)'), // ... linked in cap/dev setup
|
|
62
|
+
..._versions_from(_pkg_path('@sap/cds-dk', npmRoot), '@sap/cds-dk (global)'), // ... or installed globally
|
|
63
|
+
..._versions_from(_pkg_path('@sap/cds-dk', cwd)), // local dk, important for Java projects
|
|
64
|
+
..._versions_from(_pkg_path('@sap/cds', __dirname)), // @sap/cds from here
|
|
65
|
+
..._versions_from(cwd), // ... or from local app dependencies
|
|
66
|
+
..._versions_from(_pkg_path('@sap/cds-compiler', cwd, __dirname)), // compiler is no direct dependency, so list it explicitly
|
|
67
|
+
'Node.js': process.version,
|
|
68
|
+
'home': require('../lib/cds').home // effective (local) cds
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function _versions_from(pkg_path, pkg_label) {
|
|
73
|
+
let pkg; try { pkg = require(join(pkg_path, 'package.json')) } catch { return {} }
|
|
74
|
+
let versions = {}
|
|
75
|
+
if (pkg.name) versions[pkg_label || pkg.name] = pkg.version
|
|
76
|
+
|
|
77
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
78
|
+
for (let dep in deps) {
|
|
79
|
+
if (!dep.match(/@sap\/.*cds.*/) && !dep.startsWith('@cap-js/')) continue
|
|
80
|
+
try {
|
|
81
|
+
const dep_path = require.resolve(join(dep, 'package.json'), {paths:[pkg_path]})
|
|
82
|
+
const dep_pkg = require(dep_path)
|
|
83
|
+
versions[dep_pkg.name] = dep_pkg.version
|
|
84
|
+
} catch (e) {
|
|
85
|
+
if (e.code !== 'MODULE_NOT_FOUND') console.error(e)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return versions
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function _markdown (versions) {
|
|
92
|
+
console.log()
|
|
93
|
+
const pkg = { name:'', repository:'', version:'' }; try {
|
|
94
|
+
Object.assign (pkg, require (resolve('package.json')))
|
|
95
|
+
} catch (e) {/* ignored */}
|
|
96
|
+
console.log ('|', pkg.name, '|', pkg.repository.url || pkg.repository, '|')
|
|
97
|
+
console.log ('|:---------------------- | ----------- |')
|
|
98
|
+
if (require('../lib').env['project-nature'] === 'nodejs') {
|
|
99
|
+
console.log ('|', v('Node.js'), '|')
|
|
100
|
+
console.log ('|', v('@sap/cds'), '|')
|
|
101
|
+
} else {
|
|
102
|
+
console.log ('|', v('CAP Java Runtime'), '|')
|
|
103
|
+
}
|
|
104
|
+
console.log ('|', v('@sap/cds-compiler'), '|')
|
|
105
|
+
console.log ('|', v('@sap/cds-dk'), '|')
|
|
106
|
+
console.log ('|', v('@sap/cds-dk (global)'), '|')
|
|
107
|
+
console.log ('|', v('@sap/eslint-plugin-cds'), '|')
|
|
108
|
+
console.log ('|', v('@sap/cds-mtxs'), '|')
|
|
109
|
+
function v (component) {
|
|
110
|
+
const version = versions [component] || MISSING
|
|
111
|
+
return (component + ' ').slice(0,22)
|
|
112
|
+
+' | '+ (version + ' ').slice(0,11)
|
|
113
|
+
}
|
|
114
|
+
console.log()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function _pkg_path(id, ...paths) {
|
|
118
|
+
try {
|
|
119
|
+
const pk_path = require.resolve(join(id, 'package.json'), { paths })
|
|
120
|
+
return resolve(pk_path, '..')
|
|
121
|
+
} catch (e) {
|
|
122
|
+
if (e.code !== 'MODULE_NOT_FOUND') throw e
|
|
123
|
+
}
|
|
124
|
+
}
|
package/bin/watch.js
CHANGED
|
@@ -125,7 +125,7 @@ async function watch ([cwd], {
|
|
|
125
125
|
|
|
126
126
|
const nodemon = require('../lib/watch/node-watch')
|
|
127
127
|
const watcher = nodemon ({
|
|
128
|
-
script:
|
|
128
|
+
script: resolve(__dirname,'watched'), cwd, env, ext, includes, ignore,
|
|
129
129
|
delay: parseInt(process.env.CDS_WATCH_DELAY) || 200,
|
|
130
130
|
options
|
|
131
131
|
}).on('restart', (files)=>{
|
|
@@ -193,37 +193,3 @@ function paths (dir) {
|
|
|
193
193
|
const parts = resolve(dir).split(sep), n = parts.length, nm = sep+'node_modules'
|
|
194
194
|
return parts.map ((_,i,a)=> a.slice(0,n-i).join(sep)+nm).filter(p => fs.existsSync(p))
|
|
195
195
|
}
|
|
196
|
-
|
|
197
|
-
//
|
|
198
|
-
// Child process impl launched by watch
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
if (!module.parent) (async()=>{ // launched by nodemon
|
|
202
|
-
// run through cli in order to use its error handling
|
|
203
|
-
const bootstrap = require('./cds')(...JSON.parse(process.env._args))
|
|
204
|
-
const {cds} = global; cds.watched = true
|
|
205
|
-
|
|
206
|
-
cds.once('listening', ({server}) => {
|
|
207
|
-
process.send ({ code:'listening', port: server.address().port })
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
await bootstrap
|
|
212
|
-
if (!cds.service.providers.length) return _no_services_found()
|
|
213
|
-
} catch (e) { switch (e.code) {
|
|
214
|
-
case 'NO_SERVICES_FOUND': return _no_services_found(e)
|
|
215
|
-
case 'MODEL_NOT_FOUND': return _no_models_found(e)
|
|
216
|
-
case 'EADDRINUSE': return process.send(e) //> tell cds watch
|
|
217
|
-
default: if (!e.messages) { // compiler messages have been written by cli already
|
|
218
|
-
console.error('\n❗️ ERROR on server start: ❗️\n\n', e)
|
|
219
|
-
}
|
|
220
|
-
}}
|
|
221
|
-
function _no_models_found(e) { console.log (`
|
|
222
|
-
No models found in ${cds.resolve(e.model||'*',false)}.
|
|
223
|
-
Waiting for some to arrive...
|
|
224
|
-
`)}
|
|
225
|
-
function _no_services_found() { console.log (`
|
|
226
|
-
No service definitions found in loaded models.
|
|
227
|
-
Waiting for some to arrive...
|
|
228
|
-
`)}
|
|
229
|
-
})()
|
package/bin/watched.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Child process impl launched by cds watch
|
|
3
|
+
// Extracted from watch.js to avoid cds.env loaded too eagerly
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
(async()=>{
|
|
7
|
+
|
|
8
|
+
// run through cli in order to use its error handling
|
|
9
|
+
const args = JSON.parse(process.env._args)
|
|
10
|
+
const bootstrap = require('./cds')(...args)
|
|
11
|
+
const {cds} = global; cds.watched = true
|
|
12
|
+
|
|
13
|
+
cds.once('listening', ({server}) => {
|
|
14
|
+
process.send ({ code:'listening', port: server.address().port })
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
await bootstrap
|
|
19
|
+
if (!cds.service.providers.length) return _no_services_found()
|
|
20
|
+
} catch (e) { switch (e.code) {
|
|
21
|
+
case 'NO_SERVICES_FOUND': return _no_services_found(e)
|
|
22
|
+
case 'MODEL_NOT_FOUND': return _no_models_found(e)
|
|
23
|
+
case 'EADDRINUSE': return process.send(e) //> tell cds watch
|
|
24
|
+
default: if (!e.messages) { // compiler messages have been written by cli already
|
|
25
|
+
console.error('\n❗️ ERROR on server start: ❗️\n\n', e)
|
|
26
|
+
}
|
|
27
|
+
}}
|
|
28
|
+
|
|
29
|
+
function _no_models_found(e) { console.log (`
|
|
30
|
+
No models found in ${cds.resolve(e.model||'*',false)}.
|
|
31
|
+
Waiting for some to arrive...
|
|
32
|
+
`)}
|
|
33
|
+
|
|
34
|
+
function _no_services_found() { console.log (`
|
|
35
|
+
No service definitions found in loaded models.
|
|
36
|
+
Waiting for some to arrive...
|
|
37
|
+
`)}
|
|
38
|
+
|
|
39
|
+
})()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const yaml = require(
|
|
1
|
+
const yaml = require('@sap/cds-foss')('yaml');
|
|
2
2
|
const { exec } = require('../util/exec');
|
|
3
3
|
|
|
4
4
|
class KubernetesApiAccessor {
|
|
@@ -9,7 +9,7 @@ class KubernetesApiAccessor {
|
|
|
9
9
|
const configString = await exec({result: 'stdout'}) `kubectl config view --raw`;
|
|
10
10
|
const config = yaml.parse(configString);
|
|
11
11
|
|
|
12
|
-
const currentContextName = config[
|
|
12
|
+
const currentContextName = config['current-context'];
|
|
13
13
|
if (!currentContextName) throw new Error(`No current context in kubectl config.`);
|
|
14
14
|
const currentContextEntry = config.contexts && config.contexts.find( entry => entry.name === currentContextName && entry.context && entry.context.cluster && entry.context.user );
|
|
15
15
|
if (!currentContextEntry) throw new Error(`Current context not found in kubectl config.`);
|
package/lib/bind/bindingUtil.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const os = require('os');
|
|
2
|
-
const IS_WIN = os.platform() === 'win32';
|
|
3
1
|
|
|
4
2
|
const KindToRequiresNameMap = {
|
|
5
3
|
xsuaa: 'auth',
|
|
@@ -89,13 +87,6 @@ class BindingUtil {
|
|
|
89
87
|
}
|
|
90
88
|
}
|
|
91
89
|
|
|
92
|
-
static execAndExit(options, command, ...args) {
|
|
93
|
-
const { spawnSync } = require('child_process');
|
|
94
|
-
// use shell with Windows only; without output is not visible and some commands cannot be run
|
|
95
|
-
const result = spawnSync(command, args, { stdio: 'inherit', shell: IS_WIN, ...options });
|
|
96
|
-
process.exit(result.status);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
90
|
static async checkIsJavaProject(projectPath) {
|
|
100
91
|
const { constants, promises: fsp } = require('fs');
|
|
101
92
|
const path = require('path');
|
|
@@ -1,89 +1,32 @@
|
|
|
1
|
-
const cp = require('child_process');
|
|
2
|
-
const fsp = require('fs').promises;
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const util = require('util');
|
|
5
|
-
|
|
6
1
|
const cds = require('../cds');
|
|
7
2
|
const DEBUG = cds.debug('cli')
|
|
8
3
|
|
|
4
|
+
const cfUtil = require('../util/cfUtil');
|
|
5
|
+
|
|
9
6
|
const axios = require('axios');
|
|
10
7
|
const { URL } = require('url');
|
|
11
|
-
const path = require('path');
|
|
12
8
|
const { bold, highlight } = require('../util/term');
|
|
13
9
|
const { CliError } = require('../client/helper/errors');
|
|
14
10
|
|
|
15
|
-
const execAsync = util.promisify(cp.exec);
|
|
16
|
-
const IS_WIN = os.platform() === 'win32';
|
|
17
|
-
|
|
18
11
|
class CFKeyProvider {
|
|
19
|
-
async _cfRead(...args) {
|
|
20
|
-
DEBUG?.(`_cfRead: cf ${args}`);
|
|
21
|
-
|
|
22
|
-
const result = await execAsync(`cf ${args}`, {
|
|
23
|
-
shell: IS_WIN,
|
|
24
|
-
stdio: ['inherit', 'pipe', 'inherit'],
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return result.stdout.toString().trim();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
extract(string, pattern, errorMsg) {
|
|
31
|
-
const match = string.match(pattern);
|
|
32
|
-
if (!match || !match[1]) {
|
|
33
|
-
throw new Error(errorMsg);
|
|
34
|
-
}
|
|
35
|
-
return match[1];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async getCfTargetFromConfigFile() {
|
|
39
|
-
const cfHome = process.env.CF_HOME || process.env.cf_home || path.join(os.homedir(), '.cf');
|
|
40
|
-
try {
|
|
41
|
-
const fileContent = await fsp.readFile(path.join(cfHome, 'config.json'));
|
|
42
|
-
const config = JSON.parse(fileContent);
|
|
43
|
-
if (config) {
|
|
44
|
-
return {
|
|
45
|
-
apiEndpoint: this.extract(config.Target, /\s*(.+)\s*/, `CF API endpoint is missing. Use 'cf login' to login.`),
|
|
46
|
-
org: this.extract(config.OrganizationFields.Name, /\s*(.+)\s*/, `CF org is missing. Use 'cf target -o <ORG> to specify.`),
|
|
47
|
-
space: this.extract(config.SpaceFields.Name, /\s*(.+)\s*/, `CF space is missing. Use 'cf target -s <SPACE>' to specify.`)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
} catch (err) {
|
|
51
|
-
DEBUG?.(`getCfTargetFromConfigFile: ${err}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async getCfTargetFromCli() {
|
|
56
|
-
const result = await this._cfRead('target');
|
|
57
|
-
return {
|
|
58
|
-
apiEndpoint: this.extract(result, /api endpoint\s*:\s*([^\s]+)/i, `CF API endpoint is missing. Use 'cf login' to login.`),
|
|
59
|
-
user: this.extract(result, /user\s*:\s*(.+)/i, `CF user is missing. Use 'cf login' to login.`),
|
|
60
|
-
org: this.extract(result, /org\s*:\s*(.+)/i, `CF org is missing. Use 'cf target -o <ORG> to specify.`),
|
|
61
|
-
space: this.extract(result, /space\s*:\s*(.+)/i, `CF space is missing. Use 'cf target -s <SPACE>' to specify.`),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async getCfTarget() {
|
|
66
|
-
return await this.getCfTargetFromConfigFile() || await this.getCfTargetFromCli();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
12
|
async getCfSpaceInfo() {
|
|
70
13
|
DEBUG?.('getting space info');
|
|
71
14
|
|
|
72
|
-
const target = await
|
|
73
|
-
const authorization = await
|
|
15
|
+
const target = await cfUtil.getCfTarget();
|
|
16
|
+
const authorization = await cfUtil.getCfAuthorization();
|
|
74
17
|
const targetWithAuth = Object.assign({}, target, { authorization });
|
|
75
18
|
|
|
76
19
|
|
|
77
20
|
const { org, space } = target;
|
|
78
21
|
const orgs = await BatchRequest.req(targetWithAuth, `/v3/organizations?names=${encodeURIComponent(encodeURIComponent(org))}`);
|
|
79
22
|
if (!(orgs && orgs.resources.length === 1)) {
|
|
80
|
-
throw new
|
|
23
|
+
throw new CliError(`CF org ${org} not found!`);
|
|
81
24
|
}
|
|
82
25
|
|
|
83
26
|
const orgGuid = orgs.resources[0].guid;
|
|
84
27
|
const spaces = await BatchRequest.req(targetWithAuth, `/v3/spaces?names=${encodeURIComponent(encodeURIComponent(space))}&organization_guids=${encodeURIComponent(encodeURIComponent(orgGuid))}`)
|
|
85
28
|
if (!(spaces && spaces.resources.length === 1)) {
|
|
86
|
-
throw new
|
|
29
|
+
throw new CliError(`CF space ${space} not found in org ${org}!`);
|
|
87
30
|
}
|
|
88
31
|
|
|
89
32
|
const spaceGuid = spaces.resources[0].guid;
|
|
@@ -91,11 +34,6 @@ class CFKeyProvider {
|
|
|
91
34
|
return Object.assign({}, target, { orgGuid, spaceGuid, authorization });
|
|
92
35
|
}
|
|
93
36
|
|
|
94
|
-
async getCfAuthorization() {
|
|
95
|
-
DEBUG?.('getting authorization');
|
|
96
|
-
return this._cfRead('oauth-token');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
37
|
async init() {
|
|
100
38
|
const target = this.target = await this.getCfSpaceInfo();
|
|
101
39
|
this.getOrg = BatchRequest.create({ target, url: '/v3/organizations' });
|
|
@@ -142,7 +80,7 @@ class CFKeyProvider {
|
|
|
142
80
|
try {
|
|
143
81
|
instanceObj = await this.getInstance({ names: instance, space_guids: spaceGuid });
|
|
144
82
|
} catch (error) {
|
|
145
|
-
throw new
|
|
83
|
+
throw new CliError(`Service instance "${instance}" not found.`);
|
|
146
84
|
}
|
|
147
85
|
switch (instanceObj.type) {
|
|
148
86
|
case 'managed':
|
|
@@ -150,7 +88,7 @@ class CFKeyProvider {
|
|
|
150
88
|
case 'user-provided':
|
|
151
89
|
return this._resolveUserProvidedService(instanceObj, instance, org, space);
|
|
152
90
|
default:
|
|
153
|
-
throw new
|
|
91
|
+
throw new CliError(`Service type ${instanceObj.type} not supported`)
|
|
154
92
|
}
|
|
155
93
|
}
|
|
156
94
|
|
|
@@ -285,9 +223,9 @@ class BatchRequest {
|
|
|
285
223
|
if (filteredResources.length === 1) {
|
|
286
224
|
filter.resolve(filteredResources[0]);
|
|
287
225
|
} else if (filteredResources.length === 0) {
|
|
288
|
-
filter.reject(new
|
|
226
|
+
filter.reject(new CliError(`Couldn't find resource for url "${this.url}" with filter "${fmt(filter.filter)}"`));
|
|
289
227
|
} else {
|
|
290
|
-
filter.reject(new
|
|
228
|
+
filter.reject(new CliError(`Found more than one resources for url "${this.url}" with filter "${fmt(filter.filter)}"`));
|
|
291
229
|
}
|
|
292
230
|
}
|
|
293
231
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const cds = require('../cds');
|
|
2
|
+
|
|
3
|
+
const { CliError } = require('../client/helper/errors');
|
|
4
|
+
|
|
5
|
+
const BindingResolver = require('./bindingResolver');
|
|
6
|
+
const { determineKinds, getRequiresNameFromKind, checkIsJavaProject, platformText, bindingText, logger } = require('./bindingUtil');
|
|
7
|
+
const { highlight, bold, info } = require('../util/term');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module.exports = { bind, parseProfile }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Executes cds build in the directory defined by cds.root.
|
|
14
|
+
*
|
|
15
|
+
* @param {object} options - command options as defined by build command.
|
|
16
|
+
*/
|
|
17
|
+
async function bind(options) {
|
|
18
|
+
let on;
|
|
19
|
+
switch(options.on) {
|
|
20
|
+
case 'k8s':
|
|
21
|
+
case 'kubernetes':
|
|
22
|
+
on = 'k8s';
|
|
23
|
+
break;
|
|
24
|
+
case undefined:
|
|
25
|
+
case null:
|
|
26
|
+
case 'cf':
|
|
27
|
+
case 'cloudfoundry':
|
|
28
|
+
on = 'cf';
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
throw new CliError(`Invalid value '${options.on}' for option --on.`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const onText = { 'cf': 'Cloud Foundry', 'k8s': 'Kubernetes' }[on];
|
|
35
|
+
logger.log(`Retrieving data from ${onText}...`);
|
|
36
|
+
let resolvedServices
|
|
37
|
+
|
|
38
|
+
const targets = options.to.split(/,/g);
|
|
39
|
+
try {
|
|
40
|
+
resolvedServices = await Promise.all(targets.map(async target => {
|
|
41
|
+
let binding;
|
|
42
|
+
if (on === 'k8s') {
|
|
43
|
+
binding = { type: on, name: target };
|
|
44
|
+
} else if (on === 'cf') {
|
|
45
|
+
const [instance, key] = target.split(/:/);
|
|
46
|
+
binding = { type: on, instance, key };
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error('Internal Error');
|
|
49
|
+
}
|
|
50
|
+
const resolvedService = await BindingResolver.resolveBinding(undefined, binding);
|
|
51
|
+
resolvedService._target = target;
|
|
52
|
+
delete resolvedService.credentials;
|
|
53
|
+
resolvedService.binding.resolved = false;
|
|
54
|
+
return resolvedService;
|
|
55
|
+
}));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error.name === 'AxiosError') {
|
|
58
|
+
const errors = error.response?.data?.errors ?? []
|
|
59
|
+
const responseInfo = errors.map(e => `${e.title}: ${e.detail} (${e.code})`).join(' \n')
|
|
60
|
+
const requestInfo = error.request?.path
|
|
61
|
+
throw new Error(`${error.toString()}\nResponse: ${responseInfo}\nRequest:${requestInfo}}`)
|
|
62
|
+
}
|
|
63
|
+
throw error
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (options.kind) {
|
|
67
|
+
resolvedServices.forEach(service => service.kind = options.kind);
|
|
68
|
+
} else {
|
|
69
|
+
determineKinds(resolvedServices);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const resolvedService of resolvedServices) {
|
|
73
|
+
if (options.serviceArg) {
|
|
74
|
+
resolvedService.name = options.serviceArg;
|
|
75
|
+
} else if (resolvedService.kind) {
|
|
76
|
+
resolvedService.name = getRequiresNameFromKind(resolvedService.binding.instance, resolvedService.kind);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let { kind, name, binding } = resolvedService;
|
|
80
|
+
name = name ?? `custom-service:${binding.instance || binding.secret}`
|
|
81
|
+
resolvedService.name = resolvedService.name ?? name
|
|
82
|
+
const kindText = kind ? ` with kind ${highlight(kind)}` : ''
|
|
83
|
+
const nameText = highlight(name)
|
|
84
|
+
|
|
85
|
+
logger.log(`Binding ${nameText} to ${platformText(binding)} ${bindingText(binding, highlight)}${kindText}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// prepare for different providers
|
|
89
|
+
const userCdsrcJsonStorageProvider = require('./userCdsrcJsonStorageProvider');
|
|
90
|
+
|
|
91
|
+
await userCdsrcJsonStorageProvider.storeServices(resolvedServices, {
|
|
92
|
+
...options
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const isJavaProject = await checkIsJavaProject(cds.root);
|
|
96
|
+
logger.log(`${info('TIP:')} Run with cloud bindings: ${bold(runCmd(options.for, isJavaProject))}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function runCmd(profile, isJavaProject) {
|
|
100
|
+
profile = parseProfile(profile);
|
|
101
|
+
if (isJavaProject) {
|
|
102
|
+
const p = profile === 'hybrid' ? '' : ` --profile ${profile}`;
|
|
103
|
+
return `cds bind exec${p} mvn spring-boot:run`;
|
|
104
|
+
} else {
|
|
105
|
+
const p = profile === 'development' ? '' : ` --profile ${profile}`;
|
|
106
|
+
return `cds watch${p}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function parseProfile(profile) {
|
|
111
|
+
if (!profile) return 'hybrid';
|
|
112
|
+
else if (profile === '-') return 'development';
|
|
113
|
+
else return profile;
|
|
114
|
+
}
|
|
@@ -44,7 +44,7 @@ class KubernetesCredentialsProvider {
|
|
|
44
44
|
|
|
45
45
|
const resolvedBinding = {
|
|
46
46
|
binding: {
|
|
47
|
-
type:
|
|
47
|
+
type: 'k8s',
|
|
48
48
|
name: bindingName,
|
|
49
49
|
cluster,
|
|
50
50
|
instance,
|
|
@@ -63,7 +63,7 @@ class KubernetesCredentialsProvider {
|
|
|
63
63
|
const { data } = secret;
|
|
64
64
|
const properties = {};
|
|
65
65
|
for (const name in data) {
|
|
66
|
-
const value = Buffer.from(data[name],
|
|
66
|
+
const value = Buffer.from(data[name], 'base64').toString()
|
|
67
67
|
properties[name] = value;
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -2,17 +2,13 @@ const os = require('os');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const readline = require('readline');
|
|
4
4
|
|
|
5
|
-
const cds = require('../cds');
|
|
6
|
-
const DEBUG = cds.debug('cli');
|
|
7
|
-
|
|
8
5
|
const fs = require('fs').promises;
|
|
9
6
|
const { highlight } = require('../util/term');
|
|
10
7
|
const { logger } = require('./bindingUtil');
|
|
11
8
|
|
|
12
|
-
const
|
|
9
|
+
const gitUtil = require('../util/gitUtil');
|
|
13
10
|
|
|
14
11
|
const CDSRC_FILENAME = '.cdsrc-private.json';
|
|
15
|
-
const GIT_IGNORE_FILE = '.gitignore';
|
|
16
12
|
|
|
17
13
|
class UserCdsrcJsonStorageProvider {
|
|
18
14
|
async askBooleanQuestion(question) {
|
|
@@ -34,44 +30,11 @@ class UserCdsrcJsonStorageProvider {
|
|
|
34
30
|
});
|
|
35
31
|
}
|
|
36
32
|
|
|
37
|
-
async ensureFileIsGitignored(file) {
|
|
38
|
-
try {
|
|
39
|
-
await commandUtil.spawnCommand('git', ['check-ignore', '-n', '-v', file], {}, undefined, true);
|
|
40
|
-
return; // file is git ignored
|
|
41
|
-
} catch (err) {
|
|
42
|
-
if (err.code === 'ENOENT') { // git command not found
|
|
43
|
-
DEBUG?.('git command not found');
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!err.stdLog.match(/::/)) { // included or not a git repo
|
|
48
|
-
DEBUG?.(err);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
logger.log(`adding entry '${file}' to ${GIT_IGNORE_FILE}.`);
|
|
54
|
-
let gitignore = await this.readFileSafely(GIT_IGNORE_FILE);
|
|
55
|
-
gitignore = gitignore + `
|
|
56
|
-
# added by cds bind
|
|
57
|
-
${file}
|
|
58
|
-
`;
|
|
59
|
-
await fs.writeFile(GIT_IGNORE_FILE, gitignore, 'utf8');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async readFileSafely(file) {
|
|
63
|
-
try {
|
|
64
|
-
return await fs.readFile(file, 'utf8');
|
|
65
|
-
} catch (err) {
|
|
66
|
-
return '';
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
33
|
async storeServices(services, options = {}) {
|
|
71
|
-
let jsonPath = options
|
|
34
|
+
let jsonPath = options.outputFile || CDSRC_FILENAME;
|
|
72
35
|
|
|
73
36
|
if (jsonPath === CDSRC_FILENAME) {
|
|
74
|
-
await
|
|
37
|
+
await gitUtil.ensureFileIsGitignored(CDSRC_FILENAME);
|
|
75
38
|
}
|
|
76
39
|
|
|
77
40
|
jsonPath = jsonPath.replace(/~/g, os.homedir());
|
|
@@ -89,13 +52,13 @@ ${file}
|
|
|
89
52
|
cdsRoot = jsonObject;
|
|
90
53
|
}
|
|
91
54
|
|
|
92
|
-
const profileKey = `[${options.
|
|
55
|
+
const profileKey = `[${options.for}]`;
|
|
93
56
|
const features = cdsRoot.features && cdsRoot.features[profileKey];
|
|
94
57
|
if (features) delete features.emulate_vcap_services;
|
|
95
58
|
|
|
96
59
|
cdsRoot.requires = cdsRoot.requires || {};
|
|
97
60
|
let section;
|
|
98
|
-
if (options.
|
|
61
|
+
if (options.for) {
|
|
99
62
|
section = cdsRoot.requires[profileKey] = cdsRoot.requires[profileKey] || {};
|
|
100
63
|
} else {
|
|
101
64
|
section = cdsRoot.requires;
|
|
@@ -109,8 +72,8 @@ ${file}
|
|
|
109
72
|
}
|
|
110
73
|
|
|
111
74
|
await this.writeJsonFile(jsonPath, jsonObject);
|
|
112
|
-
if (options.
|
|
113
|
-
logger.log(`Saving bindings to ${highlight(jsonPath)} in profile ${highlight(options.
|
|
75
|
+
if (options.for) {
|
|
76
|
+
logger.log(`Saving bindings to ${highlight(jsonPath)} in profile ${highlight(options.for)}`);
|
|
114
77
|
} else {
|
|
115
78
|
logger.log(`Saving bindings to ${highlight(jsonPath)}`);
|
|
116
79
|
}
|