@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.
Files changed (50) hide show
  1. package/dist/i18n.js +15 -3
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.js +10 -9
  4. package/dist/prompts/connectionValidator.d.ts +63 -12
  5. package/dist/prompts/connectionValidator.js +208 -50
  6. package/dist/prompts/datasources/cap-project/questions.js +2 -1
  7. package/dist/prompts/datasources/sap-system/abap-on-btp/questions.d.ts +3 -2
  8. package/dist/prompts/datasources/sap-system/abap-on-btp/questions.js +10 -10
  9. package/dist/prompts/datasources/sap-system/abap-on-prem/questions.d.ts +9 -11
  10. package/dist/prompts/datasources/sap-system/abap-on-prem/questions.js +21 -55
  11. package/dist/prompts/datasources/sap-system/credentials/questions.d.ts +21 -0
  12. package/dist/prompts/datasources/sap-system/credentials/questions.js +123 -0
  13. package/dist/prompts/datasources/sap-system/new-system/questions.d.ts +4 -26
  14. package/dist/prompts/datasources/sap-system/new-system/questions.js +18 -168
  15. package/dist/prompts/datasources/sap-system/new-system/types.d.ts +0 -10
  16. package/dist/prompts/datasources/sap-system/service-selection/index.d.ts +3 -0
  17. package/dist/prompts/datasources/sap-system/service-selection/index.js +19 -0
  18. package/dist/prompts/datasources/sap-system/service-selection/questions.d.ts +15 -0
  19. package/dist/prompts/datasources/sap-system/service-selection/questions.js +146 -0
  20. package/dist/prompts/datasources/sap-system/service-selection/service-helper.d.ts +71 -0
  21. package/dist/prompts/datasources/sap-system/service-selection/service-helper.js +282 -0
  22. package/dist/prompts/datasources/sap-system/service-selection/types.d.ts +11 -0
  23. package/dist/prompts/datasources/sap-system/service-selection/types.js +3 -0
  24. package/dist/prompts/datasources/sap-system/system-selection/index.d.ts +2 -0
  25. package/dist/prompts/datasources/sap-system/system-selection/index.js +18 -0
  26. package/dist/prompts/datasources/sap-system/system-selection/prompt-helpers.d.ts +44 -0
  27. package/dist/prompts/datasources/sap-system/system-selection/prompt-helpers.js +190 -0
  28. package/dist/prompts/datasources/sap-system/system-selection/questions.d.ts +40 -0
  29. package/dist/prompts/datasources/sap-system/system-selection/questions.js +182 -0
  30. package/dist/prompts/datasources/sap-system/validators.d.ts +8 -0
  31. package/dist/prompts/datasources/sap-system/validators.js +17 -0
  32. package/dist/prompts/datasources/service-url/questions.js +4 -3
  33. package/dist/prompts/datasources/service-url/validators.js +8 -9
  34. package/dist/prompts/prompt-helpers.d.ts +2 -3
  35. package/dist/prompts/prompt-helpers.js +4 -13
  36. package/dist/prompts/prompts.js +5 -34
  37. package/dist/prompts/validators.d.ts +1 -1
  38. package/dist/prompts/validators.js +1 -1
  39. package/dist/translations/odata-service-inquirer.i18n.json +25 -37
  40. package/dist/types.d.ts +57 -45
  41. package/dist/types.js +7 -41
  42. package/dist/utils/index.d.ts +5 -18
  43. package/dist/utils/index.js +10 -55
  44. package/package.json +10 -9
  45. package/dist/error-handler/error-handler.d.ts +0 -184
  46. package/dist/error-handler/error-handler.js +0 -465
  47. package/dist/prompts/datasources/sap-system/abap-on-btp/cf-helper.d.ts +0 -9
  48. package/dist/prompts/datasources/sap-system/abap-on-btp/cf-helper.js +0 -54
  49. package/dist/prompts/datasources/sap-system/new-system/service-helper.d.ts +0 -43
  50. package/dist/prompts/datasources/sap-system/new-system/service-helper.js +0 -175
