@sap-ux/odata-service-inquirer 0.5.59 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/error-handler/error-handler.d.ts +25 -3
- package/dist/error-handler/error-handler.js +154 -52
- package/dist/i18n.js +15 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -3
- package/dist/prompts/connectionValidator.d.ts +63 -12
- package/dist/prompts/connectionValidator.js +196 -38
- package/dist/prompts/datasources/sap-system/abap-on-btp/questions.d.ts +2 -1
- package/dist/prompts/datasources/sap-system/abap-on-btp/questions.js +3 -1
- 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 +281 -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 +181 -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 +2 -2
- package/dist/prompts/datasources/service-url/validators.js +5 -6
- package/dist/prompts/prompt-helpers.d.ts +1 -2
- package/dist/prompts/prompt-helpers.js +2 -11
- 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 +36 -15
- package/dist/types.d.ts +57 -10
- package/dist/types.js +7 -1
- package/dist/utils/index.d.ts +12 -3
- package/dist/utils/index.js +27 -5
- package/package.json +6 -6
- 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,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,281 @@
|
|
|
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 odata_service_writer_1 = require("@sap-ux/odata-service-writer");
|
|
17
|
+
const i18n_1 = require("../../../../i18n");
|
|
18
|
+
const utils_1 = require("../../../../utils");
|
|
19
|
+
const logger_helper_1 = __importDefault(require("../../../logger-helper"));
|
|
20
|
+
const prompt_helpers_1 = require("../../../prompt-helpers");
|
|
21
|
+
const validators_1 = require("../../../validators");
|
|
22
|
+
// Service ids continaining these paths should not be offered as UI compatible services
|
|
23
|
+
const nonUIServicePaths = ['/IWBEP/COMMON/'];
|
|
24
|
+
// Telemetry event name for successful service validation on BAS, note: legacy event names should not be changed
|
|
25
|
+
exports.telemEventBASServiceSuccess = 'SERVICE_INQUIRER_BAS_SUCCESS';
|
|
26
|
+
/**
|
|
27
|
+
* Builds and formats the service choices list.
|
|
28
|
+
*
|
|
29
|
+
* @param serviceInfos service information to build the choices from. Services with a service id containing '/IWBEP/COMMON' are ignored.
|
|
30
|
+
* @returns service choices list
|
|
31
|
+
*/
|
|
32
|
+
const createServiceChoices = (serviceInfos) => {
|
|
33
|
+
const choices = [];
|
|
34
|
+
// Provide additional service information in trace mode (YUI only)
|
|
35
|
+
let isLogTrace = false;
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Only specific loggers have this method
|
|
37
|
+
if (typeof logger_helper_1.default.logger.getLogLevel === 'function') {
|
|
38
|
+
isLogTrace = logger_helper_1.default.logger.getLogLevel() === 'trace';
|
|
39
|
+
}
|
|
40
|
+
serviceInfos
|
|
41
|
+
// Exclude non-UI compatible services
|
|
42
|
+
?.filter((service) => !nonUIServicePaths.some((path) => service.path.includes(path)))
|
|
43
|
+
.forEach((service) => {
|
|
44
|
+
let serviceName = service.name;
|
|
45
|
+
const servicePath = service.path;
|
|
46
|
+
serviceName = `${serviceName} (${service.serviceVersion}) - OData V${service.odataVersion}`;
|
|
47
|
+
if (isLogTrace) {
|
|
48
|
+
serviceName = `${serviceName} Service Type: ${service.serviceType}`;
|
|
49
|
+
}
|
|
50
|
+
choices.push({
|
|
51
|
+
name: serviceName,
|
|
52
|
+
value: {
|
|
53
|
+
servicePath,
|
|
54
|
+
serviceODataVersion: service.odataVersion,
|
|
55
|
+
toString: () => serviceName,
|
|
56
|
+
serviceType: service.serviceType
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
return choices.sort((a, b) => (a.name ? a.name.localeCompare(b.name ?? '') : 0));
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Logs the catalog request errors using the error handler.
|
|
64
|
+
*
|
|
65
|
+
* @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
|
|
66
|
+
* @param numOfRequests
|
|
67
|
+
*/
|
|
68
|
+
function logServiceCatalogErrorsForHelp(requestErrors, numOfRequests) {
|
|
69
|
+
const catalogRequesErrors = Object.values(requestErrors);
|
|
70
|
+
catalogRequesErrors.forEach((error) => {
|
|
71
|
+
prompt_helpers_1.errorHandler.logErrorMsgs(error); // Log and process the error -> error type
|
|
72
|
+
});
|
|
73
|
+
// If all requests failed, log a generic message, this will be stored in the error handler
|
|
74
|
+
if (numOfRequests === catalogRequesErrors.length) {
|
|
75
|
+
prompt_helpers_1.errorHandler.logErrorMsgs((0, i18n_1.t)('errors.allCatalogServiceRequestsFailed', { version: Object.keys(requestErrors).join(', ') }));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Refines the error type and logs based on the specified options. This should log more precise error messages based on inputs
|
|
80
|
+
* and the platform making the call i.e. VSC | SBAS. Errors are mapped to GA links if the platform is SBAS.
|
|
81
|
+
*
|
|
82
|
+
* @param options Options
|
|
83
|
+
* @param options.system - sap system used
|
|
84
|
+
* @param options.catRequestErrorTypes - all catalog service request error types, used to do further root cause analysis
|
|
85
|
+
* @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
|
|
86
|
+
* @param options.logMsg - the log message that will be used if a better root cause is not determined
|
|
87
|
+
* @param options.error - the original error, used to determine the error log message if otherwise not determined
|
|
88
|
+
* @param option.reqVersion - specific odata version that is required by the template
|
|
89
|
+
*/
|
|
90
|
+
/**
|
|
91
|
+
* Get the service choices from the specified catalogs.
|
|
92
|
+
*
|
|
93
|
+
* @param catalogs catalogs to get the services from. There should be one per odata version required.
|
|
94
|
+
* @returns service choices based on the provided catalogs
|
|
95
|
+
*/
|
|
96
|
+
async function getServiceChoices(catalogs) {
|
|
97
|
+
const requestErrors = {};
|
|
98
|
+
const listServicesRequests = catalogs.map(async (catalog) => {
|
|
99
|
+
try {
|
|
100
|
+
return await catalog.listServices();
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceCatalogRequest', {
|
|
104
|
+
catalogRequestUri: catalog.getUri(),
|
|
105
|
+
entitySet: catalog.entitySet,
|
|
106
|
+
error
|
|
107
|
+
}));
|
|
108
|
+
// Save any errors for processing later as we may show more useful message to the user
|
|
109
|
+
Object.assign(requestErrors, {
|
|
110
|
+
[catalog instanceof axios_extension_1.V2CatalogService ? axios_extension_1.ODataVersion.v2 : axios_extension_1.ODataVersion.v4]: error
|
|
111
|
+
});
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
const serviceInfos = await Promise.all(listServicesRequests);
|
|
116
|
+
const flatServices = serviceInfos?.flat() ?? [];
|
|
117
|
+
logger_helper_1.default.logger.debug(`Number of services available: ${flatServices.length}`);
|
|
118
|
+
if (flatServices.length === 0) {
|
|
119
|
+
logServiceCatalogErrorsForHelp(requestErrors, catalogs.length);
|
|
120
|
+
}
|
|
121
|
+
return createServiceChoices(flatServices);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Generates a telemetry event for successfully listing service(s) using a destination.
|
|
125
|
+
*
|
|
126
|
+
* @param destination the destination used to list the service(s)
|
|
127
|
+
*/
|
|
128
|
+
function sendDestinationServiceSuccessTelemetryEvent(destination) {
|
|
129
|
+
// May return undefined if the same event was already sent within some time frame
|
|
130
|
+
const telemetryData = fiori_generator_shared_1.TelemetryHelper.createTelemetryData({
|
|
131
|
+
destODataType: (0, utils_1.getTelemPropertyDestinationType)(destination)
|
|
132
|
+
}) ?? {};
|
|
133
|
+
(0, utils_1.sendTelemetryEvent)(exports.telemEventBASServiceSuccess, telemetryData);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Gets the service metadata and annotations for the specified service path.
|
|
137
|
+
*
|
|
138
|
+
* @param servicePath service path
|
|
139
|
+
* @param odataService the odata service used to get the metadata for the specified service path
|
|
140
|
+
* @param catalog the catalog service used to get the annotations for the specified service path
|
|
141
|
+
* @returns Promise<string | boolean>, string error message or true if successful
|
|
142
|
+
*/
|
|
143
|
+
async function getServiceMetadata(servicePath, odataService, catalog) {
|
|
144
|
+
let annotations = [];
|
|
145
|
+
try {
|
|
146
|
+
if (catalog) {
|
|
147
|
+
try {
|
|
148
|
+
annotations = await catalog.getAnnotations({ path: servicePath });
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
logger_helper_1.default.logger.info((0, i18n_1.t)('prompts.validationMessages.noAnnotations'));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const metadata = await odataService.metadata();
|
|
155
|
+
return {
|
|
156
|
+
annotations,
|
|
157
|
+
metadata
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceMetadataErrorLog', { servicePath, error }));
|
|
162
|
+
return (0, i18n_1.t)('errors.serviceMetadataErrorUI', { servicePath });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get service type for 'Not Determined' services from `ServiceTypeForHUBServices()`
|
|
167
|
+
*
|
|
168
|
+
* @param servicePath service path
|
|
169
|
+
* @param serviceType service type
|
|
170
|
+
* @param catalog the catalog service used to get the service type for the specified service path
|
|
171
|
+
* @returns service type
|
|
172
|
+
*/
|
|
173
|
+
async function getServiceType(servicePath, serviceType, catalog) {
|
|
174
|
+
let resolvedServiceType;
|
|
175
|
+
if (serviceType === axios_extension_1.ServiceType.NotDetermined) {
|
|
176
|
+
try {
|
|
177
|
+
resolvedServiceType = (await catalog.getServiceType(servicePath)) ?? axios_extension_1.ServiceType.NotDetermined;
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.serviceTypeRequestError', { error: e.message }));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return resolvedServiceType ?? serviceType;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Requests and sets the service details to the PromptState.odataService properties.
|
|
187
|
+
* If an error occurs, the error message is returned for use in validators.
|
|
188
|
+
*
|
|
189
|
+
* @param service the specific service to get details for
|
|
190
|
+
* @param connectionValidator a reference to the connection validator which has an active connection to the backend
|
|
191
|
+
* @param requiredOdataVersion
|
|
192
|
+
* @returns true if successful, setting the PromptState.odataService properties, or an error message indicating why the service details could not be retrieved.
|
|
193
|
+
*/
|
|
194
|
+
async function getServiceDetails(service, connectionValidator, requiredOdataVersion) {
|
|
195
|
+
const serviceCatalog = connectionValidator.catalogs?.[service.serviceODataVersion];
|
|
196
|
+
if (!connectionValidator.serviceProvider) {
|
|
197
|
+
logger_helper_1.default.logger.error('ConnectionValidator connection is not initialized');
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
// We may already have an odata service endpoint connection
|
|
201
|
+
let odataService = connectionValidator.odataService;
|
|
202
|
+
if (!odataService) {
|
|
203
|
+
odataService = connectionValidator.serviceProvider.service(service.servicePath);
|
|
204
|
+
}
|
|
205
|
+
const serviceResult = await getServiceMetadata(service.servicePath, odataService, serviceCatalog);
|
|
206
|
+
if (typeof serviceResult === 'string') {
|
|
207
|
+
return serviceResult;
|
|
208
|
+
}
|
|
209
|
+
const { validationMsg, version } = (0, validators_1.validateODataVersion)(serviceResult.metadata, requiredOdataVersion);
|
|
210
|
+
if (validationMsg) {
|
|
211
|
+
return validationMsg;
|
|
212
|
+
}
|
|
213
|
+
// If destinationUrl is available, use it, as validatedUrl may be in the form <protocal>:<destinationName>.dest
|
|
214
|
+
const url = connectionValidator.destinationUrl ?? connectionValidator.validatedUrl;
|
|
215
|
+
let origin;
|
|
216
|
+
if (url) {
|
|
217
|
+
origin = new URL(url).origin;
|
|
218
|
+
}
|
|
219
|
+
utils_1.PromptState.odataService.annotations = serviceResult?.annotations;
|
|
220
|
+
utils_1.PromptState.odataService.metadata = serviceResult?.metadata;
|
|
221
|
+
utils_1.PromptState.odataService.odataVersion =
|
|
222
|
+
version ?? service.serviceODataVersion === axios_extension_1.ODataVersion.v2 ? odata_service_writer_1.OdataVersion.v2 : odata_service_writer_1.OdataVersion.v4;
|
|
223
|
+
utils_1.PromptState.odataService.servicePath = service.servicePath;
|
|
224
|
+
utils_1.PromptState.odataService.origin = origin;
|
|
225
|
+
utils_1.PromptState.odataService.sapClient = connectionValidator.validatedClient;
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Create a value for the service selection prompt message, which may include thge active connected user name.
|
|
230
|
+
*
|
|
231
|
+
* @param username The connected user name
|
|
232
|
+
* @returns The service selection prompt message
|
|
233
|
+
*/
|
|
234
|
+
function getSelectedServiceLabel(username) {
|
|
235
|
+
let message = (0, i18n_1.t)('prompts.systemService.message');
|
|
236
|
+
if (username) {
|
|
237
|
+
message = message.concat(` ${(0, i18n_1.t)('texts.forUserName', { username })}`);
|
|
238
|
+
}
|
|
239
|
+
return message;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get the service selection prompt additional message. This prompt will make an additional call to the system backend
|
|
243
|
+
* to retrieve the service type and display a warning message if the service type is not UI.
|
|
244
|
+
*
|
|
245
|
+
* @param serviceChoices a list of service choices
|
|
246
|
+
* @param selectedService the selected service
|
|
247
|
+
* @param connectValidator the connection validator
|
|
248
|
+
* @param requiredOdataVersion the required OData version for the service
|
|
249
|
+
* @returns the service selection prompt additional message
|
|
250
|
+
*/
|
|
251
|
+
async function getSelectedServiceMessage(serviceChoices, selectedService, connectValidator, requiredOdataVersion) {
|
|
252
|
+
if (serviceChoices?.length === 0) {
|
|
253
|
+
if (requiredOdataVersion) {
|
|
254
|
+
return {
|
|
255
|
+
message: (0, i18n_1.t)('prompts.warnings.noServicesAvailableForOdataVersion', {
|
|
256
|
+
odataVersion: requiredOdataVersion
|
|
257
|
+
}),
|
|
258
|
+
severity: yeoman_ui_types_1.Severity.warning
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
return {
|
|
263
|
+
message: (0, i18n_1.t)('prompts.warnings.noServicesAvailable'),
|
|
264
|
+
severity: yeoman_ui_types_1.Severity.warning
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (selectedService) {
|
|
269
|
+
let serviceType = selectedService.serviceType;
|
|
270
|
+
if (selectedService.serviceODataVersion === axios_extension_1.ODataVersion.v2) {
|
|
271
|
+
serviceType = await getServiceType(selectedService.servicePath, selectedService.serviceType, connectValidator.catalogs[axios_extension_1.ODataVersion.v2]);
|
|
272
|
+
}
|
|
273
|
+
if (serviceType && serviceType !== axios_extension_1.ServiceType.UI) {
|
|
274
|
+
return {
|
|
275
|
+
message: (0, i18n_1.t)('prompts.warnings.nonUIServiceTypeWarningMessage', { serviceType: 'A2X' }),
|
|
276
|
+
severity: yeoman_ui_types_1.Severity.warning
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//# 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
|
|
@@ -0,0 +1,190 @@
|
|
|
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.connectWithBackendSystem = connectWithBackendSystem;
|
|
7
|
+
exports.connectWithDestination = connectWithDestination;
|
|
8
|
+
exports.getBackendSystemDisplayName = getBackendSystemDisplayName;
|
|
9
|
+
exports.createSystemChoices = createSystemChoices;
|
|
10
|
+
const btp_utils_1 = require("@sap-ux/btp-utils");
|
|
11
|
+
const store_1 = require("@sap-ux/store");
|
|
12
|
+
const error_handler_1 = require("../../../../error-handler/error-handler");
|
|
13
|
+
const i18n_1 = require("../../../../i18n");
|
|
14
|
+
const utils_1 = require("../../../../utils");
|
|
15
|
+
const logger_helper_1 = __importDefault(require("../../../logger-helper"));
|
|
16
|
+
const questions_1 = require("./questions");
|
|
17
|
+
/**
|
|
18
|
+
* Connects to the specified backend system and validates the connection.
|
|
19
|
+
* Note this will return true in the case of basic auth validation failure to defer validation to the credentials prompt.
|
|
20
|
+
*
|
|
21
|
+
* @param backendSystem the backend system to connect to
|
|
22
|
+
* @param connectionValidator the connection validator to use for the connection
|
|
23
|
+
* @param requiredOdataVersion the required OData version for the service, this will be used to narrow the catalog service connections
|
|
24
|
+
* @returns the validation result of the backend system connection
|
|
25
|
+
*/
|
|
26
|
+
async function connectWithBackendSystem(backendSystem, connectionValidator, requiredOdataVersion) {
|
|
27
|
+
// Create a new connection with the selected system
|
|
28
|
+
let connectValResult = false;
|
|
29
|
+
if (backendSystem) {
|
|
30
|
+
// Assumption: non-BAS systems are BackendSystems
|
|
31
|
+
if (backendSystem.authenticationType === 'reentranceTicket') {
|
|
32
|
+
connectValResult = await connectionValidator.validateUrl(backendSystem.url, {
|
|
33
|
+
isSystem: true,
|
|
34
|
+
odataVersion: (0, utils_1.convertODataVersionType)(requiredOdataVersion),
|
|
35
|
+
systemAuthType: 'reentranceTicket'
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else if (backendSystem.serviceKeys) {
|
|
39
|
+
connectValResult = await connectionValidator.validateServiceInfo(backendSystem.serviceKeys);
|
|
40
|
+
}
|
|
41
|
+
else if (backendSystem.authenticationType === 'basic' || !backendSystem.authenticationType) {
|
|
42
|
+
let errorType;
|
|
43
|
+
({ valResult: connectValResult, errorType } = await connectionValidator.validateAuth(backendSystem.url, backendSystem.username, backendSystem.password, {
|
|
44
|
+
isSystem: true,
|
|
45
|
+
odataVersion: (0, utils_1.convertODataVersionType)(requiredOdataVersion),
|
|
46
|
+
sapClient: backendSystem.client
|
|
47
|
+
}));
|
|
48
|
+
// If authentication failed with existing credentials the user will be prompted to enter new credentials.
|
|
49
|
+
// We log the error in case there is another issue (unresolveable) with the stored backend configuration.
|
|
50
|
+
if (errorType === error_handler_1.ERROR_TYPE.AUTH && backendSystem.username && backendSystem.password) {
|
|
51
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.storedSystemConnectionError', { systemName: backendSystem.name, error: connectValResult }));
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// If the connection is successful, we will return the connected system from the inquirer
|
|
56
|
+
if (connectValResult === true && connectionValidator.serviceProvider) {
|
|
57
|
+
utils_1.PromptState.odataService.connectedSystem = {
|
|
58
|
+
serviceProvider: connectionValidator.serviceProvider,
|
|
59
|
+
backendSystem
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return connectValResult;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Connects to the specified destination and validates the connection.
|
|
67
|
+
* Note that a destination may be a system or a service connection.
|
|
68
|
+
*
|
|
69
|
+
* @param destination the destination specifying the connection details
|
|
70
|
+
* @param connectionValidator the connection validator to use for the connection
|
|
71
|
+
* @param requiredOdataVersion the required OData version for the service, this will be used to narrow the catalog service connections
|
|
72
|
+
* @param addServicePath the service path to add to the destination URL
|
|
73
|
+
* @returns the validation result of the destination connection attempt
|
|
74
|
+
*/
|
|
75
|
+
async function connectWithDestination(destination, connectionValidator, requiredOdataVersion, addServicePath) {
|
|
76
|
+
const { valResult: connectValResult, errorType } = await connectionValidator.validateDestination(destination, (0, utils_1.convertODataVersionType)(requiredOdataVersion), addServicePath);
|
|
77
|
+
// If authentication failed with an auth error, and the system connection auth type is basic, we will defer validation to the credentials prompt.
|
|
78
|
+
if (errorType === error_handler_1.ERROR_TYPE.AUTH && connectionValidator.systemAuthType === 'basic') {
|
|
79
|
+
logger_helper_1.default.logger.error((0, i18n_1.t)('errors.destination.authError', { systemName: destination.Name, error: connectValResult }));
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
// If the connection is successful, we will return the connected system from the inquirer
|
|
83
|
+
if (connectValResult === true && connectionValidator.serviceProvider) {
|
|
84
|
+
utils_1.PromptState.odataService.connectedSystem = {
|
|
85
|
+
serviceProvider: connectionValidator.serviceProvider,
|
|
86
|
+
destination
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Deal with all destination errors here
|
|
90
|
+
return connectValResult;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Creates and returns a display name for the system, appending the system type and user display name if available.
|
|
94
|
+
*
|
|
95
|
+
* @param system the backend system to create a display name for
|
|
96
|
+
* @returns the display name for the system
|
|
97
|
+
*/
|
|
98
|
+
function getBackendSystemDisplayName(system) {
|
|
99
|
+
const userDisplayName = system.userDisplayName ? ` [${system.userDisplayName}]` : '';
|
|
100
|
+
let systemTypeName = '';
|
|
101
|
+
if (system.authenticationType === 'reentranceTicket') {
|
|
102
|
+
systemTypeName = ` (${(0, i18n_1.t)('texts.systemTypeS4HC')})`;
|
|
103
|
+
}
|
|
104
|
+
if (system.authenticationType === 'oauth2') {
|
|
105
|
+
systemTypeName = ` (${(0, i18n_1.t)('texts.systemTypeBTP')})`;
|
|
106
|
+
}
|
|
107
|
+
return `${system.name}${systemTypeName}${userDisplayName}`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Matches the destination against the provided filters. Returns true if the destination matches any filters, false otherwise.
|
|
111
|
+
*
|
|
112
|
+
* @param destination
|
|
113
|
+
* @param filters
|
|
114
|
+
* @returns true if the destination matches any filters, false otherwise
|
|
115
|
+
*/
|
|
116
|
+
function matchesFilters(destination, filters) {
|
|
117
|
+
if (!filters) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
if (filters.odata_abap && (0, btp_utils_1.isAbapODataDestination)(destination)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
if (filters.odata_generic && (0, btp_utils_1.isGenericODataDestination)(destination)) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
if (filters.full_service_url && (0, btp_utils_1.isFullUrlDestination)(destination)) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
if (filters.partial_service_url && (0, btp_utils_1.isPartialUrlDestination)(destination)) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
logger_helper_1.default.logger.debug(`Destination: ${destination.Name} does not match any filters and will be excluded as a prompt choice. Destination configuration: ${JSON.stringify(destination)}`);
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Creates a list of choices for the system selection prompt using destinations or stored backend systems, depending on the environment.
|
|
137
|
+
*
|
|
138
|
+
* @param destinationFilters
|
|
139
|
+
* @param includeCloudFoundryAbapEnvChoice
|
|
140
|
+
* @returns a list of choices for the system selection prompt
|
|
141
|
+
*/
|
|
142
|
+
async function createSystemChoices(destinationFilters, includeCloudFoundryAbapEnvChoice = false) {
|
|
143
|
+
let systemChoices = [];
|
|
144
|
+
let newSystemChoice;
|
|
145
|
+
// If this is BAS, return destinations, otherwise return stored backend systems
|
|
146
|
+
if ((0, btp_utils_1.isAppStudio)()) {
|
|
147
|
+
const destinations = await (0, btp_utils_1.listDestinations)();
|
|
148
|
+
systemChoices = Object.values(destinations)
|
|
149
|
+
.filter((destination) => {
|
|
150
|
+
return matchesFilters(destination, destinationFilters);
|
|
151
|
+
})
|
|
152
|
+
.map((destination) => {
|
|
153
|
+
return {
|
|
154
|
+
name: (0, btp_utils_1.getDisplayName)(destination),
|
|
155
|
+
value: {
|
|
156
|
+
type: 'destination',
|
|
157
|
+
system: destination
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
if (includeCloudFoundryAbapEnvChoice) {
|
|
162
|
+
newSystemChoice = {
|
|
163
|
+
name: (0, i18n_1.t)('prompts.newSystemType.choiceCFAbapEnvServiceOnBtp'),
|
|
164
|
+
value: { type: 'cfAbapEnvService', system: 'cfAbapEnvService' }
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
const backendSystems = await new store_1.SystemService(logger_helper_1.default.logger).getAll();
|
|
170
|
+
systemChoices = backendSystems.map((system) => {
|
|
171
|
+
return {
|
|
172
|
+
name: getBackendSystemDisplayName(system),
|
|
173
|
+
value: {
|
|
174
|
+
system,
|
|
175
|
+
type: 'backendSystem'
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
newSystemChoice = {
|
|
180
|
+
name: (0, i18n_1.t)('prompts.systemSelection.newSystemChoiceLabel'),
|
|
181
|
+
value: { system: questions_1.newSystemChoiceValue, type: 'newSystemChoice' }
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
systemChoices.sort(({ name: nameA }, { name: nameB }) => nameA.localeCompare(nameB, undefined, { numeric: true, caseFirst: 'lower' }));
|
|
185
|
+
if (newSystemChoice) {
|
|
186
|
+
systemChoices.unshift(newSystemChoice);
|
|
187
|
+
}
|
|
188
|
+
return systemChoices;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=prompt-helpers.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Destination } from '@sap-ux/btp-utils';
|
|
2
|
+
import type { BackendSystem } from '@sap-ux/store';
|
|
3
|
+
import type { Question } from 'inquirer';
|
|
4
|
+
import { promptNames, type OdataServicePromptOptions } from '../../../../types';
|
|
5
|
+
import { ConnectionValidator } from '../../../connectionValidator';
|
|
6
|
+
import type { ServiceAnswer } from '../service-selection';
|
|
7
|
+
export declare const newSystemChoiceValue = "!@\u00A3*&937newSystem*X~qy^";
|
|
8
|
+
type NewSystemChoice = typeof newSystemChoiceValue;
|
|
9
|
+
declare const usernamePromptName: "systemSelection:systemUsername";
|
|
10
|
+
declare const passwordPromptName: "systemSelection:systemPassword";
|
|
11
|
+
export type SystemSelectionAnswerType = {
|
|
12
|
+
type: 'destination' | 'backendSystem' | 'newSystemChoice' | 'cfAbapEnvService';
|
|
13
|
+
system: Destination | BackendSystem | NewSystemChoice | 'cfAbapEnvService';
|
|
14
|
+
};
|
|
15
|
+
interface SystemSelectionCredentialsAnswers {
|
|
16
|
+
[usernamePromptName]?: string;
|
|
17
|
+
[passwordPromptName]?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SystemSelectionAnswers extends SystemSelectionCredentialsAnswers {
|
|
20
|
+
[promptNames.systemSelection]?: SystemSelectionAnswerType;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns a list of questions for creating a new system configuration or selecting an existing stored system.
|
|
24
|
+
*
|
|
25
|
+
* @param promptOptions prompt options that may be used to customize the questions
|
|
26
|
+
* @returns a list of questions for creating a new system configuration or selecting an existing stored system
|
|
27
|
+
*/
|
|
28
|
+
export declare function getSystemSelectionQuestions(promptOptions?: OdataServicePromptOptions): Promise<Question<SystemSelectionAnswers & ServiceAnswer>[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Returns a list of existing systems, either destinations or backend systems from persistent store, depending on the environment.
|
|
31
|
+
* Note that destinations are only available in BAS environment and must include the destination attribute `WebIDEEnabled` to be listed.
|
|
32
|
+
* Additional destination attribute filters may be provided.
|
|
33
|
+
*
|
|
34
|
+
* @param connectionValidator A reference to the active connection validator, used to validate the service selection and retrieve service details.
|
|
35
|
+
* @param promptOptions
|
|
36
|
+
* @returns a list of existing systems
|
|
37
|
+
*/
|
|
38
|
+
export declare function getSystemConnectionQuestions(connectionValidator: ConnectionValidator, promptOptions?: OdataServicePromptOptions): Promise<Question<SystemSelectionAnswers>[]>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=questions.d.ts.map
|