@sap/cds-dk 6.1.4 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- package/bin/build/all.js +5 -5
- package/bin/cds.js +7 -5
- package/bin/deploy/index.js +3 -2
- package/bin/deploy/to-sqlite.js +4 -3
- package/bin/help.js +4 -0
- package/bin/init.js +2 -1
- package/bin/login.js +23 -9
- package/bin/mock.js +1 -0
- package/bin/pull.js +24 -19
- package/bin/push.js +20 -9
- package/bin/subscribe.js +40 -10
- package/bin/watch.js +15 -10
- package/lib/bind/kubernetesCredentialsProvider.js +1 -0
- package/lib/client/activate.js +42 -51
- package/lib/client/auth_manager.js +7 -8
- package/lib/client/base_command.js +5 -2
- package/lib/client/extend.js +33 -38
- package/lib/client/helper/cf_helper.js +11 -11
- package/lib/client/helper/dependency_helper.js +2 -2
- package/lib/client/helper/errors.js +4 -3
- package/lib/client/helper/logging.js +17 -23
- package/lib/client/params.js +5 -5
- package/lib/client/pull.js +19 -21
- package/lib/client/push.js +16 -15
- package/lib/client/settings_manager.js +54 -55
- package/lib/compile/openapi/csdl2openapi.js +18 -12
- package/lib/import/message.js +1 -1
- package/lib/import/odata/metadataconverter/MetadataConverter.js +23 -17
- package/lib/import/odata/v2parser.js +43 -17
- package/lib/import/odata/v4parser.js +77 -22
- package/lib/init/constants.js +5 -2
- package/lib/init/index.js +16 -4
- package/lib/init/template/_merging/registry-mta.js +13 -0
- package/lib/init/template/approuter/index.js +9 -0
- package/lib/{k8s/connectivity/templates/connectivity.yaml → init/template/auditlog/files/auditlog.yaml} +0 -0
- package/lib/init/template/auditlog/index.js +46 -27
- package/lib/{k8s/connectivity/templates → init/template/connectivity/files}/connectivity-binding.yaml +0 -0
- package/lib/{k8s/connectivity/templates → init/template/connectivity/files}/connectivity-proxy-info.yaml +1 -1
- package/lib/init/template/connectivity/files/connectivity.yaml +1 -0
- package/lib/init/template/connectivity/files/values.yaml.hbs +26 -0
- package/lib/init/template/connectivity/index.js +41 -0
- package/lib/init/template/data/index.js +8 -8
- package/lib/init/template/destinations/files/destination.yaml +1 -0
- package/lib/init/template/destinations/index.js +44 -0
- package/lib/init/template/enterprise-messaging/files/cds.package.json +10 -0
- package/lib/init/template/enterprise-messaging/files/cds.profile.package.json.hbs +12 -0
- package/lib/init/template/enterprise-messaging/files/cdsrc.json +8 -0
- package/lib/init/template/enterprise-messaging/files/cdsrc.json.hbs +10 -0
- package/lib/init/template/enterprise-messaging/files/event-mesh.yaml +1 -0
- package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +13 -0
- package/lib/init/template/enterprise-messaging/files/values.yaml +8 -0
- package/lib/init/template/enterprise-messaging/index.js +56 -0
- package/lib/init/template/extensibility/files/cdsrc.json +5 -0
- package/lib/init/template/extensibility/files/cdsrc.json.hbs +7 -0
- package/lib/init/template/extensibility/index.js +18 -13
- package/lib/{k8s/hana-deployer/templates → init/template/hana/files}/hana-deployer-job.yaml +0 -0
- package/lib/init/template/hana/files/java/{cdsrc.json.hbs → cds.json.hbs} +0 -0
- package/lib/init/template/hana/files/java/{profile.cdsrc.json.hbs → cds.profile.json.hbs} +0 -0
- package/lib/init/template/hana/files/java/cds.shortcut.json.hbs +5 -0
- package/lib/init/template/hana/files/java/cds.shortcut.profile.json.hbs +8 -0
- package/lib/init/template/hana/files/java/db/package.json +2 -1
- package/lib/init/template/hana/files/mta.yaml.hbs +6 -0
- package/lib/init/template/hana/files/nodejs/{cds.package.json.hbs → cds.json.hbs} +0 -0
- package/lib/init/template/hana/files/nodejs/{cds.profile.package.json.hbs → cds.profile.json.hbs} +0 -0
- package/lib/init/template/hana/files/nodejs/cds.shortcut.json.hbs +7 -0
- package/lib/init/template/hana/files/nodejs/cds.shortcut.profile.json.hbs +10 -0
- package/lib/init/template/hana/files/values.yaml.hbs +19 -0
- package/lib/init/template/hana/index.js +29 -29
- package/lib/{k8s → init/template/helm}/Model.d.ts +0 -0
- package/lib/{k8s/resources → init/template}/helm/chart/templates/NOTES.txt +0 -0
- package/lib/{k8s/resources → init/template}/helm/chart/templates/_deployment_helpers.tpl +0 -0
- package/lib/{k8s/resources → init/template}/helm/chart/templates/_helpers.tpl +4 -5
- package/lib/{k8s/resources → init/template}/helm/chart/templates/_sapcp_helpers.tpl +0 -0
- package/lib/{k8s/resources/helm/chart/schemas → init/template/helm/chart}/values.root.schema.json +0 -0
- package/lib/{k8s/resources/helm/chart/schemas → init/template/helm/chart}/values.schema.json +0 -0
- package/lib/init/template/helm/files/Chart.yaml.hbs +13 -0
- package/lib/init/template/helm/files/values.yaml.hbs +26 -0
- package/lib/init/template/helm/index.js +74 -14
- package/lib/{k8s/deployment → init/template/helm}/subchart/Chart.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/_helpers.tpl +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/api-rule.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/deployment.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/network-policy.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/pod-disruption-budget.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/secret.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/service-binding.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/templates/service.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/values-lint.yaml +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/values.md +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/values.schema.json +0 -0
- package/lib/{k8s/deployment → init/template/helm}/subchart/values.yaml +0 -0
- package/lib/{k8s/html5-apps-deployer/templates → init/template/html5-repo/files}/_html5_deployment_helpers.tpl +0 -0
- package/lib/{k8s/html5-apps-deployer/templates → init/template/html5-repo/files}/html5-apps-deployer-job.yaml +1 -1
- package/lib/{k8s/html5-apps-repo-host/templates → init/template/html5-repo/files}/html5-apps-repo-host.yaml +0 -0
- package/lib/init/template/html5-repo/index.js +59 -0
- package/lib/init/template/kibana-logging/index.js +8 -0
- package/lib/init/template/lint/index.js +1 -4
- package/lib/init/template/mta/files/mta.yaml.hbs +3 -2
- package/lib/init/template/mta/index.js +6 -1
- package/lib/init/template/multitenancy/files/java/.cdsrc.json +3 -0
- package/lib/init/template/multitenancy/files/java/package.json +2 -6
- package/lib/{k8s/multitenancy/templates → init/template/multitenancy/files}/saas-registry.yaml +3 -3
- package/lib/init/template/multitenancy/files/xsuaa.yaml +1 -0
- package/lib/init/template/multitenancy/index.js +53 -26
- package/lib/init/template/nodejs/files/.gitignore.hbs +1 -0
- package/lib/init/template/templateBase.js +1 -1
- package/lib/init/template/xsuaa/files/values.yaml.hbs +10 -0
- package/lib/init/template/xsuaa/files/xsuaa.yaml +1 -0
- package/lib/init/template/xsuaa/index.js +34 -22
- package/lib/init/util/fsUtil.js +11 -5
- package/lib/init/util/projectReader.js +24 -32
- package/lib/init/util/templateUtil.js +17 -5
- package/lib/lint/Linter.js +9 -17
- package/lib/lint/checks.js +0 -1
- package/lib/lint/generators.js +2 -192
- package/lib/lint/io.js +1 -3
- package/lib/watch/node-watch.js +2 -2
- package/npm-shrinkwrap.json +1412 -791
- package/package.json +5 -4
- package/lib/init/template/helm/update/index.js +0 -28
- package/lib/k8s/ChartAdder.js +0 -75
- package/lib/k8s/ChartBuilder.js +0 -192
- package/lib/k8s/Context.js +0 -71
- package/lib/k8s/ImageUtil.js +0 -21
- package/lib/k8s/auditlog/index.js +0 -29
- package/lib/k8s/auditlog/templates/auditlog.yaml +0 -1
- package/lib/k8s/buildModel.js +0 -68
- package/lib/k8s/connectivity/index.js +0 -80
- package/lib/k8s/deployment/index.js +0 -79
- package/lib/k8s/deployment/subchart-override/templates/_web_application_helpers.tpl +0 -81
- package/lib/k8s/destinations/index.js +0 -40
- package/lib/k8s/destinations/lib.js +0 -16
- package/lib/k8s/destinations/templates/destinations.yaml +0 -1
- package/lib/k8s/docker/push.js +0 -8
- package/lib/k8s/event-mesh/index.js +0 -53
- package/lib/k8s/event-mesh/lib.js +0 -9
- package/lib/k8s/event-mesh/templates/event-mesh.yaml +0 -1
- package/lib/k8s/hana-deployer/index.js +0 -48
- package/lib/k8s/helm/Release.js +0 -80
- package/lib/k8s/html5-apps-deployer/index.js +0 -53
- package/lib/k8s/html5-apps-repo-host/index.js +0 -26
- package/lib/k8s/html5-apps-repo-host/lib.js +0 -16
- package/lib/k8s/index.js +0 -153
- package/lib/k8s/modules.js +0 -36
- package/lib/k8s/multitenancy/index.js +0 -24
- package/lib/k8s/multitenancy/lib.js +0 -25
- package/lib/k8s/readProject.js +0 -14
- package/lib/k8s/util.js +0 -186
- package/lib/k8s/wrapFeature.js +0 -55
- package/lib/k8s/xsuaa/index.js +0 -64
- package/lib/k8s/xsuaa/lib.js +0 -17
- package/lib/k8s/xsuaa/templates/xsuaa.yaml +0 -1
package/lib/client/activate.js
CHANGED
|
@@ -2,12 +2,13 @@ const fs = require('fs').promises;
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const axios = require('axios');
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const BaseCommand = require('./base_command');
|
|
5
|
+
const log = require('./helper/logging');
|
|
7
6
|
const { collectFileContent, collectFiles, toUnixPath } = require('./helper/fs_helper');
|
|
8
|
-
const Logger = require('./helper/logging');
|
|
9
7
|
const { CliError } = require('./helper/errors');
|
|
10
8
|
|
|
9
|
+
const AuthManager = require('./auth_manager');
|
|
10
|
+
const BaseCommand = require('./base_command');
|
|
11
|
+
|
|
11
12
|
const COMMAND_URL_SUFFIX = 'asyncActivate';
|
|
12
13
|
const COMMAND_URL_SUFFIX_SYNC = 'activate';
|
|
13
14
|
const UPDATE_CUSTOM_FILE_URL_SUFFIX = 'updateCustomTenantContent';
|
|
@@ -28,9 +29,9 @@ async function checkFinished(jobId, statusUrl, params, finisher) {
|
|
|
28
29
|
finisher.finished = true;
|
|
29
30
|
clearInterval(finisher.timer);
|
|
30
31
|
if (status === JOB_STATUS.FAILED) {
|
|
31
|
-
return finisher.reject(new CliError(`Job ${jobId} failed
|
|
32
|
+
return finisher.reject(new CliError(`Job ${jobId} failed`, error));
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
console.log('Extension active');
|
|
34
35
|
finisher.resolve();
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -42,34 +43,30 @@ module.exports = class Activate extends BaseCommand {
|
|
|
42
43
|
static get UPDATE_CUSTOM_FILE_URL_SUFFIX() { return UPDATE_CUSTOM_FILE_URL_SUFFIX; }
|
|
43
44
|
|
|
44
45
|
static async run(injection, paramValues) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
46
|
+
const params = await AuthManager.login(paramValues);
|
|
47
|
+
|
|
48
|
+
if (process.env.DEBUG) {
|
|
49
|
+
console.log('Activating extension with parameters', JSON.stringify({
|
|
50
|
+
appUrl: params.get('appUrl'),
|
|
51
|
+
projectFolder: params.get('projectFolder'),
|
|
52
|
+
undeploy: params.get('undeploy'),
|
|
53
|
+
sync: params.get('sync')
|
|
54
|
+
}));
|
|
55
|
+
} else {
|
|
56
|
+
console.log('Activating extension located at', params.get('projectFolder'), 'to URL', params.get('appUrl'));
|
|
57
|
+
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
if (!await this.checkProject(params.get('projectFolder'))) {
|
|
60
|
+
throw new CliError(params.get('projectFolder') + ' is not a valid extension project');
|
|
61
|
+
}
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
} catch (error) {
|
|
69
|
-
await this.handleHttpError(error, params);
|
|
63
|
+
try {
|
|
64
|
+
await this.runActivate(injection.cds, params);
|
|
65
|
+
if (params.get('wsdl')) {
|
|
66
|
+
await this.runCustomFileUpload(params);
|
|
70
67
|
}
|
|
71
68
|
} catch (error) {
|
|
72
|
-
|
|
69
|
+
await this.handleHttpError(error, params);
|
|
73
70
|
}
|
|
74
71
|
}
|
|
75
72
|
|
|
@@ -94,7 +91,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
94
91
|
let allFiles = new Map();
|
|
95
92
|
|
|
96
93
|
if (resolvedPaths.length < 1) {
|
|
97
|
-
|
|
94
|
+
console.warn('No extension files found');
|
|
98
95
|
return allFiles;
|
|
99
96
|
}
|
|
100
97
|
|
|
@@ -105,7 +102,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
105
102
|
if (! entry.startsWith(projectFolder)) {
|
|
106
103
|
/* Current file might be below the base model's node_modules, in which case compilation on server should succeed.
|
|
107
104
|
Otherwise, compilation will probably fail, with this message giving a hint. */
|
|
108
|
-
|
|
105
|
+
log.debug(`Source file outside project folder will not be uploaded: ${entry}`);
|
|
109
106
|
return false;
|
|
110
107
|
}
|
|
111
108
|
const unixFilename = toUnixPath(entry);
|
|
@@ -123,8 +120,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
123
120
|
return !(/.*node_modules\/_base\/.*/.test(unixFilename));
|
|
124
121
|
});
|
|
125
122
|
|
|
126
|
-
|
|
127
|
-
i18nFolders.forEach(async(folder) => {
|
|
123
|
+
i18nFolders.forEach(folder => {
|
|
128
124
|
const i18nFiles = collectFiles(projectFolder, folder, entry => {
|
|
129
125
|
const ext = path.extname(entry);
|
|
130
126
|
return I18N_WHITELIST.includes(ext);
|
|
@@ -132,13 +128,13 @@ module.exports = class Activate extends BaseCommand {
|
|
|
132
128
|
allFiles = new Map([...allFiles, ...i18nFiles]);
|
|
133
129
|
});
|
|
134
130
|
|
|
131
|
+
let pkgJson;
|
|
135
132
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
Logger.log('No package.json file found');
|
|
140
|
-
Logger.error('No package.json file found', e);
|
|
133
|
+
pkgJson = await fs.readFile(path.join(absoluteFolder, 'package.json'), 'utf-8');
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw new CliError('No package.json file found', error);
|
|
141
136
|
}
|
|
137
|
+
allFiles.set('package.json', pkgJson);
|
|
142
138
|
|
|
143
139
|
return allFiles;
|
|
144
140
|
}
|
|
@@ -146,16 +142,11 @@ module.exports = class Activate extends BaseCommand {
|
|
|
146
142
|
static collectCustomFiles(projectFolder) {
|
|
147
143
|
const wsdlFolder = path.join(projectFolder, 'wsdl');
|
|
148
144
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Logger.log('No custom files found');
|
|
153
|
-
}
|
|
154
|
-
return wsdlFiles;
|
|
155
|
-
} catch (error) {
|
|
156
|
-
Logger.error(undefined, error);
|
|
157
|
-
throw new CliError('No custom files found');
|
|
145
|
+
const wsdlFiles = collectFiles(projectFolder, wsdlFolder);
|
|
146
|
+
if (wsdlFiles.size === 0) {
|
|
147
|
+
console.log('No custom files found');
|
|
158
148
|
}
|
|
149
|
+
return wsdlFiles;
|
|
159
150
|
}
|
|
160
151
|
|
|
161
152
|
static async runActivate(cds, params) {
|
|
@@ -168,7 +159,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
168
159
|
return null;
|
|
169
160
|
}
|
|
170
161
|
|
|
171
|
-
|
|
162
|
+
console.log('Activating extension...');
|
|
172
163
|
|
|
173
164
|
const urlSuffix = isSync ? this.COMMAND_URL_SUFFIX_SYNC : this.COMMAND_URL_SUFFIX;
|
|
174
165
|
activationUrl = this.getMtxApiUrl(params.get('appUrl'), urlSuffix);
|
|
@@ -197,7 +188,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
197
188
|
throw new CliError(`Job ${jobId} failed: did not receive job-status path`);
|
|
198
189
|
}
|
|
199
190
|
|
|
200
|
-
|
|
191
|
+
log.debug(`Job ID: ${jobId}`);
|
|
201
192
|
|
|
202
193
|
return new Promise((resolve, reject) => {
|
|
203
194
|
const statusUrl = this.concatUrls(params.get('appUrl'), statusPath);
|
|
@@ -213,7 +204,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
213
204
|
}
|
|
214
205
|
|
|
215
206
|
static async runCustomFileUpload(params) {
|
|
216
|
-
|
|
207
|
+
console.log('Uploading custom files to', params.get('appUrl'), '...');
|
|
217
208
|
|
|
218
209
|
const customFiles = this.collectCustomFiles(params.get('projectFolder'));
|
|
219
210
|
|
|
@@ -236,7 +227,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
236
227
|
content: customFilesSerialized
|
|
237
228
|
}, requestOptions);
|
|
238
229
|
|
|
239
|
-
|
|
230
|
+
console.log('Custom file upload finished');
|
|
240
231
|
}
|
|
241
232
|
|
|
242
233
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
const util = require('util');
|
|
2
1
|
const axios = require('axios');
|
|
3
2
|
|
|
4
|
-
const
|
|
3
|
+
const log = require('./helper/logging');
|
|
5
4
|
const { SettingsManager } = require('./settings_manager');
|
|
6
5
|
const { ParamCollection } = require('./params');
|
|
7
6
|
const { CliError } = require('./helper/errors');
|
|
@@ -40,7 +39,7 @@ function getTokenUrl(params) {
|
|
|
40
39
|
async function retrieveTokenOrPasscodeUrl(params) {
|
|
41
40
|
if (params.has('token')) {
|
|
42
41
|
if (params.get('renewLogin') || params.get('tokenExpirationDate') <= Date.now()) {
|
|
43
|
-
|
|
42
|
+
log.debug((params.get('renewLogin') ? 'Renewing' : 'Refreshing expired') + ' authentication token');
|
|
44
43
|
params.delete('token');
|
|
45
44
|
params.delete('tokenExpirationDate');
|
|
46
45
|
} else {
|
|
@@ -55,13 +54,13 @@ async function retrieveTokenOrPasscodeUrl(params) {
|
|
|
55
54
|
let authData;
|
|
56
55
|
do {
|
|
57
56
|
const tokenUrl = getTokenUrl(params);
|
|
58
|
-
|
|
57
|
+
log.debug(`Getting authentication token or passcode URL from ${(params.obfuscateQueryParams(tokenUrl))}`);
|
|
59
58
|
|
|
60
59
|
let response;
|
|
61
60
|
try {
|
|
62
61
|
response = await axios.get(tokenUrl);
|
|
63
62
|
} catch (error) {
|
|
64
|
-
throw new CliError(
|
|
63
|
+
throw new CliError('Failed to get authentication token', error);
|
|
65
64
|
}
|
|
66
65
|
authData = response.data;
|
|
67
66
|
|
|
@@ -90,9 +89,9 @@ module.exports = class AuthManager {
|
|
|
90
89
|
if (params.get('saveData')) {
|
|
91
90
|
await SettingsManager.saveSettings(params);
|
|
92
91
|
}
|
|
93
|
-
throw new CliError(
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
throw new CliError(`Failed to login: no valid token or passcode provided. Get a passcode${
|
|
93
|
+
params.get('passcodeUrl') ? ' from ' + params.get('passcodeUrl') : ''
|
|
94
|
+
} and supply the code when re-running the command`);
|
|
96
95
|
}
|
|
97
96
|
params.set('reqAuth', { headers: { Authorization: 'Bearer ' + params.get('token') } });
|
|
98
97
|
}
|
|
@@ -26,9 +26,12 @@ module.exports = class BaseCommand {
|
|
|
26
26
|
(params.has('passcodeUrl') ? ` from ${params.get('passcodeUrl')}` : ''), error);
|
|
27
27
|
case 404:
|
|
28
28
|
throw new CliError(`Request failed. Please check application URL ${params.get('appUrl')}`, error);
|
|
29
|
-
|
|
30
|
-
//
|
|
29
|
+
case 422:
|
|
30
|
+
// Compilation or native-extension error.
|
|
31
31
|
throw new CliError(undefined, error);
|
|
32
|
+
default:
|
|
33
|
+
// Unexpected error should be transparent to user.
|
|
34
|
+
throw error;
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
|
package/lib/client/extend.js
CHANGED
|
@@ -5,7 +5,6 @@ const axios = require('axios');
|
|
|
5
5
|
const AuthManager = require('./auth_manager');
|
|
6
6
|
const BaseCommand = require('./base_command');
|
|
7
7
|
const { normalizePath, isParent } = require('./helper/fs_helper');
|
|
8
|
-
const Logger = require('./helper/logging');
|
|
9
8
|
const Question = require('./helper/question');
|
|
10
9
|
const { CliError } = require('./helper/errors');
|
|
11
10
|
|
|
@@ -63,7 +62,7 @@ module.exports = class Extend extends BaseCommand {
|
|
|
63
62
|
await Extend.storeFiles(templates, directory, async filepath => {
|
|
64
63
|
const normalizedPath = normalizePath(filepath);
|
|
65
64
|
if (!isParent(path.join(directory, DB_FOLDER), normalizedPath) && !isParent(path.join(directory, SRV_FOLDER), normalizedPath)) {
|
|
66
|
-
|
|
65
|
+
console.log('Ignoring template', normalizedPath, ': not in', DB_FOLDER, 'or', SRV_FOLDER);
|
|
67
66
|
return false;
|
|
68
67
|
}
|
|
69
68
|
return true;
|
|
@@ -71,34 +70,30 @@ module.exports = class Extend extends BaseCommand {
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
static async run(paramValues) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
73
|
+
const params = await AuthManager.login(paramValues);
|
|
74
|
+
|
|
75
|
+
if (process.env.DEBUG) {
|
|
76
|
+
console.log('\n\nCreating extension project with parameters', JSON.stringify({
|
|
77
|
+
appUrl: params.get('appUrl'),
|
|
78
|
+
projectFolder: params.get('projectFolder'),
|
|
79
|
+
subdomain: params.get('subdomain'),
|
|
80
|
+
passcode: params.get('passcode'),
|
|
81
|
+
username: params.get('username'),
|
|
82
|
+
password: params.get('password') ? '***' : 'undefined'
|
|
83
|
+
}));
|
|
84
|
+
} else {
|
|
85
|
+
console.log('\n\nCreating extension project for', params.get('appUrl'), 'subdomain', params.get('subdomain'), 'in folder', params.get('projectFolder'));
|
|
86
|
+
}
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
const runOnExistingProject = await Extend.checkProject(params.get('projectFolder'));
|
|
89
|
+
if (runOnExistingProject && !(params.get('force') || params.get('templates'))) {
|
|
90
|
+
throw new CliError(folderExists(params.get('projectFolder')));
|
|
91
|
+
}
|
|
94
92
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
} catch (mainError) {
|
|
101
|
-
Logger.error(undefined, mainError);
|
|
93
|
+
try {
|
|
94
|
+
await Extend.runExtend(params);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
await Extend.handleHttpError(error, params);
|
|
102
97
|
}
|
|
103
98
|
}
|
|
104
99
|
|
|
@@ -106,11 +101,11 @@ module.exports = class Extend extends BaseCommand {
|
|
|
106
101
|
const contentUrl = Extend.getMtxApiUrl(params.get('appUrl'), COMMAND_URL_SUFFIX);
|
|
107
102
|
const requestOptions = Object.assign({ retry: 0 }, params.get('reqAuth'));
|
|
108
103
|
|
|
109
|
-
|
|
104
|
+
console.log('Retrieving files...');
|
|
110
105
|
|
|
111
106
|
const [ response ] = (await axios.get(contentUrl, requestOptions)).data;
|
|
112
107
|
|
|
113
|
-
|
|
108
|
+
console.log('\nWriting files to', params.get('projectFolder'));
|
|
114
109
|
|
|
115
110
|
if (params.get('templates')) {
|
|
116
111
|
await Extend.storeTemplateFilesToTpl(response.templates, params.get('projectFolder'));
|
|
@@ -124,21 +119,21 @@ module.exports = class Extend extends BaseCommand {
|
|
|
124
119
|
await fs.promises.mkdir(path.join(params.get('projectFolder'), DB_FOLDER), { recursive: true });
|
|
125
120
|
await fs.promises.mkdir(path.join(params.get('projectFolder'), SRV_FOLDER), { recursive: true });
|
|
126
121
|
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
console.log('\nPut database extension models into', DB_FOLDER, 'folder.');
|
|
123
|
+
console.log('Put service extension models into', SRV_FOLDER, 'folder.');
|
|
129
124
|
|
|
130
125
|
if (response.templates && response.templates.length > 0) {
|
|
131
126
|
// only write templates if there are no extensions so far
|
|
132
127
|
if (response.extension && response.extension.length === 0) {
|
|
133
|
-
|
|
128
|
+
console.log('Writing template files to', DB_FOLDER, 'and', SRV_FOLDER, 'folder');
|
|
134
129
|
await Extend.storeTemplateFiles(response.templates, params.get('projectFolder'));
|
|
135
130
|
} else {
|
|
136
|
-
|
|
131
|
+
console.log('Ignoring templates because extension is already active.');
|
|
137
132
|
}
|
|
138
133
|
}
|
|
139
134
|
|
|
140
135
|
if (params.get('wsdl')) {
|
|
141
|
-
|
|
136
|
+
console.log('Writing custom files');
|
|
142
137
|
const customFileUrl = Extend.getMtxApiUrl(params.get('appUrl'), Extend.CUSTOM_FILE_URL_SUFFIX);
|
|
143
138
|
const customFiles = (await axios.get(customFileUrl, requestOptions)).data;
|
|
144
139
|
await Extend.storeCustomFiles(params.get('projectFolder'), customFiles);
|
|
@@ -153,12 +148,12 @@ module.exports = class Extend extends BaseCommand {
|
|
|
153
148
|
if (targetExists) {
|
|
154
149
|
await fs.promises.rm(targetDirectory, { force: true, recursive: true });
|
|
155
150
|
}
|
|
156
|
-
|
|
151
|
+
console.log('Writing template files to', TEMPLATE_FOLDER, 'folder');
|
|
157
152
|
await Extend.storeTemplateFiles(templates, targetDirectory);
|
|
158
153
|
}
|
|
159
154
|
|
|
160
155
|
} else {
|
|
161
|
-
|
|
156
|
+
console.log('No templates available');
|
|
162
157
|
}
|
|
163
158
|
}
|
|
164
159
|
|
|
@@ -167,7 +162,7 @@ module.exports = class Extend extends BaseCommand {
|
|
|
167
162
|
}
|
|
168
163
|
|
|
169
164
|
static _logWrittenFile(file) {
|
|
170
|
-
|
|
165
|
+
console.log('CREATE:', file);
|
|
171
166
|
}
|
|
172
167
|
|
|
173
168
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const os = require('os');
|
|
2
2
|
const { execFile } = require('child_process');
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const log = require('./logging');
|
|
5
5
|
const Question = require('./question');
|
|
6
6
|
const { formatObjectsFixedWidth } = require('./string_helper');
|
|
7
7
|
const { schemaRegex } = require('./url_helper');
|
|
@@ -20,7 +20,7 @@ function getErrorMessage(error, stdout) {
|
|
|
20
20
|
async function getAppFromSuggestions() {
|
|
21
21
|
const apps = await getApps();
|
|
22
22
|
if (apps.length === 0) {
|
|
23
|
-
|
|
23
|
+
log.debug('Failed to obtain list of apps from CF');
|
|
24
24
|
return undefined;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -36,7 +36,7 @@ Your choice: `);
|
|
|
36
36
|
console.log();
|
|
37
37
|
|
|
38
38
|
if (!choice) {
|
|
39
|
-
|
|
39
|
+
log.debug('No app URL selected');
|
|
40
40
|
return undefined;
|
|
41
41
|
}
|
|
42
42
|
choiceNr = Number(choice);
|
|
@@ -46,7 +46,7 @@ Your choice: `);
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
async function getApps(nameRegex = /(?<!-db)$/) {
|
|
49
|
-
|
|
49
|
+
log.debug('Getting running apps from CF');
|
|
50
50
|
|
|
51
51
|
return new Promise(resolve => {
|
|
52
52
|
runCf(['apps'], function(error, stdout) {
|
|
@@ -120,13 +120,13 @@ async function getApps(nameRegex = /(?<!-db)$/) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
function errorResult(message) {
|
|
123
|
-
|
|
123
|
+
log.debug(`Failed to get apps: ${message}`);
|
|
124
124
|
return [];
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
async function getSubdomain(appName) {
|
|
129
|
-
|
|
129
|
+
log.debug('Getting subdomain from CF env');
|
|
130
130
|
|
|
131
131
|
return new Promise(resolve => {
|
|
132
132
|
runCf(['env', appName], function(error, stdout) {
|
|
@@ -155,13 +155,13 @@ async function getSubdomain(appName) {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
log.debug(`Subdomain determined from CF app environment: ${value}`);
|
|
159
159
|
return resolve(value);
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
function errorResult(message) {
|
|
164
|
-
|
|
164
|
+
log.debug(`Failed to get subdomain: ${message}`);
|
|
165
165
|
return undefined;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
@@ -171,14 +171,14 @@ async function getAppName(appUrl) {
|
|
|
171
171
|
return url1.replace(schemaRegex, '') === url2.replace(schemaRegex, '');
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
log.debug('Getting app name from CF apps');
|
|
175
175
|
const apps = await getApps();
|
|
176
176
|
const app = apps.find(app => equalIgnoringTls(app.url, appUrl));
|
|
177
177
|
if (!app) {
|
|
178
|
-
|
|
178
|
+
log.debug(`Failed to find app with URL ${appUrl}. Running apps: ${apps.map(app => app.name)}`);
|
|
179
179
|
return;
|
|
180
180
|
}
|
|
181
|
-
|
|
181
|
+
log.debug(`App name determined from CF: ${app.name}`);
|
|
182
182
|
return app.name;
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const os = require('os');
|
|
2
2
|
const { execFileSync } = require('child_process');
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const log = require('./logging');
|
|
5
5
|
|
|
6
6
|
let cachedDir;
|
|
7
7
|
|
|
@@ -21,6 +21,6 @@ module.exports = function requireGlobal(packageId) {
|
|
|
21
21
|
return require(packagePath);
|
|
22
22
|
} catch (error) {
|
|
23
23
|
// Ignore error.
|
|
24
|
-
|
|
24
|
+
log.debug(`Failed to find module '${packageId}' in ${globalModulesDir()}`, error);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { getMessage } = require('./logging');
|
|
2
|
+
|
|
2
3
|
class CliError extends Error {
|
|
3
|
-
|
|
4
|
+
// noinspection JSAnnotator
|
|
4
5
|
constructor(message, error) {
|
|
5
|
-
|
|
6
|
+
throw getMessage(message, error);
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
9
|
|
|
@@ -1,30 +1,24 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
console.log(logText);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
static error(errorText, error) {
|
|
10
|
-
console.error(this.getMessage(errorText, error));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
static debug(debugText, error) {
|
|
14
|
-
if (process.env.DEBUG) {
|
|
15
|
-
console.error(this.getMessage(debugText, error));
|
|
16
|
-
}
|
|
3
|
+
function debug(debugText, error) {
|
|
4
|
+
if (process.env.DEBUG) {
|
|
5
|
+
console.error(getMessage(debugText, error));
|
|
17
6
|
}
|
|
7
|
+
}
|
|
18
8
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return message;
|
|
23
|
-
}
|
|
24
|
-
message += error.response?.data?.error?.message || error.message;
|
|
25
|
-
if (process.env.DEBUG && error.stack) {
|
|
26
|
-
message += '\n' + error.stack;
|
|
27
|
-
}
|
|
9
|
+
function getMessage(errorText, error) {
|
|
10
|
+
let message = errorText ? errorText : '';
|
|
11
|
+
if (!error) {
|
|
28
12
|
return message;
|
|
29
13
|
}
|
|
14
|
+
message += '\n' + (error.response?.data?.error?.message || error.message);
|
|
15
|
+
if (process.env.DEBUG && error.stack) {
|
|
16
|
+
message += '\n' + error.stack;
|
|
17
|
+
}
|
|
18
|
+
return message;
|
|
30
19
|
}
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
debug,
|
|
23
|
+
getMessage
|
|
24
|
+
};
|
package/lib/client/params.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const log = require('./helper/logging');
|
|
2
2
|
const { escapeRegex } = require('./helper/string_helper');
|
|
3
3
|
const { CliError } = require('./helper/errors');
|
|
4
4
|
|
|
@@ -178,7 +178,7 @@ class BasicParams {
|
|
|
178
178
|
this.appUrl = new Param('appUrl', '', { persist: Persistence.setting });
|
|
179
179
|
this.to = this.appUrl.newAlias('to');
|
|
180
180
|
this.url = this.appUrl.newAlias('url');
|
|
181
|
-
this.subdomain = new Param('subdomain', '', { persist: Persistence.setting });
|
|
181
|
+
this.subdomain = new Param('subdomain', '', { persist: Persistence.setting }); // only needed to fetch token
|
|
182
182
|
this.passcodeUrl = new Param('passcodeUrl', '', { persist: Persistence.setting, abbreviate: true });
|
|
183
183
|
this.passcode_url = this.passcodeUrl.newAlias('passcode_url');
|
|
184
184
|
this.tokenUrl = new Param('tokenUrl', '', { persist: Persistence.setting, abbreviate: true })
|
|
@@ -247,7 +247,7 @@ class ParamCollection {
|
|
|
247
247
|
*/
|
|
248
248
|
checkFrozen() {
|
|
249
249
|
if (this.isFrozen) {
|
|
250
|
-
throw new
|
|
250
|
+
throw new Error('cannot modify read-only parameter collection');
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
|
|
@@ -268,7 +268,7 @@ class ParamCollection {
|
|
|
268
268
|
static mainName(name) {
|
|
269
269
|
const paramDef = ParamDefs[name];
|
|
270
270
|
if (!paramDef) {
|
|
271
|
-
throw new
|
|
271
|
+
throw new Error(`Unknown parameter: '${name}'`);
|
|
272
272
|
}
|
|
273
273
|
return paramDef.mainName;
|
|
274
274
|
}
|
|
@@ -312,7 +312,7 @@ class ParamCollection {
|
|
|
312
312
|
this.params[mainName] = ParamDefs[mainName].clone(val);
|
|
313
313
|
}
|
|
314
314
|
if (mainName !== name) {
|
|
315
|
-
|
|
315
|
+
log.debug(`Migrated setting '${name}' to new key '${mainName}'`);
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
|
package/lib/client/pull.js
CHANGED
|
@@ -1,40 +1,38 @@
|
|
|
1
|
+
const cds = require ('../cds')
|
|
2
|
+
const { local, tar } = cds.utils;
|
|
3
|
+
|
|
1
4
|
const fs = require('fs');
|
|
2
5
|
const { join } = require('path');
|
|
3
6
|
const axios = require('axios');
|
|
4
7
|
|
|
5
|
-
const { unpackTarArchive } = require('@sap/cds/lib/utils/resources');
|
|
6
|
-
|
|
7
8
|
const { login } = require('./auth_manager');
|
|
8
9
|
const BaseCommand = require('./base_command');
|
|
9
|
-
const Logger = require('./helper/logging');
|
|
10
|
-
const { CliError } = require('./helper/errors');
|
|
11
10
|
|
|
12
11
|
module.exports = class Pull extends BaseCommand {
|
|
13
12
|
|
|
14
13
|
static async run(paramValues) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (!tar) {
|
|
15
|
+
console.error(`cds pull requires @sap/cds version >= 6.2. Current version is ${cds.version}\n`);
|
|
16
|
+
return process.exitCode = 1;
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const params = await login(paramValues);
|
|
20
|
+
const url = params.get('appUrl')
|
|
21
|
+
const home = params.get('projectFolder');
|
|
22
|
+
const target = join(home, 'node_modules', this.getAppPackageName(home));
|
|
23
|
+
const subdomain = params.get('subdomain') // REVISIT: Why are subdomains not transparently encoded in URLs?
|
|
24
|
+
console.log(`Pulling app base model`, Object.assign({ from: url, to: local(target) }, subdomain && {subdomain}))
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
fs.rmSync(target, { force: true, recursive: true });
|
|
27
|
+
fs.mkdirSync(target, { recursive: true });
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
29
|
+
const tgzBuffer = Buffer.from(await this.getTgz(params));
|
|
30
|
+
return tar.xz(tgzBuffer).to(target);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
static getAppPackageName(projectFolder) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} catch (error) {
|
|
36
|
-
return '_base';
|
|
37
|
-
}
|
|
34
|
+
const env = cds.env.for('cds', projectFolder);
|
|
35
|
+
return env.extends || '_base';
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
static async getTgz(params) {
|