@@ -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 inquirer_common_1 = require("@sap-ux/inquirer-common");
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 === inquirer_common_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 === inquirer_common_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
@@ -0,0 +1,182 @@
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.newSystemChoiceValue = void 0;
7
+ exports.getSystemSelectionQuestions = getSystemSelectionQuestions;
8
+ exports.getSystemConnectionQuestions = getSystemConnectionQuestions;
9
+ const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
10
+ const btp_utils_1 = require("@sap-ux/btp-utils");
11
+ const inquirer_common_1 = require("@sap-ux/inquirer-common");
12
+ const i18n_1 = require("../../../../i18n");
13
+ const types_1 = require("../../../../types");
14
+ const utils_1 = require("../../../../utils");
15
+ const connectionValidator_1 = require("../../../connectionValidator");
16
+ const logger_helper_1 = __importDefault(require("../../../logger-helper"));
17
+ const questions_1 = require("../credentials/questions");
18
+ const questions_2 = require("../new-system/questions");
19
+ const questions_3 = require("../service-selection/questions");
20
+ const validators_1 = require("../validators");
21
+ const prompt_helpers_1 = require("./prompt-helpers");
22
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
23
+ // New system choice value is a hard to guess string to avoid conflicts with existing system names or user named systems
24
+ // since it will be used as a new system value in the system selection prompt.
25
+ exports.newSystemChoiceValue = '!@£*&937newSystem*X~qy^';
26
+ const systemSelectionPromptNamespace = 'systemSelection';
27
+ const usernamePromptName = `${systemSelectionPromptNamespace}:${questions_1.BasicCredentialsPromptNames.systemUsername}`;
28
+ const passwordPromptName = `${systemSelectionPromptNamespace}:${questions_1.BasicCredentialsPromptNames.systemPassword}`;
29
+ const systemSelectionPromptNames = {
30
+ systemSelectionCli: 'systemSelectionCli',
31
+ destinationServicePath: 'destinationServicePath'
32
+ };
33
+ /**
34
+ * Validates the system selection, connecting to the selected system and validating the connection.
35
+ *
36
+ * @param systemSelection
37
+ * @param connectionValidator
38
+ * @param requiredOdataVersion
39
+ * @returns the validation result of the selected system connection attempt
40
+ */
41
+ async function validateSystemSelection(systemSelection, connectionValidator, requiredOdataVersion) {
42
+ utils_1.PromptState.reset();
43
+ if (systemSelection.type === 'newSystemChoice') {
44
+ return true;
45
+ }
46
+ let connectValResult = false;
47
+ if (systemSelection.type === 'backendSystem') {
48
+ connectValResult = await (0, prompt_helpers_1.connectWithBackendSystem)(systemSelection.system, connectionValidator, requiredOdataVersion);
49
+ }
50
+ else if (systemSelection.type === 'destination') {
51
+ // Partial URL destinations will require additional service path prompt input, so we skip the connection validation here by returning true
52
+ // The service URL connection will need to be validated by the service path prompt
53
+ if ((0, btp_utils_1.isPartialUrlDestination)(systemSelection.system)) {
54
+ // Reset the connection state as we are deferring the connection validation to the service path prompt, any existing connection state should be cleared
55
+ // connectionValidator.resetConnectionState(true);
56
+ return true;
57
+ }
58
+ connectValResult = await (0, prompt_helpers_1.connectWithDestination)(systemSelection.system, connectionValidator, requiredOdataVersion);
59
+ }
60
+ return connectValResult;
61
+ }
62
+ /**
63
+ * Returns a list of questions for creating a new system configuration or selecting an existing stored system.
64
+ *
65
+ * @param promptOptions prompt options that may be used to customize the questions
66
+ * @returns a list of questions for creating a new system configuration or selecting an existing stored system
67
+ */
68
+ async function getSystemSelectionQuestions(promptOptions) {
69
+ utils_1.PromptState.reset();
70
+ const connectValidator = new connectionValidator_1.ConnectionValidator();
71
+ const questions = await getSystemConnectionQuestions(connectValidator, promptOptions);
72
+ // Existing system (BackendSystem or Destination) selected,
73
+ // In future, make the service prompt optional by wrapping in condition `[promptOptions?.serviceSelection?.hide]`
74
+ questions.push(...(0, inquirer_common_1.withCondition)((0, questions_3.getSystemServiceQuestion)(connectValidator, systemSelectionPromptNamespace, promptOptions), (answers) => answers.systemSelection?.type !== 'newSystemChoice'));
75
+ // Create new system connection for storage only supported on non-App Studio environments
76
+ if (!(0, btp_utils_1.isAppStudio)()) {
77
+ questions.push(...(0, inquirer_common_1.withCondition)((0, questions_2.getNewSystemQuestions)(promptOptions), (answers) => answers.systemSelection?.type === 'newSystemChoice'));
78
+ }
79
+ return questions;
80
+ }
81
+ /**
82
+ * Returns a list of existing systems, either destinations or backend systems from persistent store, depending on the environment.
83
+ * Note that destinations are only available in BAS environment and must include the destination attribute `WebIDEEnabled` to be listed.
84
+ * Additional destination attribute filters may be provided.
85
+ *
86
+ * @param connectionValidator A reference to the active connection validator, used to validate the service selection and retrieve service details.
87
+ * @param promptOptions
88
+ * @returns a list of existing systems
89
+ */
90
+ async function getSystemConnectionQuestions(connectionValidator, promptOptions) {
91
+ const requiredOdataVersion = promptOptions?.serviceSelection?.requiredOdataVersion;
92
+ const destinationFilters = promptOptions?.systemSelection?.destinationFilters;
93
+ const systemChoices = await (0, prompt_helpers_1.createSystemChoices)(destinationFilters, promptOptions?.systemSelection?.includeCloudFoundryAbapEnvChoice);
94
+ const questions = [
95
+ {
96
+ type: promptOptions?.systemSelection?.useAutoComplete ? 'autocomplete' : 'list',
97
+ name: types_1.promptNames.systemSelection,
98
+ message: (0, i18n_1.t)('prompts.systemSelection.message'),
99
+ source: (prevAnswers, input) => (0, inquirer_common_1.searchChoices)(input, systemChoices),
100
+ choices: systemChoices,
101
+ validate: async (selectedSystem) => {
102
+ if (!selectedSystem) {
103
+ return false;
104
+ }
105
+ let selectedSystemAnswer = selectedSystem;
106
+ // Autocomplete passes the entire choice object as the answer, so we need to extract the value
107
+ if (promptOptions?.systemSelection?.useAutoComplete && selectedSystem.value) {
108
+ selectedSystemAnswer = selectedSystem.value;
109
+ }
110
+ return (validateSystemSelection(selectedSystemAnswer, connectionValidator, requiredOdataVersion) ?? false);
111
+ },
112
+ additionalMessages: async (selectedSystem) => {
113
+ // Backend systems credentials may need to be updated
114
+ if (selectedSystem.type === 'backendSystem' &&
115
+ connectionValidator.systemAuthType === 'basic' &&
116
+ (await connectionValidator.isAuthRequired())) {
117
+ return {
118
+ message: (0, i18n_1.t)('prompts.systemSelection.authenticationFailedUpdateCredentials'),
119
+ severity: yeoman_ui_types_1.Severity.information
120
+ };
121
+ }
122
+ }
123
+ }
124
+ ];
125
+ if ((0, btp_utils_1.isAppStudio)()) {
126
+ // Additional service path prompt for partial URL destinations
127
+ const servicePathPrompt = {
128
+ when: (answers) => {
129
+ const selectedSystem = answers?.[types_1.promptNames.systemSelection];
130
+ if (selectedSystem?.type === 'destination') {
131
+ return (0, btp_utils_1.isPartialUrlDestination)(selectedSystem.system);
132
+ }
133
+ return false;
134
+ },
135
+ type: 'input',
136
+ name: systemSelectionPromptNames.destinationServicePath,
137
+ message: (0, i18n_1.t)('prompts.destinationServicePath.message'),
138
+ guiOptions: {
139
+ hint: (0, i18n_1.t)('prompts.destinationServicePath.hint'),
140
+ mandatory: true,
141
+ breadcrumb: true
142
+ },
143
+ validate: async (servicePath, answers) => {
144
+ if (!servicePath) {
145
+ return (0, i18n_1.t)('prompts.destinationServicePath.invalidServicePathWarning');
146
+ }
147
+ // Validate format of the service path, note this relies on the assumption that the destination is correctly configured with a valid URL
148
+ const selectedDestination = answers?.[types_1.promptNames.systemSelection]?.system;
149
+ const valUrlResult = (0, validators_1.validateServiceUrl)(selectedDestination.Host, servicePath);
150
+ if (valUrlResult !== true) {
151
+ return valUrlResult;
152
+ }
153
+ const connectValResult = await (0, prompt_helpers_1.connectWithDestination)(selectedDestination, connectionValidator, requiredOdataVersion, servicePath);
154
+ return connectValResult;
155
+ }
156
+ };
157
+ questions.push(servicePathPrompt);
158
+ }
159
+ // Only for CLI use as `list` prompt validation does not run on CLI unless autocomplete plugin is used
160
+ if ((0, utils_1.getPromptHostEnvironment)() === fiori_generator_shared_1.hostEnvironment.cli && !promptOptions?.systemSelection?.useAutoComplete) {
161
+ questions.push({
162
+ when: async (answers) => {
163
+ const selectedSystem = answers?.[types_1.promptNames.systemSelection];
164
+ if (!selectedSystem) {
165
+ return false;
166
+ }
167
+ const connectValResult = await validateSystemSelection(selectedSystem, connectionValidator, requiredOdataVersion);
168
+ // An issue occurred with the selected system, there is no need to continue on the CLI, log and exit
169
+ // Note that for connection authentication errors, the result will be true, the user will be prompted to update their credentials in the next prompt
170
+ if (connectValResult !== true) {
171
+ logger_helper_1.default.logger.error(connectValResult.toString);
172
+ throw new Error(connectValResult.toString());
173
+ }
174
+ return false;
175
+ },
176
+ name: `${systemSelectionPromptNames.systemSelectionCli}`
177
+ });
178
+ }
179
+ questions.push(...(0, questions_1.getCredentialsPrompts)(connectionValidator, systemSelectionPromptNamespace));
180
+ return questions;
181
+ }
182
+ //# sourceMappingURL=questions.js.map
@@ -13,4 +13,12 @@ export declare function validateSystemName(systemName: string): Promise<boolean
13
13
  * @returns the service key info if the file is valid, otherwise an error message
