@sap-ux/odata-service-inquirer 0.8.8 → 1.1.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/README.md CHANGED
@@ -1,9 +1,6 @@
1
1
  # @sap-ux/odata-service-inquirer
2
2
 
3
- Provides Inquirer based end-user prompting to allow selection of a service from multiple data source types. This involves acquiring a connection to backend systems and retrieving edmx metadata for services provided by the catalog, from a local file or CAP project.
4
-
5
- **Note:**
6
- Current implementation is limited to metadata file and Local Cap projects as datasources only.
3
+ Provides Inquirer based end-user prompting to allow selection of a service from multiple data source types. This involves acquiring a connection to backend systems and retrieving edmx metadata for services provided by the catalog, from a local file or CAP project. This module also provides prompts that may be used to gather user selections to define the main and navigation entities and related prompts relating to application layout and annotation generation when creating a UI5 application using the `@sap-ux/fiori-freestyle-writer` and `@sap-ux/fiori-elements-writer` modules.
7
4
 
8
5
  ## Installation
9
6
  Npm
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- import { type InquirerAdapter } from '@sap-ux/inquirer-common';
2
- import type { Question } from 'inquirer';
1
+ import { type InquirerAdapter, ERROR_TYPE, ErrorHandler } from '@sap-ux/inquirer-common';
3
2
  import { type Logger } from '@sap-ux/logger';
4
3
  import { OdataVersion } from '@sap-ux/odata-service-writer';
5
4
  import { type ToolsSuiteTelemetryClient } from '@sap-ux/telemetry';
6
- import { ERROR_TYPE, ErrorHandler } from '@sap-ux/inquirer-common';
7
- import { type SystemSelectionAnswers, SystemSelectionAnswerType } from './prompts/datasources/sap-system/system-selection';
5
+ import type { Question } from 'inquirer';
8
6
  import type { ServiceAnswer } from './prompts/datasources/sap-system/service-selection';
9
- import type { NewSystemChoice, CfAbapEnvServiceChoice } from './prompts/datasources/sap-system/system-selection/prompt-helpers';
10
- import { DatasourceType, promptNames, type CapRuntime, type CapService, type OdataServiceAnswers, type OdataServicePromptOptions, type OdataServiceQuestion, type SapSystemType } from './types';
7
+ import { type SystemSelectionAnswers, SystemSelectionAnswerType } from './prompts/datasources/sap-system/system-selection';
8
+ import type { CfAbapEnvServiceChoice, NewSystemChoice } from './prompts/datasources/sap-system/system-selection/prompt-helpers';
9
+ import type { Annotations } from '@sap-ux/axios-extension';
10
+ import type { TemplateType } from '@sap-ux/fiori-elements-writer';
11
+ import { type CapRuntime, type CapService, type OdataServiceAnswers, type OdataServicePromptOptions, type OdataServiceQuestion, type SapSystemType, type EntityPromptOptions, DatasourceType, EntityRelatedAnswers, promptNames } from './types';
11
12
  /**
12
13
  * Get the inquirer prompts for odata service.
13
14
  *
@@ -32,6 +33,20 @@ declare function getSystemSelectionQuestions(promptOptions?: OdataServicePromptO
32
33
  prompts: Question<SystemSelectionAnswers & ServiceAnswer>[];
33
34
  answers: Partial<OdataServiceAnswers>;
34
35
  }>;
36
+ /**
37
+ * Get the questions that may be used to prompt for entity selection, table configuration, annotation generation, and ALP specific table configuration.
38
+ * Since these are releated to service metadata processing and entity selection, they are grouped together.
39
+ *
40
+ * @param metadata the metadata (edmx) string from which to extract entity choices
41
+ * @param templateType the template type which will define the type of prompts and their choices
42
+ * @param isCapService if true, the service is a CAP service, some prompts will be adjusted accordingly
43
+ * @param promptOptions options that can control some of the prompt behavior. See {@link EntityPromptOptions} for details
44
+ * @param annotations annotations to be used for entity selection, only used for analytical list page presentation variant qualifier choices when the edmx odata version is `2`
45
+ * @param logger a logger compatible with the {@link Logger} interface
46
+ * @param isYUI if true, the prompt is being called from the Yeoman UI extension host
47
+ * @returns the prompts which may be used to prompt for entity selection, table configuration, annotation generation, and ALP specific table configuration
48
+ */
49
+ declare function getEntityRelatedPrompts(metadata: string, templateType: TemplateType, isCapService?: boolean, promptOptions?: EntityPromptOptions, annotations?: Annotations, logger?: Logger, isYUI?: boolean): Question<EntityRelatedAnswers>[];
35
50
  /**
36
51
  * Prompt for odata service writer inputs.
37
52
  *
@@ -44,5 +59,5 @@ declare function getSystemSelectionQuestions(promptOptions?: OdataServicePromptO
44
59
  * @returns the prompt answers
45
60
  */
46
61
  declare function prompt(adapter: InquirerAdapter, promptOptions?: OdataServicePromptOptions, logger?: Logger, enableGuidedAnswers?: boolean, telemetryClient?: ToolsSuiteTelemetryClient, isYUI?: boolean): Promise<OdataServiceAnswers>;
47
- export { DatasourceType, ERROR_TYPE, ErrorHandler, getPrompts, OdataVersion, prompt, promptNames, SystemSelectionAnswerType, type CapRuntime, type CapService, type InquirerAdapter, type OdataServiceAnswers, type OdataServicePromptOptions, type SapSystemType, NewSystemChoice, CfAbapEnvServiceChoice, getSystemSelectionQuestions };
62
+ export { CfAbapEnvServiceChoice, DatasourceType, EntityRelatedAnswers, ERROR_TYPE, ErrorHandler, getEntityRelatedPrompts, getPrompts, getSystemSelectionQuestions, NewSystemChoice, OdataVersion, prompt, promptNames, SystemSelectionAnswerType, type CapRuntime, type CapService, type InquirerAdapter, type OdataServiceAnswers, type OdataServicePromptOptions, type SapSystemType };
48
63
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -4,18 +4,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.promptNames = exports.OdataVersion = exports.ErrorHandler = exports.ERROR_TYPE = exports.DatasourceType = void 0;
7
+ exports.getEntityRelatedPrompts = getEntityRelatedPrompts;
7
8
  exports.getPrompts = getPrompts;
8
- exports.prompt = prompt;
9
9
  exports.getSystemSelectionQuestions = getSystemSelectionQuestions;
10
- const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
11
- Object.defineProperty(exports, "OdataVersion", { enumerable: true, get: function () { return odata_service_writer_1.OdataVersion; } });
12
- const inquirer_autocomplete_prompt_1 = __importDefault(require("inquirer-autocomplete-prompt"));
10
+ exports.prompt = prompt;
13
11
  const inquirer_common_1 = require("@sap-ux/inquirer-common");
14
12
  Object.defineProperty(exports, "ERROR_TYPE", { enumerable: true, get: function () { return inquirer_common_1.ERROR_TYPE; } });
15
13
  Object.defineProperty(exports, "ErrorHandler", { enumerable: true, get: function () { return inquirer_common_1.ErrorHandler; } });
14
+ const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
15
+ Object.defineProperty(exports, "OdataVersion", { enumerable: true, get: function () { return odata_service_writer_1.OdataVersion; } });
16
+ const inquirer_autocomplete_prompt_1 = __importDefault(require("inquirer-autocomplete-prompt"));
16
17
  const i18n_1 = require("./i18n");
17
18
  const prompts_1 = require("./prompts");
18
19
  const system_selection_1 = require("./prompts/datasources/sap-system/system-selection");
20
+ const questions_1 = require("./prompts/edmx/questions");
19
21
  const logger_helper_1 = __importDefault(require("./prompts/logger-helper"));
20
22
  const types_1 = require("./types");
21
23
  Object.defineProperty(exports, "DatasourceType", { enumerable: true, get: function () { return types_1.DatasourceType; } });
@@ -62,6 +64,26 @@ async function getSystemSelectionQuestions(promptOptions) {
62
64
  answers: utils_1.PromptState.odataService
63
65
  };
64
66
  }
