@sap-ux/odata-service-inquirer 2.9.14 → 2.11.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.
@@ -1,9 +1,10 @@
1
- import type { InputQuestion, PasswordQuestion } from '@sap-ux/inquirer-common';
1
+ import type { InputQuestion, PasswordQuestion, ConfirmQuestion } from '@sap-ux/inquirer-common';
2
2
  import type { Answers } from 'inquirer';
3
3
  import type { ConnectionValidator } from '../../../connectionValidator';
4
4
  export declare enum BasicCredentialsPromptNames {
5
5
  systemUsername = "systemUsername",
6
- systemPassword = "systemPassword"
6
+ systemPassword = "systemPassword",
7
+ storeSystemCredentials = "storeSystemCredentials"
7
8
  }
8
9
  /**
9
10
  * Re-usable credentials prompts for connection to systems using basic auth.
@@ -18,5 +19,5 @@ export declare enum BasicCredentialsPromptNames {
18
19
  export declare function getCredentialsPrompts<T extends Answers>(connectionValidator: ConnectionValidator, promptNamespace?: string, sapClient?: {
19
20
  sapClient: string | undefined;
20
21
  isValid: boolean;
21
- }): (InputQuestion<T> | PasswordQuestion<T>)[];
22
+ }): (InputQuestion<T> | PasswordQuestion<T> | ConfirmQuestion<T>)[];
22
23
  //# sourceMappingURL=questions.d.ts.map
@@ -11,6 +11,7 @@ var BasicCredentialsPromptNames;
11
11
  (function (BasicCredentialsPromptNames) {
12
12
  BasicCredentialsPromptNames["systemUsername"] = "systemUsername";
13
13
  BasicCredentialsPromptNames["systemPassword"] = "systemPassword";
14
+ BasicCredentialsPromptNames["storeSystemCredentials"] = "storeSystemCredentials";
14
15
  })(BasicCredentialsPromptNames || (exports.BasicCredentialsPromptNames = BasicCredentialsPromptNames = {}));
15
16
  /**
16
17
  * Re-usable credentials prompts for connection to systems using basic auth.
@@ -25,9 +26,10 @@ var BasicCredentialsPromptNames;
25
26
  function getCredentialsPrompts(connectionValidator, promptNamespace, sapClient) {
26
27
  const usernamePromptName = `${promptNamespace ? promptNamespace + ':' : ''}${BasicCredentialsPromptNames.systemUsername}`;
27
28
  const passwordPromptName = `${promptNamespace ? promptNamespace + ':' : ''}${BasicCredentialsPromptNames.systemPassword}`;
29
+ const storeCredentialsPromptName = `${promptNamespace ? promptNamespace + ':' : ''}${BasicCredentialsPromptNames.storeSystemCredentials}`;
28
30
  // Optimization to prevent re-checking of auth
29
31
  let authRequired;
30
- return [
32
+ const credentialsPrompts = [
31
33
  {
32
34
  when: async () => {
33
35
  authRequired = await connectionValidator.isAuthRequired();
@@ -83,7 +85,7 @@ function getCredentialsPrompts(connectionValidator, promptNamespace, sapClient)
83
85
  updatePromptStateWithConnectedSystem(connectionValidator.serviceProvider, selectedSystem, {
84
86
  username: answers?.[usernamePromptName],
85
87
  password: password
86
- });
88
+ }); // Store credentials temporarily - will be conditionally kept/removed in store credentials prompt
87
89
  return true;
88
90
  }
89
91
  return valResult;
@@ -100,9 +102,42 @@ function getCredentialsPrompts(connectionValidator, promptNamespace, sapClient)
100
102
  severity: yeoman_ui_types_1.Severity.warning
101
103
  };
102
104
  }
105
+ // Lower priority than the cert error warning - we can only show one at a time, hence this should always be last
106
+ if (utils_1.PromptState.odataService.connectedSystem?.backendSystem) {
107
+ return {
108
+ message: (0, i18n_1.t)('texts.passwordStoreWarning'),
109
+ severity: yeoman_ui_types_1.Severity.warning
110
+ };
111
+ }
103
112
  }
104
113
  }
105
114
  ];
115
+ const confirmCredentialStoragePrompt = {
116
+ when: (answers) => !!(connectionValidator.systemAuthType === 'basic' &&
117
+ authRequired &&
118
+ connectionValidator.validity.authenticated &&
119
+ answers[passwordPromptName]),
120
+ type: 'confirm',
121
+ name: storeCredentialsPromptName,
122
+ message: (0, i18n_1.t)('prompts.storeSystemCredentials.message'),
123
+ default: false,
124
+ guiOptions: {
125
+ breadcrumb: (0, i18n_1.t)('prompts.storeSystemCredentials.breadcrumb')
126
+ },
127
+ validate: async (storeCredentials) => {
128
+ if (utils_1.PromptState.odataService.connectedSystem?.backendSystem) {
129
+ const backendSystem = utils_1.PromptState.odataService.connectedSystem.backendSystem;
130
+ utils_1.PromptState.odataService.connectedSystem.backendSystem = Object.assign(backendSystem, {
131
+ newOrUpdated: storeCredentials
132
+ });
133
+ }
134
+ return true;
135
+ }
136
+ };
137
+ if (!(0, btp_utils_1.isAppStudio)()) {
138
+ credentialsPrompts.push(confirmCredentialStoragePrompt);
139
+ }
140
+ return credentialsPrompts;
106
141
  }
107
142
  /**
108
143
  * Updates the prompt state with the connected system.
@@ -120,13 +155,12 @@ function updatePromptStateWithConnectedSystem(serviceProvider, selectedSystem, {
120
155
  // Update the existing backend system with the new credentials that may be used to update in the store.
121
156
  if (selectedSystem?.type === 'backendSystem') {
122
157
  const backendSystem = selectedSystem.system;
123
- // Have the credentials changed..
158
+ // Have the credentials changed..?
124
159
  if (backendSystem.username !== username || backendSystem.password !== password) {
125
160
  utils_1.PromptState.odataService.connectedSystem.backendSystem = Object.assign(backendSystem, {
126
161
  username: username,
127
- password,
128
- userDisplayName: username,
129
- newOrUpdated: true
162
+ password: password,
163
+ userDisplayName: username
130
164
  });
131
165
  }
132
166
  // If the connection is successful and a destination was selected, assign the connected destination to the prompt state.
@@ -7,6 +7,8 @@ import type { Answers } from 'inquirer';
7
7
  import type { ConnectedSystem } from '../../../../types';
8
8
  import type { ConnectionValidator } from '../../../connectionValidator';
9
9
  import { type NewSystemAnswers } from '../new-system/types';
10
+ import type { SystemSelectionAnswers } from '../system-selection/questions';
11
+ import type { AbapOnPremAnswers } from '../abap-on-prem/questions';
10
12
  /**
11
13
  * Get the system url prompt. The system url prompt is used to connect to a new system using the user input system url.
12
14
  *
@@ -27,5 +29,5 @@ export declare function getSystemUrlQuestion<T extends Answers>(connectValidator
27
29
  * This prevents conflicts with other prompts of the same types where the same prompt is used by multiple other prompts but cannot share the name.
28
30
  * @returns the new system name prompt
29
31
  */