14
14
  */
15
15
  export declare function validateServiceKey(path: string): string | ServiceInfo | boolean;
16
+ /**
17
+ * Validates the specified origin and service path can be used to form a valid URL.
18
+ *
19
+ * @param origin the origin of the service
20
+ * @param servicePath the path to the service
21
+ * @returns true if a URL can be created from the specified parameters, otherwise an error message
22
+ */
23
+ export declare function validateServiceUrl(origin: string, servicePath: string): string | boolean;
16
24
  //# sourceMappingURL=validators.d.ts.map
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.validateSystemName = validateSystemName;
7
7
  exports.validateServiceKey = validateServiceKey;
8
+ exports.validateServiceUrl = validateServiceUrl;
8
9
  const i18n_1 = require("../../../i18n");
9
10
  const store_1 = require("@sap-ux/store");
10
11
  const logger_helper_1 = __importDefault(require("../../logger-helper"));
@@ -59,4 +60,20 @@ function validateServiceKey(path) {
59
60
  return error.name === 'SyntaxError' ? (0, i18n_1.t)('prompts.serviceKey.unparseableServiceKey') : error.message;
60
61
  }
61
62
  }
63
+ /**
64
+ * Validates the specified origin and service path can be used to form a valid URL.
65
+ *
66
+ * @param origin the origin of the service
67
+ * @param servicePath the path to the service
68
+ * @returns true if a URL can be created from the specified parameters, otherwise an error message
69
+ */
70
+ function validateServiceUrl(origin, servicePath) {
71
+ try {
72
+ new URL(servicePath, origin);
73
+ return true;
74
+ }
75
+ catch (error) {
76
+ return (0, i18n_1.t)('errors.invalidUrl', { input: `${origin}${servicePath}` });
77
+ }
78
+ }
62
79
  //# sourceMappingURL=validators.js.map