67
+ /**
68
+ * Get the questions that may be used to prompt for entity selection, table configuration, annotation generation, and ALP specific table configuration.
69
+ * Since these are releated to service metadata processing and entity selection, they are grouped together.
70
+ *
71
+ * @param metadata the metadata (edmx) string from which to extract entity choices
72
+ * @param templateType the template type which will define the type of prompts and their choices
73
+ * @param isCapService if true, the service is a CAP service, some prompts will be adjusted accordingly
74
+ * @param promptOptions options that can control some of the prompt behavior. See {@link EntityPromptOptions} for details
75
+ * @param annotations annotations to be used for entity selection, only used for analytical list page presentation variant qualifier choices when the edmx odata version is `2`
76
+ * @param logger a logger compatible with the {@link Logger} interface
77
+ * @param isYUI if true, the prompt is being called from the Yeoman UI extension host
78
+ * @returns the prompts which may be used to prompt for entity selection, table configuration, annotation generation, and ALP specific table configuration
79
+ */
80
+ function getEntityRelatedPrompts(metadata, templateType, isCapService = false, promptOptions, annotations, logger, isYUI = false) {
81
+ if (logger) {
82
+ logger_helper_1.default.logger = logger;
83
+ }
84
+ utils_1.PromptState.isYUI = isYUI;
85
+ return (0, questions_1.getEntitySelectionQuestions)(metadata, templateType, isCapService, promptOptions, annotations);
86
+ }
65
87
  /**
66
88
  * Prompt for odata service writer inputs.
67
89
  *
@@ -0,0 +1,14 @@
1
+ import type { Annotations } from '@sap-ux/axios-extension';
2
+ import { OdataVersion } from '@sap-ux/odata-service-writer';
3
+ import type { Question } from 'inquirer';
4
+ import type { AlpTableConfigAnswers } from '../../types';
5
+ /**
6
+ * Get questions that related to generation of Analytical List Page type applications.
7
+ *
8
+ * @param odataVersion odata version '2' or '4' will the table layout prompts to be shown
9
+ * @param annotations used to determine if the select presentation qualifier prompt should be shown
10
+ * @param hideTableLayoutPrompts hide the table layout prompts, certain consumers do not need these prompts
11
+ * @returns alp specific questions
12
+ */
13
+ export declare function getAnalyticListPageQuestions(odataVersion: OdataVersion, annotations?: Annotations, hideTableLayoutPrompts?: boolean): Question<AlpTableConfigAnswers>[];
14
+ //# sourceMappingURL=alp-questions.d.ts.map
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAnalyticListPageQuestions = getAnalyticListPageQuestions;
4
+ const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
5
+ const i18n_1 = require("../../i18n");
6
+ const types_1 = require("../../types");
7
+ const utils_1 = require("../../utils");
8
+ /**
9
+ * Return the annotation `UI.selectionPresentationVariant.qualifier` properties as prompt choices for the specified annotations and entityType.
10
+ *
11
+ * @param annotations the annotations in which to search for the annotation: `UI.selectionPresentationVariant.qualifier`
12
+ * @param entityType the entityType of the annotations target in which to search for the annotation: `UI.selectionPresentationVariant.qualifier`
13
+ * @returns the matching `UI.selectionPresentationVariant` qualifers as prompt choices
14
+ */
15
+ function getQualifierChoices(annotations, entityType) {
16
+ const qualifierChoices = [{ name: (0, i18n_1.t)('texts.choiceNameNone'), value: undefined }];
17
+ const parsedDefinitions = (0, utils_1.xmlToJson)(annotations?.Definitions) || {};
18
+ const parsedAnnotations = parsedDefinitions.Edmx.DataServices.Schema?.Annotations;
19
+ let filteredAnnotations = [];
20
+ if (Array.isArray(parsedAnnotations)) {
21
+ filteredAnnotations = parsedAnnotations;
22
+ }
23
+ else if (typeof parsedAnnotations === 'object') {
24
+ filteredAnnotations.push(parsedAnnotations);
25
+ }
26
+ filteredAnnotations = filteredAnnotations.filter((a) => {
27
+ return a.Target === entityType;
28
+ });
29
+ if (filteredAnnotations.length > 0) {
30
+ const selectionPresentationTerm = 'UI.SelectionPresentationVariant';
31
+ let filterQualifiers = filteredAnnotations[0]?.Annotation;
32
+ if (Array.isArray(filterQualifiers)) {
33
+ filterQualifiers
34
+ .filter((a) => a.Term === selectionPresentationTerm)
35
+ .forEach((a) => {
36
+ if (a.Qualifier) {
37
+ qualifierChoices.push({ name: a.Qualifier, value: a.Qualifier });
38
+ }
39
+ });
40
+ }
41
+ else if (filterQualifiers.Term === selectionPresentationTerm) {
42
+ filterQualifiers = [];
43
+ qualifierChoices.push({ name: filterQualifiers.Qualifier, value: filterQualifiers.Qualifier });
44
+ }
45
+ }
46
+ return qualifierChoices;
47
+ }
48
+ /**
49
+ * Get questions that related to generation of Analytical List Page type applications.
50
+ *
51
+ * @param odataVersion odata version '2' or '4' will the table layout prompts to be shown
52
+ * @param annotations used to determine if the select presentation qualifier prompt should be shown
53
+ * @param hideTableLayoutPrompts hide the table layout prompts, certain consumers do not need these prompts
54
+ * @returns alp specific questions
55
+ */
56
+ function getAnalyticListPageQuestions(odataVersion, annotations, hideTableLayoutPrompts = false) {
57
+ const alpQuestions = [];
58
+ if (annotations && odataVersion === odata_service_writer_1.OdataVersion.v2) {
59
+ const qualifierChoices = [];
60
+ alpQuestions.push({
61
+ when: (answers) => {
62
+ if (answers.mainEntity) {
63
+ qualifierChoices.push(...getQualifierChoices(annotations, answers.mainEntity?.entitySetType));
64
+ }
65
+ return qualifierChoices.length > 1;
66
+ },
67
+ type: 'list',
68
+ name: types_1.EntityPromptNames.presentationQualifier,
69
+ message: (0, i18n_1.t)('prompts.presentationQualifier.message'),
70
+ guiOptions: {
71
+ hint: (0, i18n_1.t)('prompts.presentationQualifier.hint'),
72
+ breadcrumb: true
73
+ },
74
+ choices: () => qualifierChoices,
75
+ default: 0
76
+ });
77
+ }
78
+ // Layout prompts
79
+ if (!hideTableLayoutPrompts) {
80
+ // v4 specific options
81
+ if (odataVersion === odata_service_writer_1.OdataVersion.v4) {
82
+ alpQuestions.push({
83
+ when: (prevAnswers) => {
84
+ return !!prevAnswers.mainEntity;
85
+ },
86
+ type: 'list',
87
+ name: types_1.EntityPromptNames.tableSelectionMode,
88
+ message: (0, i18n_1.t)('prompts.tableSelectionMode.message'),
89
+ guiOptions: {
90
+ hint: (0, i18n_1.t)('prompts.tableSelectionMode.hint'),
91
+ breadcrumb: true
92
+ },
93
+ choices: () => [
94
+ { name: (0, i18n_1.t)('prompts.tableSelectionMode.choiceNone'), value: 'None' },
95
+ { name: (0, i18n_1.t)('prompts.tableSelectionMode.choiceAuto'), value: 'Auto' },
96
+ { name: (0, i18n_1.t)('prompts.tableSelectionMode.choiceMulti'), value: 'Multi' },
97
+ { name: (0, i18n_1.t)('prompts.tableSelectionMode.choiceSingle'), value: 'Single' }
98
+ ]
99
+ });
100
+ }
101
+ else {
102
+ // v2 specific options
103
+ alpQuestions.push({
104
+ type: 'confirm',
105
+ name: types_1.EntityPromptNames.tableMultiSelect,
106
+ message: (0, i18n_1.t)('prompts.tableMultiSelect.message'),
107
+ guiOptions: {
108
+ hint: (0, i18n_1.t)('prompts.tableMultiSelect.hint'),
109
+ breadcrumb: true
110
+ },
111
+ default: false
112
+ }, {
113
+ type: 'confirm',
114
+ name: types_1.EntityPromptNames.tableAutoHide,
115
+ message: (0, i18n_1.t)('prompts.tableAutoHide.message'),
116
+ guiOptions: {
117
+ hint: (0, i18n_1.t)('prompts.tableAutoHide.hint'),
118
+ breadcrumb: true
119
+ },
120
+ default: true
121
+ }, {
122
+ type: 'confirm',
123
+ name: types_1.EntityPromptNames.smartVariantManagement,
124
+ message: (0, i18n_1.t)('prompts.smartVariantManagement.message'),
125
+ guiOptions: {
126
+ hint: (0, i18n_1.t)('prompts.smartVariantManagement.hint'),
127
+ breadcrumb: true
128
+ },
129
+ default: false
130
+ });
131
+ }
132
+ }
133
+ return alpQuestions;
134
+ }
135
+ //# sourceMappingURL=alp-questions.js.map
@@ -0,0 +1,47 @@
1
+ import { OdataVersion } from '@sap-ux/odata-service-writer';
2
+ import type { ConvertedMetadata } from '@sap-ux/vocabularies-types';
3
+ import type { ListChoiceOptions } from 'inquirer';
4
+ export type EntityAnswer = {
5
+ entitySetName: string;
6
+ entitySetType: string;
7
+ };
8
+ export type NavigationEntityAnswer = {
9
+ navigationPropertyName: string;
10
+ entitySetName: string;
11
+ };
12
+ export interface EntityChoiceOptions {
13
+ choices: ListChoiceOptions<EntityAnswer>[];
14
+ draftRootIndex?: number;
15
+ defaultMainEntityIndex?: number;
16
+ convertedMetadata?: ConvertedMetadata;
17
+ odataVersion?: OdataVersion;
18
+ }
19
+ export type EntitySetFilter = 'filterDraftEnabled' | 'filterAggregateTransformationsOnly';
20
+ /**
21
+ * Returns the entity choice options for use in a list inquirer prompt.
22
+ *
23
+ * @param edmx metadata string
24
+ * @param options
25
+ * @param options.useEntityTypeAsName Choice options will use the non-namepspaced entity set type as the choice name (label) and value property `entitySetName` when true, otherwise the entity set name will be used.
26
+ * @param options.entitySetFilter
27
+ * `filterDraftEnabled` : Only draft enabled entities wil be returned when true, useful for Form Object Page app generation.
28
+ * `filterAggregateTransformationsOnly` : Only return entity choices that have an aggregate annotation (Aggregation.ApplySupported) with the `Transformations` property set,
29
+ * specifically used for ALP V4 app generation. If this option is set and the specified metadata is not V4, the option will be ignored.
30
+ * @param options.defaultMainEntityName The default selected entity set name
31
+ * @returns entity options
32
+ */
33
+ export declare function getEntityChoices(edmx: string, { useEntityTypeAsName, entitySetFilter, defaultMainEntityName }?: {
34
+ useEntityTypeAsName?: boolean;
35
+ entitySetFilter?: EntitySetFilter;
36
+ defaultMainEntityName?: string;
37
+ }): EntityChoiceOptions;
38
+ /**
39
+ * Get the navigation entity choices for a main entity.
40
+ *
41
+ * @param metadata the converted metadata (edmx)
42
+ * @param odataVersion the odata version, which will determine the navigation properties to return
43
+ * @param mainEntityName the main entity name to get the navigation properties for
44
+ * @returns the navigation entity choices
45
+ */
46
+ export declare function getNavigationEntityChoices(metadata: ConvertedMetadata, odataVersion: OdataVersion, mainEntityName: string): ListChoiceOptions<NavigationEntityAnswer>[];
47
+ //# sourceMappingURL=entity-helper.d.ts.map
@@ -0,0 +1,154 @@
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.getEntityChoices = getEntityChoices;
7
+ exports.getNavigationEntityChoices = getNavigationEntityChoices;
8
+ const annotation_converter_1 = require("@sap-ux/annotation-converter");
9
+ const edmx_parser_1 = require("@sap-ux/edmx-parser");
10
+ const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
11
+ const i18n_1 = require("../../i18n");
12
+ const logger_helper_1 = __importDefault(require("../logger-helper"));
13
+ /**
14
+ * Returns the entity choice options for use in a list inquirer prompt.
15
+ *
16
+ * @param edmx metadata string
17
+ * @param options
18
+ * @param options.useEntityTypeAsName Choice options will use the non-namepspaced entity set type as the choice name (label) and value property `entitySetName` when true, otherwise the entity set name will be used.
19
+ * @param options.entitySetFilter
20
+ * `filterDraftEnabled` : Only draft enabled entities wil be returned when true, useful for Form Object Page app generation.
21
+ * `filterAggregateTransformationsOnly` : Only return entity choices that have an aggregate annotation (Aggregation.ApplySupported) with the `Transformations` property set,
22
+ * specifically used for ALP V4 app generation. If this option is set and the specified metadata is not V4, the option will be ignored.
23
+ * @param options.defaultMainEntityName The default selected entity set name
24
+ * @returns entity options
25
+ */
26
+ function getEntityChoices(edmx, { useEntityTypeAsName = false, entitySetFilter, defaultMainEntityName } = {}) {
27
+ const choices = [];
28
+ let draftRootIndex;
29
+ let defaultMainEntityIndex;
30
+ let convertedMetadata;
31
+ let odataVersion;
32
+ try {
33
+ convertedMetadata = (0, annotation_converter_1.convert)((0, edmx_parser_1.parse)(edmx));
34
+ const parsedOdataVersion = parseInt(convertedMetadata?.version, 10);
35
+ if (Number.isNaN(parsedOdataVersion)) {
36
+ logger_helper_1.default.logger.error((0, i18n_1.t)('errors.unparseableOdataVersion'));
37
+ throw new Error((0, i18n_1.t)('errors.unparseableOdataVersion'));
38
+ }
39
+ // Note that odata version > `4` e.g. `4.1`, is not currently supported by `@sap-ux/edmx-converter`
40
+ odataVersion = parsedOdataVersion === 4 ? odata_service_writer_1.OdataVersion.v4 : odata_service_writer_1.OdataVersion.v2;
41
+ let entitySets = [];
42
+ if (entitySetFilter === 'filterDraftEnabled') {
43
+ entitySets = filterDraftEnabledEntities(convertedMetadata.entitySets) ?? [];
44
+ }
45
+ else if (entitySetFilter === 'filterAggregateTransformationsOnly' && odataVersion === odata_service_writer_1.OdataVersion.v4) {
46
+ // Only for v4 odata version, if a v2 metadata is passed, this will be ignored
47
+ entitySets = filterAggregateTransformations(convertedMetadata.entitySets);
48
+ }
49
+ else {
50
+ entitySets = convertedMetadata.entitySets;
51
+ }
52
+ entitySets.forEach((entitySet, index) => {
53
+ // Determine whether to use the entity set type name or the entity set name as the choice name.
54
+ // Note that in the case of the entity type name, the namespace will be removed.
55
+ const entitySetChoiceName = useEntityTypeAsName
56
+ ? entitySet.entityTypeName.substring(entitySet.entityTypeName.lastIndexOf('.') + 1)
57
+ : entitySet.name;
58
+ const choice = {
59
+ name: entitySetChoiceName,
60
+ value: {
61
+ entitySetName: entitySetChoiceName,
62
+ entitySetType: entitySet.entityTypeName // Fully qualified entity type name
63
+ }
64
+ };
65
+ choices.push(choice);
66
+ // Select the first found draft root index
67
+ if (!draftRootIndex && entitySet.annotations?.Common?.DraftRoot) {
68
+ draftRootIndex = index;
69
+ }
70
+ if (defaultMainEntityName && entitySet.name === defaultMainEntityName) {
71
+ defaultMainEntityIndex = index;
72
+ }
73
+ });
74
+ }
75
+ catch (err) {
76
+ logger_helper_1.default.logger.log((0, i18n_1.t)('errors.unparseableMetadata', { error: err.message }));
77
+ }
78
+ return {
79
+ choices,
80
+ draftRootIndex,
81
+ defaultMainEntityIndex,
82
+ convertedMetadata,
83
+ odataVersion
84
+ };
85
+ }
86
+ /**
87
+ * Get the entity set name from its type name.
88
+ *
89
+ * @param entitySets the entity sets to search
90
+ * @param entityType the entity type name to search for
91
+ * @returns the entity set name if found, otherwise undefined
92
+ */
93
+ function findEntitySetName(entitySets, entityType) {
94
+ const foundEntitySet = entitySets.find((entitySet) => {
95
+ return entitySet.entityTypeName === entityType;
96
+ });
97
+ return foundEntitySet ? foundEntitySet.name : undefined;
98
+ }
99
+ /**
100
+ * Get the navigation entity choices for a main entity.
101
+ *
102
+ * @param metadata the converted metadata (edmx)
103
+ * @param odataVersion the odata version, which will determine the navigation properties to return
104
+ * @param mainEntityName the main entity name to get the navigation properties for
105
+ * @returns the navigation entity choices
106
+ */
107
+ function getNavigationEntityChoices(metadata, odataVersion, mainEntityName) {
108
+ const choices = [];
109
+ const mainEntitySet = metadata.entitySets.find((entitySet) => entitySet.name === mainEntityName);
110
+ let navProps = [];
111
+ if (odataVersion === odata_service_writer_1.OdataVersion.v4) {
112
+ navProps = mainEntitySet?.entityType.navigationProperties.filter((navProp) => navProp.isCollection) ?? [];
113
+ }
114
+ else {
115
+ navProps = mainEntitySet?.entityType.navigationProperties ?? [];
116
+ }
117
+ navProps.forEach((navProp) => {
118
+ choices.push({
119
+ name: navProp.name,
120
+ value: {
121
+ navigationPropertyName: navProp.name,
122
+ entitySetName: findEntitySetName(metadata.entitySets, navProp.targetTypeName)
123
+ }
124
+ });
125
+ });
126
+ if (choices.length > 0) {
127
+ choices.unshift({ name: (0, i18n_1.t)('prompts.navigationEntitySelection.choiceNone'), value: {} });
128
+ }
129
+ return choices;
130
+ }
131
+ /**
132
+ * Returns only entity sets that have the `Aggregation.ApplySupported` annotation term with the `Transformations` property.
133
+ *
134
+ * @param entitySets the entity sets to filter
135
+ * @returns the filtered entity sets
136
+ */
137
+ function filterAggregateTransformations(entitySets) {
138
+ return entitySets.filter((entitySet) => {
139
+ return !!entitySet.annotations?.Aggregation?.ApplySupported?.Transformations;
140
+ });
141
+ }
142
+ /**
143
+ * Returns only entities that have a type property of 'HasDraftEnabled'.
144
+ *
145
+ * @param entitySets the entity sets to filter by draft enabled entities
146
+ * @returns the filtered entity sets
147
+ */
148
+ function filterDraftEnabledEntities(entitySets) {
149
+ return entitySets.filter((entitySet) => {
150
+ const entitySetTypeProperties = entitySet.entityType.entityProperties;
151
+ return !!entitySetTypeProperties.find((property) => property.name === 'HasDraftEntity');
152
+ });
153
+ }
154
+ //# sourceMappingURL=entity-helper.js.map
@@ -0,0 +1,17 @@
1
+ import type { Annotations } from '@sap-ux/axios-extension';
2
+ import type { TemplateType } from '@sap-ux/fiori-elements-writer';
3
+ import type { Question } from 'inquirer';
4
+ import type { AlpTableConfigAnswers, AnnotationGenerationAnswers, EntityPromptOptions, EntitySelectionAnswers, TableConfigAnswers } from '../../types';
5
+ /**
6
+ * Get the questions that may be used to prompt for entity selection and related information, table types, layout options and annotation generation.
7
+ *
8
+ * @param metadata the metadata (edmx) string of the service
9
+ * @param templateType the template type of the application to be generated from the prompt answers
10
+ * @param isCapService whether the service is a CAP service or not
11
+ * @param promptOptions options that can control some of the prompt behavior. See {@link EntityPromptOptions} for details
12
+ * @param annotations annotations should be provided when the specified template type is analytic list page, and the metadata odata version is '2', in order to determine the presentation variant qualifiers.
13
+ * If none are provided, or the odata version is not '2', the presentation variant qualifier prompt will not be shown.
14
+ * @returns the prompts used to provide input for system selection and a reference to the answers object which will be populated with the user's responses once `inquirer.prompt` returns
15
+ */
16
+ export declare function getEntitySelectionQuestions(metadata: string, templateType: TemplateType, isCapService?: boolean, promptOptions?: EntityPromptOptions, annotations?: Annotations): Question<EntitySelectionAnswers & TableConfigAnswers & AnnotationGenerationAnswers & AlpTableConfigAnswers>[];
17
+ //# sourceMappingURL=questions.d.ts.map
@@ -0,0 +1,283 @@
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.getEntitySelectionQuestions = getEntitySelectionQuestions;
7
+ const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
8
+ const inquirer_common_1 = require("@sap-ux/inquirer-common");
9
+ const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
10
+ const i18n_1 = require("../../i18n");
11
+ const types_1 = require("../../types");
12
+ const utils_1 = require("../../utils");
13
+ const logger_helper_1 = __importDefault(require("../logger-helper"));
14
+ const alp_questions_1 = require("./alp-questions");
15
+ const entity_helper_1 = require("./entity-helper");
16
+ /**
17
+ * Validate the entity choice options. If the entity choice options are empty, a validation message will be returned.
18
+ *
19
+ * @param entityChoiceOptions the entity choice options to validate
20
+ * @param templateType the template type, the validation message may vary based on the template type
21
+ * @param odataVersion the OData version, used to generate a specific validation message for ALP V4
22
+ * @param isCapService whether the service is a CAP service or not
23
+ * @returns true is validation passes, otherwise a string with the validation message
24
+ */
25
+ function validateEntityChoices(entityChoiceOptions, templateType, odataVersion, isCapService) {
26
+ let validationMsg;
27
+ if (entityChoiceOptions.length === 0) {
28
+ if (templateType === 'feop' && isCapService) {
29
+ validationMsg = (0, i18n_1.t)('prompts.mainEntitySelection.noDraftEnabledEntitiesError');
30
+ }
31
+ else if (templateType === 'alp' && odataVersion === odata_service_writer_1.OdataVersion.v4) {
32
+ validationMsg = (0, i18n_1.t)('prompts.mainEntitySelection.noEntitiesAlpV4Error');
33
+ }
34
+ else {
35
+ validationMsg = (0, i18n_1.t)('prompts.mainEntitySelection.noEntitiesError');
36
+ }
37
+ }
38
+ if (!utils_1.PromptState.isYUI && validationMsg) {
39
+ logger_helper_1.default.logger.debug(`Exiting due to validation error: ${validationMsg}`);
40
+ throw new Error((0, i18n_1.t)('errors.exitingGeneration', { exitReason: validationMsg }));
41
+ }
42
+ return validationMsg ?? true;
43
+ }
44
+ /**
45
+ * Get the questions that may be used to prompt for entity selection and related information, table types, layout options and annotation generation.
46
+ *
47
+ * @param metadata the metadata (edmx) string of the service
48
+ * @param templateType the template type of the application to be generated from the prompt answers
49
+ * @param isCapService whether the service is a CAP service or not
50
+ * @param promptOptions options that can control some of the prompt behavior. See {@link EntityPromptOptions} for details
51
+ * @param annotations annotations should be provided when the specified template type is analytic list page, and the metadata odata version is '2', in order to determine the presentation variant qualifiers.
52
+ * If none are provided, or the odata version is not '2', the presentation variant qualifier prompt will not be shown.
53
+ * @returns the prompts used to provide input for system selection and a reference to the answers object which will be populated with the user's responses once `inquirer.prompt` returns
54
+ */
55
+ function getEntitySelectionQuestions(metadata, templateType, isCapService = false, promptOptions, annotations) {
56
+ const useAutoComplete = promptOptions?.useAutoComplete;
57
+ let entitySetFilter;
58
+ if (templateType === 'feop' && !!isCapService) {
59
+ entitySetFilter = 'filterDraftEnabled';
60
+ }
61
+ else if (templateType === 'alp') {
62
+ entitySetFilter = 'filterAggregateTransformationsOnly';
63
+ }
64
+ const entityChoices = (0, entity_helper_1.getEntityChoices)(metadata, {
65
+ useEntityTypeAsName: templateType === 'ovp',
66
+ defaultMainEntityName: promptOptions?.defaultMainEntityName,
67
+ entitySetFilter
68
+ });
69
+ if (!entityChoices.convertedMetadata || !entityChoices.odataVersion) {
70
+ // getEntityChoiceOptions will log an error if the metadata or its odata version are unparseable
71
+ return [];
72
+ }
73
+ const odataVersion = entityChoices.odataVersion;
74
+ const entityQuestions = [];
75
+ // OVP only has filter entity, does not use tables and we do not add annotations
76
+ if (templateType === 'ovp') {
77
+ entityQuestions.push(getFilterEntityTypeQuestions(entityChoices, useAutoComplete));
78
+ // Return early since OVP does not have table layout prompts
79
+ return entityQuestions;
80
+ }
81
+ entityQuestions.push({
82
+ type: useAutoComplete ? 'autocomplete' : 'list',
83
+ name: types_1.EntityPromptNames.mainEntity,
84
+ message: (0, i18n_1.t)('prompts.mainEntitySelection.message'),
85
+ guiOptions: {
86
+ breadcrumb: true
87
+ },
88
+ choices: entityChoices.choices,
89
+ source: (prevAnswers, input) => (0, inquirer_common_1.searchChoices)(input, entityChoices.choices),
90
+ default: entityChoices.defaultMainEntityIndex ?? entityChoices.draftRootIndex ?? 0,
91
+ validate: () => validateEntityChoices(entityChoices.choices, templateType, odataVersion, isCapService),
92
+ additionalMessages: () => {
93
+ if (promptOptions?.defaultMainEntityName && entityChoices.defaultMainEntityIndex === undefined) {
94
+ return {
95
+ message: (0, i18n_1.t)('prompts.mainEntitySelection.defaultEntityNameNotFoundWarning'),
96
+ severity: yeoman_ui_types_1.Severity.warning
97
+ };
98
+ }
99
+ }
100
+ });
101
+ const convertedMetadata = entityChoices.convertedMetadata;
102
+ // No nav entity for FPM
103
+ if (templateType !== 'fpm') {
104
+ let navigationEntityChoices;
105
+ entityQuestions.push({
106
+ when: (answers) => {
107
+ if (answers.mainEntity) {
108
+ navigationEntityChoices = (0, entity_helper_1.getNavigationEntityChoices)(convertedMetadata, odataVersion, answers.mainEntity.entitySetName);
109
+ return navigationEntityChoices.length > 0;
110
+ }
111
+ return false;
112
+ },
113
+ type: useAutoComplete ? 'autocomplete' : 'list',
114
+ name: types_1.EntityPromptNames.navigationEntity,
115
+ message: (0, i18n_1.t)('prompts.navigationEntitySelection.message'),
116
+ guiOptions: {
117
+ applyDefaultWhenDirty: true, // Selected nav entity may no longer be present if main entity changes
118
+ breadcrumb: true
119
+ },
120
+ choices: () => navigationEntityChoices,
121
+ source: (preAnswers, input) => (0, inquirer_common_1.searchChoices)(input, navigationEntityChoices),
122
+ default: 0
123
+ });
124
+ }
125
+ entityQuestions.push(...getAddAnnotationQuestions(metadata, templateType, odataVersion, isCapService));
126
+ if (!promptOptions?.hideTableLayoutPrompts) {
127
+ entityQuestions.push(...getTableLayoutQuestions(templateType, odataVersion, isCapService));
128
+ }
129
+ if (templateType === 'alp') {
130
+ entityQuestions.push(...(0, alp_questions_1.getAnalyticListPageQuestions)(odataVersion, annotations, promptOptions?.hideTableLayoutPrompts));
131
+ }
132
+ return entityQuestions;
133
+ }
134
+ /**
135
+ * Get the questions that may be used to prompt for table layout options.
136
+ *
137
+ * @param templateType used to determine if the tree table option should be included
138
+ * @param odataVersion used to determine if the hierarchy qualifier is required when the selected table type is TreeTable
139
+ * @param isCapService used to determine if the tree table option should be included
140
+ * @returns the table layout questions
141
+ */
142
+ function getTableLayoutQuestions(templateType, odataVersion, isCapService) {
143
+ const tableTypeChoices = [
144
+ { name: (0, i18n_1.t)('prompts.tableType.choiceAnalytical'), value: 'AnalyticalTable' },
145
+ { name: (0, i18n_1.t)('prompts.tableType.choiceGrid'), value: 'GridTable' },
146
+ { name: (0, i18n_1.t)('prompts.tableType.choiceResponsive'), value: 'ResponsiveTable' }
147
+ ];
148
+ if (templateType !== 'alp' && !isCapService) {
149
+ tableTypeChoices.push({ name: (0, i18n_1.t)('prompts.tableType.choiceTree'), value: 'TreeTable' });
150
+ }
151
+ const tableLayoutQuestions = [];
152
+ if (templateType === 'lrop' || templateType === 'worklist' || templateType === 'alp') {
153
+ const tableTypeDefault = templateType === 'alp' ? 'AnalyticalTable' : 'ResponsiveTable';
154
+ tableLayoutQuestions.push({
155
+ when: (prevAnswers) => !!prevAnswers.mainEntity,
156
+ type: 'list',
157
+ name: types_1.EntityPromptNames.tableType,
158
+ message: (0, i18n_1.t)('prompts.tableType.message'),
159
+ guiOptions: {
160
+ hint: (0, i18n_1.t)('prompts.tableType.hint'),
161
+ breadcrumb: true
162
+ },
163
+ choices: tableTypeChoices,
164
+ default: tableTypeDefault
165
+ });
166
+ tableLayoutQuestions.push({
167
+ when: (prevAnswers) => prevAnswers?.tableType === 'TreeTable' && odataVersion === odata_service_writer_1.OdataVersion.v4,
168
+ type: 'input',
169
+ name: types_1.EntityPromptNames.hierarchyQualifier,
170
+ message: (0, i18n_1.t)('prompts.hierarchyQualifier.message'),
171
+ guiOptions: {
172
+ hint: (0, i18n_1.t)('prompts.hierarchyQualifier.hint'),
173
+ breadcrumb: true,
174
+ mandatory: true
175
+ },
176
+ default: '',
177
+ validate: (input) => {
178
+ if (!input) {
179
+ return (0, i18n_1.t)('prompts.hierarchyQualifier.qualifierRequiredForV4Warning');
180
+ }
181
+ return true;
182
+ }
183
+ });
184
+ }
185
+ return tableLayoutQuestions;
186
+ }
187
+ /**
188
+ * Returns the size of an EDMX string in kilobytes.
189
+ *
190
+ * @param {string} edmx The EDMX string to measure.
191
+ * @returns {number} The size of the EDMX string in kilobytes. Returns 0 if the input is null, undefined, or an empty string.
192
+ */
193
+ function getEdmxSizeInKb(edmx) {
194
+ if (edmx) {
195
+ const sizeInBytes = Buffer.byteLength(edmx);
196
+ return sizeInBytes / 1024;
197
+ }
198
+ return 0;
199
+ }
200
+ /**
201
+ * Get the questions that may be used to prompt for adding annotations. Only a subset of the questions will be returned based on the template type and OData version.
202
+ *
203
+ * @param metadata the metadata (edmx) string of the service, used to determine if the metadata is large and the user should be warned about processing time
204
+ * @param templateType only specific template types will have line item annotations
205
+ * @param odataVersion only specific OData versions will have line item annotations
206
+ * @param isCapService whether the service is a CAP service or not
207
+ * @returns the annotation generation questions
208
+ */
209
+ function getAddAnnotationQuestions(metadata, templateType, odataVersion, isCapService) {
210
+ const largeEdmxDataset = getEdmxSizeInKb(metadata) > types_1.MetadataSizeWarningLimitKb;
211
+ const annotationQuestions = [];
212
+ if (templateType === 'feop') {
213
+ annotationQuestions.push({
214
+ type: 'confirm',
215
+ name: types_1.EntityPromptNames.addFEOPAnnotations,
216
+ guiOptions: {
217
+ breadcrumb: (0, i18n_1.t)('prompts.addFEOPAnnotations.breadcrumb')
218
+ },
219
+ message: (0, i18n_1.t)('prompts.addFEOPAnnotations.message'),
220
+ additionalMessages: (addFEOPAnnotations) => {
221
+ if (addFEOPAnnotations && largeEdmxDataset) {
222
+ return {
223
+ message: (0, i18n_1.t)('warnings.largeMetadataDocument'),
224
+ severity: yeoman_ui_types_1.Severity.warning
225
+ };
226
+ }
227
+ },
228
+ default: !largeEdmxDataset
229
+ });
230
+ // Return early since FEOP does not have line item annotations
231
+ return annotationQuestions;
232
+ }
233
+ if ((templateType === 'lrop' || templateType === 'worklist') && odataVersion === odata_service_writer_1.OdataVersion.v4) {
234
+ annotationQuestions.push({
235
+ type: 'confirm',
236
+ name: types_1.EntityPromptNames.addLineItemAnnotations,
237
+ guiOptions: {
238
+ breadcrumb: (0, i18n_1.t)('prompts.addLineItemAnnotations.breadcrumb')
239
+ },
240
+ message: (0, i18n_1.t)('prompts.addLineItemAnnotations.message'),
241
+ additionalMessages: (answer) => {
242
+ if (answer) {
243
+ if (largeEdmxDataset) {
244
+ return {
245
+ message: (0, i18n_1.t)('warnings.largeMetadataDocument'),
246
+ severity: yeoman_ui_types_1.Severity.warning
247
+ };
248
+ }
249
+ else if (isCapService) {
250
+ return {
251
+ message: (0, i18n_1.t)('prompts.addLineItemAnnotations.valueHelpsAnnotationsInfoMessage'),
252
+ severity: yeoman_ui_types_1.Severity.information
253
+ };
254
+ }
255
+ }
256
+ },
257
+ default: !largeEdmxDataset
258
+ });
259
+ }
260
+ return annotationQuestions;
261
+ }
262
+ /**
263
+ * Get the questions that may be used to prompt for filter entity selection for the OVP template type.
264
+ *
265
+ * @param entityChoices Filter entity type prompt choices
266
+ * @param useAutoComplete Determines if entity related prompts should use auto complete on user input
267
+ * @returns the ovp specific filter entity type selection question
268
+ */
269
+ function getFilterEntityTypeQuestions(entityChoices, useAutoComplete = false) {
270
+ return {
271
+ type: useAutoComplete ? 'autocomplete' : 'list',
272
+ name: types_1.EntityPromptNames.filterEntityType,
273
+ message: (0, i18n_1.t)('prompts.filterEntityType.message'),
274
+ guiOptions: {
275
+ breadcrumb: true
276
+ },
277
+ choices: entityChoices.choices,
278
+ source: (preAnswers, input) => (0, inquirer_common_1.searchChoices)(input, entityChoices.choices),
279
+ default: entityChoices.defaultMainEntityIndex ?? entityChoices.draftRootIndex ?? 0,
280
+ validate: () => (entityChoices.choices.length === 0 ? (0, i18n_1.t)('prompts.filterEntityType.noEntitiesError') : true)
281
+ };
282
+ }
283
+ //# sourceMappingURL=questions.js.map
@@ -28,7 +28,7 @@ function getDatasourceTypeChoices({ includeNone = false } = {}) {
28
28
  choices.push({ name: (0, i18n_1.t)('prompts.datasourceType.capProjectChoiceText'), value: types_1.DatasourceType.capProject });
29
29
  choices.push({ name: (0, i18n_1.t)('prompts.datasourceType.metadataFileChoiceText'), value: types_1.DatasourceType.metadataFile });
30
30
  if (includeNone) {
31
- choices.unshift({ name: (0, i18n_1.t)('prompts.datasourceType.noneName'), value: types_1.DatasourceType.none });
31
+ choices.unshift({ name: (0, i18n_1.t)('prompts.datasourceType.choiceNone'), value: types_1.DatasourceType.none });
32
32
  }
33
33
  return choices;
34
34
  }
