@sap-ux/adp-tooling 0.12.17 → 0.12.19

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.
@@ -64,7 +64,17 @@ export declare function parseStringToObject(str: string): {
64
64
  * // Returns the string "nonJSONValue" because it cannot be parsed as JSON
65
65
  * getParsedPropertyValue('nonJSONValue');
66
66
  */
67
- export declare function getParsedPropertyValue(propertyValue: PropertyValueType): PropertyValueType;
67
+ export declare function getParsedPropertyValue(propertyValue: string): PropertyValueType;
68
+ /**
69
+ * Retrieves all change files from a specified project path that match a given change type,
70
+ * optionally within a specific subdirectory.
71
+ *
72
+ * @param {string} projectPath - The base path of the project.
73
+ * @param {ChangeType} changeType - The type of changes to filter by, ensuring only changes of this type are returned.
74
+ * @param {string} [subDir] - Optional subdirectory within the main changes directory.
75
+ * @returns An array of change objects matching the specified change type.
76
+ */
77
+ export declare function getChangesByType(projectPath: string, changeType: ChangeType, subDir?: string): ManifestChangeProperties[];
68
78
  /**
69
79
  * Searches for a change file with a specific inbound ID within a project's change directory.
70
80
  *
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getChange = exports.findChangeWithInboundId = exports.getParsedPropertyValue = exports.parseStringToObject = exports.writeChangeToFile = exports.writeChangeToFolder = exports.writeAnnotationChange = void 0;
6
+ exports.getChange = exports.findChangeWithInboundId = exports.getChangesByType = exports.getParsedPropertyValue = exports.parseStringToObject = exports.writeChangeToFile = exports.writeChangeToFolder = exports.writeAnnotationChange = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const fs_1 = require("fs");
9
9
  const project_access_1 = require("@sap-ux/project-access");
@@ -118,6 +118,48 @@ function getParsedPropertyValue(propertyValue) {
118
118
  }
119
119
  }
120
120
  exports.getParsedPropertyValue = getParsedPropertyValue;
121
+ /**
122
+ * Retrieves all change files from a specified project path that match a given change type,
123
+ * optionally within a specific subdirectory.
124
+ *
125
+ * @param {string} projectPath - The base path of the project.
126
+ * @param {ChangeType} changeType - The type of changes to filter by, ensuring only changes of this type are returned.
127
+ * @param {string} [subDir] - Optional subdirectory within the main changes directory.
128
+ * @returns An array of change objects matching the specified change type.
129
+ */
130
+ function getChangesByType(projectPath, changeType, subDir) {
131
+ try {
132
+ let targetDir = `${projectPath}/webapp/changes`;
133
+ if (!(0, fs_1.existsSync)(targetDir)) {
134
+ return [];
135
+ }
136
+ if (subDir) {
137
+ targetDir = `${targetDir}/${subDir}`;
138
+ if (!(0, fs_1.existsSync)(targetDir)) {
139
+ return [];
140
+ }
141
+ }
142
+ const fileNames = (0, fs_1.readdirSync)(targetDir, { withFileTypes: true })
143
+ .filter((dirent) => dirent.isFile() && dirent.name.endsWith('.change'))
144
+ .map((dirent) => dirent.name);
145
+ if (fileNames.length === 0) {
146
+ return [];
147
+ }
148
+ const changeFiles = fileNames
149
+ .map((fileName) => {
150
+ const filePath = path_1.default.resolve(targetDir, fileName);
151
+ const fileContent = (0, fs_1.readFileSync)(filePath, 'utf-8');
152
+ const change = JSON.parse(fileContent);
153
+ return change;
154
+ })
155
+ .filter((changeFileObject) => changeFileObject.changeType === changeType);
156
+ return changeFiles;
157
+ }
158
+ catch (e) {
159
+ throw new Error(`Error reading change files: ${e.message}`);
160
+ }
161
+ }
162
+ exports.getChangesByType = getChangesByType;
121
163
  /**
122
164
  * Searches for a change file with a specific inbound ID within a project's change directory.
123
165
  *
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.promptTarget = exports.promptGeneratorInput = void 0;
7
+ const uuid_1 = require("uuid");
7
8
  const prompts_1 = __importDefault(require("prompts"));
8
9
  const system_access_1 = require("@sap-ux/system-access");
9
- const validators_1 = require("./validators");
10
- const uuid_1 = require("uuid");
10
+ const project_input_validator_1 = require("@sap-ux/project-input-validator");
11
11
  const project_utils_1 = require("../writer/project-utils");
12
12
  /**
13
13
  * Prompt the user for the required properties for an adaptation project.
@@ -114,7 +114,7 @@ async function promptTarget(defaults, logger) {
114
114
  name: 'url',
115
115
  message: 'Target system url:',
116
116
  initial: target.url,
117
- validate: validators_1.isNotEmptyString,
117
+ validate: project_input_validator_1.validateEmptyString,
118
118
  format: (input) => input.trim()
119
119
  },
120
120
  {
@@ -122,7 +122,7 @@ async function promptTarget(defaults, logger) {
122
122
  name: 'client',
123
123
  message: 'Client (optional):',
124
124
  initial: target.client,
125
- validate: validators_1.isValidSapClient
125
+ validate: project_input_validator_1.validateClient
126
126
  }
127
127
  ]);
128
128
  const systemInfo = await fetchSystemInformation(target, defaults.ignoreCertErrors, logger);
package/dist/index.d.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  export * from './types';
2
2
  export * from './prompts';
3
- export * from './preview/adp-preview';
4
- export * from './base/helper';
5
- export * from './base/validators';
3
+ export * from './base/cf';
6
4
  export * from './base/abap';
5
+ export * from './base/helper';
6
+ export * from './preview/adp-preview';
7
7
  export { generate, migrate } from './writer';
8
8
  export { generateChange } from './writer/editors';
9
9
  export { promptGeneratorInput, PromptDefaults } from './base/prompt';
10
- export { isCFEnvironment } from './base/cf';
11
10
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -14,13 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.isCFEnvironment = exports.promptGeneratorInput = exports.generateChange = exports.migrate = exports.generate = void 0;
17
+ exports.promptGeneratorInput = exports.generateChange = exports.migrate = exports.generate = void 0;
18
18
  __exportStar(require("./types"), exports);
19
19
  __exportStar(require("./prompts"), exports);
20
- __exportStar(require("./preview/adp-preview"), exports);
21
- __exportStar(require("./base/helper"), exports);
22
- __exportStar(require("./base/validators"), exports);
20
+ __exportStar(require("./base/cf"), exports);
23
21
  __exportStar(require("./base/abap"), exports);
22
+ __exportStar(require("./base/helper"), exports);
23
+ __exportStar(require("./preview/adp-preview"), exports);
24
24
  var writer_1 = require("./writer");
25
25
  Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return writer_1.generate; } });
26
26
  Object.defineProperty(exports, "migrate", { enumerable: true, get: function () { return writer_1.migrate; } });
@@ -28,6 +28,4 @@ var editors_1 = require("./writer/editors");
28
28
  Object.defineProperty(exports, "generateChange", { enumerable: true, get: function () { return editors_1.generateChange; } });
29
29
  var prompt_1 = require("./base/prompt");
30
30
  Object.defineProperty(exports, "promptGeneratorInput", { enumerable: true, get: function () { return prompt_1.promptGeneratorInput; } });
31
- var cf_1 = require("./base/cf");
32
- Object.defineProperty(exports, "isCFEnvironment", { enumerable: true, get: function () { return cf_1.isCFEnvironment; } });
33
31
  //# sourceMappingURL=index.js.map
@@ -4,7 +4,7 @@ exports.getPrompts = void 0;
4
4
  const i18n_1 = require("../../i18n");
5
5
  const project_access_1 = require("@sap-ux/project-access");
6
6
  const fs_1 = require("fs");
7
- const validators_1 = require("../../base/validators");
7
+ const project_input_validator_1 = require("@sap-ux/project-input-validator");
8
8
  const path_1 = require("path");
9
9
  /**
10
10
  * Gets the prompts for adding annotations to OData service.
@@ -56,8 +56,9 @@ function getPrompts(basePath, dataSources) {
56
56
  default: '',
57
57
  when: (answers) => answers.id !== '' && answers.fileSelectOption === 1 /* AnnotationFileSelectType.ExistingFile */,
58
58
  validate: (value) => {
59
- if (!(0, validators_1.isNotEmptyString)(value)) {
60
- return (0, i18n_1.t)('validators.inputCannotBeEmpty');
59
+ const validationResult = (0, project_input_validator_1.validateEmptyString)(value);
60
+ if (typeof validationResult === 'string') {
61
+ return validationResult;
61
62
  }
62
63
  const filePath = (0, path_1.isAbsolute)(value) ? value : (0, path_1.join)(basePath, value);
63
64
  if (!(0, fs_1.existsSync)(filePath)) {
@@ -0,0 +1,12 @@
1
+ import type { YUIQuestion } from '@sap-ux/inquirer-common';
2
+ import type { UI5FlexLayer } from '@sap-ux/project-access';
3
+ import { type NewModelAnswers } from '../../types';
4
+ /**
5
+ * Gets the prompts for adding the new model.
6
+ *
7
+ * @param {string} projectPath - The root path of the project.
8
+ * @param {UI5FlexLayer} layer - UI5 Flex layer.
9
+ * @returns {YUIQuestion<NewModelAnswers>[]} The questions/prompts.
10
+ */
11
+ export declare function getPrompts(projectPath: string, layer: UI5FlexLayer): YUIQuestion<NewModelAnswers>[];
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPrompts = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ const change_utils_1 = require("../../base/change-utils");
6
+ const cf_1 = require("../../base/cf");
7
+ const project_input_validator_1 = require("@sap-ux/project-input-validator");
8
+ const oDataVersions = [
9
+ { name: '2.0', value: '2.0' },
10
+ { name: '4.0', value: '4.0' }
11
+ ];
12
+ /**
13
+ * Exucute generic validation for input.
14
+ *
15
+ * @param value The value to validate.
16
+ * @returns {string | boolean} An error message if the value is an empty string, or true if it is not.
17
+ */
18
+ function validatePromptInput(value) {
19
+ const validators = [project_input_validator_1.validateEmptyString, project_input_validator_1.validateEmptySpaces, project_input_validator_1.validateSpecialChars];
20
+ for (const validator of validators) {
21
+ const validationResult = validator(value);
22
+ if (typeof validationResult === 'string') {
23
+ return validationResult;
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+ /**
29
+ * Validates a JSON string.
30
+ *
31
+ * @param value The JSON string to validate.
32
+ * @returns {boolean | string} True if the JSON is valid, or an error message if validation fails.
33
+ */
34
+ function validatePromptJSON(value) {
35
+ const validationResult = (0, project_input_validator_1.validateEmptyString)(value);
36
+ if (typeof validationResult === 'string') {
37
+ return true;
38
+ }
39
+ return (0, project_input_validator_1.validateJSON)(value);
40
+ }
41
+ /**
42
+ * Validates the OData Service name prompt.
43
+ *
44
+ * @param value The value to validate.
45
+ * @param answers The answers object.
46
+ * @param isCustomerBase Whether the validation is for customer usage.
47
+ * @param changeFiles The list of existing change files to check against.
48
+ * @returns {boolean | string} True if no duplication is found, or an error message if validation fails.
49
+ */
50
+ function validatePromptODataName(value, answers, isCustomerBase, changeFiles) {
51
+ const validationResult = validatePromptInput(value);
52
+ if (typeof validationResult === 'string') {
53
+ return validationResult;
54
+ }
55
+ if (isCustomerBase && !(0, project_input_validator_1.hasCustomerPrefix)(value)) {
56
+ return (0, i18n_1.t)('validators.errorInputInvalidValuePrefix', {
57
+ value: (0, i18n_1.t)('prompts.oDataServiceNameLabel'),
58
+ prefix: "customer." /* NamespacePrefix.CUSTOMER */
59
+ });
60
+ }
61
+ if ((0, project_input_validator_1.hasContentDuplication)(value, 'dataSource', changeFiles)) {
62
+ return (0, i18n_1.t)('validators.errorDuplicatedValueOData');
63
+ }
64
+ if (value === answers.dataSourceName) {
65
+ return (0, i18n_1.t)('validators.errorDuplicateNamesOData');
66
+ }
67
+ return true;
68
+ }
69
+ /**
70
+ * Validates the OData Annotation name prompt.
71
+ *
72
+ * @param value The value to validate.
73
+ * @param answers The answers object.
74
+ * @param isCustomerBase Whether the validation is for customer usage.
75
+ * @param changeFiles The list of existing change files to check against.
76
+ * @returns {boolean | string} True if no duplication is found, or an error message if validation fails.
77
+ */
78
+ function validatePromptODataAnnotationsName(value, answers, isCustomerBase, changeFiles) {
79
+ const validationResult = validatePromptInput(value);
80
+ if (typeof validationResult === 'string') {
81
+ return validationResult;
82
+ }
83
+ if (isCustomerBase && !(0, project_input_validator_1.hasCustomerPrefix)(value)) {
84
+ return (0, i18n_1.t)('validators.errorInputInvalidValuePrefix', {
85
+ value: (0, i18n_1.t)('prompts.oDataAnnotationDataSourceNameLabel'),
86
+ prefix: "customer." /* NamespacePrefix.CUSTOMER */
87
+ });
88
+ }
89
+ if ((0, project_input_validator_1.hasContentDuplication)(value, 'dataSource', changeFiles)) {
90
+ return (0, i18n_1.t)('validators.errorDuplicatedValueOData');
91
+ }
92
+ if (value === answers.name) {
93
+ return (0, i18n_1.t)('validators.errorDuplicateNamesOData');
94
+ }
95
+ return true;
96
+ }
97
+ /**
98
+ * Validates the model name prompts.
99
+ *
100
+ * @param value The value to validate.
101
+ * @param isCustomerBase Whether the validation is for customer usage.
102
+ * @param changeFiles The list of existing change files to check against.
103
+ * @returns {boolean | string} True if no duplication is found, or an error message if validation fails.
104
+ */
105
+ function validatePromptModelName(value, isCustomerBase, changeFiles) {
106
+ const validationResult = validatePromptInput(value);
107
+ if (typeof validationResult === 'string') {
108
+ return validationResult;
109
+ }
110
+ if (isCustomerBase && !(0, project_input_validator_1.hasCustomerPrefix)(value)) {
111
+ return (0, i18n_1.t)('validators.errorInputInvalidValuePrefix', {
112
+ value: (0, i18n_1.t)('prompts.oDataServiceModelNameLabel'),
113
+ prefix: "customer." /* NamespacePrefix.CUSTOMER */
114
+ });
115
+ }
116
+ if ((0, project_input_validator_1.hasContentDuplication)(value, 'model', changeFiles)) {
117
+ return (0, i18n_1.t)('validators.errorDuplicatedValueSapui5Model');
118
+ }
119
+ return true;
120
+ }
121
+ /**
122
+ * Validates the OData Source URI prompt.
123
+ *
124
+ * @param value The value to validate.
125
+ * @returns {boolean | string} True if the URI is valid, or an error message if validation fails.
126
+ */
127
+ function validatePromptURI(value) {
128
+ const validationResult = (0, project_input_validator_1.validateEmptyString)(value);
129
+ if (typeof validationResult === 'string') {
130
+ return validationResult;
131
+ }
132
+ if (!(0, project_input_validator_1.isDataSourceURI)(value)) {
133
+ return (0, i18n_1.t)('validators.errorInvalidDataSourceURI');
134
+ }
135
+ return true;
136
+ }
137
+ /**
138
+ * Gets the prompts for adding the new model.
139
+ *
140
+ * @param {string} projectPath - The root path of the project.
141
+ * @param {UI5FlexLayer} layer - UI5 Flex layer.
142
+ * @returns {YUIQuestion<NewModelAnswers>[]} The questions/prompts.
143
+ */
144
+ function getPrompts(projectPath, layer) {
145
+ const isCustomerBase = "CUSTOMER_BASE" /* FlexLayer.CUSTOMER_BASE */ === layer;
146
+ const defaultSeviceName = isCustomerBase ? "customer." /* NamespacePrefix.CUSTOMER */ : "" /* NamespacePrefix.EMPTY */;
147
+ const isCFEnv = (0, cf_1.isCFEnvironment)(projectPath);
148
+ const changeFiles = (0, change_utils_1.getChangesByType)(projectPath, "appdescr_ui5_addNewModel" /* ChangeType.ADD_NEW_MODEL */, 'manifest');
149
+ return [
150
+ {
151
+ type: 'input',
152
+ name: 'name',
153
+ message: (0, i18n_1.t)('prompts.oDataServiceNameLabel'),
154
+ default: defaultSeviceName,
155
+ store: false,
156
+ validate: (value, answers) => {
157
+ return validatePromptODataName(value, answers, isCustomerBase, changeFiles);
158
+ },
159
+ guiOptions: {
160
+ mandatory: true,
161
+ hint: (0, i18n_1.t)('prompts.oDataServiceNameTooltip')
162
+ }
163
+ },
164
+ {
165
+ type: 'input',
166
+ name: 'uri',
167
+ message: (0, i18n_1.t)('prompts.oDataServiceUriLabel'),
168
+ guiOptions: {
169
+ mandatory: true,
170
+ hint: (0, i18n_1.t)('prompts.oDataServiceUriTooltip')
171
+ },
172
+ validate: validatePromptURI,
173
+ store: false
174
+ },
175
+ {
176
+ type: 'list',
177
+ name: 'version',
178
+ message: (0, i18n_1.t)('prompts.oDataServiceVersionLabel'),
179
+ choices: oDataVersions,
180
+ default: (answers) => {
181
+ if (answers.uri?.startsWith(isCFEnv ? '/odata/v4/' : '/sap/opu/odata4/')) {
182
+ return oDataVersions[1].value;
183
+ }
184
+ return oDataVersions[0].value;
185
+ },
186
+ store: false,
187
+ validate: project_input_validator_1.validateEmptyString,
188
+ guiOptions: {
189
+ mandatory: true,
190
+ hint: (0, i18n_1.t)('prompts.oDataServiceVersionTooltip'),
191
+ applyDefaultWhenDirty: true
192
+ }
193
+ },
194
+ {
195
+ type: 'input',
196
+ name: 'modelName',
197
+ message: (0, i18n_1.t)('prompts.oDataServiceModelNameLabel'),
198
+ guiOptions: {
199
+ mandatory: true,
200
+ hint: (0, i18n_1.t)('prompts.oDataServiceModelNameTooltip')
201
+ },
202
+ default: defaultSeviceName,
203
+ validate: (value) => {
204
+ return validatePromptModelName(value, isCustomerBase, changeFiles);
205
+ },
206
+ store: false
207
+ },
208
+ {
209
+ type: 'editor',
210
+ name: 'modelSettings',
211
+ message: (0, i18n_1.t)('prompts.oDataServiceModelSettingsLabel'),
212
+ store: false,
213
+ validate: validatePromptJSON,
214
+ guiOptions: {
215
+ hint: (0, i18n_1.t)('prompts.oDataServiceModelSettingsTooltip')
216
+ }
217
+ },
218
+ {
219
+ type: 'confirm',
220
+ name: 'addAnnotationMode',
221
+ message: 'Do you want to add annotation?',
222
+ default: false
223
+ },
224
+ {
225
+ type: 'input',
226
+ name: 'dataSourceName',
227
+ message: (0, i18n_1.t)('prompts.oDataAnnotationDataSourceNameLabel'),
228
+ validate: (value, answers) => {
229
+ return validatePromptODataAnnotationsName(value, answers, isCustomerBase, changeFiles);
230
+ },
231
+ default: defaultSeviceName,
232
+ store: false,
233
+ guiOptions: {
234
+ mandatory: true,
235
+ hint: (0, i18n_1.t)('prompts.oDataAnnotationDataSourceNameTooltip')
236
+ },
237
+ when: (answers) => answers.addAnnotationMode
238
+ },
239
+ {
240
+ type: 'input',
241
+ name: 'dataSourceURI',
242
+ message: (0, i18n_1.t)('prompts.oDataAnnotationDataSourceUriLabel'),
243
+ validate: project_input_validator_1.validateEmptyString,
244
+ store: false,
245
+ guiOptions: {
246
+ mandatory: true,
247
+ hint: (0, i18n_1.t)('prompts.oDataAnnotationDataSourceUriTooltip')
248
+ },
249
+ when: (answers) => answers.addAnnotationMode
250
+ },
251
+ {
252
+ type: 'editor',
253
+ name: 'annotationSettings',
254
+ message: (0, i18n_1.t)('prompts.oDataAnnotationSettingsLabel'),
255
+ validate: validatePromptJSON,
256
+ store: false,
257
+ guiOptions: {
258
+ hint: (0, i18n_1.t)('prompts.oDataAnnotationSettingsTooltip')
259
+ },
260
+ when: (answers) => answers.addAnnotationMode
261
+ }
262
+ ];
263
+ }
264
+ exports.getPrompts = getPrompts;
265
+ //# sourceMappingURL=index.js.map
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPrompts = void 0;
4
4
  const i18n_1 = require("../../i18n");
5
5
  const project_access_1 = require("@sap-ux/project-access");
6
- const validators_1 = require("../../base/validators");
6
+ const project_input_validator_1 = require("@sap-ux/project-input-validator");
7
7
  /**
8
8
  * Gets the prompts for changing the data source.
9
9
  *
@@ -33,7 +33,7 @@ function getPrompts(dataSources) {
33
33
  mandatory: true,
34
34
  hint: (0, i18n_1.t)('prompts.oDataSourceURITooltip')
35
35
  },
36
- validate: validators_1.isNotEmptyString,
36
+ validate: project_input_validator_1.validateEmptyString,
37
37
  when: !!dataSourceIds.length,
38
38
  store: false
39
39
  },
@@ -0,0 +1,9 @@
1
+ import type { YUIQuestion } from '@sap-ux/inquirer-common';
2
+ import type { InboundChangeAnswers } from '../../types';
3
+ /**
4
+ * Gets the prompts for Inbound Change.
5
+ *
6
+ * @returns {YUIQuestion<InboundChangeAnswers>[]} The questions/prompts.
7
+ */
8
+ export declare function getPrompts(): YUIQuestion<InboundChangeAnswers>[];
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPrompts = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * Gets the prompts for Inbound Change.
7
+ *
8
+ * @returns {YUIQuestion<InboundChangeAnswers>[]} The questions/prompts.
9
+ */
10
+ function getPrompts() {
11
+ return [
12
+ {
13
+ type: 'input',
14
+ name: 'title',
15
+ message: (0, i18n_1.t)('prompts.title'),
16
+ guiOptions: {
17
+ hint: (0, i18n_1.t)('tooltips.title')
18
+ },
19
+ validate: (value, answers) => answers.subTitle || answers.icon !== '' || value ? true : (0, i18n_1.t)('missingIconOrTitleOrSubtitle'),
20
+ store: false
21
+ },
22
+ {
23
+ type: 'input',
24
+ name: 'subtitle',
25
+ message: (0, i18n_1.t)('prompts.subtitle'),
26
+ guiOptions: {
27
+ hint: (0, i18n_1.t)('tooltips.subtitle')
28
+ },
29
+ validate: (value, answers) => value || answers.icon !== '' || answers.title !== '' ? true : (0, i18n_1.t)('missingIconOrTitleOrSubtitle'),
30
+ store: false
31
+ },
32
+ {
33
+ type: 'input',
34
+ name: 'icon',
35
+ message: (0, i18n_1.t)('prompts.icon'),
36
+ guiOptions: {
37
+ hint: (0, i18n_1.t)('tooltips.icon')
38
+ },
39
+ store: false,
40
+ validate: (value, answers) => answers.subTitle || value || answers.title !== '' ? true : (0, i18n_1.t)('missingIconOrTitleOrSubtitle')
41
+ }
42
+ ];
43
+ }
44
+ exports.getPrompts = getPrompts;
45
+ //# sourceMappingURL=index.js.map
@@ -1,3 +1,5 @@
1
1
  export { getPrompts as getPromptsForChangeDataSource } from './change-data-source';
2
+ export { getPrompts as getPromptsForNewModel } from './add-new-model';
3
+ export { getPrompts as getPromptsForChangeInbound } from './change-inbound';
2
4
  export { getPrompts as getPromptsForAddAnnotationsToOData } from './add-annotations-to-odata';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPromptsForAddAnnotationsToOData = exports.getPromptsForChangeDataSource = void 0;
3
+ exports.getPromptsForAddAnnotationsToOData = exports.getPromptsForChangeInbound = exports.getPromptsForNewModel = exports.getPromptsForChangeDataSource = void 0;
4
4
  var change_data_source_1 = require("./change-data-source");
5
5
  Object.defineProperty(exports, "getPromptsForChangeDataSource", { enumerable: true, get: function () { return change_data_source_1.getPrompts; } });
6
+ var add_new_model_1 = require("./add-new-model");
7
+ Object.defineProperty(exports, "getPromptsForNewModel", { enumerable: true, get: function () { return add_new_model_1.getPrompts; } });
8
+ var change_inbound_1 = require("./change-inbound");
9
+ Object.defineProperty(exports, "getPromptsForChangeInbound", { enumerable: true, get: function () { return change_inbound_1.getPrompts; } });
6
10
  var add_annotations_to_odata_1 = require("./add-annotations-to-odata");
7
11
  Object.defineProperty(exports, "getPromptsForAddAnnotationsToOData", { enumerable: true, get: function () { return add_annotations_to_odata_1.getPrompts; } });
8
12
  //# sourceMappingURL=index.js.map
@@ -8,21 +8,50 @@
8
8
  "maxAgeTooltip": "(Optional) Enter the time in seconds it takes for a cached response of the service to expire.",
9
9
  "oDataAnnotationSourceURILabel": "OData Annotation Data Source URI",
10
10
  "oDataAnnotationSourceURITooltip": "Server side annotations have been detected for the selected OData service. If needed, enter new annotation data source URI for the changed service",
11
- "addAnnotationOdataSourceTooltip": "Select the annotation file from your workspace",
12
11
  "fileSelectOptionLabel": "Annotation XML",
13
12
  "fileSelectOptionTooltip": "Select the annotation file source",
14
13
  "filePathLabel": "Annotation File path",
15
- "filePathTooltip": "Select the annotation file from your workspace"
14
+ "filePathTooltip": "Select the annotation file from your workspace",
15
+ "addAnnotationOdataSourceTooltip": "Select the annotation file from your workspace",
16
+ "oDataServiceNameLabel": "OData Service Name",
17
+ "oDataServiceNameTooltip": "Enter a name for the OData service you want to add",
18
+ "oDataServiceUriLabel": "OData Service URI",
19
+ "oDataServiceUriTooltip": "Enter the URI for the OData service you want to add, e.g. /path/to/odata/",
20
+ "oDataServiceVersionLabel": "OData Version",
21
+ "oDataServiceVersionTooltip": "Select the version of OData of the service you want to add",
22
+ "oDataServiceModelNameLabel": "OData Service SAPUI5 Model Name",
23
+ "oDataServiceModelNameTooltip": "Enter a name for the SAPUI5 model you want to use from the service",
24
+ "oDataServiceModelSettingsLabel": "OData Service SAPUI5 Model Settings",
25
+ "oDataServiceModelSettingsTooltip": "If needed enter any additional model settings in the 'key1':'value1','key2':'value2' format",
26
+ "oDataAnnotationDataSourceNameLabel": "OData Annotation Data Source Name",
27
+ "oDataAnnotationDataSourceNameTooltip": "Enter a name for the OData annotation data source",
28
+ "oDataAnnotationDataSourceUriLabel": "OData Annotation Data Source URI",
29
+ "oDataAnnotationDataSourceUriTooltip": "Enter URI for the OData annotation data source",
30
+ "oDataAnnotationSettingsLabel": "OData Annotation Settings",
31
+ "oDataAnnotationSettingsTooltip": "If needed enter any additional {{value}} settings in the 'key':'value1','key2':'value2' format",
32
+ "title": "Title",
33
+ "subtitle": "Subtitle",
34
+ "icon": "Icon"
35
+ },
36
+ "tooltips": {
37
+ "title": "Enter title for your FLP configuration",
38
+ "subtitle": "Enter subtitle for your FLP configuration",
39
+ "icon": "Enter icon path for your FLP configuration"
40
+ },
41
+ "validators": {
42
+ "missingIconOrTitleOrSubtitle": "At least one of Title, Subtitle and Icon should have a value.",
43
+ "fileDoesNotExist": "The file doesn't exist",
44
+ "annotationFileAlreadyExists": "There is already an annotation file with the same name, please choose another file or rename the file and select it again",
45
+ "errorDuplicatedValueOData": "OData Annotation or OData Service with the same name was already added to the project",
46
+ "errorDuplicatedValueSapui5Model": "SAPUI5 Model with the same name was already added to the project",
47
+ "errorDuplicateNamesOData": "OData Service Name must be different from OData Annotation Data Source Name",
48
+ "errorInputInvalidValuePrefix": "{{value}} should start with '{{prefix}}'",
49
+ "errorInvalidDataSourceURI": "Invalid URI. Should start and end with '/' and contain no spaces"
16
50
  },
17
51
  "choices": {
18
52
  "annotationFile": {
19
53
  "selectFromWorkspace": "Select annotation file from workspace",
20
54
  "createEmptyFile": "Create an empty annotation file"
21
55
  }
22
- },
23
- "validators": {
24
- "inputCannotBeEmpty": "Input cannot be empty.",
25
- "fileDoesNotExist": "The file doesn't exist",
26
- "annotationFileAlreadyExists": "There is already an annotation file with the same name, please choose another file or rename the file and select it again"
27
56
  }
28
57
  }
package/dist/types.d.ts CHANGED
@@ -8,7 +8,12 @@ export interface DescriptorVariant {
8
8
  reference: string;
9
9
  id: string;
10
10
  namespace: string;
11
- content: object[];
11
+ content: DescriptorVariantContent[];
12
+ }
13
+ export interface DescriptorVariantContent {
14
+ changeType: string;
15
+ content: Record<string, unknown>;
16
+ texts?: string;
12
17
  }
13
18
  export interface ToolsSupport {
14
19
  id: string;
@@ -172,12 +177,19 @@ export interface CodeExtChange extends CommonChangeProperties {
172
177
  controllerName: string;
173
178
  };
174
179
  }
175
- export declare const CUSTOMER_BASE = "CUSTOMER_BASE";
176
180
  export declare const enum TemplateFileName {
177
181
  Fragment = "fragment.xml",
178
182
  Controller = "controller.ejs",
179
183
  Annotation = "annotation.xml"
180
184
  }
185
+ export declare const enum FlexLayer {
186
+ CUSTOMER_BASE = "CUSTOMER_BASE",
187
+ VENDOR = "VENDOR"
188
+ }
189
+ export declare const enum NamespacePrefix {
190
+ CUSTOMER = "customer.",
191
+ EMPTY = ""
192
+ }
181
193
  export declare const enum HttpStatusCodes {
182
194
  OK = 200,
183
195
  CREATED = 201,
@@ -271,51 +283,46 @@ export interface ComponentUsagesData {
271
283
  };
272
284
  }
273
285
  export interface NewModelData {
274
- projectData: AdpProjectData;
275
- timestamp: number;
276
- annotation: {
277
- /** Name of the OData annotation data source. */
278
- dataSourceName: string;
279
- /** Optional URI of the OData annotation data source. */
280
- dataSourceURI?: string;
281
- /** Optional settings for the OData annotation. */
282
- settings?: string;
283
- };
284
- service: {
285
- /** Name of the OData service. */
286
- name: string;
287
- /** URI of the OData service. */
288
- uri: string;
289
- /** Name of the OData service model. */
290
- modelName: string;
291
- /** Version of OData used. */
292
- version: string;
293
- /** Settings for the OData service model. */
294
- modelSettings: string;
295
- };
296
- /** Indicates whether annotation mode is added. */
286
+ variant: DescriptorVariant;
287
+ answers: NewModelAnswers;
288
+ }
289
+ export interface NewModelAnswers {
297
290
  addAnnotationMode: boolean;
291
+ /** Name of the OData service. */
292
+ name: string;
293
+ /** URI of the OData service. */
294
+ uri: string;
295
+ /** Name of the OData service model. */
296
+ modelName: string;
297
+ /** Version of OData used. */
298
+ version: string;
299
+ /** Settings for the OData service model. */
300
+ modelSettings: string;
301
+ /** Name of the OData annotation data source. */
302
+ dataSourceName: string;
303
+ /** Optional URI of the OData annotation data source. */
304
+ dataSourceURI?: string;
305
+ /** Optional settings for the OData annotation. */
306
+ annotationSettings?: string;
298
307
  }
299
308
  export interface DataSourceData {
300
309
  variant: DescriptorVariant;
301
310
  dataSources: Record<string, ManifestNamespace.DataSource>;
302
311
  answers: ChangeDataSourceAnswers;
303
312
  }
313
+ export interface InboundChangeAnswers {
314
+ /** Title associated with the inbound navigation data. */
315
+ title: string;
316
+ /** Subtitle associated with the inbound navigation data. */
317
+ subTitle: string;
318
+ /** Icon associated with the inbound navigation data. */
319
+ icon: string;
320
+ }
304
321
  export interface InboundData {
305
- projectData: AdpProjectData;
306
- timestamp: number;
307
322
  /** Identifier for the inbound navigation data. */
308
323
  inboundId: string;
309
- flp: {
310
- /** Title associated with the inbound navigation data. */
311
- title: PropertyValueType;
312
- /** Subtitle associated with the inbound navigation data. */
313
- subTitle: PropertyValueType;
314
- /** Icon associated with the inbound navigation data. */
315
- icon: PropertyValueType;
316
- };
317
- /** Optional flag indicating if the project is in safe mode. */
318
- isInSafeMode?: boolean;
324
+ variant: DescriptorVariant;
325
+ answers: InboundChangeAnswers;
319
326
  }
320
327
  export interface InboundContent {
321
328
  inboundId: string;
package/dist/types.js CHANGED
@@ -1,5 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CUSTOMER_BASE = void 0;
4
- exports.CUSTOMER_BASE = 'CUSTOMER_BASE';
5
3
  //# sourceMappingURL=types.js.map
@@ -25,7 +25,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.AnnotationsWriter = void 0;
27
27
  const path_1 = __importStar(require("path"));
28
- const types_1 = require("../../../types");
29
28
  const change_utils_1 = require("../../../base/change-utils");
30
29
  /**
31
30
  * Handles the creation and writing of annotations data changes for a project.
@@ -50,7 +49,7 @@ class AnnotationsWriter {
50
49
  constructContent(data) {
51
50
  const { variant: { layer }, fileName, answers: { id } } = data;
52
51
  const annotationFileNameWithoutExtension = fileName?.toLocaleLowerCase().replace('.xml', '');
53
- const annotationNameSpace = layer === types_1.CUSTOMER_BASE
52
+ const annotationNameSpace = layer === "CUSTOMER_BASE" /* FlexLayer.CUSTOMER_BASE */
54
53
  ? `customer.annotation.${annotationFileNameWithoutExtension}`
55
54
  : `annotation.${annotationFileNameWithoutExtension}`;
56
55
  return {
@@ -26,14 +26,6 @@ export declare class InboundWriter implements IWriter<InboundData> {
26
26
  * @returns {void}
27
27
  */
28
28
  private getEnhancedContent;
29
- /**
30
- * Processes the provided answers object to parse its properties into the correct format.
31
- *
32
- * @param {InboundData} data - An object containing raw answers for inboundId, title, subTitle, and icon.
33
- * @returns {InboundData} A new answers object with properties modified
34
- * to ensure they are in the correct format for use in content construction.
35
- */
36
- private getModifiedData;
37
29
  /**
38
30
  * Writes the inbound data change to the project based on the provided data.
39
31
  *
@@ -39,47 +39,29 @@ class InboundWriter {
39
39
  * @returns {void}
40
40
  */
41
41
  getEnhancedContent(data, content) {
42
- const { icon, title, subTitle } = data.flp;
42
+ const { icon, title, subTitle } = data.answers;
43
43
  if (title) {
44
44
  content.entityPropertyChange.push({
45
45
  propertyPath: 'title',
46
46
  operation: 'UPSERT',
47
- propertyValue: title
47
+ propertyValue: (0, change_utils_1.getParsedPropertyValue)(title)
48
48
  });
49
49
  }
50
50
  if (subTitle) {
51
51
  content.entityPropertyChange.push({
52
52
  propertyPath: 'subTitle',
53
53
  operation: 'UPSERT',
54
- propertyValue: subTitle
54
+ propertyValue: (0, change_utils_1.getParsedPropertyValue)(subTitle)
55
55
  });
56
56
  }
57
57
  if (icon) {
58
58
  content.entityPropertyChange.push({
59
59
  propertyPath: 'icon',
60
60
  operation: 'UPSERT',
61
- propertyValue: icon
61
+ propertyValue: (0, change_utils_1.getParsedPropertyValue)(icon)
62
62
  });
63
63
  }
64
64
  }
65
- /**
66
- * Processes the provided answers object to parse its properties into the correct format.
67
- *
68
- * @param {InboundData} data - An object containing raw answers for inboundId, title, subTitle, and icon.
69
- * @returns {InboundData} A new answers object with properties modified
70
- * to ensure they are in the correct format for use in content construction.
71
- */
72
- getModifiedData(data) {
73
- const { title, subTitle, icon } = data.flp;
74
- return {
75
- ...data,
76
- flp: {
77
- title: (0, change_utils_1.getParsedPropertyValue)(title),
78
- subTitle: (0, change_utils_1.getParsedPropertyValue)(subTitle),
79
- icon: (0, change_utils_1.getParsedPropertyValue)(icon)
80
- }
81
- };
82
- }
83
65
  /**
84
66
  * Writes the inbound data change to the project based on the provided data.
85
67
  *
@@ -87,16 +69,16 @@ class InboundWriter {
87
69
  * @returns {Promise<void>} A promise that resolves when the change writing process is completed.
88
70
  */
89
71
  async write(data) {
90
- const answers = this.getModifiedData(data);
91
- const { changeWithInboundId, filePath } = (0, change_utils_1.findChangeWithInboundId)(this.projectPath, answers.inboundId);
72
+ const { changeWithInboundId, filePath } = (0, change_utils_1.findChangeWithInboundId)(this.projectPath, data.inboundId);
73
+ const timestamp = Date.now();
92
74
  if (!changeWithInboundId) {
93
- const content = this.constructContent(answers);
94
- const change = (0, change_utils_1.getChange)(data.projectData, data.timestamp, content, "appdescr_app_changeInbound" /* ChangeType.CHANGE_INBOUND */);
95
- (0, change_utils_1.writeChangeToFolder)(this.projectPath, change, `id_${data.timestamp}_changeInbound.change`, this.fs, project_access_1.DirName.Manifest);
75
+ const content = this.constructContent(data);
76
+ const change = (0, change_utils_1.getChange)(data.variant, timestamp, content, "appdescr_app_changeInbound" /* ChangeType.CHANGE_INBOUND */);
77
+ (0, change_utils_1.writeChangeToFolder)(this.projectPath, change, `id_${timestamp}_changeInbound.change`, this.fs, project_access_1.DirName.Manifest);
96
78
  }
97
79
  else {
98
80
  if (changeWithInboundId.content) {
99
- this.getEnhancedContent(answers, changeWithInboundId.content);
81
+ this.getEnhancedContent(data, changeWithInboundId.content);
100
82
  }
101
83
  (0, change_utils_1.writeChangeToFile)(filePath, changeWithInboundId, this.fs);
102
84
  }
@@ -14,7 +14,7 @@ export declare class NewModelWriter implements IWriter<NewModelData> {
14
14
  /**
15
15
  * Constructs the content for an new model change based on provided data.
16
16
  *
17
- * @param {NewModelData} data - The answers object containing information needed to construct the content property.
17
+ * @param {NewModelAnswers} data - The answers object containing information needed to construct the content property.
18
18
  * @returns {object} The constructed content object for the new model change.
19
19
  */
20
20
  private constructContent;
@@ -20,37 +20,37 @@ class NewModelWriter {
20
20
  /**
21
21
  * Constructs the content for an new model change based on provided data.
22
22
  *
23
- * @param {NewModelData} data - The answers object containing information needed to construct the content property.
23
+ * @param {NewModelAnswers} data - The answers object containing information needed to construct the content property.
24
24
  * @returns {object} The constructed content object for the new model change.
25
25
  */
26
- constructContent({ service, annotation, addAnnotationMode }) {
26
+ constructContent({ name, uri, addAnnotationMode, dataSourceName, modelName, modelSettings, version, dataSourceURI, annotationSettings }) {
27
27
  const content = {
28
28
  dataSource: {
29
- [service.name]: {
30
- uri: service.uri,
29
+ [name]: {
30
+ uri,
31
31
  type: 'OData',
32
32
  settings: {
33
- odataVersion: service.version
33
+ odataVersion: version
34
34
  }
35
35
  }
36
36
  },
37
37
  model: {
38
- [service.modelName]: {
39
- dataSource: service.name
38
+ [modelName]: {
39
+ dataSource: name
40
40
  }
41
41
  }
42
42
  };
43
- if (service.modelSettings && service.modelSettings.length !== 0) {
44
- content.model[service.modelName].settings = (0, change_utils_1.parseStringToObject)(service.modelSettings);
43
+ if (modelSettings && modelSettings.length !== 0) {
44
+ content.model[modelName].settings = (0, change_utils_1.parseStringToObject)(modelSettings);
45
45
  }
46
46
  if (addAnnotationMode) {
47
- content.dataSource[service.name].settings.annotations = [`${annotation.dataSourceName}`];
48
- content.dataSource[annotation.dataSourceName] = {
49
- uri: annotation.dataSourceURI,
47
+ content.dataSource[name].settings.annotations = [`${dataSourceName}`];
48
+ content.dataSource[dataSourceName] = {
49
+ uri: dataSourceURI,
50
50
  type: 'ODataAnnotation'
51
51
  };
52
- if (annotation.settings && annotation.settings.length !== 0) {
53
- content.dataSource[annotation.dataSourceName].settings = (0, change_utils_1.parseStringToObject)(annotation.settings);
52
+ if (annotationSettings && annotationSettings.length !== 0) {
53
+ content.dataSource[dataSourceName].settings = (0, change_utils_1.parseStringToObject)(annotationSettings);
54
54
  }
55
55
  }
56
56
  return content;
@@ -62,9 +62,10 @@ class NewModelWriter {
62
62
  * @returns {Promise<void>} A promise that resolves when the change writing process is completed.
63
63
  */
64
64
  async write(data) {
65
- const content = this.constructContent(data);
66
- const change = (0, change_utils_1.getChange)(data.projectData, data.timestamp, content, "appdescr_ui5_addNewModel" /* ChangeType.ADD_NEW_MODEL */);
67
- (0, change_utils_1.writeChangeToFolder)(this.projectPath, change, `id_${data.timestamp}_addNewModel.change`, this.fs, project_access_1.DirName.Manifest);
65
+ const timestamp = Date.now();
66
+ const content = this.constructContent(data.answers);
67
+ const change = (0, change_utils_1.getChange)(data.variant, timestamp, content, "appdescr_ui5_addNewModel" /* ChangeType.ADD_NEW_MODEL */);
68
+ (0, change_utils_1.writeChangeToFolder)(this.projectPath, change, `id_${timestamp}_addNewModel.change`, this.fs, project_access_1.DirName.Manifest);
68
69
  }
69
70
  }
70
71
  exports.NewModelWriter = NewModelWriter;
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "bugs": {
10
10
  "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aadp-tooling"
11
11
  },
12
- "version": "0.12.17",
12
+ "version": "0.12.19",
13
13
  "license": "Apache-2.0",
14
14
  "author": "@SAP/ux-tools-team",
15
15
  "main": "dist/index.js",
@@ -34,9 +34,10 @@
34
34
  "uuid": "10.0.0",
35
35
  "@sap-ux/axios-extension": "1.16.1",
36
36
  "@sap-ux/btp-utils": "0.15.0",
37
- "@sap-ux/inquirer-common": "0.4.2",
37
+ "@sap-ux/inquirer-common": "0.4.3",
38
38
  "@sap-ux/logger": "0.6.0",
39
39
  "@sap-ux/project-access": "1.25.7",
40
+ "@sap-ux/project-input-validator": "0.3.2",
40
41
  "@sap-ux/system-access": "0.5.3",
41
42
  "@sap-ux/ui5-config": "0.23.1"
42
43
  },
@@ -1,15 +0,0 @@
1
- /**
2
- * Checks if the input is a non-empty string.
3
- *
4
- * @param input - input to check
5
- * @returns true if the input is a non-empty string
6
- */
7
- export declare function isNotEmptyString(input: string | undefined): boolean;
8
- /**
9
- * Checks if the input is a valid SAP client.
10
- *
11
- * @param input - input to check
12
- * @returns true if the input is a valid SAP client
13
- */
14
- export declare function isValidSapClient(input: string | undefined): boolean;
15
- //# sourceMappingURL=validators.d.ts.map
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isValidSapClient = exports.isNotEmptyString = void 0;
4
- /**
5
- * Checks if the input is a non-empty string.
6
- *
7
- * @param input - input to check
8
- * @returns true if the input is a non-empty string
9
- */
10
- function isNotEmptyString(input) {
11
- return typeof input === 'string' && input.trim().length > 0;
12
- }
13
- exports.isNotEmptyString = isNotEmptyString;
14
- /**
15
- * Checks if the input is a valid SAP client.
16
- *
17
- * @param input - input to check
18
- * @returns true if the input is a valid SAP client
19
- */
20
- function isValidSapClient(input) {
21
- return !input || (input.length < 4 && !!new RegExp(/^\d*$/).exec(input));
22
- }
23
- exports.isValidSapClient = isValidSapClient;
24
- //# sourceMappingURL=validators.js.map