@@ -12,6 +12,7 @@ const connectionValidator_1 = require("../../connectionValidator");
12
12
  const logger_helper_1 = __importDefault(require("../../logger-helper"));
13
13
  const types_2 = require("./types");
14
14
  const validators_1 = require("./validators");
15
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
15
16
  /**
16
17
  * Prompt for the service URL.
17
18
  *
@@ -168,15 +169,15 @@ function getPasswordPrompt(connectValidator, requiredVersion) {
168
169
  applyDefaultWhenDirty: true,
169
170
  mandatory: true
170
171
  },
172
+ guiType: 'login',
171
173
  name: types_1.promptNames.serviceUrlPassword,
172
174
  message: (0, i18n_1.t)('prompts.servicePassword.message'),
173
- guiType: 'login',
174
175
  mask: '*',
175
176
  validate: async (password, { username, serviceUrl, ignoreCertError, sapClient }) => {
176
177
  if (!serviceUrl || !username || !password) {
177
178
  return false;
178
179
  }
179
- const validAuth = await connectValidator.validateAuth(serviceUrl, username, password, {
180
+ const { valResult: validAuth } = await connectValidator.validateAuth(serviceUrl, username, password, {
180
181
  ignoreCertError,
181
182
  sapClient
182
183
  });
@@ -207,7 +208,7 @@ function getServiceUrlQuestions({ serviceUrl: serviceUrlOpts, serviceUrlPassword
207
208
  getServiceUrlPrompt(connectValidator, requiredVersion),
208
209
  getIgnoreCertErrorsPrompt(connectValidator, requiredVersion)
209
210
  ];
210
- if ((0, utils_1.getHostEnvironment)() === types_1.hostEnvironment.cli) {
211
+ if ((0, utils_1.getPromptHostEnvironment)() === fiori_generator_shared_1.hostEnvironment.cli) {
211
212
  questions.push(getCliIgnoreCertValidatePrompt(connectValidator, requiredVersion));
212
213
  }
213
214
  questions.push(getUsernamePrompt(connectValidator), getPasswordPrompt(connectValidator, requiredVersion));
@@ -5,13 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.validateService = validateService;
7
7
  const axios_extension_1 = require("@sap-ux/axios-extension");
8
- const error_handler_1 = require("../../../error-handler/error-handler");
8
+ const inquirer_common_1 = require("@sap-ux/inquirer-common");
9
9
  const i18n_1 = require("../../../i18n");
10
10
  const types_1 = require("../../../types");
11
11
  const utils_1 = require("../../../utils");
12
12
  const connectionValidator_1 = require("../../connectionValidator");
13
13
  const logger_helper_1 = __importDefault(require("../../logger-helper"));
14
14
  const prompt_helpers_1 = require("../../prompt-helpers");
15
+ const validators_1 = require("../../validators");
15
16
  /**
16
17
  * Validates that a service specified by the service url is accessible, has the required version and returns valid metadata.
17
18
  * Retrieves annotations (from Abap backends) if available and stores them in the PromptState.
@@ -30,13 +31,11 @@ async function validateService(url, { odataService, axiosConfig }, requiredVersi
30
31
  connectionValidator_1.ConnectionValidator.setGlobalRejectUnauthorized(!ignoreCertError);
31
32
  }
32
33
  const metadata = await odataService.metadata();
33
- const serviceOdataVersion = (0, utils_1.parseOdataVersion)(metadata);
34
- if (requiredVersion && requiredVersion !== serviceOdataVersion) {
35
- return `${(0, i18n_1.t)('errors.odataServiceVersionMismatch', {
36
- serviceVersion: serviceOdataVersion,
37
- requiredVersion
38
- })}`;
34
+ const odataVersionValResult = (0, validators_1.validateODataVersion)(metadata, requiredVersion);
35
+ if (odataVersionValResult.validationMsg) {
36
+ return odataVersionValResult.validationMsg;
39
37
  }
38
+ const serviceOdataVersion = odataVersionValResult.version;
40
39
  // Remove all occurrences of the origin from the metadata to make backend uris relative
41
40
  utils_1.PromptState.odataService.metadata = (0, utils_1.originToRelative)(metadata);
42
41
  utils_1.PromptState.odataService.odataVersion = serviceOdataVersion;
@@ -69,9 +68,9 @@ async function validateService(url, { odataService, axiosConfig }, requiredVersi
69
68
  catch (error) {
70
69
  delete utils_1.PromptState.odataService.metadata;
71
70
  // Provide a more specific error message if the metadata service URL is not found
72
- if (error_handler_1.ErrorHandler.getErrorType(error) === error_handler_1.ERROR_TYPE.NOT_FOUND) {
71
+ if (inquirer_common_1.ErrorHandler.getErrorType(error) === inquirer_common_1.ERROR_TYPE.NOT_FOUND) {
73
72
  // No metadata implies not a valid odata service
74
- return error_handler_1.ErrorHandler.getErrorMsgFromType(error_handler_1.ERROR_TYPE.ODATA_URL_NOT_FOUND) ?? false;
73
+ return inquirer_common_1.ErrorHandler.getErrorMsgFromType(inquirer_common_1.ERROR_TYPE.ODATA_URL_NOT_FOUND) ?? false;
75
74
  }
76
75
  return prompt_helpers_1.errorHandler.logErrorMsgs(error);
77
76
  }
@@ -1,5 +1,5 @@
1
1
  import type { ListChoiceOptions } from 'inquirer';
2
- import { ErrorHandler } from '../error-handler/error-handler';
2
+ import { ErrorHandler } from '@sap-ux/inquirer-common';
3
3
  import { type DatasourceTypePromptOptions } from '../types';
4
4
  export declare const errorHandler: ErrorHandler;
5
5
  /**
@@ -7,8 +7,7 @@ export declare const errorHandler: ErrorHandler;
7
7
  *
8
8
  * @param options - optionally include some of the supported datasource type choices
9
9
  * @param options.includeNone - Include the `NONE` option in the datasource type prompt
10
- * @param options.includeProjectSpecificDest - Include the `projectSpecificDestination` option in the datasource type prompt
11
10
  * @returns The datasource type choices
12
11
  */