@@ -8,7 +8,7 @@
8
8
  "odataServiceUrlName": "OData Service",
9
9
  "capProjectName": "Local CAP Project",
10
10
  "metadataFileName": "Metadata Document",
11
- "noneName": "None",
11
+ "choiceNone": "$t(texts.choiceNameNone)",
12
12
  "projectSpecificDestChoiceText": "Connect to a $t(prompts.datasourceType.projectSpecificDestName)",
13
13
  "businessHubChoiceText": "Connect to $t(prompts.datasourceType.businessHubName)",
14
14
  "sapSystemChoiceText": "Connect to a $t(prompts.datasourceType.sapSystemName)",
@@ -101,7 +101,7 @@
101
101
  },
102
102
  "systemSelection": {
103
103
  "newSystemChoiceLabel": "New system",
104
- "hint": "Select a system configuration",
104
+ "hint": "Select a system configuration.",
105
105
  "message": "System",
106
106
  "authenticationFailedUpdateCredentials": "Authentication failed. Please try updating the credentials."
107
107
  },
@@ -113,18 +113,82 @@
113
113
  },
114
114
  "serviceKey": {
115
115
  "message": "Service key file path",
116
- "hint": "Select a local file that defines the service connection for an ABAP Environment on SAP Business Technology Platform",
116
+ "hint": "Select a local file that defines the service connection for an ABAP Environment on SAP Business Technology Platform.",
117
117
  "incompleteServiceKeyInfo": "Service keys file does not contain the required information",
118
118
  "unparseableServiceKey": "Service keys file contents are not a valid JSON format"
119
119
  },