30
- export declare function getUserSystemNameQuestion(connectValidator: ConnectionValidator, promptNamespace?: string): InputQuestion<Partial<NewSystemAnswers>>;
32
+ export declare function getUserSystemNameQuestion(connectValidator: ConnectionValidator, promptNamespace?: string): InputQuestion<Partial<NewSystemAnswers & AbapOnPremAnswers & SystemSelectionAnswers>>;
31
33
  //# sourceMappingURL=shared-prompts.d.ts.map
@@ -10,6 +10,7 @@ const types_2 = require("../new-system/types");
10
10
  const prompt_helpers_1 = require("../prompt-helpers");
11
11
  const validators_1 = require("../validators");
12
12
  const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
13
+ const questions_1 = require("../credentials/questions");
13
14
  /**
14
15
  * Convert the system connection scheme (Service Key, Rentrance Ticket, etc) to the store specific authentication type.
15
16
  * Note the absence of CF Discovery, in this case the service key file (UAA) is also used for the Abap connectivity.
@@ -129,7 +130,7 @@ function getUserSystemNameQuestion(connectValidator, promptNamespace) {
129
130
  }
130
131
  return defaultSystemName;
131
132
  },
132
- validate: async (systemName) => {
133
+ validate: async (systemName, previousAnswers) => {
133
134
  if (!systemName) {
134
135
  return false;
135
136
  }
@@ -143,6 +144,7 @@ function getUserSystemNameQuestion(connectValidator, promptNamespace) {
143
144
  defaultSystemName = systemName;
144
145
  isValid = await (0, validators_1.validateSystemName)(systemName);
145
146
  }
147
+ const shouldStoreCreds = !!previousAnswers?.[`${promptNamespacePart}${questions_1.BasicCredentialsPromptNames.storeSystemCredentials}`];
146
148
  if (isValid === true) {
147
149
  // Update or create the BackendSystem with the new system details for persistent storage
148
150
  if (connectValidator.validatedUrl && utils_1.PromptState.odataService.connectedSystem) {
@@ -151,8 +153,8 @@ function getUserSystemNameQuestion(connectValidator, promptNamespace) {
151
153
  name: systemName,
152
154
  url: connectValidator.validatedUrl,
153
155
  client: connectValidator.validatedClient,
154
- username: connectValidator.axiosConfig?.auth?.username,
155
- password: connectValidator.axiosConfig?.auth?.password,
156
+ username: shouldStoreCreds ? connectValidator.axiosConfig?.auth?.username : undefined,
157
+ password: shouldStoreCreds ? connectValidator.axiosConfig?.auth?.password : undefined,
156
158
  serviceKeys: connectValidator.serviceInfo, // This will not be persisted and is only used to determine cached connection equality for CF provided uaa keys
157
159
  userDisplayName: connectValidator.connectedUserName,
158
160
  systemType: (0, store_1.getBackendSystemType)({
@@ -125,7 +125,6 @@ async function getSystemConnectionQuestions(connectionValidator, promptOptions,
125
125
  return (validateSystemSelection(selectedSystemAnswer, connectionValidator, requiredOdataVersion, cachedConnectedSystem) ?? false);
126
126
  },
127
127
  additionalMessages: async (selectedSystem) => {
128
- // Backend systems credentials may need to be updated
129
128
  if (selectedSystem.type === 'backendSystem' &&
130
129
  connectionValidator.systemAuthType === 'basic' &&
131
130
  (await connectionValidator.isAuthRequired())) {
@@ -4,11 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.showCollabDraftWarning = showCollabDraftWarning;
7
- const annotation_converter_1 = require("@sap-ux/annotation-converter");
8
- const edmx_parser_1 = require("@sap-ux/edmx-parser");
9
7
  const entity_helper_1 = require("../../edmx/entity-helper");
10
8
  const logger_helper_1 = __importDefault(require("../../logger-helper"));
11
9
  const i18n_1 = require("../../../i18n");
10
+ const annotation_converter_1 = require("@sap-ux/annotation-converter");
11
+ const edmx_parser_1 = require("@sap-ux/edmx-parser");
12
12
  /**
13
13
  * If any of the draft root annotated entity sets have the share action property, then collaborative draft is enabled.
14
14
  *
@@ -181,40 +181,6 @@ function filterDraftEnabledEntities(entitySets) {
181
181
  return !!entitySetTypeProperties.find((property) => property.name === 'HasDraftEntity');
182
182
  });
183
183
  }
184
- /**
185
- * Determines if AnalyticalTable should be used based on entity annotations and service type.
186
- *
187
- * AnalyticalTable is used when entity has hierarchical and analytical data together with complete transformations,
188
- * for CAP services with analytical data, or for non-CAP services with complete analytical transformations.
189
- *
190
- * @param entitySet The entity set to check for annotations.
191
- * @param isCapService Whether the service is a CAP service (affects analytical requirements).
192
- * @returns True if AnalyticalTable should be used, false otherwise.
193
- */
194
- function shouldUseAnalyticalTable(entitySet, isCapService) {
195
- // Evaluate annotations once to avoid multiple iterations
196
- const hasAnalytical = (0, inquirer_common_1.hasAggregateTransformations)(entitySet);
197
- const hasHierarchy = (0, inquirer_common_1.hasRecursiveHierarchyForEntitySet)(entitySet);
198
- // No analytical data means no need for AnalyticalTable
199
- if (!hasAnalytical) {
200
- return false;
201
- }
202
- // If entity has both analytical and hierarchical data, check requirements based on service type
203
- if (hasHierarchy) {
204
- // For CAP services, any analytical annotations are sufficient even with hierarchy
205
- if (isCapService) {
206
- return true;
207
- }
208
- // For non-CAP services, require complete analytical transformations
209
- return (0, inquirer_common_1.hasAggregateTransformationsForEntitySet)(entitySet, inquirer_common_1.transformationsRequiredForAnalyticalTable);
210
- }
211
- // For CAP services, analytical annotations are sufficient
212
- if (isCapService) {
213
- return true;
214
- }
215
- // For non-CAP services, require complete analytical transformations
216
- return (0, inquirer_common_1.hasAggregateTransformationsForEntitySet)(entitySet, inquirer_common_1.transformationsRequiredForAnalyticalTable);
217
- }
218
184
  /**
219
185
  * Get the default table type based on the template type and entity capabilities.
220
186
  *
@@ -235,13 +201,18 @@ function getDefaultTableType(templateType, metadata, odataVersion, isCapService,
235
201
  // Handle OData v4 specific logic
236
202
  if (odataVersion === odata_service_writer_1.OdataVersion.v4 && entitySet) {
237
203
  const canUseAnalytical = templateType === 'lrop' || templateType === 'worklist' || templateType === 'alp';
238
- const hasAnalyticalCapabilities = shouldUseAnalyticalTable(entitySet, isCapService);
239
204
  const hasHierarchy = (0, inquirer_common_1.hasRecursiveHierarchyForEntitySet)(entitySet);
240
- // Check for analytical data requirements
241
- if (canUseAnalytical && hasAnalyticalCapabilities) {
242
- return 'AnalyticalTable';
205
+ const hasAnalyticalData = (0, inquirer_common_1.hasAggregateTransformations)(entitySet);
206
+ // Check for analytical capabilities first (highest priority)
207
+ if (canUseAnalytical && hasAnalyticalData) {
208
+ // For CAP services, any analytical data is sufficient
209
+ // For non-CAP services, require complete transformations
210
+ const hasAnalyticalCapabilities = (0, inquirer_common_1.shouldUseAnalyticalTable)(entitySet, !isCapService);
211
+ if (hasAnalyticalCapabilities) {
212
+ return 'AnalyticalTable';
213
+ }
243
214
  }
244
- // Check for hierarchical data requirements
215
+ // Check for hierarchical data only (no analytical data or analytical requirements not met)
245
216
  if ((templateType === 'lrop' || templateType === 'worklist') && hasHierarchy) {
246
217
  return 'TreeTable';
247
218
  }
@@ -200,9 +200,9 @@ function getTableLayoutQuestions(templateType, odataVersion, isCapService, metad
200
200
  }
201
201
  const tableLayoutQuestions = [];
202
202
  if (templateType === 'lrop' || templateType === 'worklist' || templateType === 'alp') {
203
- // Variables to manage analytical table defaults across prompts
204
- let setAnalyticalTableDefault = false;
203
+ // Variables to track selected entity and default table type
205
204
  let selectedEntity;
205
+ let defaultTableType;
206
206
  tableLayoutQuestions.push({
207
207
  when: (prevAnswers) => !!prevAnswers.mainEntity,
208
208
  type: 'list',
@@ -218,24 +218,30 @@ function getTableLayoutQuestions(templateType, odataVersion, isCapService, metad
218
218
  const currentEntity = prevAnswers?.mainEntity;
219
219
  // Only re-evaluate if entity has changed or no previous selection exists
220
220
  if (currentEntity?.entitySetName !== selectedEntity?.entitySetName || !prevAnswers?.tableType) {
221
- const defaultTableType = (0, entity_helper_1.getDefaultTableType)(templateType, metadata, odataVersion, isCapService, currentEntity?.entitySetName);
221
+ defaultTableType = (0, entity_helper_1.getDefaultTableType)(templateType, metadata, odataVersion, isCapService, currentEntity?.entitySetName);
222
222
  // Update tracking variables
223
223
  selectedEntity = currentEntity;
224
- setAnalyticalTableDefault = defaultTableType === 'AnalyticalTable';
225
224
  return defaultTableType;
226
225
  }
227
226
  // Entity hasn't changed and user has a selection - preserve their choice
228
- // Reset the analytical table default flag since this is user's choice, not system default
229
- setAnalyticalTableDefault = false;
227
+ // Reset the default table type since this is user's choice, not system default
228
+ defaultTableType = undefined;
230
229
  return prevAnswers.tableType;
231
230
  },
232
231
  additionalMessages: () => {
233
- if (setAnalyticalTableDefault) {
232
+ if (defaultTableType === 'AnalyticalTable') {
234
233
  return {
235
234
  message: (0, i18n_1.t)('prompts.tableType.analyticalTableDefault'),
236
235
  severity: yeoman_ui_types_1.Severity.information
237
236
  };
238
237
  }
238
+ else if (defaultTableType === 'TreeTable') {
239
+ return {
240
+ message: (0, i18n_1.t)('prompts.tableType.treeTableDefault'),
241
+ severity: yeoman_ui_types_1.Severity.information
242
+ };
243
+ }
244
+ return undefined;
239
245
  }
240
246
  });
241
247
  tableLayoutQuestions.push({
@@ -84,6 +84,10 @@
84
84
  "systemPassword": {
85
85
  "message": "Password"
86
86
  },
87
+ "storeSystemCredentials": {
88
+ "message": "Do you want to store the system credentials?",
89
+ "breadcrumb": "Store Credentials"
90
+ },
87
91
  "systemService": {
88
92
  "message": "Service",
89
93
  "breadcrumb": "Service",
@@ -160,7 +164,8 @@
160
164
  "choiceAnalytical": "Analytical",
161
165
  "choiceResponsive": "Responsive",
162
166
  "choiceTree": "Tree",
163
- "analyticalTableDefault": "The 'Analytical' table type is chosen by default because the selected entity supports it."
167
+ "analyticalTableDefault": "The 'Analytical' table type is chosen by default because the selected entity supports it.",
168
+ "treeTableDefault": "The 'Tree' table type is chosen by default because the selected entity supports it."
164
169
  },
165
170
  "hierarchyQualifier": {
166
171
  "message": "Hierarchy Qualifier",
@@ -256,6 +261,7 @@
256
261
  "forUserName": "(for user [{{username}}])",
257
262
  "httpStatus": "HTTP Status {{httpStatus}}",
258
263
  "checkDestinationAuthConfig": "Please check the SAP BTP destination authentication configuration.",
259
- "choiceNameNone": "None"
264
+ "choiceNameNone": "None",
265
+ "passwordStoreWarning": "Passwords are stored in your operating system's credential manager and are protected by its security policies."
260
266
  }
261
267
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/odata-service-inquirer",
3
3
  "description": "Prompts module that can prompt users for inputs required for odata service writing",
4
- "version": "2.9.14",
4
+ "version": "2.11.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -34,7 +34,7 @@
34
34
  "@sap-ux/fiori-generator-shared": "0.13.31",
35
35
  "@sap-ux/guided-answers-helper": "0.4.0",
36
36
  "@sap-ux/telemetry": "0.6.36",
37
- "@sap-ux/inquirer-common": "0.8.10",
37
+ "@sap-ux/inquirer-common": "0.9.0",
38
38
  "@sap-ux/logger": "0.7.0",
39
39
  "@sap-ux/nodejs-utils": "0.2.7",
40
40
  "@sap-ux/project-access": "1.32.7",