@sap-ux/odata-service-inquirer 0.5.33 → 0.5.35

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.
@@ -14,6 +14,7 @@ export declare enum ERROR_TYPE {
14
14
  CERT_SELF_SIGNED_CERT_IN_CHAIN = "CERT_SELF_SIGNED_CERT_IN_CHAIN",
15
15
  UNKNOWN = "UNKNOWN",
16
16
  INVALID_URL = "INVALID_URL",
17
+ TIMEOUT = "TIMEOUT",
17
18
  CONNECTION = "CONNECTION",
18
19
  SERVICES_UNAVAILABLE = "SERVICES_UNAVAILABLE",// All services
19
20
  SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",// Specific service
@@ -32,7 +33,7 @@ export declare enum ERROR_TYPE {
32
33
  NO_V4_SERVICES = "NO_V4_SERVICES"
33
34
  }
34
35
  export declare const ERROR_MAP: Record<ERROR_TYPE, RegExp[]>;
35
- type ValidationLinkOrString = string | ValidationLink | undefined;
36
+ type ValidationLinkOrString = string | ValidationLink;
36
37
  /**
37
38
  * Maps errors to end-user messages using some basic root cause analysis based on regex matching.
38
39
  * This class will also log errors and provide help links for validation errors in some limited use cases.
@@ -138,7 +139,7 @@ export declare class ErrorHandler {
138
139
  * @param reset optional, resets the previous error state if true
139
140
  * @returns An instance of @see {ValidationLink}
140
141
  */
141
- getValidationErrorHelp(error?: any, reset?: boolean): ValidationLinkOrString;
142
+ getValidationErrorHelp(error?: any, reset?: boolean): ValidationLinkOrString | undefined;
142
143
  /**
143
144
  * Get the error message for the specified error type.
144
145
  *
@@ -177,7 +178,7 @@ export declare class ErrorHandler {
177
178
  * @param errorMsg - the message to appear with the help link
178
179
  * @returns A validation help link or help link message
179
180
  */
180
- static getHelpForError(errorType: ERROR_TYPE, errorMsg?: string): ValidationLinkOrString;
181
+ static getHelpForError(errorType: ERROR_TYPE, errorMsg?: string): ValidationLinkOrString | undefined;
181
182
  }
182
183
  export {};
183
184
  //# sourceMappingURL=error-handler.d.ts.map
@@ -23,6 +23,7 @@ var ERROR_TYPE;
23
23
  ERROR_TYPE["CERT_SELF_SIGNED_CERT_IN_CHAIN"] = "CERT_SELF_SIGNED_CERT_IN_CHAIN";
24
24
  ERROR_TYPE["UNKNOWN"] = "UNKNOWN";
25
25
  ERROR_TYPE["INVALID_URL"] = "INVALID_URL";
26
+ ERROR_TYPE["TIMEOUT"] = "TIMEOUT";
26
27
  ERROR_TYPE["CONNECTION"] = "CONNECTION";
27
28
  ERROR_TYPE["SERVICES_UNAVAILABLE"] = "SERVICES_UNAVAILABLE";