120
120
  "cloudFoundryAbapSystem": {
121
121
  "message": "ABAP environment",
122
- "hint": "Enter the name of the Cloud Foundry service that contains the ABAP Environment instance"
122
+ "hint": "Enter the name of the Cloud Foundry service that contains the ABAP Environment instance."
123
123
  },
124
124
  "destinationServicePath": {
125
125
  "message": "Service path",
126
- "hint": "Enter the path to the OData service, relative to the selected destination URL",
126
+ "hint": "Enter the path to the OData service, relative to the selected destination URL.",
127
127
  "invalidServicePathWarning": "Please enter a valid service path"
128
+ },
129
+ "mainEntitySelection": {
130
+ "message": "Main entity",
131
+ "defaultEntityNameNotFoundWarning": "The supplied entity cannot be found in the service. Please choose from the list above.",
132
+ "noDraftEnabledEntitiesError": "The CAP service you have chosen does not have any entities that are draft enabled. In order to generate a V4 Fiori application using this floor plan for a CAP project, the entity selected must be draft enabled.",
133
+ "noEntitiesError": "$t(errors.noRelevantEntities)",
134
+ "noEntitiesAlpV4Error": "The OData V4 service you have provided is not suitable for use in an Analytical List Page application. The service must contain aggregate based entity sets for this template."
135
+ },
136
+ "navigationEntitySelection": {
137
+ "message": "Navigation entity",
138
+ "choiceNone": "$t(texts.choiceNameNone)"
139
+ },
140
+ "filterEntityType": {
141
+ "message": "Filter entity",
142
+ "noEntitiesError": "$t(errors.noRelevantEntities)"
143
+ },
144
+ "tableType": {
145
+ "message": "Table type",
146
+ "hint": "Defines the table type for the List Report Page.",
147
+ "choiceNone": "$t(texts.choiceNameNone)",
148
+ "choiceGrid": "Grid",
149
+ "choiceAnalytical": "Analytical",
150
+ "choiceResponsive": "Responsive",
151
+ "choiceTree": "Tree"
152
+ },
153
+ "hierarchyQualifier": {
154
+ "message": "Hierarchy qualifier",
155
+ "hint": "Leading property that decides between either a recursive hierarchy or data aggregation.",
156
+ "qualifierRequiredForV4Warning": "Hierarchy qualifier is required for V4 OData services"
157
+ },
158
+ "addFEOPAnnotations": {
159
+ "message": "Automatically add a form to the generated application if none already exists?",
160
+ "hint": "Choose the annotation generation method.",
161
+ "breadcrumb": "Generate Annotations"
162
+ },
163
+ "addLineItemAnnotations": {
164
+ "message": "Automatically add table columns to the list page and a section to the object page if none already exists?",
165
+ "hint": "Choose the annotation generation method.",
166
+ "breadcrumb": "Generate Annotations",
167
+ "valueHelpsAnnotationsInfoMessage": "Basic value helps will also be created."
168
+ },
169
+ "presentationQualifier": {
170
+ "message": "Qualifier",
171
+ "hint": "Represents the qualifier of the SelectionPresentationVariant. Analytical List Page looks for SelectionPresentationVariant with this qualifier and if not found, it looks for PresentationVariant with this qualifier."
172
+ },
173
+ "tableSelectionMode": {
174
+ "message": "Selection mode",
175
+ "hint": "Defines different selection modes for the SmartTable in Analytical List Page.",
176
+ "choiceNone": "$t(texts.choiceNameNone)",
177
+ "choiceSingle": "Single",
178
+ "choiceAuto": "Auto",
179
+ "choiceMulti": "Multi"
180
+ },
181
+ "tableMultiSelect": {
182
+ "message": "Allow multi select",
183
+ "hint": "Allows you to show a checkbox for selecting multiple items in a table. This setting comes into effect only if there are actions defined either through annotation or manifest."
184
+ },
185
+ "tableAutoHide": {
186
+ "message": "Auto hide",
187
+ "hint": "Determines chart/table interaction. If set to true, the chart acts as a filter for the table. If set to false, the matching table rows are highlighted but the table is not filtered."
188
+ },
189
+ "smartVariantManagement": {
190
+ "message": "Enable smart variant management",
191
+ "hint": "Enables page level variant."
128
192
  }