13
- export declare function getDatasourceTypeChoices({ includeNone, includeProjectSpecificDest }?: DatasourceTypePromptOptions): ListChoiceOptions[];
12
+ export declare function getDatasourceTypeChoices({ includeNone }?: DatasourceTypePromptOptions): ListChoiceOptions[];
14
13
  //# sourceMappingURL=prompt-helpers.d.ts.map
@@ -2,21 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.errorHandler = void 0;
4
4
  exports.getDatasourceTypeChoices = getDatasourceTypeChoices;
5
- const btp_utils_1 = require("@sap-ux/btp-utils");
6
- const error_handler_1 = require("../error-handler/error-handler");
5
+ const inquirer_common_1 = require("@sap-ux/inquirer-common");
7
6
  const i18n_1 = require("../i18n");
8
7
  const types_1 = require("../types");
9
8
  // Error handling is a cross-cutting concern, a single instance is required
10
- exports.errorHandler = new error_handler_1.ErrorHandler();
9
+ exports.errorHandler = new inquirer_common_1.ErrorHandler();
11
10
  /**
12
11
  * Get the datasource type choices.
13
12
  *
14
13
  * @param options - optionally include some of the supported datasource type choices
15
14
  * @param options.includeNone - Include the `NONE` option in the datasource type prompt
16
- * @param options.includeProjectSpecificDest - Include the `projectSpecificDestination` option in the datasource type prompt
17
15
  * @returns The datasource type choices
18
16
  */
