@sap-ux/repo-app-import-sub-generator 0.3.15 → 0.3.16

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.
@@ -46,7 +46,9 @@ exports.getAbapDeployConfig = getAbapDeployConfig;
46
46
  */
47
47
  const fetchServiceMetadata = async (provider, serviceUrl) => {
48
48
  try {
49
- return await provider.service(serviceUrl).metadata();
49
+ const metdata = await provider.service(serviceUrl).metadata();
50
+ logger_1.default.logger?.debug('Metadata fetched successfully');
51
+ return metdata;
50
52
  }
51
53
  catch (err) {
52
54
  logger_1.default.logger?.error((0, i18n_1.t)('error.metadataFetchError', { error: err.message }));
@@ -94,7 +94,7 @@ class default_1 extends yeoman_generator_1.default {
94
94
  */
95
95
  async prompting() {
96
96
  const quickDeployedAppConfig = this.options?.data?.quickDeployedAppConfig;
97
- const questions = await (0, prompts_1.getPrompts)(this.appRootPath, quickDeployedAppConfig, this.appWizard);
97
+ const questions = await (0, prompts_1.getPrompts)(this.appRootPath, quickDeployedAppConfig, this.appWizard, (0, fiori_generator_shared_1.isCli)());
98
98
  const answers = await this.prompt(questions);
99
99
  const { targetFolder } = answers;
100
100
  if (quickDeployedAppConfig?.appId) {
@@ -203,7 +203,9 @@ class default_1 extends yeoman_generator_1.default {
203
203
  async install() {
204
204
  if (!this.options.skipInstall) {
205
205
  try {
206
+ logger_1.default.logger?.debug('Running npm install...');
206
207
  await this._runNpmInstall(this.projectPath);
208
+ logger_1.default.logger?.debug('npm install completed successfully.');
207
209
  }
208
210
  catch (error) {
209
211
  logger_1.default.logger?.error((0, i18n_1.t)('error.installationErrors.npmInstall', { error }));
@@ -57,9 +57,13 @@ exports.extractAppData = extractAppData;
57
57
  const formatAppChoices = (appList) => {
58
58
  return appList
59
59
  .filter((app) => {
60
- const hasRequiredFields = app['sap.app/id'] && app['sap.app/title'] && app['repoName'] && app['url'];
60
+ logger_1.default.logger?.debug(`formatAppChoices: ${JSON.stringify(app)}`);
61
+ const hasRequiredFields = app['sap.app/id'] &&
62
+ app['repoName'] &&
63
+ app['url'] &&
64
+ Object.prototype.hasOwnProperty.call(app, 'sap.app/title'); // allow for empty title
61
65
  if (!hasRequiredFields) {
62
- logger_1.default.logger?.warn((0, i18n_1.t)('warn.requiredFieldsMissing', { app: app.appId }));
66
+ logger_1.default.logger?.warn((0, i18n_1.t)('warn.requiredFieldsMissing', { app: app['sap.app/id'] }));
63
67
  }
64
68
  return hasRequiredFields;
65
69
  })
@@ -85,6 +89,7 @@ async function getAppList(provider, appId) {
85
89
  }
86
90
  catch (error) {
87
91
  logger_1.default.logger?.error((0, i18n_1.t)('error.applicationListFetchError', { error: error.message }));
92
+ logger_1.default.logger?.debug((0, i18n_1.t)('error.applicationListFetchError', { error: JSON.stringify(error) }));
88
93
  return [];
89
94
  }
90
95
  }
@@ -6,7 +6,8 @@ import type { AppWizard } from '@sap-devx/yeoman-ui-types';
6
6
  * @param {string} [appRootPath] - The root path of the application.
7
7
  * @param {QuickDeployedAppConfig} [quickDeployedAppConfig] - The quick deployed app configuration.
8
8
  * @param {AppWizard} [appWizard] - The app wizard instance.
9
+ * @param {boolean} [isCli] - Indicates if the prompts are being generated for CLI usage.
9
10
  * @returns {Promise<RepoAppDownloadQuestions[]>} A list of prompts for user interaction.
10
11
  */
11
- export declare function getPrompts(appRootPath?: string, quickDeployedAppConfig?: QuickDeployedAppConfig, appWizard?: AppWizard): Promise<RepoAppDownloadQuestions[]>;
12
+ export declare function getPrompts(appRootPath?: string, quickDeployedAppConfig?: QuickDeployedAppConfig, appWizard?: AppWizard, isCli?: boolean): Promise<RepoAppDownloadQuestions[]>;
12
13
  //# sourceMappingURL=prompts.d.ts.map
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.getPrompts = void 0;
4
7
  const odata_service_inquirer_1 = require("@sap-ux/odata-service-inquirer");
@@ -8,6 +11,7 @@ const project_input_validator_1 = require("@sap-ux/project-input-validator");
8
11
  const prompt_state_1 = require("./prompt-state");
9
12
  const prompt_helpers_1 = require("./prompt-helpers");
10
13
  const validators_1 = require("../utils/validators");
14
+ const logger_1 = __importDefault(require("../utils/logger"));
11
15
  /**
12
16
  * Gets the target folder selection prompt.
13
17
  *
@@ -43,23 +47,45 @@ const getTargetFolderPrompt = (appRootPath, appId) => {
43
47
  default: () => appRootPath
44
48
  };
45
49
  };
50
+ const getCliValidatePrompts = async (appList, quickDeployedAppConfig, appWizard) => {
51
+ return {
52
+ when: async (answers) => {
53
+ if (answers?.[types_1.PromptNames.selectedApp]) {
54
+ try {
55
+ await (0, validators_1.validateAppSelection)(answers[types_1.PromptNames.selectedApp], appList, quickDeployedAppConfig, appWizard);
56
+ }
57
+ catch (error) {
58
+ if (error instanceof Error) {
59
+ logger_1.default.logger?.error(error.message);
60
+ }
61
+ else {
62
+ logger_1.default.logger?.error((0, i18n_1.t)('error.appDownloadErrors.validationError', { error: error }));
63
+ }
64
+ }
65
+ }
66
+ return false;
67
+ },
68
+ name: `${types_1.PromptNames.selectedApp}-validation`
69
+ };
70
+ };
46
71
  /**
47
72
  * Retrieves prompts for selecting a system, app list, and target folder where the app will be generated.
48
73
  *
49
74
  * @param {string} [appRootPath] - The root path of the application.
50
75
  * @param {QuickDeployedAppConfig} [quickDeployedAppConfig] - The quick deployed app configuration.
51
76
  * @param {AppWizard} [appWizard] - The app wizard instance.
77
+ * @param {boolean} [isCli] - Indicates if the prompts are being generated for CLI usage.
52
78
  * @returns {Promise<RepoAppDownloadQuestions[]>} A list of prompts for user interaction.
53
79
  */
54
- async function getPrompts(appRootPath, quickDeployedAppConfig, appWizard) {
80
+ async function getPrompts(appRootPath, quickDeployedAppConfig, appWizard, isCli = false) {
55
81
  try {
56
82
  prompt_state_1.PromptState.reset();
57
83
  const systemQuestions = await (0, odata_service_inquirer_1.getSystemSelectionQuestions)({
58
- serviceSelection: { hide: true },
84
+ serviceSelection: { hide: true, useAutoComplete: isCli },
59
85
  systemSelection: { defaultChoice: quickDeployedAppConfig?.serviceProviderInfo?.name }
60
- }, true);
86
+ }, !isCli);
61
87
  let appList = [];
62
- const appSelectionPrompt = [
88
+ const appSelectionPrompts = [
63
89
  {
64
90
  when: async (answers) => {
65
91
  if (answers[types_1.PromptNames.systemSelection] &&
@@ -78,11 +104,18 @@ async function getPrompts(appRootPath, quickDeployedAppConfig, appWizard) {
78
104
  },
79
105
  message: (0, i18n_1.t)('prompts.appSelection.message'),
80
106
  choices: () => (appList.length ? (0, prompt_helpers_1.formatAppChoices)(appList) : []),
81
- validate: async (answers) => (0, validators_1.validateAppSelection)(answers, appList, quickDeployedAppConfig, appWizard)
107
+ validate: async (answers) => {
108
+ const result = await (0, validators_1.validateAppSelection)(answers, appList, quickDeployedAppConfig, appWizard);
109
+ return !!result;
110
+ }
82
111
  }
83
112
  ];
113
+ // Only for CLI use as `list` prompt validation does not run on CLI unless autocomplete plugin is used
114
+ if (isCli) {
115
+ appSelectionPrompts?.push(getCliValidatePrompts(appList, quickDeployedAppConfig, appWizard));
116
+ }
84
117
  const targetFolderPrompts = getTargetFolderPrompt(appRootPath, quickDeployedAppConfig?.appId);
85
- return [...systemQuestions.prompts, ...appSelectionPrompt, targetFolderPrompts];
118
+ return [...systemQuestions.prompts, ...appSelectionPrompts, targetFolderPrompts];
86
119
  }
87
120
  catch (error) {
88
121
  throw new Error(`Failed to generate prompts: ${error.message}`);
@@ -32,6 +32,8 @@ async function extractZip(extractedProjectPath, fs) {
32
32
  if (!zipEntry.isDirectory) {
33
33
  // Extract the file content
34
34
  const fileContent = zipEntry.getData().toString('utf8');
35
+ const filePath = (0, path_1.join)(extractedProjectPath, zipEntry.entryName);
36
+ logger_1.default.logger?.debug(`extractZip: Extracting file: "${filePath}" with contents: "${fileContent}" .`);
35
37
  // Load the file content into mem-fs for use in the temporary extracted project directory
36
38
  fs.write((0, path_1.join)(extractedProjectPath, zipEntry.entryName), fileContent);
37
39
  }
@@ -49,7 +51,11 @@ exports.extractZip = extractZip;
49
51
  */
50
52
  async function downloadApp(repoName) {
51
53
  const serviceProvider = prompt_state_1.PromptState.systemSelection?.connectedSystem?.serviceProvider;
52
- const downloadedAppPackage = await serviceProvider.getUi5AbapRepository().downloadFiles(repoName);
54
+ const ui5AbapRepository = await serviceProvider.getUi5AbapRepository();
55
+ ui5AbapRepository.log = logger_1.default.logger;
56
+ logger_1.default.logger?.debug(`App download started: ${repoName}`);
57
+ const downloadedAppPackage = await ui5AbapRepository.downloadFiles(repoName);
58
+ logger_1.default.logger?.debug(`App download completed: ${repoName}`);
53
59
  // store downloaded package in prompt state
54
60
  prompt_state_1.PromptState.admZip = downloadedAppPackage;
55
61
  }
@@ -75,7 +75,21 @@ async function replaceWebappFiles(projectPath, extractedPath, fs) {
75
75
  const extractedFilePath = (0, path_1.join)(extractedPath, extractedFile);
76
76
  // Check if the extracted file exists before replacing
77
77
  if (fs.exists(extractedFilePath)) {
78
- fs.copy(extractedFilePath, webappFilePath);
78
+ if (extractedFile === project_access_1.FileName.Manifest) {
79
+ // Use datasource and model from the generated manifest
80
+ const extractedManifestJSON = fs.readJSON(extractedFilePath);
81
+ const generatedManifestJSON = fs.readJSON(webappFilePath);
82
+ if (generatedManifestJSON?.['sap.app']?.dataSources && extractedManifestJSON?.['sap.app']) {
83
+ extractedManifestJSON['sap.app'].dataSources = generatedManifestJSON['sap.app'].dataSources;
84
+ }
85
+ if (generatedManifestJSON?.['sap.ui5']?.models && extractedManifestJSON?.['sap.ui5']) {
86
+ extractedManifestJSON['sap.ui5'].models = generatedManifestJSON['sap.ui5']?.models;
87
+ }
88
+ fs.writeJSON(webappFilePath, extractedManifestJSON, undefined, 2);
89
+ }
90
+ else {
91
+ fs.copy(extractedFilePath, webappFilePath);
92
+ }
79
93
  }
80
94
  else {
81
95
  logger_1.default.logger?.warn((0, i18n_1.t)('warn.extractedFileNotFound', { extractedFilePath }));
@@ -133,6 +133,7 @@ async function validateAppSelection(answers, appList, quickDeployedAppConfig, ap
133
133
  return isQfaJsonPresent;
134
134
  }
135
135
  catch (error) {
136
+ logger_1.default.logger?.debug(`validateAppSelection: Error downloading app: ${error.message}`);
136
137
  return (0, i18n_1.t)('error.appDownloadErrors.appDownloadFailure', { error: error.message });
137
138
  }
138
139
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/repo-app-import-sub-generator",
3
3
  "description": "Generator to download LROP Fiori applications deployed from an ABAP repository.",
4
- "version": "0.3.15",
4
+ "version": "0.3.16",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -25,21 +25,22 @@
25
25
  "inquirer": "8.2.6",
26
26
  "yeoman-generator": "5.10.0",
27
27
  "@sap-ux/feature-toggle": "0.3.0",
28
- "@sap-ux/project-access": "1.30.2",
29
28
  "@sap-ux/inquirer-common": "0.7.5",
30
- "@sap-ux/fiori-generator-shared": "0.12.4",
29
+ "@sap-ux/project-access": "1.30.2",
31
30
  "@sap-ux/odata-service-inquirer": "2.4.10",
32
31
  "@sap-ux/logger": "0.7.0",
33
- "@sap-ux/fiori-elements-writer": "2.4.10",
34
32
  "@sap-ux/project-input-validator": "0.6.2",
33
+ "@sap-ux/fiori-elements-writer": "2.4.10",
35
34
  "@sap-ux/launch-config": "0.10.2",
35
+ "@sap-ux/fiori-generator-shared": "0.12.4",
36
36
  "@sap-ux/fiori-tools-settings": "0.2.0",
37
37
  "@sap-ux/abap-deploy-config-writer": "0.1.3",
38
38
  "@sap-ux/btp-utils": "1.1.0",
39
- "@sap-ux/ui5-info": "0.11.0",
40
39
  "@sap-ux/axios-extension": "1.21.1",
41
- "@sap-ux/store": "1.1.0",
42
- "@sap-ux/guided-answers-helper": "0.3.0"
40
+ "@sap-ux/ui5-info": "0.11.0",
41
+ "@sap-ux/system-access": "0.6.1",
42
+ "@sap-ux/guided-answers-helper": "0.3.0",
43
+ "@sap-ux/store": "1.1.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@jest/types": "29.6.3",
@@ -65,8 +66,8 @@
65
66
  "yeoman-test": "6.3.0",
66
67
  "yo": "4",
67
68
  "@sap-ux/nodejs-utils": "0.2.0",
68
- "@sap-ux/store": "1.1.0",
69
- "@sap-ux/ui5-config": "0.28.2"
69
+ "@sap-ux/ui5-config": "0.28.2",
70
+ "@sap-ux/store": "1.1.0"
70
71
  },
71
72
  "engines": {
72
73
  "node": ">=20.x"