129
193
  },
130
194
  "errors": {
@@ -153,7 +217,14 @@
153
217
  "serviceCatalogRequest": "An error occurred requesting services from: {{- catalogRequestUri }} and entity set: {{entitySet}}. {{error}}",
154
218
  "storedSystemConnectionError": "An error occurred while validating the stored system connection info. System name: {{-systemName}}, error: {{- error}}",
155
219
  "noCatalogOrServiceAvailable": "No active system or OData service endpoint connection available to retrieve service(s).",
156
- "allCatalogServiceRequestsFailed": "All catalog service requests failed for the selected system. OData version(s): V{{version}}."
220
+ "allCatalogServiceRequestsFailed": "All catalog service requests failed for the selected system. OData version(s): V{{version}}.",
221
+ "unparseableMetadata": "Unable to parse entities from metadata document. {{-error}}",
222
+ "unparseableOdataVersion": "Unable to parse the odata version from the metadata.",
223
+ "unparseableXML": "Unparseable XML was specified: {{-error}}",
224
+ "noRelevantEntities": "The template and service selected have no relevant entities that you can use."
225
+ },
226
+ "warnings": {
227
+ "largeMetadataDocument": "The metadata for this OData service is significantly large. It may take some time before this operation completes."
157
228
  },
158
229
  "texts": {
159
230
  "suggestedSystemNameClient": ", client {{client}}",
@@ -162,6 +233,7 @@
162
233
  "systemTypeBTP": "BTP",
163
234
  "systemTypeS4HC": "S4HC",
164
235
  "httpStatus": "http status {{httpStatus}}",
165
- "checkDestinationAuthConfig": "Please check the SAP BTP destination authentication configuration."
236
+ "checkDestinationAuthConfig": "Please check the SAP BTP destination authentication configuration.",
237
+ "choiceNameNone": "None"
166
238
  }