19
- function getDatasourceTypeChoices({ includeNone = false, includeProjectSpecificDest = false } = {}) {
17
+ function getDatasourceTypeChoices({ includeNone = false } = {}) {
20
18
  const choices = [
21
19
  {
22
20
  name: (0, i18n_1.t)('prompts.datasourceType.sapSystemChoiceText'),
@@ -25,15 +23,8 @@ function getDatasourceTypeChoices({ includeNone = false, includeProjectSpecificD
25
23
  {
26
24
  name: (0, i18n_1.t)('prompts.datasourceType.odataServiceUrlChoiceText'),
27
25
  value: types_1.DatasourceType.odataServiceUrl
28
- },
29
- { name: (0, i18n_1.t)('prompts.datasourceType.businessHubChoiceText'), value: types_1.DatasourceType.businessHub }
26
+ }
30
27
  ];
31
- if ((0, btp_utils_1.isAppStudio)() && includeProjectSpecificDest) {
32
- choices.push({
33
- name: (0, i18n_1.t)('prompts.datasourceType.projectSpecificDestChoiceText'),
34
- value: types_1.DatasourceType.projectSpecificDestination
35
- });
36
- }
37
28
  choices.push({ name: (0, i18n_1.t)('prompts.datasourceType.capProjectChoiceText'), value: types_1.DatasourceType.capProject });
38
29
  choices.push({ name: (0, i18n_1.t)('prompts.datasourceType.metadataFileChoiceText'), value: types_1.DatasourceType.metadataFile });
39
30
  if (includeNone) {