28
29
  ERROR_TYPE["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
@@ -50,6 +51,7 @@ exports.ERROR_MAP = {
50
51
  /Unable to retrieve SAP Business Accelerator Hub key/ // API Hub error msg
51
52
  ],
52
53
  [ERROR_TYPE.AUTH_TIMEOUT]: [/UAATimeoutError/],
54
+ [ERROR_TYPE.TIMEOUT]: [/Timeout/],
53
55
  [ERROR_TYPE.CERT]: [], // General cert error, unspecified root cause
54
56
  [ERROR_TYPE.CERT_UKNOWN_OR_INVALID]: [
55
57
  /UNABLE_TO_GET_ISSUER_CERT/,
@@ -60,7 +62,7 @@ exports.ERROR_MAP = {
60
62
  [ERROR_TYPE.CERT_SELF_SIGNED]: [/DEPTH_ZERO_SELF_SIGNED_CERT/],
61
63
  [ERROR_TYPE.CERT_SELF_SIGNED_CERT_IN_CHAIN]: [/SELF_SIGNED_CERT_IN_CHAIN/],
62
64
  [ERROR_TYPE.UNKNOWN]: [],
63
- [ERROR_TYPE.CONNECTION]: [/ENOTFOUND/, /ECONNRESET/, /ECONNREFUSED/],
65
+ [ERROR_TYPE.CONNECTION]: [/ENOTFOUND/, /ECONNRESET/, /ECONNREFUSED/, /ConnectionError/],
64
66
  [ERROR_TYPE.SERVICES_UNAVAILABLE]: [],
65
67
  [ERROR_TYPE.SERVICE_UNAVAILABLE]: [/503/],
66
68
  [ERROR_TYPE.INVALID_URL]: [/Invalid URL/, /ERR_INVALID_URL/],
@@ -111,6 +113,7 @@ class ErrorHandler {
111
113
  }),
112
114
  [ERROR_TYPE.AUTH]: (0, i18n_1.t)('errors.authenticationFailed', { error }),
113
115
  [ERROR_TYPE.AUTH_TIMEOUT]: (0, i18n_1.t)('errors.authenticationTimeout'),
116
+ [ERROR_TYPE.TIMEOUT]: (0, i18n_1.t)('errors.timeout, { error }'),
114
117
  [ERROR_TYPE.INVALID_URL]: (0, i18n_1.t)('errors.invalidUrl'),
115
118
  [ERROR_TYPE.CONNECTION]: (0, i18n_1.t)('errors.connectionError', {
116
119
  error: error?.message || JSON.stringify(error)
@@ -170,7 +173,8 @@ class ErrorHandler {
170
173
  [ERROR_TYPE.NOT_FOUND]: undefined,
171
174
  [ERROR_TYPE.ODATA_URL_NOT_FOUND]: undefined,
172
175
  [ERROR_TYPE.INTERNAL_SERVER_ERROR]: undefined,
173
- [ERROR_TYPE.NO_V2_SERVICES]: undefined
176
+ [ERROR_TYPE.NO_V2_SERVICES]: undefined,
177
+ [ERROR_TYPE.TIMEOUT]: undefined
174
178
  };
175
179
  return errorToHelp[errorType];
176
180
  };
@@ -39,7 +39,7 @@ export declare class ConnectionValidator {
39
39
  *
40
40
  * @returns the axios configuration
41
41
  */
42
- get axiosConfig(): AxiosRequestConfig | undefined;
42
+ get axiosConfig(): AxiosRequestConfig;
43
43
  /**
44
44
  * Get the odata service instance.
45
45
  *
@@ -18,6 +18,8 @@ const types_2 = require("./types");
18
18
  const questions_1 = require("../abap-on-prem/questions");
19
19
  const questions_2 = require("../abap-on-btp/questions");
20
20
  const logger_helper_1 = __importDefault(require("../../../logger-helper"));
21
+ const prompt_helpers_2 = require("../../../prompt-helpers");
22
+ const error_handler_1 = require("../../../../error-handler/error-handler");
21
23
  // New system choice value is a hard to guess string to avoid conflicts with existing system names or user named systems
22
24
  // since it will be used as a new system value in the system selection prompt.
23
25
  exports.newSystemChoiceValue = '!@£*&937newSystem*X~qy^';
@@ -233,6 +235,10 @@ function getSystemServiceQuestion(connectValidator, promptNamespace, promptOptio
233
235
  if (!connectValidator.validatedUrl) {
234
236
  return false;
235
237
  }
238
+ // if no choices are available and an error is present, return the error message
239
+ if (serviceChoices.length === 0 && prompt_helpers_2.errorHandler.hasError()) {
240
+ return error_handler_1.ErrorHandler.getHelpForError(error_handler_1.ERROR_TYPE.SERVICES_UNAVAILABLE) ?? false;
241
+ }
236
242
  // Dont re-request the same service details
237
243
  if (service && previousService?.servicePath !== service.servicePath) {
238
244
  previousService = service;
@@ -254,6 +260,10 @@ function getSystemServiceQuestion(connectValidator, promptNamespace, promptOptio
254
260
  throw new Error(result);
255
261
  }
256
262
  }
263
+ if (serviceChoices.length === 0 && prompt_helpers_2.errorHandler.hasError()) {
264
+ const noServicesError = error_handler_1.ErrorHandler.getHelpForError(error_handler_1.ERROR_TYPE.SERVICES_UNAVAILABLE).toString();
265
+ throw new Error(noServicesError);
266
+ }
257
267
  return false;
258
268
  },
259
269
  name: `${promptNamespace}:${cliServicePromptName}`
@@ -1,4 +1,4 @@
1
- import { ServiceType, type Annotations, type CatalogService, type V2CatalogService, type ServiceProvider } from '@sap-ux/axios-extension';
1
+ import { type CatalogService, ServiceType, V2CatalogService, type Annotations, type ServiceProvider } from '@sap-ux/axios-extension';
2
2
  import type { ListChoiceOptions } from 'inquirer';
3
3
  import type { ServiceAnswer } from './types';
4
4
  import type { ConnectionValidator } from '../../../connectionValidator';
@@ -9,6 +9,7 @@ const i18n_1 = require("../../../../i18n");
9
9
  const logger_helper_1 = __importDefault(require("../../../logger-helper"));
10
10
  const utils_1 = require("../../../../utils");
11
11
  const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
12
+ const prompt_helpers_1 = require("../../../prompt-helpers");
12
13
  // Service ids continaining these paths should not be offered as UI compatible services
13
14
  const nonUIServicePaths = ['/IWBEP/COMMON/'];
14
15
  /**
@@ -47,6 +48,18 @@ const createServiceChoices = (serviceInfos) => {
47
48
  });
48
49
  return choices.sort((a, b) => (a.name ? a.name.localeCompare(b.name ?? '') : 0));
49
50
  };
51
+ /**
52
+ * Logs the catalog reuest errors.
53
+ *
54
+ * @param requestErrors catalog request errors
55
+ */
56
+ function logErrorsForHelp(requestErrors) {
57
+ // Log the first error only
58
+ const catalogErrors = Object.values(requestErrors);
59
+ if (catalogErrors.length > 0) {
60
+ catalogErrors.forEach((error) => prompt_helpers_1.errorHandler.logErrorMsgs(error));
61
+ }
62
+ }
50
63
  /**
51
64
  * Get the service choices from the specified catalogs.
52
65
  *
@@ -54,18 +67,30 @@ const createServiceChoices = (serviceInfos) => {
54
67
  * @returns service choices based on the provided catalogs
55
68
  */
56
69
  async function getServiceChoices(catalogs) {
70
+ const requestErrors = {};
57
71
  const listServicesRequests = catalogs.map(async (catalog) => {
58
72
  try {
59
73
  return await catalog.listServices();
60
74
  }
61
75
  catch (error) {
62
- logger_helper_1.default.logger.error(`An error occurred requesting services from: ${catalog.entitySet}. Some services may not be listed.`);
76
+ logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceCatalogRequest', {
77
+ catalogRequestUri: catalog.getUri(),
78
+ entitySet: catalog.entitySet,
79
+ error
80
+ }));
81
+ // Save any errors for processing later as we may show more useful message to the user
82
+ Object.assign(requestErrors, {
83
+ [catalog instanceof axios_extension_1.V2CatalogService ? axios_extension_1.ODataVersion.v2 : axios_extension_1.ODataVersion.v4]: error
84
+ });
63
85
  return [];
64
86
  }
65
87
  });
66
88
  const serviceInfos = await Promise.all(listServicesRequests);
67
89
  const flatServices = serviceInfos?.flat() ?? [];
68
90
  logger_helper_1.default.logger.debug(`Number of services available: ${flatServices.length}`);
91
+ if (flatServices.length === 0) {
92
+ logErrorsForHelp(requestErrors);
93
+ }
69
94
  return createServiceChoices(flatServices);
70
95
  }
71
96
  exports.getServiceChoices = getServiceChoices;
@@ -8,8 +8,8 @@ const inquirer_common_1 = require("@sap-ux/inquirer-common");
8
8
  const i18n_1 = require("../../../i18n");
9
9
  const types_1 = require("../../../types");
10
10
  const utils_1 = require("../../../utils");
11
- const logger_helper_1 = __importDefault(require("../../logger-helper"));
12
11
  const connectionValidator_1 = require("../../connectionValidator");
12
+ const logger_helper_1 = __importDefault(require("../../logger-helper"));
13
13
  const types_2 = require("./types");
14
14
  const validators_1 = require("./validators");
15
15
  /**
@@ -39,7 +39,7 @@ function getServiceUrlPrompt(connectValidator, requiredVersion) {
39
39
  if (!connectValidator.validity.authRequired && connectValidator.odataService) {
40
40
  return (0, validators_1.validateService)(url, {
41
41
  odataService: connectValidator.odataService,
42
- abapServiceProvider: connectValidator.serviceProvider
42
+ axiosConfig: connectValidator.axiosConfig
43
43
  }, requiredVersion);
44
44
  }
45
45
  return true;
@@ -82,7 +82,7 @@ function getIgnoreCertErrorsPrompt(connectValidator, requiredVersion) {
82
82
  if (!connectValidator.validity.authRequired && connectValidator.odataService) {
83
83
  return (0, validators_1.validateService)(serviceUrl, {
84
84
  odataService: connectValidator.odataService,
85
- abapServiceProvider: connectValidator.serviceProvider
85
+ axiosConfig: connectValidator.axiosConfig
86
86
  }, requiredVersion, ignoreCertError);
87
87
  }
88
88
  return true;
@@ -123,7 +123,7 @@ function getCliIgnoreCertValidatePrompt(connectValidator, requiredVersion) {
123
123
  // Will log on CLI
124
124
  const validService = await (0, validators_1.validateService)(serviceUrl, {
125
125
  odataService: connectValidator.odataService,
126
- abapServiceProvider: connectValidator.serviceProvider
126
+ axiosConfig: connectValidator.axiosConfig
127
127
  }, requiredVersion, true);
128
128
  if (validService !== true) {
129
129
  throw new Error((0, i18n_1.t)('errors.exitingGeneration', { exitReason: validService.toString() }));
@@ -183,7 +183,7 @@ function getPasswordPrompt(connectValidator, requiredVersion) {
183
183
  if (validAuth === true && connectValidator.odataService) {
184
184
  return (0, validators_1.validateService)(serviceUrl, {
185
185
  odataService: connectValidator.odataService,
186
- abapServiceProvider: connectValidator.serviceProvider
186
+ axiosConfig: connectValidator.axiosConfig
187
187
  }, requiredVersion, ignoreCertError);
188
188
  }
189
189
  return validAuth;
@@ -1,4 +1,4 @@
1
- import type { AbapServiceProvider, ODataService } from '@sap-ux/axios-extension';
1
+ import { type AxiosRequestConfig, type ODataService } from '@sap-ux/axios-extension';
2
2
  import type { OdataVersion } from '@sap-ux/odata-service-writer';
3
3
  /**
4
4
  * Validates that a service specified by the service url is accessible, has the required version and returns valid metadata.
@@ -7,13 +7,13 @@ import type { OdataVersion } from '@sap-ux/odata-service-writer';
7
7
  * @param url the full odata service url including query parameters
8
8
  * @param connectionConfig the connection configuration to use for the validation, a subset of the ConnectionValidator properties
9
9
  * @param connectionConfig.odataService the odata service instance used to retrieve the metadata (as used by ConnectionValidator)
10
- * @param connectionConfig.abapServiceProvider the abap service provider instance used to retrieve annotations (as used by ConnectionValidator)
10
+ * @param connectionConfig.axiosConfig the axios config to use for the annotations request (as used by ConnectionValidator)
11
11
  * @param requiredVersion if specified and the service odata version does not match this version, an error is returned
12
12
  * @param ignoreCertError if true some certificate errors are ignored
13
13
  * @returns true if a valid odata service was returned, false or an error message string otherwise
14
14
  */
15
- export declare function validateService(url: string, { odataService, abapServiceProvider }: {
15
+ export declare function validateService(url: string, { odataService, axiosConfig }: {
16
16
  odataService: ODataService;
17
- abapServiceProvider: AbapServiceProvider;
17
+ axiosConfig: AxiosRequestConfig;
18
18
  }, requiredVersion?: OdataVersion | undefined, ignoreCertError?: boolean): Promise<boolean | string>;
19
19
  //# sourceMappingURL=validators.d.ts.map
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.validateService = void 0;
7
+ const axios_extension_1 = require("@sap-ux/axios-extension");
7
8
  const error_handler_1 = require("../../../error-handler/error-handler");
8
9
  const i18n_1 = require("../../../i18n");
9
10
  const types_1 = require("../../../types");
@@ -18,12 +19,12 @@ const prompt_helpers_1 = require("../../prompt-helpers");
18
19
  * @param url the full odata service url including query parameters
19
20
  * @param connectionConfig the connection configuration to use for the validation, a subset of the ConnectionValidator properties
20
21
  * @param connectionConfig.odataService the odata service instance used to retrieve the metadata (as used by ConnectionValidator)
21
- * @param connectionConfig.abapServiceProvider the abap service provider instance used to retrieve annotations (as used by ConnectionValidator)
22
+ * @param connectionConfig.axiosConfig the axios config to use for the annotations request (as used by ConnectionValidator)
22
23
  * @param requiredVersion if specified and the service odata version does not match this version, an error is returned
23
24
  * @param ignoreCertError if true some certificate errors are ignored
24
25
  * @returns true if a valid odata service was returned, false or an error message string otherwise
25
26
  */
26
- async function validateService(url, { odataService, abapServiceProvider }, requiredVersion = undefined, ignoreCertError = false) {
27
+ async function validateService(url, { odataService, axiosConfig }, requiredVersion = undefined, ignoreCertError = false) {
27
28
  try {
28
29
  if (ignoreCertError === true) {
29
30
  connectionValidator_1.ConnectionValidator.setGlobalRejectUnauthorized(!ignoreCertError);
@@ -49,7 +50,8 @@ async function validateService(url, { odataService, abapServiceProvider }, requi
49
50
  // Best effort attempt to get annotations but dont throw an error if it fails as this may not even be an Abap system
50
51
  try {
51
52
  // Create an abap provider instance to get the annotations using the same request config
52
- const catalogService = abapServiceProvider.catalog(serviceOdataVersion);
53
+ const abapProvider = (0, axios_extension_1.createForAbap)(axiosConfig);
54
+ const catalogService = abapProvider.catalog(serviceOdataVersion);
53
55
  logger_helper_1.default.attachAxiosLogger(catalogService.interceptors);
54
56
  logger_helper_1.default.logger.debug('Getting annotations for service');
55
57
  const annotations = await catalogService.getAnnotations({ path: fullUrl.pathname });
@@ -130,6 +130,7 @@
130
130
  "authenticationTimeout": "Authorization was not verified within the allowed time. Please ensure you have authenticated using the associated browser window.",
131
131
  "invalidUrl": "Not a valid URL",
132
132
  "connectionError": "A connection error occurred, please ensure the target host is available on the network: {{- error}}",
133
+ "timeout": "A connection timeout error occurred: {{- error}}",
133
134
  "serviceUnavailable": "Selected service is returning an error.",
134
135
  "catalogServiceNotActive": "Catalog service is not active",
135
136
  "internalServerError": "The URL you have provided cannot be accessed and is returning: '{{- error}}'. Please ensure that the URL is accessible externally.",
@@ -155,7 +156,8 @@
155
156
  "serviceTypeRequestError": "Error retrieving service type: {{- error}}",
156
157
  "noAbapEnvsInCFSpace": "No ABAP environments in CF space found.",
157
158
  "abapEnvsCFDiscoveryFailed": "Discovering ABAP Environments failed. Please ensure you are logged into Cloud Foundry (see https://docs.cloudfoundry.org/cf-cli/getting-started.html#login).",
158
- "abapServiceAuthenticationFailed": "ABAP environment authentication using UAA failed."
159
+ "abapServiceAuthenticationFailed": "ABAP environment authentication using UAA failed.",
160
+ "serviceCatalogRequest": "An error occurred requesting services from: {{- catalogRequestUri }} and entity set: {{entitySet}}. {{error}}"
159
161
  },
160
162
  "texts": {
161
163
  "anExpiredCert": "an expired",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/odata-service-inquirer",
3
3
  "description": "Prompts module that can prompt users for inputs required for odata service writing",
4
- "version": "0.5.33",
4
+ "version": "0.5.35",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",