167
239
  }
package/dist/types.d.ts CHANGED
@@ -5,6 +5,8 @@ import type { OdataVersion } from '@sap-ux/odata-service-writer';
5
5
  import type { CdsVersionInfo } from '@sap-ux/project-access';
6
6
  import type { BackendSystem } from '@sap-ux/store';
7
7
  import type { ListChoiceOptions } from 'inquirer';
8
+ import type { EntityAnswer, NavigationEntityAnswer } from './prompts/edmx/entity-helper';
9
+ import type { TableSelectionMode, TableType } from '@sap-ux/fiori-elements-writer';
8
10
  /**
9
11
  * This file contains types that are exported by the module and are needed for consumers using the APIs `prompt` and `getPrompts`.
10
12
  */
@@ -22,6 +24,11 @@ export declare const SapSystemTypes: {
22
24
  readonly abapOnBtp: "abapOnBtp";
23
25
  };
24
26
  export type SapSystemType = keyof typeof SapSystemTypes;
27
+ export declare const SAP_CLIENT_KEY = "sap-client";
28
+ /**
29
+ * The limit for the metadata file size in KB above which a warning will be displayed to the user regarding processing time.
30
+ */
31
+ export declare const MetadataSizeWarningLimitKb = 1000;
25
32
  /**
26
33
  * Answers returned by the OdataServiceInquirer prompt API.
27
34
  * These values may be used to write an OData service and may be derived from the user's input rather than direct answers.
@@ -126,6 +133,48 @@ export declare enum promptNames {
126
133
  */
