@sap/cds-dk 6.1.1 → 6.1.4
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 +26 -0
- package/bin/build/all.js +10 -4
- package/bin/compile/index.js +1 -1
- package/bin/login.js +15 -5
- package/bin/subscribe.js +1 -1
- package/lib/cds.js +2 -3
- package/lib/client/activate.js +16 -15
- package/lib/client/auth_manager.js +3 -2
- package/lib/client/base_command.js +4 -6
- package/lib/client/extend.js +2 -1
- package/lib/client/helper/errors.js +11 -0
- package/lib/client/helper/logging.js +3 -10
- package/lib/client/params.js +5 -4
- package/lib/client/pull.js +6 -9
- package/lib/client/push.js +10 -14
- package/lib/client/settings_manager.js +9 -8
- package/lib/import/odata/v2parser.js +50 -25
- package/lib/import/odata/v4parser.js +7 -0
- package/lib/init/constants.js +1 -1
- package/lib/init/template/_merging/registry-mta.js +2 -8
- package/lib/init/template/approuter/files/xs-app.json.hbs +7 -7
- package/lib/init/template/approuter/index.js +2 -2
- package/lib/init/template/data/index.js +2 -4
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/util/templateUtil.js +8 -8
- package/lib/k8s/ChartAdder.js +4 -2
- package/lib/k8s/ChartBuilder.js +1 -1
- package/lib/k8s/resources/helm/chart/schemas/values.root.schema.json +11 -0
- package/lib/k8s/resources/helm/chart/{values.schema.json → schemas/values.schema.json} +30 -0
- package/lib/lint/io.js +0 -1
- package/npm-shrinkwrap.json +114 -398
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
9
9
|
|
|
10
|
+
## Version 6.1.4 - 2022-09-09
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `cds build` now works again with `@sap/cds` version 4. Previously, this silently failed with no output. However, a warning is now emitted that strongly recommends an upgrade to version 6.
|
|
15
|
+
|
|
16
|
+
## Version 6.1.3 - 2022-09-06
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- `cds extend` and other commands no longer fail with `TypeError: Class constructor CliError cannot be invoked without 'new'`
|
|
21
|
+
|
|
22
|
+
## Version 6.1.2 - 2022-08-25
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- `cds init` uses latest Maven Java archetype version 1.27.1 for creating Java projects.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- `cds add helm` fixed JSON Schema for `srv` property in values.yaml
|
|
29
|
+
- `cds add helm` fixed env property errors for `hana_deployer` and `html5_apps_deployer`
|
|
30
|
+
- `cds add data` now creates proper data file names for entites in a `context`, i.e. `sap.common-Countries.csv` instead of `sap-common-Countries.csv`
|
|
31
|
+
- `cds import` now captures the parameter/property of collection type differently and the associated annotations are pulled out of the `items` object of the parameter/property entry in the csn.
|
|
32
|
+
- Remove redundant `console.log()` statement in `cds lint`
|
|
33
|
+
- `cds push` now shows complete error messages from extension validation
|
|
34
|
+
- `cds push` and related commands now show properly formatted error messages and also fail with a non-zero exit code in error situations
|
|
35
|
+
|
|
10
36
|
## Version 6.1.1 - 2022-08-11
|
|
11
37
|
|
|
12
38
|
### Added
|
package/bin/build/all.js
CHANGED
|
@@ -65,9 +65,15 @@ function build([project], options = {}) {
|
|
|
65
65
|
delete options["options-model"]
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
const cds = require('../../lib/cds')
|
|
69
|
+
if (typeof cds.build.build === 'function') {
|
|
70
|
+
console.warn(`
|
|
71
|
+
> WARNING: This application uses a very old version ${cds.version} of package '@sap/cds',
|
|
72
|
+
> which will no longer be supported with the next major version of '@sap/cds-dk'.
|
|
73
|
+
> We strongly recommend an upgrade to latest version 6 of '@sap/cds'.
|
|
74
|
+
`)
|
|
75
|
+
return cds.build.build(options)
|
|
72
76
|
}
|
|
77
|
+
return cds.build(options)
|
|
78
|
+
|
|
73
79
|
}
|
package/bin/compile/index.js
CHANGED
|
@@ -283,7 +283,7 @@ function _log (messages, options) {
|
|
|
283
283
|
const { sortMessagesSeverityAware, deduplicateMessages } = cds.compiler
|
|
284
284
|
deduplicateMessages(messages)
|
|
285
285
|
messages = sortMessagesSeverityAware (messages)
|
|
286
|
-
cds.
|
|
286
|
+
cds._log (messages, options)
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/* eslint no-console:0 */
|
package/bin/login.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { bold } = require('../lib/util/term');
|
|
2
2
|
|
|
3
3
|
module.exports = Object.assign(login, {
|
|
4
|
-
options: ['--subdomain', '--directory', '--passcode', '--clientid'],
|
|
5
|
-
shortcuts: ['-s', '-d', '-p', '-c'],
|
|
4
|
+
options: ['--subdomain', '--directory', '--passcode', '--user', '--clientid'],
|
|
5
|
+
shortcuts: ['-s', '-d', '-p', '-u', '-c'],
|
|
6
6
|
flags: ['--plain'],
|
|
7
7
|
get help() {
|
|
8
8
|
const config = require('../lib/client/settings_manager').SettingsManager.config
|
|
@@ -71,10 +71,16 @@ module.exports = Object.assign(login, {
|
|
|
71
71
|
|
|
72
72
|
Tenant-specific passcode for authentication.
|
|
73
73
|
|
|
74
|
-
*-u* | *--
|
|
74
|
+
*-u* | *--user* <name>[:[<password>]]
|
|
75
75
|
|
|
76
|
-
Username for authentication with Basic Auth in test scenarios.
|
|
77
|
-
|
|
76
|
+
Username and optionally password for authentication with Basic Auth in test scenarios.
|
|
77
|
+
See https://cap.cloud.sap/docs/guides/multitenancy/#send-subscribe-events for information
|
|
78
|
+
on suitable mock users.
|
|
79
|
+
|
|
80
|
+
When typing the colon but omitting <password>, the password is assumed empty.
|
|
81
|
+
|
|
82
|
+
For security reasons, username will only be saved for app URLs that look like localhost.
|
|
83
|
+
The same is true for an empty password. Non-empty passwords will never be saved.
|
|
78
84
|
|
|
79
85
|
*-c* | *--clientid* <clientid>
|
|
80
86
|
|
|
@@ -105,8 +111,12 @@ module.exports = Object.assign(login, {
|
|
|
105
111
|
|
|
106
112
|
|
|
107
113
|
async function login ([url], options = {}) {
|
|
114
|
+
const [username, password] = options.user?.split(':') ?? [];
|
|
115
|
+
delete options.user;
|
|
108
116
|
Object.assign(options, {
|
|
109
117
|
url,
|
|
118
|
+
username,
|
|
119
|
+
password,
|
|
110
120
|
tokenStorage: options.plain ? 'plain' : 'keyring',
|
|
111
121
|
renewLogin: true,
|
|
112
122
|
saveData: true
|
package/bin/subscribe.js
CHANGED
|
@@ -36,7 +36,7 @@ async function subscribe([tenant], { to: url, user } = {}) {
|
|
|
36
36
|
if (!tenant) throw new Error('Must provide a tenant')
|
|
37
37
|
if (!url) throw new Error('Must provide an app URL via `--to`') // for now, if we don't infer it from the project
|
|
38
38
|
if (typeof user !== 'string') throw new Error('Must provide a username')
|
|
39
|
-
const [
|
|
39
|
+
const [username, password = ''] = user.split(':');
|
|
40
40
|
Logger.log(`Subscribing to ${url} for tenant '${tenant}' with user '${username}'${password === '' ? ' and empty password' : ''}`);
|
|
41
41
|
const options = { auth: { username, password } };
|
|
42
42
|
return require('axios').post (url+'/-/cds/deployment/subscribe', { tenant }, options);
|
package/lib/cds.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
/** @type { import('@sap/cds/
|
|
1
|
+
/** @type { import('@sap/cds/lib') } */
|
|
2
2
|
const cds = module.exports = require(_local ('@sap/cds'))
|
|
3
3
|
|
|
4
4
|
// for internal use in cds-dk only
|
|
5
|
-
cds.
|
|
6
|
-
|
|
5
|
+
cds._log = require(_local ('@sap/cds/bin/utils/log'))
|
|
7
6
|
|
|
8
7
|
function _local (id) {
|
|
9
8
|
return require.resolve (id, {paths:[
|
package/lib/client/activate.js
CHANGED
|
@@ -6,6 +6,7 @@ const AuthManager = require('./auth_manager');
|
|
|
6
6
|
const BaseCommand = require('./base_command');
|
|
7
7
|
const { collectFileContent, collectFiles, toUnixPath } = require('./helper/fs_helper');
|
|
8
8
|
const Logger = require('./helper/logging');
|
|
9
|
+
const { CliError } = require('./helper/errors');
|
|
9
10
|
|
|
10
11
|
const COMMAND_URL_SUFFIX = 'asyncActivate';
|
|
11
12
|
const COMMAND_URL_SUFFIX_SYNC = 'activate';
|
|
@@ -27,7 +28,7 @@ async function checkFinished(jobId, statusUrl, params, finisher) {
|
|
|
27
28
|
finisher.finished = true;
|
|
28
29
|
clearInterval(finisher.timer);
|
|
29
30
|
if (status === JOB_STATUS.FAILED) {
|
|
30
|
-
return finisher.reject(new
|
|
31
|
+
return finisher.reject(new CliError(`Job ${jobId} failed: ${error.message || JSON.stringify(error)}`));
|
|
31
32
|
}
|
|
32
33
|
Logger.log('Extension active');
|
|
33
34
|
finisher.resolve();
|
|
@@ -55,17 +56,17 @@ module.exports = class Activate extends BaseCommand {
|
|
|
55
56
|
Logger.log(`Activating extension located at ${params.get('projectFolder')} to URL ${params.get('appUrl')}`);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
if (!await
|
|
59
|
-
throw new
|
|
59
|
+
if (!await this.checkProject(params.get('projectFolder'))) {
|
|
60
|
+
throw new CliError(params.get('projectFolder') + ' is not a valid extension project');
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
try {
|
|
63
|
-
await
|
|
64
|
+
await this.runActivate(injection.cds, params);
|
|
64
65
|
if (params.get('wsdl')) {
|
|
65
|
-
await
|
|
66
|
+
await this.runCustomFileUpload(params);
|
|
66
67
|
}
|
|
67
68
|
} catch (error) {
|
|
68
|
-
|
|
69
|
+
await this.handleHttpError(error, params);
|
|
69
70
|
}
|
|
70
71
|
} catch (error) {
|
|
71
72
|
Logger.error(undefined, error);
|
|
@@ -153,7 +154,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
153
154
|
return wsdlFiles;
|
|
154
155
|
} catch (error) {
|
|
155
156
|
Logger.error(undefined, error);
|
|
156
|
-
throw new
|
|
157
|
+
throw new CliError('No custom files found');
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
160
|
|
|
@@ -161,7 +162,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
161
162
|
let activationUrl;
|
|
162
163
|
const isSync = params.get('sync');
|
|
163
164
|
|
|
164
|
-
return
|
|
165
|
+
return this.collectExtensionFiles(cds, params.get('projectFolder'))
|
|
165
166
|
.then(allFiles => {
|
|
166
167
|
if (allFiles.size === 0) {
|
|
167
168
|
return null;
|
|
@@ -169,8 +170,8 @@ module.exports = class Activate extends BaseCommand {
|
|
|
169
170
|
|
|
170
171
|
Logger.log('Activating extension...');
|
|
171
172
|
|
|
172
|
-
const urlSuffix = isSync ?
|
|
173
|
-
activationUrl =
|
|
173
|
+
const urlSuffix = isSync ? this.COMMAND_URL_SUFFIX_SYNC : this.COMMAND_URL_SUFFIX;
|
|
174
|
+
activationUrl = this.getMtxApiUrl(params.get('appUrl'), urlSuffix);
|
|
174
175
|
const requestOptions = Object.assign({
|
|
175
176
|
headers: {}
|
|
176
177
|
}, params.get('reqAuth'));
|
|
@@ -189,17 +190,17 @@ module.exports = class Activate extends BaseCommand {
|
|
|
189
190
|
const { jobID: jobId, statusPath } = response.data;
|
|
190
191
|
|
|
191
192
|
if (jobId === undefined) {
|
|
192
|
-
throw new
|
|
193
|
+
throw new CliError('Activation failed: did not receive job ID');
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
if (!statusPath) {
|
|
196
|
-
throw new
|
|
197
|
+
throw new CliError(`Job ${jobId} failed: did not receive job-status path`);
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
Logger.debug(`Job ID: ${jobId}`);
|
|
200
201
|
|
|
201
202
|
return new Promise((resolve, reject) => {
|
|
202
|
-
const statusUrl =
|
|
203
|
+
const statusUrl = this.concatUrls(params.get('appUrl'), statusPath);
|
|
203
204
|
const finisher = {
|
|
204
205
|
resolve,
|
|
205
206
|
reject,
|
|
@@ -214,7 +215,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
214
215
|
static async runCustomFileUpload(params) {
|
|
215
216
|
Logger.log(`Uploading custom files to ${params.get('appUrl')}...`);
|
|
216
217
|
|
|
217
|
-
const customFiles =
|
|
218
|
+
const customFiles = this.collectCustomFiles(params.get('projectFolder'));
|
|
218
219
|
|
|
219
220
|
const customFilesSerialized = [];
|
|
220
221
|
customFiles.forEach((value, key) => {
|
|
@@ -225,7 +226,7 @@ module.exports = class Activate extends BaseCommand {
|
|
|
225
226
|
});
|
|
226
227
|
});
|
|
227
228
|
|
|
228
|
-
const customFileUrl =
|
|
229
|
+
const customFileUrl = this.getMtxApiUrl(params.get('appUrl'), this.UPDATE_CUSTOM_FILE_URL_SUFFIX);
|
|
229
230
|
const requestOptions = Object.assign({
|
|
230
231
|
headers: {},
|
|
231
232
|
}, params.get('reqAuth'));
|
|
@@ -4,6 +4,7 @@ const axios = require('axios');
|
|
|
4
4
|
const Logger = require('./helper/logging');
|
|
5
5
|
const { SettingsManager } = require('./settings_manager');
|
|
6
6
|
const { ParamCollection } = require('./params');
|
|
7
|
+
const { CliError } = require('./helper/errors');
|
|
7
8
|
|
|
8
9
|
function addTokenInfo(params, authData) {
|
|
9
10
|
params.set('token', authData.access_token);
|
|
@@ -60,7 +61,7 @@ async function retrieveTokenOrPasscodeUrl(params) {
|
|
|
60
61
|
try {
|
|
61
62
|
response = await axios.get(tokenUrl);
|
|
62
63
|
} catch (error) {
|
|
63
|
-
throw new
|
|
64
|
+
throw new CliError(`Failed to get authentication token: ${error}.\nResponse body: ${util.inspect(error.response && error.response.data)}`);
|
|
64
65
|
}
|
|
65
66
|
authData = response.data;
|
|
66
67
|
|
|
@@ -89,7 +90,7 @@ module.exports = class AuthManager {
|
|
|
89
90
|
if (params.get('saveData')) {
|
|
90
91
|
await SettingsManager.saveSettings(params);
|
|
91
92
|
}
|
|
92
|
-
throw new
|
|
93
|
+
throw new CliError('Failed to login: no valid token or passcode provided. ' +
|
|
93
94
|
'Get a passcode' + (params.get('passcodeUrl') ? ' from ' + params.get('passcodeUrl') : '') +
|
|
94
95
|
' and supply the code when re-running the command');
|
|
95
96
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs').promises;
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const { CliError } = require('./helper/errors');
|
|
5
5
|
|
|
6
6
|
const MTX_URL_PATH_PREFIX = 'mtx/v1/model/';
|
|
7
7
|
const CUSTOM_FILE_URL_SUFFIX = 'customTenantContent';
|
|
@@ -22,15 +22,13 @@ module.exports = class BaseCommand {
|
|
|
22
22
|
|
|
23
23
|
switch (error.response && error.response.status) {
|
|
24
24
|
case 401:
|
|
25
|
-
|
|
25
|
+
throw new CliError('Request failed: authorization might have expired. Please retry with valid passcode' +
|
|
26
26
|
(params.has('passcodeUrl') ? ` from ${params.get('passcodeUrl')}` : ''), error);
|
|
27
|
-
break;
|
|
28
27
|
case 404:
|
|
29
|
-
|
|
30
|
-
break;
|
|
28
|
+
throw new CliError(`Request failed. Please check application URL ${params.get('appUrl')}`, error);
|
|
31
29
|
default:
|
|
32
30
|
// Including 422 (compilation or native-extension error).
|
|
33
|
-
|
|
31
|
+
throw new CliError(undefined, error);
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
|
package/lib/client/extend.js
CHANGED
|
@@ -7,6 +7,7 @@ const BaseCommand = require('./base_command');
|
|
|
7
7
|
const { normalizePath, isParent } = require('./helper/fs_helper');
|
|
8
8
|
const Logger = require('./helper/logging');
|
|
9
9
|
const Question = require('./helper/question');
|
|
10
|
+
const { CliError } = require('./helper/errors');
|
|
10
11
|
|
|
11
12
|
const COMMAND_URL_SUFFIX = 'content';
|
|
12
13
|
const CUSTOM_FILE_FOLDERS = ['wsdl'];
|
|
@@ -88,7 +89,7 @@ module.exports = class Extend extends BaseCommand {
|
|
|
88
89
|
|
|
89
90
|
const runOnExistingProject = await Extend.checkProject(params.get('projectFolder'));
|
|
90
91
|
if (runOnExistingProject && !(params.get('force') || params.get('templates'))) {
|
|
91
|
-
throw new
|
|
92
|
+
throw new CliError(folderExists(params.get('projectFolder')));
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
try {
|
|
@@ -17,20 +17,13 @@ module.exports = class Logger {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
static getMessage(errorText, error) {
|
|
20
|
-
let message = errorText
|
|
20
|
+
let message = errorText ? errorText + '\n' : '';
|
|
21
21
|
if (!error) {
|
|
22
22
|
return message;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const body = error.response.data;
|
|
27
|
-
if (body.error && body.error.message) {
|
|
28
|
-
message += body.error.message + '\n';
|
|
29
|
-
}
|
|
30
|
-
}
|
|
24
|
+
message += error.response?.data?.error?.message || error.message;
|
|
25
|
+
if (process.env.DEBUG && error.stack) {
|
|
31
26
|
message += '\n' + error.stack;
|
|
32
|
-
} else {
|
|
33
|
-
message += error.message;
|
|
34
27
|
}
|
|
35
28
|
return message;
|
|
36
29
|
}
|
package/lib/client/params.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const Logger = require('./helper/logging');
|
|
2
2
|
const { escapeRegex } = require('./helper/string_helper');
|
|
3
|
+
const { CliError } = require('./helper/errors');
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
// PARAM BASE TYPES
|
|
@@ -104,10 +105,10 @@ class Param {
|
|
|
104
105
|
expectedType = typeof this.allowedValues[0];
|
|
105
106
|
}
|
|
106
107
|
if (typeof val !== expectedType) {
|
|
107
|
-
throw new
|
|
108
|
+
throw new CliError(`Failed to set '${(this.name)}' = ${JSON.stringify(val)}: expected value of type ${expectedType}`);
|
|
108
109
|
}
|
|
109
110
|
if (this.allowedValues && !(this.allowedValues).includes(val)) {
|
|
110
|
-
throw new
|
|
111
|
+
throw new CliError(`Failed to set '${(this.name)}' = ${JSON.stringify(val)}: expected one of ${JSON.stringify(this.allowedValues)}`);
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
@@ -246,7 +247,7 @@ class ParamCollection {
|
|
|
246
247
|
*/
|
|
247
248
|
checkFrozen() {
|
|
248
249
|
if (this.isFrozen) {
|
|
249
|
-
throw new
|
|
250
|
+
throw new CliError('cannot modify read-only parameter collection');
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
|
|
@@ -267,7 +268,7 @@ class ParamCollection {
|
|
|
267
268
|
static mainName(name) {
|
|
268
269
|
const paramDef = ParamDefs[name];
|
|
269
270
|
if (!paramDef) {
|
|
270
|
-
throw new
|
|
271
|
+
throw new CliError(`Unknown parameter: '${name}'`);
|
|
271
272
|
}
|
|
272
273
|
return paramDef.mainName;
|
|
273
274
|
}
|
package/lib/client/pull.js
CHANGED
|
@@ -7,13 +7,13 @@ const { unpackTarArchive } = require('@sap/cds/lib/utils/resources');
|
|
|
7
7
|
const { login } = require('./auth_manager');
|
|
8
8
|
const BaseCommand = require('./base_command');
|
|
9
9
|
const Logger = require('./helper/logging');
|
|
10
|
+
const { CliError } = require('./helper/errors');
|
|
10
11
|
|
|
11
12
|
module.exports = class Pull extends BaseCommand {
|
|
12
13
|
|
|
13
14
|
static async run(paramValues) {
|
|
14
15
|
try {
|
|
15
16
|
const params = await login(paramValues);
|
|
16
|
-
|
|
17
17
|
Logger.log(`Pulling base model from ${params.get('appUrl')}, for subdomain '${params.get('subdomain')}', to project folder '${params.get('projectFolder')}'`);
|
|
18
18
|
|
|
19
19
|
const projectFolder = params.get('projectFolder');
|
|
@@ -24,8 +24,8 @@ module.exports = class Pull extends BaseCommand {
|
|
|
24
24
|
const tgzBuffer = Buffer.from(await this.getTgz(params));
|
|
25
25
|
return unpackTarArchive(tgzBuffer, targetDir, false);
|
|
26
26
|
|
|
27
|
-
} catch (
|
|
28
|
-
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new CliError(undefined, error);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -41,11 +41,8 @@ module.exports = class Pull extends BaseCommand {
|
|
|
41
41
|
const pullUrl = `${(params.get('appUrl'))}/-/cds/extensibility/pull`;
|
|
42
42
|
const options = { ...params.get('reqAuth'), responseType: 'arraybuffer' };
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} catch (error) {
|
|
48
|
-
return this.handleHttpError(error, params);
|
|
49
|
-
}
|
|
44
|
+
return axios.post(pullUrl, {}, options)
|
|
45
|
+
.then(response => response.data)
|
|
46
|
+
.catch(error => this.handleHttpError(error, params));
|
|
50
47
|
}
|
|
51
48
|
}
|
package/lib/client/push.js
CHANGED
|
@@ -5,23 +5,22 @@ const axios = require('axios');
|
|
|
5
5
|
const { login } = require('./auth_manager');
|
|
6
6
|
const BaseCommand = require('./base_command');
|
|
7
7
|
const Logger = require('./helper/logging');
|
|
8
|
+
const { CliError } = require('./helper/errors');
|
|
8
9
|
|
|
9
10
|
module.exports = class Push extends BaseCommand {
|
|
10
11
|
|
|
11
12
|
static async run(paramValues) {
|
|
12
13
|
try {
|
|
13
14
|
const params = await login(paramValues);
|
|
14
|
-
|
|
15
15
|
const projectFolder = params.get('projectFolder');
|
|
16
16
|
Logger.log(`Pushing extension from project folder '${projectFolder}', for subdomain '${params.get('subdomain')}', to app URL ${params.get('appUrl')}`);
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
const tgz = fs.readFileSync(tgzPath, { encoding: 'base64' });
|
|
18
|
+
const tgz = fs.readFileSync(join(projectFolder, 'gen', 'extension.tgz'), { encoding: 'base64' });
|
|
20
19
|
const extensionName = this.getExtensionName(projectFolder);
|
|
21
20
|
return this.pushTgz(params, tgz, extensionName);
|
|
22
21
|
|
|
23
|
-
} catch (
|
|
24
|
-
|
|
22
|
+
} catch (error) {
|
|
23
|
+
throw new CliError(undefined, error);
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -29,7 +28,7 @@ module.exports = class Push extends BaseCommand {
|
|
|
29
28
|
try {
|
|
30
29
|
return require(join(projectFolder, 'package.json')).name;
|
|
31
30
|
} catch (error) {
|
|
32
|
-
throw new
|
|
31
|
+
throw new CliError(`Extension project at ${projectFolder} is missing package.json`);
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -37,13 +36,10 @@ module.exports = class Push extends BaseCommand {
|
|
|
37
36
|
const pushUrl = `${params.get('appUrl')}/-/cds/extensibility/push`;
|
|
38
37
|
const options = { ...params.get('reqAuth') };
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} catch (error) {
|
|
46
|
-
return this.handleHttpError(error, params);
|
|
47
|
-
}
|
|
39
|
+
return axios.post(pushUrl, {
|
|
40
|
+
extension: tgz,
|
|
41
|
+
tag: extensionName
|
|
42
|
+
}, options)
|
|
43
|
+
.catch(error => this.handleHttpError(error, params));
|
|
48
44
|
}
|
|
49
45
|
}
|
|
@@ -9,6 +9,7 @@ const { getAppFromSuggestions, getAppName, getSubdomain } = require('./helper/cf
|
|
|
9
9
|
const isBas = require('./helper/env_helper');
|
|
10
10
|
const Logger = require('./helper/logging');
|
|
11
11
|
const Question = require('./helper/question');
|
|
12
|
+
const { CliError } = require('./helper/errors');
|
|
12
13
|
const { httpSchema, httpsSchema, extractSubdomain, schemaRegex, localhostRegex } = require('./helper/url_helper');
|
|
13
14
|
const { ParamCollection, Persistence } = require('./params');
|
|
14
15
|
const { capitalize } = require('./helper/string_helper');
|
|
@@ -95,7 +96,7 @@ async function getTokenBaseUrl(params, renewUrl) {
|
|
|
95
96
|
return params.get('tokenUrl');
|
|
96
97
|
}
|
|
97
98
|
if (!params.has('appUrl')) {
|
|
98
|
-
throw new
|
|
99
|
+
throw new CliError('Failed to determine token URL: app URL not given');
|
|
99
100
|
}
|
|
100
101
|
const baseUrl = new URL(params.get('appUrl'));
|
|
101
102
|
const cleanPathname = pathname => baseUrl.pathname.replace(/\/?$/, pathname);
|
|
@@ -116,7 +117,7 @@ async function getTokenBaseUrl(params, renewUrl) {
|
|
|
116
117
|
if (e.response?.status === 404) {
|
|
117
118
|
continue;
|
|
118
119
|
} else {
|
|
119
|
-
throw
|
|
120
|
+
throw new CliError(`Failed with root cause ${e.message}`);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
}
|
|
@@ -230,12 +231,12 @@ class SettingsManager {
|
|
|
230
231
|
}
|
|
231
232
|
}
|
|
232
233
|
if (!params.has('appUrl')) {
|
|
233
|
-
throw new
|
|
234
|
+
throw new CliError('App URL not given. Please specify it or log in to Cloud Foundry and repeat this command.');
|
|
234
235
|
}
|
|
235
236
|
if (!params.has('subdomain')) {
|
|
236
237
|
const subdomain = extractSubdomain(params.get('appUrl'));
|
|
237
238
|
if (!subdomain) {
|
|
238
|
-
throw new
|
|
239
|
+
throw new CliError('Subdomain not given');
|
|
239
240
|
}
|
|
240
241
|
params.set('subdomain', subdomain);
|
|
241
242
|
Logger.log(`Subdomain determined from app URL: ${subdomain}`);
|
|
@@ -267,7 +268,7 @@ class SettingsManager {
|
|
|
267
268
|
return;
|
|
268
269
|
}
|
|
269
270
|
if (params.get('tokenStorage') === 'keyring') {
|
|
270
|
-
throw new
|
|
271
|
+
throw new CliError(`${capitalize(TOKEN_STORAGE_DESC.keyring)} requested but keytar not installed. Run 'npm install -g keytar' or ` +
|
|
271
272
|
`switch to ${TOKEN_STORAGE_DESC.plain} by adding '--plain' (discouraged).`);
|
|
272
273
|
}
|
|
273
274
|
if (params.get('renewLogin') || logout) {
|
|
@@ -288,7 +289,7 @@ class SettingsManager {
|
|
|
288
289
|
params.set('clientsecret', await Question.askQuestion('clientsecret: ', undefined, true));
|
|
289
290
|
console.log();
|
|
290
291
|
if (params.get('clientsecret') === '') {
|
|
291
|
-
throw new
|
|
292
|
+
throw new CliError('clientsecret cannot be empty');
|
|
292
293
|
}
|
|
293
294
|
}
|
|
294
295
|
async function addPasscode() {
|
|
@@ -296,7 +297,7 @@ class SettingsManager {
|
|
|
296
297
|
params.set('passcode', await Question.askQuestion(prompt, undefined, true));
|
|
297
298
|
console.log();
|
|
298
299
|
if (params.get('passcode') === '') {
|
|
299
|
-
throw new
|
|
300
|
+
throw new CliError('Passcode cannot be empty');
|
|
300
301
|
}
|
|
301
302
|
}
|
|
302
303
|
function setRelevantAuth(auth) {
|
|
@@ -338,7 +339,7 @@ class SettingsManager {
|
|
|
338
339
|
if (params.get('password') === '') {
|
|
339
340
|
params.set('isEmptyPassword', true);
|
|
340
341
|
// TODO check password only in production env
|
|
341
|
-
// throw new
|
|
342
|
+
// throw new CliError('Password cannot be empty');
|
|
342
343
|
} else {
|
|
343
344
|
params.delete('isEmptyPassword');
|
|
344
345
|
}
|