@sap-ux/repo-app-import-sub-generator 0.0.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.
Files changed (34) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +16 -0
  3. package/generators/app/app-config.d.ts +25 -0
  4. package/generators/app/app-config.js +122 -0
  5. package/generators/app/index.d.ts +72 -0
  6. package/generators/app/index.js +291 -0
  7. package/generators/app/types.d.ts +136 -0
  8. package/generators/app/types.js +13 -0
  9. package/generators/prompts/prompt-helpers.d.ts +40 -0
  10. package/generators/prompts/prompt-helpers.js +108 -0
  11. package/generators/prompts/prompt-state.d.ts +48 -0
  12. package/generators/prompts/prompt-state.js +65 -0
  13. package/generators/prompts/prompts.d.ts +10 -0
  14. package/generators/prompts/prompts.js +111 -0
  15. package/generators/telemetryEvents/index.d.ts +7 -0
  16. package/generators/telemetryEvents/index.js +11 -0
  17. package/generators/translations/repo-app-import-sub-generator.i18n.json +67 -0
  18. package/generators/utils/constants.d.ts +14 -0
  19. package/generators/utils/constants.js +44 -0
  20. package/generators/utils/download-utils.d.ts +17 -0
  21. package/generators/utils/download-utils.js +48 -0
  22. package/generators/utils/event-hook.d.ts +18 -0
  23. package/generators/utils/event-hook.js +34 -0
  24. package/generators/utils/file-helpers.d.ts +19 -0
  25. package/generators/utils/file-helpers.js +52 -0
  26. package/generators/utils/i18n.d.ts +14 -0
  27. package/generators/utils/i18n.js +34 -0
  28. package/generators/utils/logger.d.ts +33 -0
  29. package/generators/utils/logger.js +41 -0
  30. package/generators/utils/updates.d.ts +23 -0
  31. package/generators/utils/updates.js +90 -0
  32. package/generators/utils/validators.d.ts +17 -0
  33. package/generators/utils/validators.js +94 -0
  34. package/package.json +84 -0