127
134
  systemSelection = "systemSelection"
128
135
  }
136
+ /**
137
+ * Prompt names for entity related prompts. These indirectly define the properties of the answers object returned by the entity related prompts.
138
+ */
139
+ export declare const EntityPromptNames: {
140
+ readonly mainEntity: "mainEntity";
141
+ readonly navigationEntity: "navigationEntity";
142
+ readonly filterEntityType: "filterEntityType";
143
+ readonly tableType: "tableType";
144
+ readonly hierarchyQualifier: "hierarchyQualifier";
145
+ readonly addFEOPAnnotations: "addFEOPAnnotations";
146
+ readonly addLineItemAnnotations: "addLineItemAnnotations";
147
+ readonly presentationQualifier: "presentationQualifier";
148
+ readonly tableSelectionMode: "tableSelectionMode";
149
+ readonly tableMultiSelect: "tableMultiSelect";
150
+ readonly tableAutoHide: "tableAutoHide";
151
+ readonly smartVariantManagement: "smartVariantManagement";
152
+ };
153
+ export type EntityPromptNames = (typeof EntityPromptNames)[keyof typeof EntityPromptNames];
154
+ export interface EntitySelectionAnswers {
155
+ [EntityPromptNames.mainEntity]?: EntityAnswer;
156
+ [EntityPromptNames.navigationEntity]?: NavigationEntityAnswer;
157
+ [EntityPromptNames.filterEntityType]?: EntityAnswer;
158
+ }
159
+ export interface TableConfigAnswers {
160
+ [EntityPromptNames.tableType]?: TableType;
161
+ [EntityPromptNames.hierarchyQualifier]?: string;
162
+ }
163
+ export interface AnnotationGenerationAnswers {
164
+ [EntityPromptNames.addFEOPAnnotations]?: boolean;
165
+ [EntityPromptNames.addLineItemAnnotations]?: boolean;
166
+ }
167
+ export interface AlpTableConfigAnswers {
168
+ [EntityPromptNames.tableAutoHide]?: boolean;
169
+ [EntityPromptNames.tableMultiSelect]?: boolean;
170
+ [EntityPromptNames.tableSelectionMode]?: TableSelectionMode;
171
+ [EntityPromptNames.presentationQualifier]?: string;
172
+ [EntityPromptNames.smartVariantManagement]?: boolean;
173
+ }
174
+ /**
175
+ * Convienience alias type for the entity related answers
176
+ */
177
+ export type EntityRelatedAnswers = EntitySelectionAnswers & TableConfigAnswers & AnnotationGenerationAnswers & AlpTableConfigAnswers;
129
178
  export type CapRuntime = 'Node.js' | 'Java';
130
179
  export interface CapService {
131
180
  /**
@@ -287,6 +336,23 @@ export type OdataServiceUrlPasswordOptions = Pick<CommonPromptOptions, 'addition
287
336
  type odataServiceInquirerPromptOptions = Record<promptNames.datasourceType, DatasourceTypePromptOptions> & Record<promptNames.metadataFilePath, MetadataPromptOptions> & Record<promptNames.capProject, CapProjectPromptOptions> & Record<promptNames.capService, CapServicePromptOptions> & Record<promptNames.serviceUrl, OdataServiceUrlPromptOptions> & Record<promptNames.serviceUrlPassword, OdataServiceUrlPasswordOptions> & Record<promptNames.serviceSelection, ServiceSelectionPromptOptions> & Record<promptNames.userSystemName, SystemNamePromptOptions> & Record<promptNames.systemSelection, SystemSelectionPromptOptions>;
288
337
  export type OdataServiceQuestion = YUIQuestion<OdataServiceAnswers>;
289
338
  export type OdataServicePromptOptions = Partial<odataServiceInquirerPromptOptions>;
290
- export declare const SAP_CLIENT_KEY = "sap-client";
339
+ /**
340
+ * The entity related prompt options. These options are used to configure the entity related prompts.
341
+ */
342
+ export type EntityPromptOptions = {
343
+ /**
344
+ * Determines if entity related prompts should use auto complete on user input.
345
+ * Note that the auto-complete module must be registered with the inquirer instance to use this feature.
346
+ */
347
+ useAutoComplete?: boolean;
348
+ /**
349
+ * Provide an entity name that will be preselected as the default option for the prompt.
350
+ */
351
+ defaultMainEntityName?: string;
352
+ /**
353
+ * Hides the table layout related prompts when true, default is false.
354
+ */
355
+ hideTableLayoutPrompts?: boolean;
356
+ };
291
357
  export {};
292
358
  //# sourceMappingURL=types.d.ts.map
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SAP_CLIENT_KEY = exports.promptNames = exports.SapSystemTypes = exports.DatasourceType = void 0;
3
+ exports.EntityPromptNames = exports.promptNames = exports.MetadataSizeWarningLimitKb = exports.SAP_CLIENT_KEY = exports.SapSystemTypes = exports.DatasourceType = void 0;
4
4
  /**
5
5
  * This file contains types that are exported by the module and are needed for consumers using the APIs `prompt` and `getPrompts`.
6
6
  */
@@ -20,6 +20,11 @@ exports.SapSystemTypes = {
20
20
  abapOnPrem: 'abapOnPrem',
21
21
  abapOnBtp: 'abapOnBtp'
22
22
  };
23
+ exports.SAP_CLIENT_KEY = 'sap-client';
24
+ /**
25
+ * The limit for the metadata file size in KB above which a warning will be displayed to the user regarding processing time.
26
+ */
27
+ exports.MetadataSizeWarningLimitKb = 1000;
23
28
  /**
24
29
  * Enumeration of prompt names used by OdataServiceInquirerPromptOptions
25
30
  */
@@ -62,5 +67,21 @@ var promptNames;
62
67
  */
63
68
  promptNames["systemSelection"] = "systemSelection";
64
69
  })(promptNames || (exports.promptNames = promptNames = {}));
