@sap-ux/odata-service-inquirer 0.5.60 → 0.6.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/i18n.js +15 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +10 -9
- package/dist/prompts/connectionValidator.d.ts +63 -12
- package/dist/prompts/connectionValidator.js +208 -50
- package/dist/prompts/datasources/cap-project/questions.js +2 -1
- package/dist/prompts/datasources/sap-system/abap-on-btp/questions.d.ts +3 -2
- package/dist/prompts/datasources/sap-system/abap-on-btp/questions.js +10 -10
- package/dist/prompts/datasources/sap-system/abap-on-prem/questions.d.ts +9 -11
- package/dist/prompts/datasources/sap-system/abap-on-prem/questions.js +21 -55
- package/dist/prompts/datasources/sap-system/credentials/questions.d.ts +21 -0
- package/dist/prompts/datasources/sap-system/credentials/questions.js +123 -0
- package/dist/prompts/datasources/sap-system/new-system/questions.d.ts +4 -26
- package/dist/prompts/datasources/sap-system/new-system/questions.js +18 -168
- package/dist/prompts/datasources/sap-system/new-system/types.d.ts +0 -10
- package/dist/prompts/datasources/sap-system/service-selection/index.d.ts +3 -0
- package/dist/prompts/datasources/sap-system/service-selection/index.js +19 -0
- package/dist/prompts/datasources/sap-system/service-selection/questions.d.ts +15 -0
- package/dist/prompts/datasources/sap-system/service-selection/questions.js +146 -0
- package/dist/prompts/datasources/sap-system/service-selection/service-helper.d.ts +71 -0
- package/dist/prompts/datasources/sap-system/service-selection/service-helper.js +282 -0
- package/dist/prompts/datasources/sap-system/service-selection/types.d.ts +11 -0
- package/dist/prompts/datasources/sap-system/service-selection/types.js +3 -0
- package/dist/prompts/datasources/sap-system/system-selection/index.d.ts +2 -0
- package/dist/prompts/datasources/sap-system/system-selection/index.js +18 -0
- package/dist/prompts/datasources/sap-system/system-selection/prompt-helpers.d.ts +44 -0
- package/dist/prompts/datasources/sap-system/system-selection/prompt-helpers.js +190 -0
- package/dist/prompts/datasources/sap-system/system-selection/questions.d.ts +40 -0
- package/dist/prompts/datasources/sap-system/system-selection/questions.js +182 -0
- package/dist/prompts/datasources/sap-system/validators.d.ts +8 -0
- package/dist/prompts/datasources/sap-system/validators.js +17 -0
- package/dist/prompts/datasources/service-url/questions.js +4 -3
- package/dist/prompts/datasources/service-url/validators.js +8 -9
- package/dist/prompts/prompt-helpers.d.ts +2 -3
- package/dist/prompts/prompt-helpers.js +4 -13
- package/dist/prompts/prompts.js +5 -34
- package/dist/prompts/validators.d.ts +1 -1
- package/dist/prompts/validators.js +1 -1
- package/dist/translations/odata-service-inquirer.i18n.json +25 -37
- package/dist/types.d.ts +57 -45
- package/dist/types.js +7 -41
- package/dist/utils/index.d.ts +5 -18
- package/dist/utils/index.js +10 -55
- package/package.json +10 -9
- package/dist/error-handler/error-handler.d.ts +0 -184
- package/dist/error-handler/error-handler.js +0 -465
- package/dist/prompts/datasources/sap-system/abap-on-btp/cf-helper.d.ts +0 -9
- package/dist/prompts/datasources/sap-system/abap-on-btp/cf-helper.js +0 -54
- package/dist/prompts/datasources/sap-system/new-system/service-helper.d.ts +0 -43
- package/dist/prompts/datasources/sap-system/new-system/service-helper.js +0 -175
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getSystemServiceQuestion = getSystemServiceQuestion;
|
|
7
|
+
const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
|
|
8
|
+
const inquirer_common_1 = require("@sap-ux/inquirer-common");
|
|
9
|
+
const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
|
|
10
|
+
const i18n_1 = require("../../../../i18n");
|
|
11
|
+
const types_1 = require("../../../../types");
|
|
12
|
+
const utils_1 = require("../../../../utils");
|
|
13
|
+
const logger_helper_1 = __importDefault(require("../../../logger-helper"));
|
|
14
|
+
const prompt_helpers_1 = require("../../../prompt-helpers");
|
|
15
|
+
const service_helper_1 = require("../service-selection/service-helper");
|
|
16
|
+
const cliServicePromptName = 'cliServiceSelection';
|
|
17
|
+
/**
|
|
18
|
+
* Get the service selection prompt for an Abap system connection (on-prem or on-btp). The service selection prompt is used to select a service from the system catalog.
|
|
19
|
+
*
|
|
20
|
+
* @param connectValidator A reference to the active connection validator, used to validate the service selection and retrieve service details.
|
|
21
|
+
* @param promptNamespace The namespace for the prompt, used to identify the prompt instance and namespaced answers.
|
|
22
|
+
* This is used to avoid conflicts with other prompts of the same types.
|
|
23
|
+
* @param promptOptions Options for the service selection prompt see {@link OdataServicePromptOptions}
|
|
24
|
+
* @returns the service selection prompt
|
|
25
|
+
*/
|
|
26
|
+
function getSystemServiceQuestion(connectValidator, promptNamespace, promptOptions) {
|
|
27
|
+
let serviceChoices = [];
|
|
28
|
+
// Prevent re-requesting services repeatedly by only requesting them once and when the system or client is changed
|
|
29
|
+
let previousSystemUrl;
|
|
30
|
+
let previousClient;
|
|
31
|
+
let previousService;
|
|
32
|
+
const requiredOdataVersion = promptOptions?.serviceSelection?.requiredOdataVersion;
|
|
33
|
+
const systemServiceQuestion = {
|
|
34
|
+
when: () => connectValidator.validity.authenticated || connectValidator.validity.authRequired === false,
|
|
35
|
+
name: `${promptNamespace}:${types_1.promptNames.serviceSelection}`,
|
|
36
|
+
type: promptOptions?.serviceSelection?.useAutoComplete ? 'autocomplete' : 'list',
|
|
37
|
+
message: () => (0, service_helper_1.getSelectedServiceLabel)(connectValidator.connectedUserName),
|
|
38
|
+
guiOptions: {
|
|
39
|
+
breadcrumb: (0, i18n_1.t)('prompts.systemService.breadcrumb'),
|
|
40
|
+
mandatory: true,
|
|
41
|
+
applyDefaultWhenDirty: true
|
|
42
|
+
},
|
|
43
|
+
source: (prevAnswers, input) => (0, inquirer_common_1.searchChoices)(input, serviceChoices),
|
|
44
|
+
// SystemSelectionAnswers should not be needed here in the interest of keeping these prompts decoupled but TelemetryHelper is used here and it requires the previously selected destination
|
|
45
|
+
choices: async (answers) => {
|
|
46
|
+
if (serviceChoices.length === 0 ||
|
|
47
|
+
previousSystemUrl !== connectValidator.validatedUrl ||
|
|
48
|
+
previousClient !== connectValidator.validatedClient) {
|
|
49
|
+
// if we have a catalog, use it to list services
|
|
50
|
+
if (connectValidator.catalogs[odata_service_writer_1.OdataVersion.v2] || connectValidator.catalogs[odata_service_writer_1.OdataVersion.v4]) {
|
|
51
|
+
serviceChoices = await createServiceChoicesFromCatalog(connectValidator.catalogs, requiredOdataVersion);
|
|
52
|
+
previousSystemUrl = connectValidator.validatedUrl;
|
|
53
|
+
previousClient = connectValidator.validatedClient;
|
|
54
|
+
// Telemetry event for successful service listing using a destination
|
|
55
|
+
if (answers?.[`${types_1.promptNames.systemSelection}`]?.type === 'destination') {
|
|
56
|
+
(0, service_helper_1.sendDestinationServiceSuccessTelemetryEvent)(answers?.[`${types_1.promptNames.systemSelection}`]?.system);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (connectValidator.odataService && connectValidator.validatedUrl) {
|
|
60
|
+
// We have connected to a service endpoint, use this service as the only choice
|
|
61
|
+
const serviceUrl = new URL(connectValidator.destinationUrl ?? connectValidator.validatedUrl);
|
|
62
|
+
serviceChoices = [
|
|
63
|
+
{
|
|
64
|
+
name: serviceUrl.toString(),
|
|
65
|
+
value: {
|
|
66
|
+
servicePath: serviceUrl.pathname
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
// Telemetry event for successful service listing using a destination
|
|
71
|
+
if (answers?.[`${types_1.promptNames.systemSelection}`]?.type === 'destination') {
|
|
72
|
+
(0, service_helper_1.sendDestinationServiceSuccessTelemetryEvent)(answers?.[`${types_1.promptNames.systemSelection}`]?.system);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('error.noCatalogOrServiceAvailable'));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return serviceChoices;
|
|
80
|
+
},
|
|
81
|
+
additionalMessages: (selectedService) => (0, service_helper_1.getSelectedServiceMessage)(serviceChoices, selectedService, connectValidator, requiredOdataVersion),
|
|
82
|
+
default: () => (0, utils_1.getDefaultChoiceIndex)(serviceChoices),
|
|
83
|
+
// Warning: only executes in YUI and cli when automcomplete is used
|
|
84
|
+
validate: async (service) => {
|
|
85
|
+
let serviceAnswer = service;
|
|
86
|
+
// Autocomplete passes the entire choice object as the answer, so we need to extract the value
|
|
87
|
+
if (promptOptions?.serviceSelection?.useAutoComplete && service.value) {
|
|
88
|
+
serviceAnswer = service.value;
|
|
89
|
+
}
|
|
90
|
+
if (!connectValidator.validatedUrl) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
// if no choices are available and an error is present, return the error message
|
|
94
|
+
if (serviceChoices.length === 0 && prompt_helpers_1.errorHandler.hasError()) {
|
|
95
|
+
return inquirer_common_1.ErrorHandler.getHelpForError(inquirer_common_1.ERROR_TYPE.SERVICES_UNAVAILABLE) ?? false;
|
|
96
|
+
}
|
|
97
|
+
// Dont re-request the same service details
|
|
98
|
+
if (serviceAnswer && previousService?.servicePath !== serviceAnswer.servicePath) {
|
|
99
|
+
previousService = serviceAnswer;
|
|
100
|
+
return await (0, service_helper_1.getServiceDetails)(serviceAnswer, connectValidator, requiredOdataVersion);
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const questions = [systemServiceQuestion];
|
|
106
|
+
// Only for CLI use as `list` prompt validation does not run on CLI unless autocomplete plugin is used
|
|
107
|
+
if ((0, utils_1.getPromptHostEnvironment)() === fiori_generator_shared_1.hostEnvironment.cli && !promptOptions?.serviceSelection?.useAutoComplete) {
|
|
108
|
+
questions.push({
|
|
109
|
+
when: async (answers) => {
|
|
110
|
+
const selectedService = answers?.[`${promptNamespace}:${types_1.promptNames.serviceSelection}`];
|
|
111
|
+
if (selectedService && connectValidator.validatedUrl) {
|
|
112
|
+
const result = await (0, service_helper_1.getServiceDetails)(selectedService, connectValidator);
|
|
113
|
+
if (typeof result === 'string') {
|
|
114
|
+
logger_helper_1.default.logger.error(result);
|
|
115
|
+
throw new Error(result);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (serviceChoices.length === 0 && prompt_helpers_1.errorHandler.hasError()) {
|
|
119
|
+
const noServicesError = inquirer_common_1.ErrorHandler.getHelpForError(inquirer_common_1.ERROR_TYPE.SERVICES_UNAVAILABLE).toString();
|
|
120
|
+
throw new Error(noServicesError);
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
},
|
|
124
|
+
name: `${promptNamespace}:${cliServicePromptName}`
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return questions;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Create service choices from the catalog.
|
|
131
|
+
*
|
|
132
|
+
* @param availableCatalogs catalogs that can be used to list services
|
|
133
|
+
* @param requiredOdataVersion the required OData version to list services for, if not provided all available catalogs will be used
|
|
134
|
+
* @returns service choices
|
|
135
|
+
*/
|
|
136
|
+
async function createServiceChoicesFromCatalog(availableCatalogs, requiredOdataVersion) {
|
|
137
|
+
let catalogs = [];
|
|
138
|
+
if (requiredOdataVersion && availableCatalogs[requiredOdataVersion]) {
|
|
139
|
+
catalogs.push(availableCatalogs[requiredOdataVersion]);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
catalogs = Object.values(availableCatalogs).filter((cat) => cat !== undefined);
|
|
143
|
+
}
|
|
144
|
+
return await (0, service_helper_1.getServiceChoices)(catalogs);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=questions.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type IMessageSeverity } from '@sap-devx/yeoman-ui-types';
|
|
2
|
+
import { type CatalogService, ServiceType, V2CatalogService } from '@sap-ux/axios-extension';
|
|
3
|
+
import type { Destination } from '@sap-ux/btp-utils';
|
|
4
|
+
import { OdataVersion } from '@sap-ux/odata-service-writer';
|
|
5
|
+
import type { ListChoiceOptions } from 'inquirer';
|
|
6
|
+
import type { ConnectionValidator } from '../../../connectionValidator';
|
|
7
|
+
import type { ServiceAnswer } from './types';
|
|
8
|
+
export declare const telemEventBASServiceSuccess = "SERVICE_INQUIRER_BAS_SUCCESS";
|
|
9
|
+
/**
|
|
10
|
+
* Refines the error type and logs based on the specified options. This should log more precise error messages based on inputs
|
|
11
|
+
* and the platform making the call i.e. VSC | SBAS. Errors are mapped to GA links if the platform is SBAS.
|
|
12
|
+
*
|
|
13
|
+
* @param options Options
|
|
14
|
+
* @param options.system - sap system used
|
|
15
|
+
* @param options.catRequestErrorTypes - all catalog service request error types, used to do further root cause analysis
|
|
16
|
+
* @param options.rootCauseErrorType - the error type as determined by the caller, will be used if a more precise error type cannot be determined by rca
|
|
17
|
+
* @param options.logMsg - the log message that will be used if a better root cause is not determined
|
|
18
|
+
* @param options.error - the original error, used to determine the error log message if otherwise not determined
|
|
19
|
+
* @param option.reqVersion - specific odata version that is required by the template
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Get the service choices from the specified catalogs.
|
|
23
|
+
*
|
|
24
|
+
* @param catalogs catalogs to get the services from. There should be one per odata version required.
|
|
25
|
+
* @returns service choices based on the provided catalogs
|
|
26
|
+
*/
|
|
27
|
+
export declare function getServiceChoices(catalogs: CatalogService[]): Promise<ListChoiceOptions<ServiceAnswer>[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Generates a telemetry event for successfully listing service(s) using a destination.
|
|
30
|
+
*
|
|
31
|
+
* @param destination the destination used to list the service(s)
|
|
32
|
+
*/
|
|
33
|
+
export declare function sendDestinationServiceSuccessTelemetryEvent(destination: Destination): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get service type for 'Not Determined' services from `ServiceTypeForHUBServices()`
|
|
36
|
+
*
|
|
37
|
+
* @param servicePath service path
|
|
38
|
+
* @param serviceType service type
|
|
39
|
+
* @param catalog the catalog service used to get the service type for the specified service path
|
|
40
|
+
* @returns service type
|
|
41
|
+
*/
|
|
42
|
+
export declare function getServiceType(servicePath: string, serviceType: string | undefined, catalog: V2CatalogService): Promise<ServiceType | undefined>;
|
|
43
|
+
/**
|
|
44
|
+
* Requests and sets the service details to the PromptState.odataService properties.
|
|
45
|
+
* If an error occurs, the error message is returned for use in validators.
|
|
46
|
+
*
|
|
47
|
+
* @param service the specific service to get details for
|
|
48
|
+
* @param connectionValidator a reference to the connection validator which has an active connection to the backend
|
|
49
|
+
* @param requiredOdataVersion
|
|
50
|
+
* @returns true if successful, setting the PromptState.odataService properties, or an error message indicating why the service details could not be retrieved.
|
|
51
|
+
*/
|
|
52
|
+
export declare function getServiceDetails(service: ServiceAnswer, connectionValidator: ConnectionValidator, requiredOdataVersion?: OdataVersion): Promise<string | boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Create a value for the service selection prompt message, which may include thge active connected user name.
|
|
55
|
+
*
|
|
56
|
+
* @param username The connected user name
|
|
57
|
+
* @returns The service selection prompt message
|
|
58
|
+
*/
|
|
59
|
+
export declare function getSelectedServiceLabel(username: string | undefined): string;
|
|
60
|
+
/**
|
|
61
|
+
* Get the service selection prompt additional message. This prompt will make an additional call to the system backend
|
|
62
|
+
* to retrieve the service type and display a warning message if the service type is not UI.
|
|
63
|
+
*
|
|
64
|
+
* @param serviceChoices a list of service choices
|
|
65
|
+
* @param selectedService the selected service
|
|
66
|
+
* @param connectValidator the connection validator
|
|
67
|
+
* @param requiredOdataVersion the required OData version for the service
|
|
68
|
+
* @returns the service selection prompt additional message
|
|
69
|
+
*/
|
|
70
|
+
export declare function getSelectedServiceMessage(serviceChoices: ListChoiceOptions<ServiceAnswer>[], selectedService: ServiceAnswer, connectValidator: ConnectionValidator, requiredOdataVersion?: OdataVersion): Promise<IMessageSeverity | undefined>;
|
|
71
|
+
//# sourceMappingURL=service-helper.d.ts.map
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.telemEventBASServiceSuccess = void 0;
|
|
7
|
+
exports.getServiceChoices = getServiceChoices;
|
|
8
|
+
exports.sendDestinationServiceSuccessTelemetryEvent = sendDestinationServiceSuccessTelemetryEvent;
|
|
9
|
+
exports.getServiceType = getServiceType;
|
|
10
|
+
exports.getServiceDetails = getServiceDetails;
|
|
11
|
+
exports.getSelectedServiceLabel = getSelectedServiceLabel;
|
|
12
|
+
exports.getSelectedServiceMessage = getSelectedServiceMessage;
|
|
13
|
+
const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
|
|
14
|
+
const axios_extension_1 = require("@sap-ux/axios-extension");
|
|
15
|
+
const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
|
|
16
|
+
const inquirer_common_1 = require("@sap-ux/inquirer-common");
|
|
17
|
+
const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
|
|
18
|
+
const i18n_1 = require("../../../../i18n");
|
|
19
|
+
const utils_1 = require("../../../../utils");
|
|
20
|
+
const logger_helper_1 = __importDefault(require("../../../logger-helper"));
|
|
21
|
+
const prompt_helpers_1 = require("../../../prompt-helpers");
|
|
22
|
+
const validators_1 = require("../../../validators");
|
|
23
|
+
// Service ids continaining these paths should not be offered as UI compatible services
|
|
24
|
+
const nonUIServicePaths = ['/IWBEP/COMMON/'];
|
|
25
|
+
// Telemetry event name for successful service validation on BAS, note: legacy event names should not be changed
|
|
26
|
+
exports.telemEventBASServiceSuccess = 'SERVICE_INQUIRER_BAS_SUCCESS';
|
|
27
|
+
/**
|
|
28
|
+
* Builds and formats the service choices list.
|
|
29
|
+
*
|
|
30
|
+
* @param serviceInfos service information to build the choices from. Services with a service id containing '/IWBEP/COMMON' are ignored.
|
|
31
|
+
* @returns service choices list
|
|
32
|
+
*/
|
|
33
|
+
const createServiceChoices = (serviceInfos) => {
|
|
34
|
+
const choices = [];
|
|
35
|
+
// Provide additional service information in trace mode (YUI only)
|
|
36
|
+
let isLogTrace = false;
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Only specific loggers have this method
|
|
38
|
+
if (typeof logger_helper_1.default.logger.getLogLevel === 'function') {
|
|
39
|
+
isLogTrace = logger_helper_1.default.logger.getLogLevel() === 'trace';
|
|
40
|
+
}
|
|
41
|
+
serviceInfos
|
|
42
|
+
// Exclude non-UI compatible services
|
|
43
|
+
?.filter((service) => !nonUIServicePaths.some((path) => service.path.includes(path)))
|
|
44
|
+
.forEach((service) => {
|
|
45
|
+
let serviceName = service.name;
|
|
46
|
+
const servicePath = service.path;
|
|
47
|
+
serviceName = `${serviceName} (${service.serviceVersion}) - OData V${service.odataVersion}`;
|
|
48
|
+
if (isLogTrace) {
|
|
49
|
+
serviceName = `${serviceName} Service Type: ${service.serviceType}`;
|
|
50
|
+
}
|
|
51
|
+
choices.push({
|
|
52
|
+
name: serviceName,
|
|
53
|
+
value: {
|
|
54
|
+
servicePath,
|
|
55
|
+
serviceODataVersion: service.odataVersion,
|
|
56
|
+
toString: () => serviceName,
|
|
57
|
+
serviceType: service.serviceType
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
return choices.sort((a, b) => (a.name ? a.name.localeCompare(b.name ?? '') : 0));
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Logs the catalog request errors using the error handler.
|
|
65
|
+
*
|
|
66
|
+
* @param requestErrors catalog request errors, keyed by the OData version of the catalog service, with the error, status code number or error message as the value
|
|
67
|
+
* @param numOfRequests
|
|
68
|
+
*/
|
|
69
|
+
function logServiceCatalogErrorsForHelp(requestErrors, numOfRequests) {
|
|
70
|
+
const catalogRequesErrors = Object.values(requestErrors);
|
|
71
|
+
catalogRequesErrors.forEach((error) => {
|
|
72
|
+
prompt_helpers_1.errorHandler.logErrorMsgs(error); // Log and process the error -> error type
|
|
73
|
+
});
|
|
74
|
+
// If all requests failed, log a generic message, this will be stored in the error handler
|
|
75
|
+
if (numOfRequests === catalogRequesErrors.length) {
|
|
76
|
+
prompt_helpers_1.errorHandler.logErrorMsgs((0, i18n_1.t)('errors.allCatalogServiceRequestsFailed', { version: Object.keys(requestErrors).join(', ') }));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Refines the error type and logs based on the specified options. This should log more precise error messages based on inputs
|
|
81
|
+
* and the platform making the call i.e. VSC | SBAS. Errors are mapped to GA links if the platform is SBAS.
|
|
82
|
+
*
|
|
83
|
+
* @param options Options
|
|
84
|
+
* @param options.system - sap system used
|
|
85
|
+
* @param options.catRequestErrorTypes - all catalog service request error types, used to do further root cause analysis
|
|
86
|
+
* @param options.rootCauseErrorType - the error type as determined by the caller, will be used if a more precise error type cannot be determined by rca
|
|
87
|
+
* @param options.logMsg - the log message that will be used if a better root cause is not determined
|
|
88
|
+
* @param options.error - the original error, used to determine the error log message if otherwise not determined
|
|
89
|
+
* @param option.reqVersion - specific odata version that is required by the template
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* Get the service choices from the specified catalogs.
|
|
93
|
+
*
|
|
94
|
+
* @param catalogs catalogs to get the services from. There should be one per odata version required.
|
|
95
|
+
* @returns service choices based on the provided catalogs
|
|
96
|
+
*/
|
|
97
|
+
async function getServiceChoices(catalogs) {
|
|
98
|
+
const requestErrors = {};
|
|
99
|
+
const listServicesRequests = catalogs.map(async (catalog) => {
|
|
100
|
+
try {
|
|
101
|
+
return await catalog.listServices();
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceCatalogRequest', {
|
|
105
|
+
catalogRequestUri: catalog.getUri(),
|
|
106
|
+
entitySet: catalog.entitySet,
|
|
107
|
+
error
|
|
108
|
+
}));
|
|
109
|
+
// Save any errors for processing later as we may show more useful message to the user
|
|
110
|
+
Object.assign(requestErrors, {
|
|
111
|
+
[catalog instanceof axios_extension_1.V2CatalogService ? axios_extension_1.ODataVersion.v2 : axios_extension_1.ODataVersion.v4]: error
|
|
112
|
+
});
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
const serviceInfos = await Promise.all(listServicesRequests);
|
|
117
|
+
const flatServices = serviceInfos?.flat() ?? [];
|
|
118
|
+
logger_helper_1.default.logger.debug(`Number of services available: ${flatServices.length}`);
|
|
119
|
+
if (flatServices.length === 0) {
|
|
120
|
+
logServiceCatalogErrorsForHelp(requestErrors, catalogs.length);
|
|
121
|
+
}
|
|
122
|
+
return createServiceChoices(flatServices);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Generates a telemetry event for successfully listing service(s) using a destination.
|
|
126
|
+
*
|
|
127
|
+
* @param destination the destination used to list the service(s)
|
|
128
|
+
*/
|
|
129
|
+
function sendDestinationServiceSuccessTelemetryEvent(destination) {
|
|
130
|
+
// May return undefined if the same event was already sent within some time frame
|
|
131
|
+
const telemetryData = fiori_generator_shared_1.TelemetryHelper.createTelemetryData({
|
|
132
|
+
destODataType: (0, inquirer_common_1.getTelemPropertyDestinationType)(destination)
|
|
133
|
+
}) ?? {};
|
|
134
|
+
(0, inquirer_common_1.sendTelemetryEvent)(exports.telemEventBASServiceSuccess, telemetryData);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Gets the service metadata and annotations for the specified service path.
|
|
138
|
+
*
|
|
139
|
+
* @param servicePath service path
|
|
140
|
+
* @param odataService the odata service used to get the metadata for the specified service path
|
|
141
|
+
* @param catalog the catalog service used to get the annotations for the specified service path
|
|
142
|
+
* @returns Promise<string | boolean>, string error message or true if successful
|
|
143
|
+
*/
|
|
144
|
+
async function getServiceMetadata(servicePath, odataService, catalog) {
|
|
145
|
+
let annotations = [];
|
|
146
|
+
try {
|
|
147
|
+
if (catalog) {
|
|
148
|
+
try {
|
|
149
|
+
annotations = await catalog.getAnnotations({ path: servicePath });
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
logger_helper_1.default.logger.info((0, i18n_1.t)('prompts.validationMessages.noAnnotations'));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const metadata = await odataService.metadata();
|
|
156
|
+
return {
|
|
157
|
+
annotations,
|
|
158
|
+
metadata
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceMetadataErrorLog', { servicePath, error }));
|
|
163
|
+
return (0, i18n_1.t)('errors.serviceMetadataErrorUI', { servicePath });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get service type for 'Not Determined' services from `ServiceTypeForHUBServices()`
|
|
168
|
+
*
|
|
169
|
+
* @param servicePath service path
|
|
170
|
+
* @param serviceType service type
|
|
171
|
+
* @param catalog the catalog service used to get the service type for the specified service path
|
|
172
|
+
* @returns service type
|
|
173
|
+
*/
|
|
174
|
+
async function getServiceType(servicePath, serviceType, catalog) {
|
|
175
|
+
let resolvedServiceType;
|
|
176
|
+
if (serviceType === axios_extension_1.ServiceType.NotDetermined) {
|
|
177
|
+
try {
|
|
178
|
+
resolvedServiceType = (await catalog.getServiceType(servicePath)) ?? axios_extension_1.ServiceType.NotDetermined;
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceTypeRequestError', { error: e.message }));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return resolvedServiceType ?? serviceType;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Requests and sets the service details to the PromptState.odataService properties.
|
|
188
|
+
* If an error occurs, the error message is returned for use in validators.
|
|
189
|
+
*
|
|
190
|
+
* @param service the specific service to get details for
|
|
191
|
+
* @param connectionValidator a reference to the connection validator which has an active connection to the backend
|
|
192
|
+
* @param requiredOdataVersion
|
|
193
|
+
* @returns true if successful, setting the PromptState.odataService properties, or an error message indicating why the service details could not be retrieved.
|
|
194
|
+
*/
|
|
195
|
+
async function getServiceDetails(service, connectionValidator, requiredOdataVersion) {
|
|
196
|
+
const serviceCatalog = connectionValidator.catalogs?.[service.serviceODataVersion];
|
|
197
|
+
if (!connectionValidator.serviceProvider) {
|
|
198
|
+
logger_helper_1.default.logger.error('ConnectionValidator connection is not initialized');
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
// We may already have an odata service endpoint connection
|
|
202
|
+
let odataService = connectionValidator.odataService;
|
|
203
|
+
if (!odataService) {
|
|
204
|
+
odataService = connectionValidator.serviceProvider.service(service.servicePath);
|
|
205
|
+
}
|
|
206
|
+
const serviceResult = await getServiceMetadata(service.servicePath, odataService, serviceCatalog);
|
|
207
|
+
if (typeof serviceResult === 'string') {
|
|
208
|
+
return serviceResult;
|
|
209
|
+
}
|
|
210
|
+
const { validationMsg, version } = (0, validators_1.validateODataVersion)(serviceResult.metadata, requiredOdataVersion);
|
|
211
|
+
if (validationMsg) {
|
|
212
|
+
return validationMsg;
|
|
213
|
+
}
|
|
214
|
+
// If destinationUrl is available, use it, as validatedUrl may be in the form <protocal>:<destinationName>.dest
|
|
215
|
+
const url = connectionValidator.destinationUrl ?? connectionValidator.validatedUrl;
|
|
216
|
+
let origin;
|
|
217
|
+
if (url) {
|
|
218
|
+
origin = new URL(url).origin;
|
|
219
|
+
}
|
|
220
|
+
utils_1.PromptState.odataService.annotations = serviceResult?.annotations;
|
|
221
|
+
utils_1.PromptState.odataService.metadata = serviceResult?.metadata;
|
|
222
|
+
utils_1.PromptState.odataService.odataVersion =
|
|
223
|
+
version ?? service.serviceODataVersion === axios_extension_1.ODataVersion.v2 ? odata_service_writer_1.OdataVersion.v2 : odata_service_writer_1.OdataVersion.v4;
|
|
224
|
+
utils_1.PromptState.odataService.servicePath = service.servicePath;
|
|
225
|
+
utils_1.PromptState.odataService.origin = origin;
|
|
226
|
+
utils_1.PromptState.odataService.sapClient = connectionValidator.validatedClient;
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Create a value for the service selection prompt message, which may include thge active connected user name.
|
|
231
|
+
*
|
|
232
|
+
* @param username The connected user name
|
|
233
|
+
* @returns The service selection prompt message
|
|
234
|
+
*/
|
|
235
|
+
function getSelectedServiceLabel(username) {
|
|
236
|
+
let message = (0, i18n_1.t)('prompts.systemService.message');
|
|
237
|
+
if (username) {
|
|
238
|
+
message = message.concat(` ${(0, i18n_1.t)('texts.forUserName', { username })}`);
|
|
239
|
+
}
|
|
240
|
+
return message;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get the service selection prompt additional message. This prompt will make an additional call to the system backend
|
|
244
|
+
* to retrieve the service type and display a warning message if the service type is not UI.
|
|
245
|
+
*
|
|
246
|
+
* @param serviceChoices a list of service choices
|
|
247
|
+
* @param selectedService the selected service
|
|
248
|
+
* @param connectValidator the connection validator
|
|
249
|
+
* @param requiredOdataVersion the required OData version for the service
|
|
250
|
+
* @returns the service selection prompt additional message
|
|
251
|
+
*/
|
|
252
|
+
async function getSelectedServiceMessage(serviceChoices, selectedService, connectValidator, requiredOdataVersion) {
|
|
253
|
+
if (serviceChoices?.length === 0) {
|
|
254
|
+
if (requiredOdataVersion) {
|
|
255
|
+
return {
|
|
256
|
+
message: (0, i18n_1.t)('prompts.warnings.noServicesAvailableForOdataVersion', {
|
|
257
|
+
odataVersion: requiredOdataVersion
|
|
258
|
+
}),
|
|
259
|
+
severity: yeoman_ui_types_1.Severity.warning
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
return {
|
|
264
|
+
message: (0, i18n_1.t)('prompts.warnings.noServicesAvailable'),
|
|
265
|
+
severity: yeoman_ui_types_1.Severity.warning
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (selectedService) {
|
|
270
|
+
let serviceType = selectedService.serviceType;
|
|
271
|
+
if (selectedService.serviceODataVersion === axios_extension_1.ODataVersion.v2) {
|
|
272
|
+
serviceType = await getServiceType(selectedService.servicePath, selectedService.serviceType, connectValidator.catalogs[axios_extension_1.ODataVersion.v2]);
|
|
273
|
+
}
|
|
274
|
+
if (serviceType && serviceType !== axios_extension_1.ServiceType.UI) {
|
|
275
|
+
return {
|
|
276
|
+
message: (0, i18n_1.t)('prompts.warnings.nonUIServiceTypeWarningMessage', { serviceType: 'A2X' }),
|
|
277
|
+
severity: yeoman_ui_types_1.Severity.warning
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=service-helper.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ODataVersion } from '@sap-ux/axios-extension';
|
|
2
|
+
/**
|
|
3
|
+
* Sap System service answer
|
|
4
|
+
*/
|
|
5
|
+
export type ServiceAnswer = {
|
|
6
|
+
servicePath: string;
|
|
7
|
+
serviceODataVersion: ODataVersion;
|
|
8
|
+
toString: () => string;
|
|
9
|
+
serviceType?: string;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./questions"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Destination } from '@sap-ux/btp-utils';
|
|
2
|
+
import type { OdataVersion } from '@sap-ux/odata-service-writer';
|
|
3
|
+
import type { BackendSystem } from '@sap-ux/store';
|
|
4
|
+
import type { ListChoiceOptions } from 'inquirer';
|
|
5
|
+
import { type DestinationFilters } from '../../../../types';
|
|
6
|
+
import type { ConnectionValidator, ValidationResult } from '../../../connectionValidator';
|
|
7
|
+
import { type SystemSelectionAnswers } from './questions';
|
|
8
|
+
/**
|
|
9
|
+
* Connects to the specified backend system and validates the connection.
|
|
10
|
+
* Note this will return true in the case of basic auth validation failure to defer validation to the credentials prompt.
|
|
11
|
+
*
|
|
12
|
+
* @param backendSystem the backend system to connect to
|
|
13
|
+
* @param connectionValidator the connection validator to use for the connection
|
|
14
|
+
* @param requiredOdataVersion the required OData version for the service, this will be used to narrow the catalog service connections
|
|
15
|
+
* @returns the validation result of the backend system connection
|
|
16
|
+
*/
|
|
17
|
+
export declare function connectWithBackendSystem(backendSystem: BackendSystem, connectionValidator: ConnectionValidator, requiredOdataVersion?: OdataVersion): Promise<ValidationResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Connects to the specified destination and validates the connection.
|
|
20
|
+
* Note that a destination may be a system or a service connection.
|
|
21
|
+
*
|
|
22
|
+
* @param destination the destination specifying the connection details
|
|
23
|
+
* @param connectionValidator the connection validator to use for the connection
|
|
24
|
+
* @param requiredOdataVersion the required OData version for the service, this will be used to narrow the catalog service connections
|
|
25
|
+
* @param addServicePath the service path to add to the destination URL
|
|
26
|
+
* @returns the validation result of the destination connection attempt
|
|
27
|
+
*/
|
|
28
|
+
export declare function connectWithDestination(destination: Destination, connectionValidator: ConnectionValidator, requiredOdataVersion?: OdataVersion, addServicePath?: string): Promise<ValidationResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Creates and returns a display name for the system, appending the system type and user display name if available.
|
|
31
|
+
*
|
|
32
|
+
* @param system the backend system to create a display name for
|
|
33
|
+
* @returns the display name for the system
|
|
34
|
+
*/
|
|
35
|
+
export declare function getBackendSystemDisplayName(system: BackendSystem): string;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a list of choices for the system selection prompt using destinations or stored backend systems, depending on the environment.
|
|
38
|
+
*
|
|
39
|
+
* @param destinationFilters
|
|
40
|
+
* @param includeCloudFoundryAbapEnvChoice
|
|
41
|
+
* @returns a list of choices for the system selection prompt
|
|
42
|
+
*/
|
|
43
|
+
export declare function createSystemChoices(destinationFilters?: Partial<DestinationFilters>, includeCloudFoundryAbapEnvChoice?: boolean): Promise<ListChoiceOptions<SystemSelectionAnswers>[]>;
|
|
44
|
+
//# sourceMappingURL=prompt-helpers.d.ts.map
|