@@ -0,0 +1,291 @@
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.PromptNames = void 0;
7
+ const yeoman_generator_1 = __importDefault(require("yeoman-generator"));
8
+ const logger_1 = __importDefault(require("../utils/logger"));
9
+ const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
10
+ const feature_toggle_1 = require("@sap-ux/feature-toggle");
11
+ const constants_1 = require("../utils/constants");
12
+ const i18n_1 = require("../utils/i18n");
13
+ const download_utils_1 = require("../utils/download-utils");
14
+ const telemetryEvents_1 = require("../telemetryEvents");
15
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
16
+ const prompts_1 = require("../prompts/prompts");
17
+ const fiori_elements_writer_1 = require("@sap-ux/fiori-elements-writer");
18
+ const path_1 = require("path");
19
+ const os_1 = require("os");
20
+ const event_hook_1 = require("../utils/event-hook");
21
+ const ui5_info_1 = require("@sap-ux/ui5-info");
22
+ const launch_config_1 = require("@sap-ux/launch-config");
23
+ const btp_utils_1 = require("@sap-ux/btp-utils");
24
+ const odata_service_inquirer_1 = require("@sap-ux/odata-service-inquirer");
25
+ const fiori_tools_settings_1 = require("@sap-ux/fiori-tools-settings");
26
+ const abap_deploy_config_writer_1 = require("@sap-ux/abap-deploy-config-writer");
27
+ const prompt_state_1 = require("../prompts/prompt-state");
28
+ const types_1 = require("./types");
29
+ Object.defineProperty(exports, "PromptNames", { enumerable: true, get: function () { return types_1.PromptNames; } });
30
+ const app_config_1 = require("./app-config");
31
+ const file_helpers_1 = require("../utils/file-helpers");
32
+ const updates_1 = require("../utils/updates");
33
+ const prompt_helpers_1 = require("../prompts/prompt-helpers");
34
+ const validators_1 = require("../utils/validators");
35
+ const project_access_1 = require("@sap-ux/project-access");
36
+ /**
37
+ * Generator class for downloading a basic app from a repository.
38
+ * This class handles the process of app selection, downloading the app and generating a fiori app from the downloaded app
39
+ */
40
+ class default_1 extends yeoman_generator_1.default {
41
+ appWizard;
42
+ vscode;
43
+ appRootPath;
44
+ prompts;
45
+ answers = constants_1.defaultAnswers;
46
+ options;
47
+ projectPath;
48
+ extractedProjectPath;
49
+ setPromptsCallback;
50
+ /**
51
+ * Constructor for Downloading App.
52
+ *
53
+ * @param args - arguments passed to the generator
54
+ * @param opts - options passed to the generator
55
+ */
56
+ constructor(args, opts) {
57
+ super(args, opts);
58
+ // Initialise properties from options
59
+ this.appWizard = opts.appWizard ?? yeoman_ui_types_1.AppWizard.create(opts);
60
+ this.vscode = opts.vscode;
61
+ this.appRootPath = opts?.appRootPath ?? (0, fiori_generator_shared_1.getDefaultTargetFolder)(this.vscode) ?? this.destinationRoot();
62
+ this.options = opts;
63
+ // Configure logging
64
+ logger_1.default.configureLogging(this.rootGeneratorName(), this.log, this.options.logWrapper, this.options.logLevel, this.options.logger, this.vscode);
65
+ // Initialise prompts and callbacks if not launched as a subgenerator
66
+ this.appWizard.setHeaderTitle(constants_1.generatorTitle);
67
+ this.prompts = new yeoman_ui_types_1.Prompts((0, prompt_helpers_1.getYUIDetails)());
68
+ this.setPromptsCallback = (fn) => {
69
+ if (this.prompts) {
70
+ this.prompts.setCallback(fn);
71
+ }
72
+ };
73
+ }
74
+ /**
75
+ * Initialises necessary settings and telemetry for the generator.
76
+ */
77
+ async initializing() {
78
+ if (this.env.conflicter) {
79
+ this.env.conflicter.force = this.options.force ?? true;
80
+ }
81
+ // Initialise telemetry settings
82
+ await fiori_generator_shared_1.TelemetryHelper.initTelemetrySettings({
83
+ consumerModule: {
84
+ name: constants_1.generatorName,
85
+ version: this.rootGeneratorVersion()
86
+ },
87
+ internalFeature: (0, feature_toggle_1.isInternalFeaturesSettingEnabled)(),
88
+ watchTelemetrySettingStore: false
89
+ });
90
+ }
91
+ /**
92
+ * Prompts the user for application details and downloads the app.
93
+ */
94
+ async prompting() {
95
+ const quickDeployedAppConfig = this.options?.data?.quickDeployedAppConfig;
96
+ const questions = await (0, prompts_1.getPrompts)(this.appRootPath, quickDeployedAppConfig);
97
+ const answers = await this.prompt(questions);
98
+ const { targetFolder } = answers;
99
+ if (quickDeployedAppConfig?.appId) {
100
+ // Handle quick deployed app download where prompts for system selection and app selection are not displayed
101
+ // Only target folder prompt is shown
102
+ this.answers.targetFolder = targetFolder;
103
+ this.answers.systemSelection = prompt_state_1.PromptState.systemSelection;
104
+ this.answers.selectedApp = answers.selectedApp;
105
+ }
106
+ else {
107
+ // Handle app download where prompts for system selection and app selection are shown
108
+ Object.assign(this.answers, answers);
109
+ }
110
+ if ((0, validators_1.isValidPromptState)(this.answers.targetFolder, this.answers.selectedApp.appId)) {
111
+ this.projectPath = (0, path_1.join)(this.answers.targetFolder, this.answers.selectedApp.appId);
112
+ this.extractedProjectPath = (0, path_1.join)(this.projectPath, constants_1.extractedFilePath);
113
+ }
114
+ }
115
+ /**
116
+ * Writes the configuration files for the project, including deployment config, and README.
117
+ */
118
+ async writing() {
119
+ // Extract downloaded app
120
+ const archive = prompt_state_1.PromptState.downloadedAppPackage;
121
+ await (0, download_utils_1.extractZip)(this.extractedProjectPath, archive, this.fs);
122
+ // Check if the qfa.json file
123
+ const qfaJsonFilePath = (0, path_1.join)(this.extractedProjectPath, constants_1.qfaJsonFileName);
124
+ if (this.fs.exists(qfaJsonFilePath)) {
125
+ const qfaJson = (0, file_helpers_1.makeValidJson)(qfaJsonFilePath, this.fs);
126
+ // Generate project files
127
+ (0, validators_1.validateQfaJsonFile)(qfaJson);
128
+ // Generate app config
129
+ const config = await (0, app_config_1.getAppConfig)(this.answers.selectedApp, this.extractedProjectPath, qfaJson, this.fs);
130
+ await (0, fiori_elements_writer_1.generate)(this.projectPath, config, this.fs);
131
+ // Generate deploy config
132
+ const deployConfig = (0, app_config_1.getAbapDeployConfig)(this.answers.selectedApp, qfaJson);
133
+ await (0, abap_deploy_config_writer_1.generate)(this.projectPath, deployConfig, undefined, this.fs);
134
+ if (this.vscode) {
135
+ // Generate Fiori launch config
136
+ const fioriOptions = this._getLaunchConfig(config);
137
+ // Create launch configuration
138
+ await (0, launch_config_1.createLaunchConfig)(this.projectPath, fioriOptions, this.fs, logger_1.default.logger);
139
+ (0, fiori_tools_settings_1.writeApplicationInfoSettings)(this.projectPath);
140
+ }
141
+ // Generate README
142
+ const readMeConfig = this._getReadMeConfig(config);
143
+ (0, fiori_generator_shared_1.generateReadMe)(this.projectPath, readMeConfig, this.fs);
144
+ // Replace webapp files with downloaded app files
145
+ await (0, updates_1.replaceWebappFiles)(this.projectPath, this.extractedProjectPath, this.fs);
146
+ await (0, updates_1.validateAndUpdateManifestUI5Version)((0, path_1.join)(this.projectPath, project_access_1.DirName.Webapp, project_access_1.FileName.Manifest), this.fs);
147
+ // Clean up extracted project files
148
+ this.fs.delete(this.extractedProjectPath);
149
+ }
150
+ else {
151
+ logger_1.default.logger?.error((0, i18n_1.t)('error.qfaJsonNotFound', { jsonFileName: constants_1.qfaJsonFileName }));
152
+ }
153
+ }
154
+ /**
155
+ * Returns the configuration for the README file.
156
+ *
157
+ * @param config - The app configuration object.
158
+ * @returns {ReadMe} The configuration for generating the README.
159
+ */
160
+ _getReadMeConfig(config) {
161
+ const readMeConfig = {
162
+ appName: config.app.id,
163
+ appTitle: config.app.title ?? '',
164
+ appNamespace: config.app.id.substring(0, config.app.id.lastIndexOf('.')),
165
+ appDescription: (0, i18n_1.t)('readMe.appDescription'),
166
+ ui5Theme: (0, ui5_info_1.getDefaultUI5Theme)(config.ui5?.version),
167
+ generatorName: constants_1.generatorName,
168
+ generatorVersion: this.rootGeneratorVersion(),
169
+ ui5Version: config.ui5?.version ?? '',
170
+ template: fiori_elements_writer_1.TemplateType.ListReportObjectPage,
171
+ serviceUrl: config.service.url,
172
+ launchText: (0, i18n_1.t)('readMe.launchText')
173
+ };
174
+ return readMeConfig;
175
+ }
176
+ /**
177
+ * Returns the configuration for launching the app with Fiori options.
178
+ *
179
+ * @param config - The app configuration object.
180
+ * @returns {FioriOptions} The launch configuration options.
181
+ */
182
+ _getLaunchConfig(config) {
183
+ const debugOptions = {
184
+ vscode: this.vscode,
185
+ addStartCmd: true,
186
+ sapClientParam: prompt_state_1.PromptState.sapClient,
187
+ flpAppId: config.app.flpAppId ?? config.app.id,
188
+ flpSandboxAvailable: true,
189
+ isAppStudio: (0, btp_utils_1.isAppStudio)(),
190
+ odataVersion: config.service.version === odata_service_inquirer_1.OdataVersion.v2 ? '2.0' : '4.0'
191
+ };
192
+ const fioriOptions = {
193
+ name: config.app.id,
194
+ projectRoot: this.projectPath,
195
+ /**
196
+ * The `enableVSCodeReload` property is set to `false` to prevent automatic reloading of the VS Code workspace
197
+ * after the app generation process. This is necessary to ensure that the `.vscode/launch-config.json` file is
198
+ * written to disk before the workspace reload occurs. See {@link _handlePostAppGeneration} for details.
199
+ */
200
+ enableVSCodeReload: false,
201
+ debugOptions
202
+ };
203
+ return fioriOptions;
204
+ }
205
+ /**
206
+ * Installs npm dependencies for the project.
207
+ */
208
+ async install() {
209
+ if (!this.options.skipInstall) {
210
+ try {
211
+ await this._runNpmInstall(this.projectPath);
212
+ }
213
+ catch (error) {
214
+ logger_1.default.logger?.error((0, i18n_1.t)('error.installationErrors.npmInstall', { error }));
215
+ }
216
+ }
217
+ else {
218
+ logger_1.default.logger?.info((0, i18n_1.t)('info.installationErrors.skippedInstallation'));
219
+ }
220
+ }
221
+ /**
222
+ * Runs npm install in the specified path.
223
+ *
224
+ * @param path - The path to run npm install.
225
+ */
226
+ async _runNpmInstall(path) {
227
+ const npm = (0, os_1.platform)() === 'win32' ? 'npm.cmd' : 'npm';
228
+ // install dependencies
229
+ await this.spawnCommand(npm, ['install', '--no-audit', '--no-fund', '--silent', '--prefer-offline', '--no-progress'], {
230
+ cwd: path
231
+ });
232
+ }
233
+ /**
234
+ * Responsible for updating workspace folders and running post-generation commands if defined.
235
+ */
236
+ async _handlePostAppGeneration() {
237
+ /**
238
+ * `enableVSCodeReload` is set to false when generating launch config here {@link _getLaunchConfig}.
239
+ * This prevents issues where the `.vscode/launch-config.json` file may not be written to disk due to the timing of mem-fs commits.
240
+ *
241
+ * In Yeoman, a commit occurs between the writing phase and the end phase. If no workspace is open in VS Code and the generated
242
+ * app is added to the workspace, VS Code automatically reloads the window. However, by this point in the end phase, the in-memory file system
243
+ * (mem-fs) has written all files except for `.vscode/launch-config.json`, because the commit happens before the end phase
244
+ * causing it to be missed when the workspace reload occurs.
245
+ *
246
+ * Workflow:
247
+ * 1. **Workspace URI**: The `updateWorkspaceFolders` object is created with the project folder's path, the project name,
248
+ * and the VS Code instance to handle workspace folder updates.
249
+ * 2. **Update Workspace Folders**: The `updateWorkspaceFoldersIfNeeded` function is called to update the workspace folders,
250
+ * if necessary. See {@link updateWorkspaceFoldersIfNeeded} for details.
251
+ * 3. **Run Post-Generation Commands**: If defined, post-generation commands from `options.data?.postGenCommands` are executed
252
+ * using the `runPostAppGenHook` function. This allows for additional setup or configuration tasks to be performed after
253
+ * the app generation process.
254
+ */
255
+ if (this.vscode) {
256
+ const updateWorkspaceFolders = {
257
+ uri: this.vscode?.Uri?.file((0, path_1.join)(this.projectPath)),
258
+ projectName: (0, path_1.basename)(this.projectPath),
259
+ vscode: this.vscode
260
+ };
261
+ (0, launch_config_1.updateWorkspaceFoldersIfNeeded)(updateWorkspaceFolders);
262
+ }
263
+ if (this.options.data?.postGenCommand) {
264
+ await (0, event_hook_1.runPostAppGenHook)({
265
+ path: this.projectPath,
266
+ vscodeInstance: this.vscode,
267
+ postGenCommand: this.options.data?.postGenCommand
268
+ });
269
+ }
270
+ }
271
+ /**
272
+ * Finalises the generator process by creating launch configurations and running post-generation hooks.
273
+ */
274
+ async end() {
275
+ try {
276
+ this.appWizard.showInformation((0, i18n_1.t)('info.repoAppDownloadCompleteMsg'), yeoman_ui_types_1.MessageType.notification);
277
+ await (0, fiori_generator_shared_1.sendTelemetry)(telemetryEvents_1.EventName.GENERATION_SUCCESS, fiori_generator_shared_1.TelemetryHelper.createTelemetryData({
278
+ appType: 'repo-app-import-sub-generator',
279
+ ...this.options.telemetryData
280
+ }) ?? {}).catch((error) => {
281
+ logger_1.default.logger?.error((0, i18n_1.t)('error.telemetry', { error: error.message }));
282
+ });
283
+ await this._handlePostAppGeneration();
284
+ }
285
+ catch (error) {
286
+ logger_1.default.logger?.error((0, i18n_1.t)('error.endPhase', { error: error.message }));
287
+ }
288
+ }
289
+ }
290
+ exports.default = default_1;
291
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,136 @@
1
+ import type Generator from 'yeoman-generator';
2
+ import type { AppWizard } from '@sap-devx/yeoman-ui-types';
3
+ import type { VSCodeInstance, TelemetryData, LogWrapper } from '@sap-ux/fiori-generator-shared';
4
+ import type { Destination } from '@sap-ux/btp-utils';
5
+ import type { BackendSystem } from '@sap-ux/store';
6
+ import type { AbapServiceProvider, AppIndex } from '@sap-ux/axios-extension';
7
+ import type { YUIQuestion } from '@sap-ux/inquirer-common';
8
+ import type { AutocompleteQuestionOptions } from 'inquirer-autocomplete-prompt';
9
+ /**
10
+ * Quick deploy app config are applicable only in scenarios where an application
11
+ * deployed via ADT Quick Deploy is being downloaded from a repository.
12
+ */
13
+ export interface QuickDeployedAppConfig {
14
+ /** application Id to be downloaded. */
15
+ appId: string;
16
+ /** appUrl is the URL pointing to the application */
17
+ appUrl?: string;
18
+ /**
19
+ * Information about the system from which the application is to be downloaded.
20
+ */
21
+ serviceProviderInfo?: {
22
+ /**
23
+ * The base URL of the system providing the application.
24
+ */
25
+ serviceUrl?: string;
26
+ /**
27
+ * The name of the system providing the application.
28
+ */
29
+ name: string;
30
+ };
31
+ }
32
+ /**
33
+ * Options for downloading an application from repository.
34
+ */
35
+ export interface RepoAppDownloadOptions extends Generator.GeneratorOptions {
36
+ /** VSCode instance for interacting with the VSCode environment. */
37
+ vscode?: VSCodeInstance;
38
+ /** The quick deploy config is provided only when an ADT quick deployed app is being downloaded */
39
+ quickDeployedAppConfig?: QuickDeployedAppConfig;
40
+ /** AppWizard instance for managing the application download flow. */
41
+ appWizard?: AppWizard;
42
+ /** Path to the application root where the Fiori launchpad configuration will be added. */
43
+ appRootPath?: string;
44
+ /** Telemetry data for tracking events post deployment configuration. */
45
+ telemetryData?: TelemetryData;
46
+ /** Logger instance for logging operations. */
47
+ logWrapper?: LogWrapper;
48
+ }
49
+ /**
50
+ * Answers related to system selection in the application download process.
51
+ */
52
+ export interface SystemSelectionAnswers {
53
+ /**
54
+ * Details of the connected system allowing downstream consumers to access it without creating new connections.
55
+ */
56
+ connectedSystem?: {
57
+ /** Service provider for the connected ABAP system. */
58
+ serviceProvider: AbapServiceProvider;
59
+ /**
60
+ * Persistable backend system representation of the connected service provider.
61
+ * `newOrUpdated` is true if the system was newly created or updated during connection validation.
62
+ */
63
+ backendSystem?: BackendSystem & {
64
+ newOrUpdated?: boolean;
65
+ };
66
+ /** Destination details of the connected system. */
67
+ destination?: Destination;
68
+ };
69
+ }
70
+ /**
71
+ * Represents a question in the app download process.
72
+ * Extends `YUIQuestion` with optional autocomplete functionality.
73
+ */
74
+ export type RepoAppDownloadQuestions = YUIQuestion<RepoAppDownloadAnswers> & Partial<Pick<AutocompleteQuestionOptions, 'source'>>;
75
+ export type AppItem = AppIndex extends (infer U)[] ? U : never;
76
+ export interface AppInfo {
77
+ appId: string;
78
+ title: string;
79
+ description: string;
80
+ repoName: string;
81
+ url: string;
82
+ }
83
+ /**
84
+ * Enum representing the names of prompts used in the application download process.
85
+ */
86
+ export declare enum PromptNames {
87
+ selectedApp = "selectedApp",
88
+ systemSelection = "systemSelection",
89
+ targetFolder = "targetFolder"
90
+ }
91
+ /**
92
+ * Structure of answers provided by the user for application download prompts.
93
+ */
94
+ export interface RepoAppDownloadAnswers {
95
+ /** Selected backend system connection details. */
96
+ [PromptNames.systemSelection]: SystemSelectionAnswers;
97
+ /** Information about the selected application for download. */
98
+ [PromptNames.selectedApp]: AppInfo;
99
+ /** Target folder where the application will be generated. */
100
+ [PromptNames.targetFolder]: string;
101
+ }
102
+ /**
103
+ * Interface representing the configuration of a QFA JSON file.
104
+ * This QFA JSON file is used for configuring the application download process
105
+ * and contains user inputs.
106
+ */
107
+ export interface QfaJsonConfig {
108
+ metadata: {
109
+ package: string;
110
+ masterLanguage?: string;
111
+ };
112
+ serviceBindingDetails: {
113
+ name?: string;
114
+ serviceName: string;
115
+ serviceVersion: string;
116
+ mainEntityName: string;
117
+ navigationEntity?: string;
118
+ };
119
+ projectAttribute: {
120
+ moduleName: string;
121
+ applicationTitle?: string;
122
+ minimumUi5Version?: string;
123
+ template?: string;
124
+ };
125
+ deploymentDetails: {
126
+ repositoryName: string;
127
+ repositoryDescription?: string;
128
+ };
129
+ fioriLaunchpadConfiguration: {
130
+ semanticObject: string;
131
+ action: string;
132
+ title: string;
133
+ subtitle?: string;
134
+ };
135
+ }
136
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PromptNames = void 0;
4
+ /**
5
+ * Enum representing the names of prompts used in the application download process.
6
+ */
7
+ var PromptNames;
8
+ (function (PromptNames) {
9
+ PromptNames["selectedApp"] = "selectedApp";
10
+ PromptNames["systemSelection"] = "systemSelection";
11
+ PromptNames["targetFolder"] = "targetFolder";
12
+ })(PromptNames || (exports.PromptNames = PromptNames = {}));
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,40 @@
1
+ import type { AbapServiceProvider, AppIndex } from '@sap-ux/axios-extension';
2
+ import type { AppInfo, AppItem } from '../app/types';
3
+ /**
4
+ * Returns the details for the YUI prompt.
5
+ *
6
+ * @returns step details
7
+ */
8
+ export declare function getYUIDetails(): {
9
+ name: string;
10
+ description: string;
11
+ }[];
12
+ /**
13
+ * Returns the prompt details for the selected application.
14
+ *
15
+ * @param {AppItem} app - The application item to extract details from.
16
+ * @returns {{ name: string; value: AppInfo }} The extracted details including name and value.
17
+ */
18
+ export declare const extractAppData: (app: AppItem) => {
19
+ name: string;
20
+ value: AppInfo;
21
+ };
22
+ /**
23
+ * Formats the application list into selectable choices.
24
+ *
25
+ * @param {AppIndex} appList - List of applications retrieved from the system.
26
+ * @returns {Array<{ name: string; value: AppInfo }>} The formatted choices for selection.
27
+ */
28
+ export declare const formatAppChoices: (appList: AppIndex) => Array<{
29
+ name: string;
30
+ value: AppInfo;
31
+ }>;
32
+ /**
33
+ * Fetches the application list for the selected system.
34
+ *
35
+ * @param {AbapServiceProvider} serviceProvider - The ABAP service provider.
36
+ * @param {string} appId - Application ID to be downloaded.
37
+ * @returns {Promise<AppIndex>} A list of applications filtered by source template.
38
+ */
39
+ export declare function fetchAppListForSelectedSystem(serviceProvider: AbapServiceProvider, appId?: string): Promise<AppIndex>;
40
+ //# sourceMappingURL=prompt-helpers.d.ts.map
@@ -0,0 +1,108 @@
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.fetchAppListForSelectedSystem = exports.formatAppChoices = exports.extractAppData = exports.getYUIDetails = void 0;
7
+ const constants_1 = require("../utils/constants");
8
+ const prompt_state_1 = require("./prompt-state");
9
+ const i18n_1 = require("../utils/i18n");
10
+ const logger_1 = __importDefault(require("../utils/logger"));
11
+ /**
12
+ * Returns the details for the YUI prompt.
13
+ *
14
+ * @returns step details
15
+ */
16
+ function getYUIDetails() {
17
+ return [
18
+ {
19
+ name: constants_1.generatorTitle,
20
+ description: constants_1.generatorDescription
21
+ }
22
+ ];
23
+ }
24
+ exports.getYUIDetails = getYUIDetails;
25
+ /**
26
+ * Returns the prompt details for the selected application.
27
+ *
28
+ * @param {AppItem} app - The application item to extract details from.
29
+ * @returns {{ name: string; value: AppInfo }} The extracted details including name and value.
30
+ */
31
+ const extractAppData = (app) => {
32
+ // cast to string because TypeScript doesn't automatically know at the point that these fields are defined
33
+ // after filtering out invalid apps.
34
+ const id = app['sap.app/id'];
35
+ const title = app['sap.app/title'];
36
+ const description = (app['sap.app/description'] ?? '');
37
+ const repoName = app.repoName;
38
+ const url = app.url;
39
+ return {
40
+ name: id,
41
+ value: {
42
+ appId: id,
43
+ title,
44
+ description,
45
+ repoName,
46
+ url
47
+ }
48
+ };
49
+ };
50
+ exports.extractAppData = extractAppData;
51
+ /**
52
+ * Formats the application list into selectable choices.
53
+ *
54
+ * @param {AppIndex} appList - List of applications retrieved from the system.
55
+ * @returns {Array<{ name: string; value: AppInfo }>} The formatted choices for selection.
56
+ */
57
+ const formatAppChoices = (appList) => {
58
+ return appList
59
+ .filter((app) => {
60
+ const hasRequiredFields = app['sap.app/id'] && app['sap.app/title'] && app['repoName'] && app['url'];
61
+ if (!hasRequiredFields) {
62
+ logger_1.default.logger?.error((0, i18n_1.t)('error.requiredFieldsMissing', { app: JSON.stringify(app) }));
63
+ }
64
+ return hasRequiredFields;
65
+ })
66
+ .map((app) => (0, exports.extractAppData)(app));
67
+ };
68
+ exports.formatAppChoices = formatAppChoices;
69
+ /**
70
+ * Fetches a list of deployed applications from the ABAP repository.
71
+ *
72
+ * @param {AbapServiceProvider} provider - The ABAP service provider.
73
+ * @param {string} appId - Application ID to filter the list.
74
+ * @returns {Promise<AppIndex>} A list of applications filtered by source template.
75
+ */
76
+ async function getAppList(provider, appId) {
77
+ try {
78
+ const searchParams = appId
79
+ ? {
80
+ ...constants_1.appListSearchParams,
81
+ 'sap.app/id': appId
82
+ }
83
+ : constants_1.appListSearchParams;
84
+ return await provider.getAppIndex().search(searchParams, constants_1.appListResultFields);
85
+ }
86
+ catch (error) {
87
+ logger_1.default.logger?.error((0, i18n_1.t)('error.applicationListFetchError', { error: error.message }));
88
+ return [];
89
+ }
90
+ }
91
+ /**
92
+ * Fetches the application list for the selected system.
93
+ *
94
+ * @param {AbapServiceProvider} serviceProvider - The ABAP service provider.
95
+ * @param {string} appId - Application ID to be downloaded.
96
+ * @returns {Promise<AppIndex>} A list of applications filtered by source template.
97
+ */
98
+ async function fetchAppListForSelectedSystem(serviceProvider, appId) {
99
+ if (serviceProvider) {
100
+ prompt_state_1.PromptState.systemSelection = {
101
+ connectedSystem: { serviceProvider }
102
+ };
103
+ return await getAppList(serviceProvider, appId);
104
+ }
105
+ return [];
106
+ }
107
+ exports.fetchAppListForSelectedSystem = fetchAppListForSelectedSystem;
108
+ //# sourceMappingURL=prompt-helpers.js.map
@@ -0,0 +1,48 @@
1
+ /// <reference types="node" />
2
+ import type { SystemSelectionAnswers } from '../app/types';
3
+ /**
4
+ * Much of the values returned by the app downloader prompting are derived from prompt answers and are not direct answer values.
5
+ * Since inquirer does not provide a way to return values that are not direct answers from prompts, this class will maintain the derived values
6
+ * across prompts statically for the lifespan of the prompting session.
7
+ *
8
+ */
9
+ export declare class PromptState {
10
+ private static _systemSelection;
11
+ private static _downloadedAppPackage?;
12
+ /**
13
+ * Returns the current state of the service config.
14
+ *
15
+ * @returns {SystemSelectionAnswers} service config
16
+ */
17
+ static get systemSelection(): SystemSelectionAnswers;
18
+ /**
19
+ * Set the state of the system selection.
20
+ *
21
+ * @param {SystemSelectionAnswers} value - system selection value
22
+ */
23
+ static set systemSelection(value: Partial<SystemSelectionAnswers>);
24
+ /**
25
+ * Set the downloaded app package.
26
+ */
27
+ static set downloadedAppPackage(archive: Buffer);
28
+ /**
29
+ * Returns the downloaded app package.
30
+ *
31
+ * @returns {Buffer} downloaded app package
32
+ */
33
+ static get downloadedAppPackage(): Buffer;
34
+ /**
35
+ * Get the baseURL from the connected system's service provider defaults.
36
+ *
37
+ * @returns {string | undefined} baseURL
38
+ */
39
+ static get baseURL(): string | undefined;
40
+ /**
41
+ * Get the sap-client parameter from the connected system's service provider defaults.
42
+ *
43
+ * @returns {string | undefined} sap-client
44
+ */
45
+ static get sapClient(): string | undefined;
46
+ static reset(): void;
47
+ }
48
+ //# sourceMappingURL=prompt-state.d.ts.map