65
- exports.SAP_CLIENT_KEY = 'sap-client';
70
+ /**
71
+ * Prompt names for entity related prompts. These indirectly define the properties of the answers object returned by the entity related prompts.
72
+ */
73
+ exports.EntityPromptNames = {
74
+ mainEntity: 'mainEntity',
75
+ navigationEntity: 'navigationEntity',
76
+ filterEntityType: 'filterEntityType',
77
+ tableType: 'tableType',
78
+ hierarchyQualifier: 'hierarchyQualifier',
79
+ addFEOPAnnotations: 'addFEOPAnnotations',
80
+ addLineItemAnnotations: 'addLineItemAnnotations',
81
+ presentationQualifier: 'presentationQualifier',
82
+ tableSelectionMode: 'tableSelectionMode',
83
+ tableMultiSelect: 'tableMultiSelect',
84
+ tableAutoHide: 'tableAutoHide',
85
+ smartVariantManagement: 'smartVariantManagement'
86
+ };
66
87
  //# sourceMappingURL=types.js.map
@@ -1,8 +1,8 @@
1
1
  import { ODataVersion } from '@sap-ux/axios-extension';
2
+ import { type HostEnvironmentId } from '@sap-ux/fiori-generator-shared';
2
3
  import { OdataVersion } from '@sap-ux/odata-service-writer';
3
4
  import type { ListChoiceOptions } from 'inquirer';
4
5
  import { PromptState } from './prompt-state';
5
- import { type HostEnvironmentId } from '@sap-ux/fiori-generator-shared';
6
6
  /**
7
7
  * Determine if the current prompting environment is cli or a hosted extension (app studio or vscode).
8
8
  *
@@ -19,6 +19,13 @@ export declare function getPromptHostEnvironment(): {
19
19
  * @returns the odata version of the specified metadata, throws an error if the metadata is invalid
20
20
  */
21
21
  export declare function parseOdataVersion(metadata: string): OdataVersion;
22
+ /**
23
+ * Convert specified xml string to JSON.
24
+ *
25
+ * @param xml - the schema to parse
26
+ * @returns parsed object representation of passed XML
27
+ */
28
+ export declare function xmlToJson(xml: string): any;
22
29
  /**
23
30
  * Replaces the origin in the metadata URIs with a relative path.
24
31
  * The path will be tested for '/sap/opu/odata/' and if found, the origin will be replaced with './'.
@@ -6,18 +6,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.PromptState = void 0;
7
7
  exports.getPromptHostEnvironment = getPromptHostEnvironment;
8
8
  exports.parseOdataVersion = parseOdataVersion;
9
+ exports.xmlToJson = xmlToJson;
9
10
  exports.originToRelative = originToRelative;
10
11
  exports.convertODataVersionType = convertODataVersionType;
11
12
  exports.getDefaultChoiceIndex = getDefaultChoiceIndex;
12
13
  const axios_extension_1 = require("@sap-ux/axios-extension");
13
14
  const btp_utils_1 = require("@sap-ux/btp-utils");
15
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
14
16
  const odata_service_writer_1 = require("@sap-ux/odata-service-writer");
15
17
  const fast_xml_parser_1 = require("fast-xml-parser");
16
18
  const i18n_1 = require("../i18n");
17
19
  const logger_helper_1 = __importDefault(require("../prompts/logger-helper"));
18
20
  const prompt_state_1 = require("./prompt-state");
19
21
  Object.defineProperty(exports, "PromptState", { enumerable: true, get: function () { return prompt_state_1.PromptState; } });
20
- const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
21
22
  /**
22
23
  * Determine if the current prompting environment is cli or a hosted extension (app studio or vscode).
23
24
  *
@@ -38,6 +39,23 @@ function getPromptHostEnvironment() {
38
39
  * @returns the odata version of the specified metadata, throws an error if the metadata is invalid
39
40
  */
40
41
  function parseOdataVersion(metadata) {
42
+ try {
43
+ const parsed = xmlToJson(metadata);
44
+ const odataVersion = parsed['Edmx']['Version'] === 1 ? odata_service_writer_1.OdataVersion.v2 : odata_service_writer_1.OdataVersion.v4;
45
+ return odataVersion;
46
+ }
47
+ catch (error) {
48
+ logger_helper_1.default.logger.error(error);
49
+ throw new Error((0, i18n_1.t)('prompts.validationMessages.metadataInvalid'));
50
+ }
51
+ }
52
+ /**
53
+ * Convert specified xml string to JSON.
54
+ *
55
+ * @param xml - the schema to parse
56
+ * @returns parsed object representation of passed XML
57
+ */
58
+ function xmlToJson(xml) {
41
59
  const options = {
42
60
  attributeNamePrefix: '',
43
61
  ignoreAttributes: false,
@@ -45,15 +63,12 @@ function parseOdataVersion(metadata) {
45
63
  parseAttributeValue: true,
46
64
  removeNSPrefix: true
47
65
  };
48
- const parser = new fast_xml_parser_1.XMLParser(options);
49
66
  try {
50
- const parsed = parser.parse(metadata, true);
51
- const odataVersion = parsed['Edmx']['Version'] === 1 ? odata_service_writer_1.OdataVersion.v2 : odata_service_writer_1.OdataVersion.v4;
52
- return odataVersion;
67
+ const parser = new fast_xml_parser_1.XMLParser(options);
68
+ return parser.parse(xml, true);
53
69
  }
54
70
  catch (error) {
55
- logger_helper_1.default.logger.error(error);
56
- throw new Error((0, i18n_1.t)('prompts.validationMessages.metadataInvalid'));
71
+ throw new Error((0, i18n_1.t)('error.unparseableXML', { error }));
57
72
  }
58
73
  }
59
74
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/odata-service-inquirer",
3
3
  "description": "Prompts module that can prompt users for inputs required for odata service writing",
4
- "version": "0.8.8",
4
+ "version": "1.1.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -20,32 +20,37 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "@sap/cf-tools": "3.2.2",
23
+ "@sap-ux/annotation-converter": "0.9.10",
24
+ "@sap-ux/edmx-parser": "0.9.0",
23
25
  "axios": "1.7.4",
24
26
  "axios-logger": "2.8.0",
25
27
  "fast-xml-parser": "4.4.1",
26
28
  "i18next": "23.5.1",
27
29
  "inquirer-autocomplete-prompt": "2.0.1",
28
30
  "os-name": "4.0.1",
29
- "@sap-ux/axios-extension": "1.18.1",
30
31
  "@sap-ux/btp-utils": "0.17.2",
32
+ "@sap-ux/axios-extension": "1.18.1",
31
33
  "@sap-ux/fiori-generator-shared": "0.7.19",
32
34
  "@sap-ux/guided-answers-helper": "0.2.0",
33
- "@sap-ux/telemetry": "0.5.51",
34
35
  "@sap-ux/inquirer-common": "0.6.4",
35
- "@sap-ux/logger": "0.6.0",
36
- "@sap-ux/project-access": "1.29.0",
36
+ "@sap-ux/telemetry": "0.5.51",
37
37
  "@sap-ux/project-input-validator": "0.3.4",
38
+ "@sap-ux/project-access": "1.29.0",
39
+ "@sap-ux/logger": "0.6.0",
38
40
  "@sap-ux/store": "1.0.0"
39
41
  },
40
42
  "devDependencies": {
43
+ "@sap-ux/vocabularies-types": "0.11.7",
41
44
  "@sap-devx/yeoman-ui-types": "1.14.4",
42
45
  "@types/inquirer-autocomplete-prompt": "2.0.1",
43
46
  "@types/inquirer": "8.2.6",
44
47
  "@types/lodash": "4.14.202",
45
48
  "jest-extended": "3.2.4",
46
49
  "@sap-ux/fiori-generator-shared": "0.7.19",
50
+ "@sap-ux/fiori-elements-writer": "2.0.0",
51
+ "@sap-ux/fiori-freestyle-writer": "2.0.0",
47
52
  "@sap-ux/feature-toggle": "0.2.3",
48
- "@sap-ux/odata-service-writer": "0.25.2"
53
+ "@sap-ux/odata-service-writer": "0.25.3"
49
54
  },
50
55
  "engines": {
51
56
  "node": ">=18.x"