@sap-ux/odata-service-inquirer 0.2.3 → 0.3.1
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/dist/error-handler/error-handler.d.ts +7 -0
- package/dist/error-handler/error-handler.js +24 -11
- package/dist/i18n.js +6 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -1
- package/dist/prompts/datasources/cap-project/questions.js +1 -1
- package/dist/prompts/datasources/service-url/connectionValidator.d.ts +99 -0
- package/dist/prompts/datasources/service-url/connectionValidator.js +271 -0
- package/dist/prompts/datasources/service-url/questions.d.ts +12 -0
- package/dist/prompts/datasources/service-url/questions.js +216 -0
- package/dist/prompts/datasources/service-url/types.d.ts +9 -0
- package/dist/prompts/datasources/service-url/types.js +13 -0
- package/dist/prompts/datasources/service-url/validators.d.ts +19 -0
- package/dist/prompts/datasources/service-url/validators.js +95 -0
- package/dist/prompts/logger-helper.d.ts +12 -0
- package/dist/prompts/logger-helper.js +59 -0
- package/dist/prompts/prompts.js +2 -0
- package/dist/prompts/validators.d.ts +1 -1
- package/dist/prompts/validators.js +6 -10
- package/dist/translations/odata-service-inquirer.i18n.json +23 -2
- package/dist/types.d.ts +42 -5
- package/dist/types.js +10 -1
- package/dist/utils/index.d.ts +18 -1
- package/dist/utils/index.js +54 -4
- package/dist/utils/prompt-state.js +4 -1
- package/package.json +9 -6
|
@@ -52,6 +52,13 @@ export declare class ErrorHandler {
|
|
|
52
52
|
* @returns The Guided Answers node for the specified error type
|
|
53
53
|
*/
|
|
54
54
|
private static readonly getHelpNode;
|
|
55
|
+
/**
|
|
56
|
+
* Find an error property for mapping to a general error type from most to least significant.
|
|
57
|
+
*
|
|
58
|
+
* @param error any type of error or object that has an error code, status, name or message
|
|
59
|
+
* @returns a value that can be used to look up a general error type
|
|
60
|
+
*/
|
|
61
|
+
private static findErrorValueForMapping;
|
|
55
62
|
/**
|
|
56
63
|
* Create an instance of the ErrorHandler.
|
|
57
64
|
*
|
|
@@ -151,8 +151,12 @@ class ErrorHandler {
|
|
|
151
151
|
* @returns the error type
|
|
152
152
|
*/
|
|
153
153
|
static getErrorType(error) {
|
|
154
|
+
let errorValueToFind = error;
|
|
155
|
+
if (error instanceof Error) {
|
|
156
|
+
errorValueToFind = ErrorHandler.findErrorValueForMapping(error);
|
|
157
|
+
}
|
|
154
158
|
return Object.keys(ERROR_TYPE).find((errorCodeType) => {
|
|
155
|
-
return exports.ERROR_MAP[errorCodeType].find((exp) => exp.test(
|
|
159
|
+
return exports.ERROR_MAP[errorCodeType].find((exp) => exp.test(errorValueToFind.toString()));
|
|
156
160
|
}, {});
|
|
157
161
|
}
|
|
158
162
|
/**
|
|
@@ -196,21 +200,14 @@ class ErrorHandler {
|
|
|
196
200
|
* @returns The mapped error message and error type
|
|
197
201
|
*/
|
|
198
202
|
static mapErrorToMsg(error) {
|
|
199
|
-
var _a
|
|
203
|
+
var _a;
|
|
200
204
|
let errorType;
|
|
201
205
|
if (Object.values(ERROR_TYPE).includes(error)) {
|
|
202
206
|
errorType = error;
|
|
203
207
|
}
|
|
204
208
|
else {
|
|
205
209
|
// Map error type using more to less specific information if available
|
|
206
|
-
errorType =
|
|
207
|
-
(_f = ErrorHandler.getErrorType(((_c = (_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.code) ||
|
|
208
|
-
((_d = error.response) === null || _d === void 0 ? void 0 : _d.status) ||
|
|
209
|
-
((_e = error.response) === null || _e === void 0 ? void 0 : _e.data) ||
|
|
210
|
-
error.code ||
|
|
211
|
-
(['TypeError', 'Error'].includes(error.name) ? error.message : error.name) || // For generic error types use the message otherwise the name is more relevant
|
|
212
|
-
error.message ||
|
|
213
|
-
error)) !== null && _f !== void 0 ? _f : ERROR_TYPE.UNKNOWN;
|
|
210
|
+
errorType = (_a = ErrorHandler.getErrorType(this.findErrorValueForMapping(error))) !== null && _a !== void 0 ? _a : ERROR_TYPE.UNKNOWN;
|
|
214
211
|
}
|
|
215
212
|
return {
|
|
216
213
|
errorMsg: ErrorHandler._errorMsg(error)[errorType],
|
|
@@ -397,7 +394,7 @@ ErrorHandler._errorMsg = (error) => ({
|
|
|
397
394
|
[ERROR_TYPE.INTERNAL_SERVER_ERROR]: (0, i18n_1.t)('errors.internalServerError', { error: error === null || error === void 0 ? void 0 : error.message }),
|
|
398
395
|
[ERROR_TYPE.NOT_FOUND]: (0, i18n_1.t)('errors.urlNotFound'),
|
|
399
396
|
[ERROR_TYPE.ODATA_URL_NOT_FOUND]: (0, i18n_1.t)('errors.odataServiceUrlNotFound'),
|
|
400
|
-
[ERROR_TYPE.BAD_GATEWAY]: (0, i18n_1.t)('errors.
|
|
397
|
+
[ERROR_TYPE.BAD_GATEWAY]: (0, i18n_1.t)('errors.badGateway'),
|
|
401
398
|
[ERROR_TYPE.DESTINATION_UNAVAILABLE]: (0, i18n_1.t)('errors.destinationUnavailable'),
|
|
402
399
|
[ERROR_TYPE.DESTINATION_NOT_FOUND]: (0, i18n_1.t)('errors.destinationNotFound'),
|
|
403
400
|
[ERROR_TYPE.DESTINATION_MISCONFIGURED]: (0, i18n_1.t)('errors.destinationMisconfigured'),
|
|
@@ -447,4 +444,20 @@ ErrorHandler.getHelpNode = (errorType) => {
|
|
|
447
444
|
};
|
|
448
445
|
return errorToHelp[errorType];
|
|
449
446
|
};
|
|
447
|
+
/**
|
|
448
|
+
* Find an error property for mapping to a general error type from most to least significant.
|
|
449
|
+
*
|
|
450
|
+
* @param error any type of error or object that has an error code, status, name or message
|
|
451
|
+
* @returns a value that can be used to look up a general error type
|
|
452
|
+
*/
|
|
453
|
+
ErrorHandler.findErrorValueForMapping = (error) => {
|
|
454
|
+
var _a, _b, _c, _d, _e;
|
|
455
|
+
return ((_c = (_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.code) ||
|
|
456
|
+
((_d = error.response) === null || _d === void 0 ? void 0 : _d.status) ||
|
|
457
|
+
((_e = error.response) === null || _e === void 0 ? void 0 : _e.data) ||
|
|
458
|
+
error.code ||
|
|
459
|
+
(['TypeError', 'Error'].includes(error.name) ? error.message : error.name) || // For generic error types use the message otherwise the name is more relevant
|
|
460
|
+
error.message ||
|
|
461
|
+
error;
|
|
462
|
+
};
|
|
450
463
|
//# sourceMappingURL=error-handler.js.map
|
package/dist/i18n.js
CHANGED
|
@@ -25,7 +25,12 @@ function initI18nOdataServiceInquirer() {
|
|
|
25
25
|
yield i18next_1.default.init({
|
|
26
26
|
lng: 'en',
|
|
27
27
|
fallbackLng: 'en',
|
|
28
|
-
missingInterpolationHandler: () => ''
|
|
28
|
+
missingInterpolationHandler: () => '',
|
|
29
|
+
interpolation: {
|
|
30
|
+
format: function odataVersionFormatter(odataVersion) {
|
|
31
|
+
return odataVersion ? ` V${odataVersion}` : '';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
29
34
|
}, () => i18next_1.default.addResourceBundle('en', odataServiceInquirerNamespace, odata_service_inquirer_i18n_json_1.default));
|
|
30
35
|
});
|
|
31
36
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,9 +16,7 @@ import { DatasourceType, promptNames, type CapRuntime, type CapService, type Oda
|
|
|
16
16
|
*/
|
|
17
17
|
declare function getPrompts(promptOptions?: OdataServicePromptOptions, logger?: Logger, enableGuidedAnswers?: boolean, telemetryClient?: ToolsSuiteTelemetryClient, isYUI?: boolean): Promise<{
|
|
18
18
|
prompts: OdataServiceQuestion[];
|
|
19
|
-
answers:
|
|
20
|
-
odataService: Partial<OdataServiceAnswers>;
|
|
21
|
-
};
|
|
19
|
+
answers: Partial<OdataServiceAnswers>;
|
|
22
20
|
}>;
|
|
23
21
|
/**
|
|
24
22
|
* Prompt for odata service writer inputs.
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ function getPrompts(promptOptions, logger, enableGuidedAnswers = false, telemetr
|
|
|
48
48
|
return {
|
|
49
49
|
prompts: yield (0, prompts_1.getQuestions)(promptOptions),
|
|
50
50
|
// Return reference to derived answers object that will be populated with user responses (after prompting is complete)
|
|
51
|
-
answers: utils_1.PromptState
|
|
51
|
+
answers: utils_1.PromptState.odataService
|
|
52
52
|
};
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -153,7 +153,7 @@ function getLocalCapProjectPrompts(promptOptions) {
|
|
|
153
153
|
})
|
|
154
154
|
}
|
|
155
155
|
];
|
|
156
|
-
if ((0, utils_1.
|
|
156
|
+
if ((0, utils_1.getHostEnvironment)() === types_1.hostEnvironment.cli) {
|
|
157
157
|
prompts.push({
|
|
158
158
|
when: (answers) => __awaiter(this, void 0, void 0, function* () {
|
|
159
159
|
if (answers === null || answers === void 0 ? void 0 : answers.capService) {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { IValidationLink } from '@sap-devx/yeoman-ui-types';
|
|
2
|
+
import type { AxiosRequestConfig, ODataService } from '@sap-ux/axios-extension';
|
|
3
|
+
/**
|
|
4
|
+
* Structure to store validity information about url to be validated.
|
|
5
|
+
*/
|
|
6
|
+
interface Validity {
|
|
7
|
+
urlFormat?: boolean;
|
|
8
|
+
reachable?: boolean;
|
|
9
|
+
authRequired?: boolean;
|
|
10
|
+
authenticated?: boolean;
|
|
11
|
+
canSkipCertError?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Class that validates the connection to a service url or catalog url.
|
|
15
|
+
* This will determine if authentication is required and if the service/catalog is reachable, generating messages to guide the user.
|
|
16
|
+
* It is optimized for re-validation of the same url, so that the validation is not repeated if not required.
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
export declare class ConnectionValidator {
|
|
20
|
+
readonly validity: Validity;
|
|
21
|
+
private _validatedUrl;
|
|
22
|
+
private _odataService;
|
|
23
|
+
private _axiosConfig;
|
|
24
|
+
/**
|
|
25
|
+
* Getter for the axios configuration.
|
|
26
|
+
*
|
|
27
|
+
* @returns the axios configuration
|
|
28
|
+
*/
|
|
29
|
+
get axiosConfig(): AxiosRequestConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Get the odata service instance.
|
|
32
|
+
*
|
|
33
|
+
* @returns the odata service instance
|
|
34
|
+
*/
|
|
35
|
+
get odataService(): ODataService;
|
|
36
|
+
/**
|
|
37
|
+
* Calls a given service url to test its reachability and authentication requirements.
|
|
38
|
+
*
|
|
39
|
+
* @param url a service url (<protocol://<host>:<port>/<service-path>)
|
|
40
|
+
* @param username optional username
|
|
41
|
+
* @param password optional password
|
|
42
|
+
* @param [ignoreCertError] optional, ignore some certificate errors
|
|
43
|
+
* @returns the status code or error returned by the connection attempt
|
|
44
|
+
*/
|
|
45
|
+
private checkSapService;
|
|
46
|
+
/**
|
|
47
|
+
* Validates the service url format as well as its reachability.
|
|
48
|
+
*
|
|
49
|
+
* @param serviceUrl the odata service url to validate
|
|
50
|
+
* @param ignoreCertError ignore some certificate errors
|
|
51
|
+
* @param forceReValidation force re-validation of the url
|
|
52
|
+
* @returns true if the url is reachable, false if not, or an error message string
|
|
53
|
+
*/
|
|
54
|
+
validateUrl(serviceUrl: string, ignoreCertError?: boolean, forceReValidation?: boolean): Promise<boolean | string | IValidationLink>;
|
|
55
|
+
/**
|
|
56
|
+
* Translate the status code into a validation result.
|
|
57
|
+
* Sets the instance validity state based on the status code.
|
|
58
|
+
*
|
|
59
|
+
* @param status a http request status code used to determine the validation result
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
private getValidationResultFromStatusCode;
|
|
63
|
+
/**
|
|
64
|
+
* Is a string nil or whitespace only.
|
|
65
|
+
*
|
|
66
|
+
* @param url the string to test
|
|
67
|
+
* @returns true if the string is nil or whitespace
|
|
68
|
+
*/
|
|
69
|
+
private isEmptyString;
|
|
70
|
+
/**
|
|
71
|
+
* Tests if the url has already been validated.
|
|
72
|
+
*
|
|
73
|
+
* @param url the full url to test for previous validation
|
|
74
|
+
* @returns true if the url has already been validated
|
|
75
|
+
*/
|
|
76
|
+
private isUrlValidated;
|
|
77
|
+
/**
|
|
78
|
+
* Test the connectivity with the specified service url using the provided credentials.
|
|
79
|
+
*
|
|
80
|
+
* @param serviceUrl optional, the service url to validate
|
|
81
|
+
* @param username user name
|
|
82
|
+
* @param password password
|
|
83
|
+
* @param ignoreCertError optional, ignore some certificate errors
|
|
84
|
+
* @returns true if the authentication is successful, false if not, or an error message string
|
|
85
|
+
*/
|
|
86
|
+
validateAuth(serviceUrl: string, username: string, password: string, ignoreCertError?: boolean): Promise<boolean | string>;
|
|
87
|
+
/**
|
|
88
|
+
* Reset the validity state.
|
|
89
|
+
*/
|
|
90
|
+
private resetValidity;
|
|
91
|
+
/**
|
|
92
|
+
* Set the rejectUnauthorized option of the global https agent.
|
|
93
|
+
*
|
|
94
|
+
* @param rejectUnauthorized - true to reject unauthorized certificates, false to accept them
|
|
95
|
+
*/
|
|
96
|
+
static setGlobalRejectUnauthorized(rejectUnauthorized: boolean): void;
|
|
97
|
+
}
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=connectionValidator.d.ts.map
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ConnectionValidator = void 0;
|
|
16
|
+
const btp_utils_1 = require("@sap-ux/btp-utils");
|
|
17
|
+
const error_handler_1 = require("../../../error-handler/error-handler");
|
|
18
|
+
const prompt_helpers_1 = require("../../prompt-helpers");
|
|
19
|
+
const i18n_1 = require("../../../i18n");
|
|
20
|
+
const https_1 = __importDefault(require("https"));
|
|
21
|
+
const logger_helper_1 = __importDefault(require("../../logger-helper"));
|
|
22
|
+
const axios_extension_1 = require("@sap-ux/axios-extension");
|
|
23
|
+
// Cert errors that may be ignored by prompt user
|
|
24
|
+
const ignorableCertErrors = [error_handler_1.ERROR_TYPE.CERT_SELF_SIGNED, error_handler_1.ERROR_TYPE.CERT_SELF_SIGNED_CERT_IN_CHAIN];
|
|
25
|
+
/**
|
|
26
|
+
* Class that validates the connection to a service url or catalog url.
|
|
27
|
+
* This will determine if authentication is required and if the service/catalog is reachable, generating messages to guide the user.
|
|
28
|
+
* It is optimized for re-validation of the same url, so that the validation is not repeated if not required.
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
class ConnectionValidator {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.validity = {};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Getter for the axios configuration.
|
|
37
|
+
*
|
|
38
|
+
* @returns the axios configuration
|
|
39
|
+
*/
|
|
40
|
+
get axiosConfig() {
|
|
41
|
+
return this._axiosConfig;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the odata service instance.
|
|
45
|
+
*
|
|
46
|
+
* @returns the odata service instance
|
|
47
|
+
*/
|
|
48
|
+
get odataService() {
|
|
49
|
+
return this._odataService;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Calls a given service url to test its reachability and authentication requirements.
|
|
53
|
+
*
|
|
54
|
+
* @param url a service url (<protocol://<host>:<port>/<service-path>)
|
|
55
|
+
* @param username optional username
|
|
56
|
+
* @param password optional password
|
|
57
|
+
* @param [ignoreCertError] optional, ignore some certificate errors
|
|
58
|
+
* @returns the status code or error returned by the connection attempt
|
|
59
|
+
*/
|
|
60
|
+
checkSapService(url, username, password, ignoreCertError = false) {
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
const isBAS = (0, btp_utils_1.isAppStudio)();
|
|
64
|
+
try {
|
|
65
|
+
// Auto add trailing '/' to path
|
|
66
|
+
url.pathname = !((_a = url.pathname) === null || _a === void 0 ? void 0 : _a.endsWith('/')) ? `${url.pathname}/` : url.pathname;
|
|
67
|
+
// VSCode default extension proxy setting does not allow bypassing cert errors using httpsAgent (as used by Axios)
|
|
68
|
+
// so we must use globalAgent to bypass cert validation
|
|
69
|
+
if (ignoreCertError === true) {
|
|
70
|
+
ConnectionValidator.setGlobalRejectUnauthorized(!ignoreCertError);
|
|
71
|
+
}
|
|
72
|
+
if (isBAS) {
|
|
73
|
+
url.searchParams.append('saml2', 'disabled');
|
|
74
|
+
}
|
|
75
|
+
let axiosConfig = {
|
|
76
|
+
params: url.searchParams,
|
|
77
|
+
ignoreCertErrors: ignoreCertError,
|
|
78
|
+
cookies: ''
|
|
79
|
+
};
|
|
80
|
+
if (username && password) {
|
|
81
|
+
axiosConfig = Object.assign(axiosConfig, {
|
|
82
|
+
auth: {
|
|
83
|
+
username,
|
|
84
|
+
password
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
this._axiosConfig = axiosConfig;
|
|
89
|
+
this._odataService = (0, axios_extension_1.createServiceForUrl)(url.origin + url.pathname, this._axiosConfig);
|
|
90
|
+
logger_helper_1.default.attachAxiosLogger(this._odataService.interceptors);
|
|
91
|
+
yield this._odataService.get('');
|
|
92
|
+
return 200;
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
logger_helper_1.default.logger.debug(`ConnectionValidator.checkSapService() - error: ${e.message}`);
|
|
96
|
+
if (e === null || e === void 0 ? void 0 : e.isAxiosError) {
|
|
97
|
+
// Only throw for 500 on App Studio
|
|
98
|
+
if (((_b = e === null || e === void 0 ? void 0 : e.response) === null || _b === void 0 ? void 0 : _b.status) === 500 && isBAS) {
|
|
99
|
+
throw e;
|
|
100
|
+
}
|
|
101
|
+
return ((_c = e === null || e === void 0 ? void 0 : e.response) === null || _c === void 0 ? void 0 : _c.status) || (e === null || e === void 0 ? void 0 : e.code);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
throw e;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
// Reset global cert validation
|
|
109
|
+
ConnectionValidator.setGlobalRejectUnauthorized(true);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Validates the service url format as well as its reachability.
|
|
115
|
+
*
|
|
116
|
+
* @param serviceUrl the odata service url to validate
|
|
117
|
+
* @param ignoreCertError ignore some certificate errors
|
|
118
|
+
* @param forceReValidation force re-validation of the url
|
|
119
|
+
* @returns true if the url is reachable, false if not, or an error message string
|
|
120
|
+
*/
|
|
121
|
+
validateUrl(serviceUrl, ignoreCertError = false, forceReValidation = false) {
|
|
122
|
+
var _a;
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
if (this.isEmptyString(serviceUrl)) {
|
|
125
|
+
this.resetValidity();
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const url = new URL(serviceUrl);
|
|
130
|
+
if (!forceReValidation && this.isUrlValidated(serviceUrl)) {
|
|
131
|
+
return (_a = this.validity.reachable) !== null && _a !== void 0 ? _a : false;
|
|
132
|
+
}
|
|
133
|
+
if (url.origin === 'null') {
|
|
134
|
+
return (0, i18n_1.t)('errors.invalidUrl');
|
|
135
|
+
}
|
|
136
|
+
// Ignore path if a system url
|
|
137
|
+
const status = yield this.checkSapService(url, undefined, undefined, ignoreCertError);
|
|
138
|
+
logger_helper_1.default.logger.debug(`ConnectionValidator.validateUrl() - status: ${status}; url: ${serviceUrl}`);
|
|
139
|
+
this.validity.urlFormat = true;
|
|
140
|
+
this._validatedUrl = serviceUrl;
|
|
141
|
+
return this.getValidationResultFromStatusCode(status);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// More helpful context specific error
|
|
145
|
+
if (error_handler_1.ErrorHandler.getErrorType(error) === error_handler_1.ERROR_TYPE.CONNECTION) {
|
|
146
|
+
this.validity.reachable = false;
|
|
147
|
+
return prompt_helpers_1.errorHandler.logErrorMsgs((0, i18n_1.t)('errors.serviceUrlNotFound', { url: serviceUrl }));
|
|
148
|
+
}
|
|
149
|
+
this.resetValidity();
|
|
150
|
+
const errorMsg = prompt_helpers_1.errorHandler.getErrorMsg(error);
|
|
151
|
+
return errorMsg !== null && errorMsg !== void 0 ? errorMsg : (0, i18n_1.t)('errors.invalidUrl');
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Translate the status code into a validation result.
|
|
157
|
+
* Sets the instance validity state based on the status code.
|
|
158
|
+
*
|
|
159
|
+
* @param status a http request status code used to determine the validation result
|
|
160
|
+
* @returns
|
|
161
|
+
*/
|
|
162
|
+
getValidationResultFromStatusCode(status) {
|
|
163
|
+
var _a, _b, _c;
|
|
164
|
+
if (status === 200) {
|
|
165
|
+
this.validity.authenticated = true;
|
|
166
|
+
this.validity.authRequired = false;
|
|
167
|
+
}
|
|
168
|
+
else if (status === 404) {
|
|
169
|
+
this.validity.reachable = false;
|
|
170
|
+
return (_a = error_handler_1.ErrorHandler.getErrorMsgFromType(error_handler_1.ERROR_TYPE.NOT_FOUND)) !== null && _a !== void 0 ? _a : false;
|
|
171
|
+
}
|
|
172
|
+
else if (error_handler_1.ErrorHandler.isCertError(status)) {
|
|
173
|
+
this.validity.reachable = true;
|
|
174
|
+
this.validity.canSkipCertError = ignorableCertErrors.includes(error_handler_1.ErrorHandler.getErrorType(status));
|
|
175
|
+
return (_b = prompt_helpers_1.errorHandler.getValidationErrorHelp(status, false)) !== null && _b !== void 0 ? _b : false;
|
|
176
|
+
}
|
|
177
|
+
else if (error_handler_1.ErrorHandler.getErrorType(status) === error_handler_1.ERROR_TYPE.AUTH) {
|
|
178
|
+
this.validity.reachable = true;
|
|
179
|
+
this.validity.authRequired = true;
|
|
180
|
+
}
|
|
181
|
+
else if (error_handler_1.ErrorHandler.getErrorType(status) === error_handler_1.ERROR_TYPE.REDIRECT) {
|
|
182
|
+
this.validity.reachable = true;
|
|
183
|
+
return (0, i18n_1.t)('errors.urlRedirect');
|
|
184
|
+
}
|
|
185
|
+
else if (status !== 404) {
|
|
186
|
+
this.validity.reachable = false;
|
|
187
|
+
return (_c = error_handler_1.ErrorHandler.getErrorMsgFromType(error_handler_1.ERROR_TYPE.CONNECTION, `http code: ${status}`)) !== null && _c !== void 0 ? _c : false;
|
|
188
|
+
}
|
|
189
|
+
this.validity.reachable = true;
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Is a string nil or whitespace only.
|
|
194
|
+
*
|
|
195
|
+
* @param url the string to test
|
|
196
|
+
* @returns true if the string is nil or whitespace
|
|
197
|
+
*/
|
|
198
|
+
isEmptyString(url) {
|
|
199
|
+
return !url || url.trim().length === 0;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Tests if the url has already been validated.
|
|
203
|
+
*
|
|
204
|
+
* @param url the full url to test for previous validation
|
|
205
|
+
* @returns true if the url has already been validated
|
|
206
|
+
*/
|
|
207
|
+
isUrlValidated(url) {
|
|
208
|
+
if (this._validatedUrl === url) {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
this.resetValidity();
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Test the connectivity with the specified service url using the provided credentials.
|
|
216
|
+
*
|
|
217
|
+
* @param serviceUrl optional, the service url to validate
|
|
218
|
+
* @param username user name
|
|
219
|
+
* @param password password
|
|
220
|
+
* @param ignoreCertError optional, ignore some certificate errors
|
|
221
|
+
* @returns true if the authentication is successful, false if not, or an error message string
|
|
222
|
+
*/
|
|
223
|
+
validateAuth(serviceUrl, username, password, ignoreCertError = false) {
|
|
224
|
+
var _a;
|
|
225
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
+
if (!serviceUrl) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
if (!this.validity.reachable) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
const url = new URL(serviceUrl);
|
|
234
|
+
this.validity.authenticated =
|
|
235
|
+
(yield this.checkSapService(url, username, password, ignoreCertError)) === 200;
|
|
236
|
+
return this.validity.authenticated === true ? true : (0, i18n_1.t)('errors.authenticationFailed');
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
return (_a = prompt_helpers_1.errorHandler.getErrorMsg(error)) !== null && _a !== void 0 ? _a : false;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Reset the validity state.
|
|
245
|
+
*/
|
|
246
|
+
resetValidity() {
|
|
247
|
+
this.validity.urlFormat = false;
|
|
248
|
+
delete this.validity.reachable;
|
|
249
|
+
delete this.validity.authRequired;
|
|
250
|
+
delete this.validity.authenticated;
|
|
251
|
+
delete this.validity.canSkipCertError;
|
|
252
|
+
this._validatedUrl = undefined;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Set the rejectUnauthorized option of the global https agent.
|
|
256
|
+
*
|
|
257
|
+
* @param rejectUnauthorized - true to reject unauthorized certificates, false to accept them
|
|
258
|
+
*/
|
|
259
|
+
static setGlobalRejectUnauthorized(rejectUnauthorized) {
|
|
260
|
+
if (https_1.default.globalAgent.options) {
|
|
261
|
+
https_1.default.globalAgent.options.rejectUnauthorized = rejectUnauthorized;
|
|
262
|
+
}
|
|
263
|
+
//@ts-expect-error - fallbackAgent is only present in BoundHttpsProxyAgent implementation and is not part of the Node.js API
|
|
264
|
+
if (https_1.default.globalAgent.fallbackAgent) {
|
|
265
|
+
//@ts-expect-error - fallbackAgent is not typed in Node.js API
|
|
266
|
+
https_1.default.globalAgent.fallbackAgent.options.rejectUnauthorized = rejectUnauthorized;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
exports.ConnectionValidator = ConnectionValidator;
|
|
271
|
+
//# sourceMappingURL=connectionValidator.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Question } from 'inquirer';
|
|
2
|
+
import type { OdataServiceAnswers, OdataServicePromptOptions } from '../../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Get the service URL questions.
|
|
5
|
+
*
|
|
6
|
+
* @param promptOptions prompt options that can be passed to the service URL questions to configure behaviour
|
|
7
|
+
* @param promptOptions.serviceUrl see {@link OdataServicePromptOptions}
|
|
8
|
+
* @param promptOptions.serviceUrlPassword see {@link OdataServicePromptOptions}
|
|
9
|
+
* @returns the odata service URL questions
|
|
10
|
+
*/
|
|
11
|
+
export declare function getServiceUrlQuestions({ serviceUrl: serviceUrlOpts, serviceUrlPassword: passwordOpts }?: OdataServicePromptOptions): Question<OdataServiceAnswers>[];
|
|
12
|
+
//# sourceMappingURL=questions.d.ts.map
|