@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.
- package/LICENSE +201 -0
- package/README.md +16 -0
- package/generators/app/app-config.d.ts +25 -0
- package/generators/app/app-config.js +122 -0
- package/generators/app/index.d.ts +72 -0
- package/generators/app/index.js +291 -0
- package/generators/app/types.d.ts +136 -0
- package/generators/app/types.js +13 -0
- package/generators/prompts/prompt-helpers.d.ts +40 -0
- package/generators/prompts/prompt-helpers.js +108 -0
- package/generators/prompts/prompt-state.d.ts +48 -0
- package/generators/prompts/prompt-state.js +65 -0
- package/generators/prompts/prompts.d.ts +10 -0
- package/generators/prompts/prompts.js +111 -0
- package/generators/telemetryEvents/index.d.ts +7 -0
- package/generators/telemetryEvents/index.js +11 -0
- package/generators/translations/repo-app-import-sub-generator.i18n.json +67 -0
- package/generators/utils/constants.d.ts +14 -0
- package/generators/utils/constants.js +44 -0
- package/generators/utils/download-utils.d.ts +17 -0
- package/generators/utils/download-utils.js +48 -0
- package/generators/utils/event-hook.d.ts +18 -0
- package/generators/utils/event-hook.js +34 -0
- package/generators/utils/file-helpers.d.ts +19 -0
- package/generators/utils/file-helpers.js +52 -0
- package/generators/utils/i18n.d.ts +14 -0
- package/generators/utils/i18n.js +34 -0
- package/generators/utils/logger.d.ts +33 -0
- package/generators/utils/logger.js +41 -0
- package/generators/utils/updates.d.ts +23 -0
- package/generators/utils/updates.js +90 -0
- package/generators/utils/validators.d.ts +17 -0
- package/generators/utils/validators.js +94 -0
- package/package.json +84 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PromptState = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Much of the values returned by the app downloader prompting are derived from prompt answers and are not direct answer values.
|
|
6
|
+
* Since inquirer does not provide a way to return values that are not direct answers from prompts, this class will maintain the derived values
|
|
7
|
+
* across prompts statically for the lifespan of the prompting session.
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
class PromptState {
|
|
11
|
+
static _systemSelection = {};
|
|
12
|
+
static _downloadedAppPackage;
|
|
13
|
+
/**
|
|
14
|
+
* Returns the current state of the service config.
|
|
15
|
+
*
|
|
16
|
+
* @returns {SystemSelectionAnswers} service config
|
|
17
|
+
*/
|
|
18
|
+
static get systemSelection() {
|
|
19
|
+
return this._systemSelection;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Set the state of the system selection.
|
|
23
|
+
*
|
|
24
|
+
* @param {SystemSelectionAnswers} value - system selection value
|
|
25
|
+
*/
|
|
26
|
+
static set systemSelection(value) {
|
|
27
|
+
this._systemSelection = value;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set the downloaded app package.
|
|
31
|
+
*/
|
|
32
|
+
static set downloadedAppPackage(archive) {
|
|
33
|
+
this._downloadedAppPackage = archive;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns the downloaded app package.
|
|
37
|
+
*
|
|
38
|
+
* @returns {Buffer} downloaded app package
|
|
39
|
+
*/
|
|
40
|
+
static get downloadedAppPackage() {
|
|
41
|
+
return this._downloadedAppPackage ?? Buffer.alloc(0);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the baseURL from the connected system's service provider defaults.
|
|
45
|
+
*
|
|
46
|
+
* @returns {string | undefined} baseURL
|
|
47
|
+
*/
|
|
48
|
+
static get baseURL() {
|
|
49
|
+
return this._systemSelection.connectedSystem?.serviceProvider?.defaults?.baseURL;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the sap-client parameter from the connected system's service provider defaults.
|
|
53
|
+
*
|
|
54
|
+
* @returns {string | undefined} sap-client
|
|
55
|
+
*/
|
|
56
|
+
static get sapClient() {
|
|
57
|
+
return this._systemSelection.connectedSystem?.serviceProvider?.defaults?.params?.['sap-client'];
|
|
58
|
+
}
|
|
59
|
+
static reset() {
|
|
60
|
+
PromptState.systemSelection = {};
|
|
61
|
+
PromptState._downloadedAppPackage = undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.PromptState = PromptState;
|
|
65
|
+
//# sourceMappingURL=prompt-state.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RepoAppDownloadQuestions, QuickDeployedAppConfig } from '../app/types';
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves prompts for selecting a system, app list, and target folder where the app will be generated.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} [appRootPath] - The root path of the application.
|
|
6
|
+
* @param {QuickDeployedAppConfig} [quickDeployedAppConfig] - The quick deployed app configuration.
|
|
7
|
+
* @returns {Promise<RepoAppDownloadQuestions[]>} A list of prompts for user interaction.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getPrompts(appRootPath?: string, quickDeployedAppConfig?: QuickDeployedAppConfig): Promise<RepoAppDownloadQuestions[]>;
|
|
10
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPrompts = void 0;
|
|
4
|
+
const odata_service_inquirer_1 = require("@sap-ux/odata-service-inquirer");
|
|
5
|
+
const types_1 = require("../app/types");
|
|
6
|
+
const i18n_1 = require("../utils/i18n");
|
|
7
|
+
const project_input_validator_1 = require("@sap-ux/project-input-validator");
|
|
8
|
+
const prompt_state_1 = require("./prompt-state");
|
|
9
|
+
const prompt_helpers_1 = require("./prompt-helpers");
|
|
10
|
+
const download_utils_1 = require("../utils/download-utils");
|
|
11
|
+
/**
|
|
12
|
+
* Gets the target folder selection prompt.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} [appRootPath] - The application root path.
|
|
15
|
+
* @param {string} appId - The application ID.
|
|
16
|
+
* @returns {FileBrowserQuestion<RepoAppDownloadAnswers>} The target folder prompt configuration.
|
|
17
|
+
*/
|
|
18
|
+
const getTargetFolderPrompt = (appRootPath, appId) => {
|
|
19
|
+
return {
|
|
20
|
+
type: 'input',
|
|
21
|
+
name: types_1.PromptNames.targetFolder,
|
|
22
|
+
message: (0, i18n_1.t)('prompts.targetPath.message'),
|
|
23
|
+
guiType: 'folder-browser',
|
|
24
|
+
when: (answers) => {
|
|
25
|
+
// Display the prompt if appId is provided. This occurs when the generator is invoked
|
|
26
|
+
// as part of the quick deployment process from ADT.
|
|
27
|
+
if (appId) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
// If appId is not provided, check if the user has selected an app.
|
|
31
|
+
// If an app is selected, display the prompt accordingly.
|
|
32
|
+
return Boolean(answers?.selectedApp?.appId);
|
|
33
|
+
},
|
|
34
|
+
guiOptions: {
|
|
35
|
+
applyDefaultWhenDirty: true,
|
|
36
|
+
mandatory: true,
|
|
37
|
+
breadcrumb: (0, i18n_1.t)('prompts.targetPath.breadcrumb')
|
|
38
|
+
},
|
|
39
|
+
validate: async (target, answers) => {
|
|
40
|
+
const selectedAppId = answers.selectedApp?.appId ?? appId;
|
|
41
|
+
return await (0, project_input_validator_1.validateFioriAppTargetFolder)(target, selectedAppId, true);
|
|
42
|
+
},
|
|
43
|
+
default: () => appRootPath
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Retrieves prompts for selecting a system, app list, and target folder where the app will be generated.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} [appRootPath] - The root path of the application.
|
|
50
|
+
* @param {QuickDeployedAppConfig} [quickDeployedAppConfig] - The quick deployed app configuration.
|
|
51
|
+
* @returns {Promise<RepoAppDownloadQuestions[]>} A list of prompts for user interaction.
|
|
52
|
+
*/
|
|
53
|
+
async function getPrompts(appRootPath, quickDeployedAppConfig) {
|
|
54
|
+
try {
|
|
55
|
+
prompt_state_1.PromptState.reset();
|
|
56
|
+
const systemQuestions = await (0, odata_service_inquirer_1.getSystemSelectionQuestions)({
|
|
57
|
+
serviceSelection: { hide: true },
|
|
58
|
+
systemSelection: { defaultChoice: quickDeployedAppConfig?.serviceProviderInfo?.name }
|
|
59
|
+
}, false);
|
|
60
|
+
let appList = [];
|
|
61
|
+
const appSelectionPrompt = [
|
|
62
|
+
{
|
|
63
|
+
when: async (answers) => {
|
|
64
|
+
if (answers[types_1.PromptNames.systemSelection]) {
|
|
65
|
+
appList = await (0, prompt_helpers_1.fetchAppListForSelectedSystem)(systemQuestions.answers.connectedSystem?.serviceProvider, quickDeployedAppConfig?.appId);
|
|
66
|
+
}
|
|
67
|
+
return !!systemQuestions.answers.connectedSystem?.serviceProvider;
|
|
68
|
+
},
|
|
69
|
+
type: 'list',
|
|
70
|
+
name: types_1.PromptNames.selectedApp,
|
|
71
|
+
default: () => (quickDeployedAppConfig?.appId ? 0 : undefined),
|
|
72
|
+
guiOptions: {
|
|
73
|
+
mandatory: !!appList.length,
|
|
74
|
+
breadcrumb: (0, i18n_1.t)('prompts.appSelection.breadcrumb')
|
|
75
|
+
},
|
|
76
|
+
message: (0, i18n_1.t)('prompts.appSelection.message'),
|
|
77
|
+
choices: () => (appList.length ? (0, prompt_helpers_1.formatAppChoices)(appList) : []),
|
|
78
|
+
validate: async (answers) => {
|
|
79
|
+
// Quick deploy config exists but no apps found
|
|
80
|
+
if (quickDeployedAppConfig?.appId && appList.length === 0) {
|
|
81
|
+
return (0, i18n_1.t)('error.quickDeployedAppDownloadErrors.noAppsFound', {
|
|
82
|
+
appId: quickDeployedAppConfig.appId
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// No apps available at all
|
|
86
|
+
if (appList.length === 0) {
|
|
87
|
+
return (0, i18n_1.t)('prompts.appSelection.noAppsDeployed');
|
|
88
|
+
}
|
|
89
|
+
// Valid app selected, try to download
|
|
90
|
+
if (answers?.appId) {
|
|
91
|
+
try {
|
|
92
|
+
await (0, download_utils_1.downloadApp)(answers.repoName);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
return (0, i18n_1.t)('error.appDownloadErrors.appDownloadFailure', { error: error.message });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
];
|
|
103
|
+
const targetFolderPrompts = getTargetFolderPrompt(appRootPath, quickDeployedAppConfig?.appId);
|
|
104
|
+
return [...systemQuestions.prompts, ...appSelectionPrompt, targetFolderPrompts];
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`Failed to generate prompts: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.getPrompts = getPrompts;
|
|
111
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventName = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Event names for telemetry for the generator when downloading an app from repository
|
|
6
|
+
*/
|
|
7
|
+
var EventName;
|
|
8
|
+
(function (EventName) {
|
|
9
|
+
EventName["GENERATION_SUCCESS"] = "GENERATION_SUCCESS";
|
|
10
|
+
})(EventName || (exports.EventName = EventName = {}));
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"error": {
|
|
3
|
+
"telemetry": "Failed to send telemetry data after downloading app from UI5 ABAP Repository. {{- error}}",
|
|
4
|
+
"qfaJsonNotFound": "{{- jsonFileName }} not found in the downloaded app",
|
|
5
|
+
"replaceWebappFilesError": "Error replacing files in the downloaded app: {{- error}}",
|
|
6
|
+
"requiredFieldsMissing": "Required fields are missing for app: {{- app }}. Check if the app is deployed correctly",
|
|
7
|
+
"applicationListFetchError": "Error fetching application list: {{- error}}",
|
|
8
|
+
"metadataFetchError": "Error fetching metadata: {{- error}}",
|
|
9
|
+
"appConfigGenError": "Error generating application configuration: {{- error}}",
|
|
10
|
+
"endPhase": "Error in end phase: {{- error}}",
|
|
11
|
+
"errorProcessingJsonFile": "Error processing JSON file: {{- error}}",
|
|
12
|
+
"validationErrors": {
|
|
13
|
+
"invalidMetadataPackage": "Invalid or missing package in metadata",
|
|
14
|
+
"invalidServiceName": "Invalid or missing serviceName in serviceBindingDetails",
|
|
15
|
+
"invalidServiceVersion": "Invalid or missing serviceVersion in serviceBindingDetails",
|
|
16
|
+
"invalidMainEntityName": "Invalid or missing mainEntityName in serviceBindingDetails",
|
|
17
|
+
"invalidModuleName": "Invalid or missing moduleName in serviceBindingDetails",
|
|
18
|
+
"invalidRepositoryName": "Invalid or missing repositoryName in serviceBindingDetails"
|
|
19
|
+
},
|
|
20
|
+
"installationErrors": {
|
|
21
|
+
"npmInstall": "Error in install phase: {{- error}}",
|
|
22
|
+
"skippedInstallation": "Option `--skipInstall` was specified. Installation of dependencies will be skipped."
|
|
23
|
+
},
|
|
24
|
+
"appDownloadErrors": {
|
|
25
|
+
"downloadedFileNotBufferError": "Error: The downloaded file is not a Buffer.",
|
|
26
|
+
"appDownloadFailure": "Error downloading app: {{- error}}",
|
|
27
|
+
"zipExtractionError": "Error extracting zip: {{- error}}"
|
|
28
|
+
},
|
|
29
|
+
"eventHookErrors": {
|
|
30
|
+
"vscodeInstanceMissing": "Error: Missing VSCode instance in event hook",
|
|
31
|
+
"postGenCommandMissing": "Error: Missing postGenCommand in event hook",
|
|
32
|
+
"commandExecutionFailed": "Error executing postGenCommand in event hook: {{- error}}"
|
|
33
|
+
},
|
|
34
|
+
"readManifestErrors": {
|
|
35
|
+
"manifestFileNotFound": "Error: Manifest file not found in the downloaded app",
|
|
36
|
+
"readManifestFailed": "Error: Failed to read manifest file",
|
|
37
|
+
"sapAppNotDefined": "Error: sap.app not defined in the manifest file",
|
|
38
|
+
"sourceTemplateNotSupported": "Error: Source template not supported",
|
|
39
|
+
"invalidManifestStructureError": "Invalid manifest structure: 'sap.ui5' or 'sap.app' are missing."
|
|
40
|
+
},
|
|
41
|
+
"quickDeployedAppDownloadErrors": {
|
|
42
|
+
"noAppsFound": "No application with id {{ appId }} found in the system. Please check if the application is deployed correctly or select another app"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"warn": {
|
|
46
|
+
"extractedFileNotFound": "Extracted file not found - {{- extractedFilePath}}"
|
|
47
|
+
},
|
|
48
|
+
"prompts": {
|
|
49
|
+
"appSelection": {
|
|
50
|
+
"message": "App",
|
|
51
|
+
"hint": "Select the app to download",
|
|
52
|
+
"breadcrumb": "App",
|
|
53
|
+
"noAppsDeployed": "No applications deployed to this system can be downloaded. {{- help}}"
|
|
54
|
+
},
|
|
55
|
+
"targetPath": {
|
|
56
|
+
"message": "Project folder path",
|
|
57
|
+
"breadcrumb": "Project Path"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"readMe": {
|
|
61
|
+
"appDescription": "This application was converted from a SAP Fiori app that was deployed from ADT using the ADT Quick Fiori Application generator",
|
|
62
|
+
"launchText": "In order to launch the generated app, simply run the following from the generated app root folder:\n\n```\n npm start\n```"
|
|
63
|
+
},
|
|
64
|
+
"info": {
|
|
65
|
+
"repoAppDownloadCompleteMsg": "The selected application has been downloaded and updated to support SAP Fiori tools."
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type RepoAppDownloadAnswers } from '../app/types';
|
|
2
|
+
export declare const generatorTitle = "Download ADT deployed app from UI5 ABAP repository";
|
|
3
|
+
export declare const generatorDescription = "Download an application that was generated with the ADT Quick Fiori Application generator";
|
|
4
|
+
export declare const generatorName = "@sap-ux/repo-app-import-sub-generator";
|
|
5
|
+
export declare const adtSourceTemplateId = "@sap.adt.sevicebinding.deploy:lrop";
|
|
6
|
+
export declare const fioriAppSourcetemplateId = "@sap/generator-fiori:lrop";
|
|
7
|
+
export declare const qfaJsonFileName = "qfa.json";
|
|
8
|
+
export declare const defaultAnswers: RepoAppDownloadAnswers;
|
|
9
|
+
export declare const extractedFilePath = "extractedFiles";
|
|
10
|
+
export declare const appListSearchParams: {
|
|
11
|
+
'sap.app/sourceTemplate/id': string;
|
|
12
|
+
};
|
|
13
|
+
export declare const appListResultFields: string[];
|
|
14
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appListResultFields = exports.appListSearchParams = exports.extractedFilePath = exports.defaultAnswers = exports.qfaJsonFileName = exports.fioriAppSourcetemplateId = exports.adtSourceTemplateId = exports.generatorName = exports.generatorDescription = exports.generatorTitle = void 0;
|
|
4
|
+
const types_1 = require("../app/types");
|
|
5
|
+
// Title and description for the generator
|
|
6
|
+
exports.generatorTitle = 'Download ADT deployed app from UI5 ABAP repository';
|
|
7
|
+
exports.generatorDescription = 'Download an application that was generated with the ADT Quick Fiori Application generator';
|
|
8
|
+
// Name of the generator used for Fiori app download
|
|
9
|
+
exports.generatorName = '@sap-ux/repo-app-import-sub-generator';
|
|
10
|
+
// The source template ID used for filtering the apps in the repository
|
|
11
|
+
exports.adtSourceTemplateId = '@sap.adt.sevicebinding.deploy:lrop';
|
|
12
|
+
// The source template ID used for Fiori app generation
|
|
13
|
+
exports.fioriAppSourcetemplateId = '@sap/generator-fiori:lrop';
|
|
14
|
+
// The name of the QFA JSON file provided with the downloaded app, containing all user inputs.
|
|
15
|
+
exports.qfaJsonFileName = 'qfa.json';
|
|
16
|
+
// Default initial answers to use as a fallback.
|
|
17
|
+
exports.defaultAnswers = {
|
|
18
|
+
[types_1.PromptNames.systemSelection]: {},
|
|
19
|
+
[types_1.PromptNames.selectedApp]: {
|
|
20
|
+
appId: '',
|
|
21
|
+
title: '',
|
|
22
|
+
description: '',
|
|
23
|
+
repoName: '',
|
|
24
|
+
url: ''
|
|
25
|
+
},
|
|
26
|
+
[types_1.PromptNames.targetFolder]: ''
|
|
27
|
+
};
|
|
28
|
+
// Path for storing the extracted files from repository
|
|
29
|
+
exports.extractedFilePath = 'extractedFiles';
|
|
30
|
+
// Search parameters to filter applications by the source template ID
|
|
31
|
+
exports.appListSearchParams = {
|
|
32
|
+
'sap.app/sourceTemplate/id': exports.adtSourceTemplateId
|
|
33
|
+
};
|
|
34
|
+
// Fields to retrieve from the app list, useful for displaying app metadata
|
|
35
|
+
exports.appListResultFields = [
|
|
36
|
+
'sap.app/id', // ID of the application
|
|
37
|
+
'sap.app/title', // Title of the application
|
|
38
|
+
'sap.app/description', // Description of the application
|
|
39
|
+
'sap.app/sourceTemplate/id', // ID of the source template
|
|
40
|
+
'repoName', // Repository name where the app is located
|
|
41
|
+
'fileType', // Type of file (.zip etc)
|
|
42
|
+
'url' // URL for accessing the app
|
|
43
|
+
];
|
|
44
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { Editor } from 'mem-fs-editor';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts a ZIP archive to a temporary directory.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} extractedProjectPath - The path where the archive should be extracted.
|
|
7
|
+
* @param {Buffer} archive - The ZIP archive buffer.
|
|
8
|
+
* @param {Editor} fs - The file system editor.
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractZip(extractedProjectPath: string, archive: Buffer, fs: Editor): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Downloads application files from the ABAP repository.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} repoName - The repository name of the application.
|
|
15
|
+
*/
|
|
16
|
+
export declare function downloadApp(repoName: string): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=download-utils.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
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.downloadApp = exports.extractZip = void 0;
|
|
7
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const prompt_state_1 = require("../prompts/prompt-state");
|
|
10
|
+
const i18n_1 = require("./i18n");
|
|
11
|
+
const logger_1 = __importDefault(require("../utils/logger"));
|
|
12
|
+
/**
|
|
13
|
+
* Extracts a ZIP archive to a temporary directory.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} extractedProjectPath - The path where the archive should be extracted.
|
|
16
|
+
* @param {Buffer} archive - The ZIP archive buffer.
|
|
17
|
+
* @param {Editor} fs - The file system editor.
|
|
18
|
+
*/
|
|
19
|
+
async function extractZip(extractedProjectPath, archive, fs) {
|
|
20
|
+
try {
|
|
21
|
+
const zip = new adm_zip_1.default(archive);
|
|
22
|
+
zip.getEntries().forEach(function (zipEntry) {
|
|
23
|
+
if (!zipEntry.isDirectory) {
|
|
24
|
+
// Extract the file content
|
|
25
|
+
const fileContent = zipEntry.getData().toString('utf8');
|
|
26
|
+
// Load the file content into mem-fs for use in the temporary extracted project directory
|
|
27
|
+
fs.write((0, path_1.join)(extractedProjectPath, zipEntry.entryName), fileContent);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.appDownloadErrors.zipExtractionError', { error: error.message }));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.extractZip = extractZip;
|
|
36
|
+
/**
|
|
37
|
+
* Downloads application files from the ABAP repository.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} repoName - The repository name of the application.
|
|
40
|
+
*/
|
|
41
|
+
async function downloadApp(repoName) {
|
|
42
|
+
const serviceProvider = prompt_state_1.PromptState.systemSelection?.connectedSystem?.serviceProvider;
|
|
43
|
+
const downloadedAppPackage = await serviceProvider.getUi5AbapRepository().downloadFiles(repoName);
|
|
44
|
+
// store downloaded package in prompt state
|
|
45
|
+
prompt_state_1.PromptState.downloadedAppPackage = downloadedAppPackage;
|
|
46
|
+
}
|
|
47
|
+
exports.downloadApp = downloadApp;
|
|
48
|
+
//# sourceMappingURL=download-utils.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { VSCodeInstance } from '@sap-ux/fiori-generator-shared';
|
|
2
|
+
/**
|
|
3
|
+
* Context object for the App generation process.
|
|
4
|
+
* Contains the path of the project and the post-generation command.
|
|
5
|
+
*/
|
|
6
|
+
export interface RepoAppGenContext {
|
|
7
|
+
path: string;
|
|
8
|
+
postGenCommand: string;
|
|
9
|
+
vscodeInstance?: VSCodeInstance;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Executes the post-generation command for the app.
|
|
13
|
+
* Runs the specified command in the context of the generated project, typically for tasks like refreshing or reloading the project in the editor.
|
|
14
|
+
*
|
|
15
|
+
* @param {RepoAppGenContext} context - The context containing the project path, post-generation command, and optional VSCode instance.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runPostAppGenHook(context: RepoAppGenContext): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=event-hook.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
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.runPostAppGenHook = void 0;
|
|
7
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
8
|
+
const i18n_1 = require("./i18n");
|
|
9
|
+
/**
|
|
10
|
+
* Executes the post-generation command for the app.
|
|
11
|
+
* Runs the specified command in the context of the generated project, typically for tasks like refreshing or reloading the project in the editor.
|
|
12
|
+
*
|
|
13
|
+
* @param {RepoAppGenContext} context - The context containing the project path, post-generation command, and optional VSCode instance.
|
|
14
|
+
*/
|
|
15
|
+
async function runPostAppGenHook(context) {
|
|
16
|
+
try {
|
|
17
|
+
// Ensure that context has necessary values before proceeding
|
|
18
|
+
if (!context.vscodeInstance) {
|
|
19
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.eventHookErrors.vscodeInstanceMissing'));
|
|
20
|
+
}
|
|
21
|
+
if (!context.postGenCommand || context.postGenCommand.trim() === '') {
|
|
22
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.eventHookErrors.postGenCommandMissing'));
|
|
23
|
+
}
|
|
24
|
+
// Execute the post-generation command
|
|
25
|
+
await context.vscodeInstance?.commands?.executeCommand?.(context.postGenCommand, {
|
|
26
|
+
fsPath: context.path
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.eventHookErrors.commandExecutionFailed', e.message));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.runPostAppGenHook = runPostAppGenHook;
|
|
34
|
+
//# sourceMappingURL=event-hook.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Editor } from 'mem-fs-editor';
|
|
2
|
+
import { type Manifest } from '@sap-ux/project-access';
|
|
3
|
+
import type { QfaJsonConfig } from '../app/types';
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param filePath - Path to the JSON file
|
|
7
|
+
* @param fs - File system editor instance
|
|
8
|
+
* @returns - Parsed JSON object
|
|
9
|
+
*/
|
|
10
|
+
export declare function makeValidJson(filePath: string, fs: Editor): QfaJsonConfig;
|
|
11
|
+
/**
|
|
12
|
+
* Reads and validates the `manifest.json` file.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} manifesFilePath - Manifest file path.
|
|
15
|
+
* @param {Editor} fs - The file system editor.
|
|
16
|
+
* @returns {Manifest} The validated manifest object.
|
|
17
|
+
*/
|
|
18
|
+
export declare function readManifest(manifesFilePath: string, fs: Editor): Manifest;
|
|
19
|
+
//# sourceMappingURL=file-helpers.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
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.readManifest = exports.makeValidJson = void 0;
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
const i18n_1 = require("./i18n");
|
|
9
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param filePath - Path to the JSON file
|
|
13
|
+
* @param fs - File system editor instance
|
|
14
|
+
* @returns - Parsed JSON object
|
|
15
|
+
*/
|
|
16
|
+
function makeValidJson(filePath, fs) {
|
|
17
|
+
try {
|
|
18
|
+
// Read the file contents
|
|
19
|
+
const fileContents = fs.read(filePath);
|
|
20
|
+
const validJson = JSON.parse(fileContents);
|
|
21
|
+
return validJson;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new Error((0, i18n_1.t)('error.errorProcessingJsonFile', { error }));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.makeValidJson = makeValidJson;
|
|
28
|
+
/**
|
|
29
|
+
* Reads and validates the `manifest.json` file.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} manifesFilePath - Manifest file path.
|
|
32
|
+
* @param {Editor} fs - The file system editor.
|
|
33
|
+
* @returns {Manifest} The validated manifest object.
|
|
34
|
+
*/
|
|
35
|
+
function readManifest(manifesFilePath, fs) {
|
|
36
|
+
if (!fs.exists(manifesFilePath)) {
|
|
37
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.readManifestErrors.manifestFileNotFound'));
|
|
38
|
+
}
|
|
39
|
+
const manifest = fs.readJSON(manifesFilePath);
|
|
40
|
+
if (!manifest) {
|
|
41
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.readManifestErrors.readManifestFailed'));
|
|
42
|
+
}
|
|
43
|
+
if (!manifest?.['sap.app']) {
|
|
44
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.readManifestErrors.sapAppNotDefined'));
|
|
45
|
+
}
|
|
46
|
+
if (manifest?.['sap.app']?.sourceTemplate?.id !== constants_1.adtSourceTemplateId) {
|
|
47
|
+
logger_1.default.logger?.error((0, i18n_1.t)('error.readManifestErrors.sourceTemplateNotSupported'));
|
|
48
|
+
}
|
|
49
|
+
return manifest;
|
|
50
|
+
}
|
|
51
|
+
exports.readManifest = readManifest;
|
|
52
|
+
//# sourceMappingURL=file-helpers.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TOptions } from 'i18next';
|
|
2
|
+
/**
|
|
3
|
+
* Initialize i18next with the translations for this module.
|
|
4
|
+
*/
|
|
5
|
+
export declare function initI18n(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Helper function facading the call to i18next. Unless a namespace option is provided the local namespace will be used.
|
|
8
|
+
*
|
|
9
|
+
* @param key i18n key
|
|
10
|
+
* @param options additional options
|
|
11
|
+
* @returns {string} localized string stored for the given key
|
|
12
|
+
*/
|
|
13
|
+
export declare function t(key: string, options?: TOptions): string;
|
|
14
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
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.t = exports.initI18n = void 0;
|
|
7
|
+
const i18next_1 = __importDefault(require("i18next"));
|
|
8
|
+
const repo_app_import_sub_generator_i18n_json_1 = __importDefault(require("../translations/repo-app-import-sub-generator.i18n.json"));
|
|
9
|
+
const repoAppDownloadGeneratorNs = 'repo-app-import-sub-generator';
|
|
10
|
+
/**
|
|
11
|
+
* Initialize i18next with the translations for this module.
|
|
12
|
+
*/
|
|
13
|
+
async function initI18n() {
|
|
14
|
+
await i18next_1.default.init({ lng: 'en', fallbackLng: 'en' }, () => i18next_1.default.addResourceBundle('en', repoAppDownloadGeneratorNs, repo_app_import_sub_generator_i18n_json_1.default));
|
|
15
|
+
}
|
|
16
|
+
exports.initI18n = initI18n;
|
|
17
|
+
/**
|
|
18
|
+
* Helper function facading the call to i18next. Unless a namespace option is provided the local namespace will be used.
|
|
19
|
+
*
|
|
20
|
+
* @param key i18n key
|
|
21
|
+
* @param options additional options
|
|
22
|
+
* @returns {string} localized string stored for the given key
|
|
23
|
+
*/
|
|
24
|
+
function t(key, options) {
|
|
25
|
+
if (!options?.ns) {
|
|
26
|
+
options = Object.assign(options ?? {}, { ns: repoAppDownloadGeneratorNs });
|
|
27
|
+
}
|
|
28
|
+
return i18next_1.default.t(key, options);
|
|
29
|
+
}
|
|
30
|
+
exports.t = t;
|
|
31
|
+
initI18n().catch(() => {
|
|
32
|
+
// Needed for lint
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { LogWrapper, type ILogWrapper } from '@sap-ux/fiori-generator-shared';
|
|
2
|
+
import type { Logger } from 'yeoman-environment';
|
|
3
|
+
import type { IVSCodeExtLogger, LogLevel } from '@vscode-logging/logger';
|
|
4
|
+
/**
|
|
5
|
+
* Static logger prevents passing of logger references through all functions, as this is a cross-cutting concern.
|
|
6
|
+
*/
|
|
7
|
+
export default class RepoAppDownloadLogger {
|
|
8
|
+
private static _logger;
|
|
9
|
+
/**
|
|
10
|
+
* Get the logger.
|
|
11
|
+
*
|
|
12
|
+
* @returns the logger
|
|
13
|
+
*/
|
|
14
|
+
static get logger(): ILogWrapper;
|
|
15
|
+
/**
|
|
16
|
+
* Set the logger.
|
|
17
|
+
*
|
|
18
|
+
* @param value the logger to set
|
|
19
|
+
*/
|
|
20
|
+
static set logger(value: ILogWrapper);
|
|
21
|
+
/**
|
|
22
|
+
* Configures the logger.
|
|
23
|
+
*
|
|
24
|
+
* @param loggerName - the logger name
|
|
25
|
+
* @param yoLogger - the yeoman logger
|
|
26
|
+
* @param logWrapper - log wrapper instance
|
|
27
|
+
* @param logLevel - the log level
|
|
28
|
+
* @param vscLogger - the vscode logger
|
|
29
|
+
* @param vscode - the vscode instance
|
|
30
|
+
*/
|
|
31
|
+
static configureLogging(loggerName: string, yoLogger: Logger, logWrapper?: LogWrapper, logLevel?: LogLevel, vscLogger?: IVSCodeExtLogger, vscode?: unknown): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
|
|
4
|
+
/**
|
|
5
|
+
* Static logger prevents passing of logger references through all functions, as this is a cross-cutting concern.
|
|
6
|
+
*/
|
|
7
|
+
class RepoAppDownloadLogger {
|
|
8
|
+
static _logger = fiori_generator_shared_1.DefaultLogger;
|
|
9
|
+
/**
|
|
10
|
+
* Get the logger.
|
|
11
|
+
*
|
|
12
|
+
* @returns the logger
|
|
13
|
+
*/
|
|
14
|
+
static get logger() {
|
|
15
|
+
return RepoAppDownloadLogger._logger;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Set the logger.
|
|
19
|
+
*
|
|
20
|
+
* @param value the logger to set
|
|
21
|
+
*/
|
|
22
|
+
static set logger(value) {
|
|
23
|
+
RepoAppDownloadLogger._logger = value;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Configures the logger.
|
|
27
|
+
*
|
|
28
|
+
* @param loggerName - the logger name
|
|
29
|
+
* @param yoLogger - the yeoman logger
|
|
30
|
+
* @param logWrapper - log wrapper instance
|
|
31
|
+
* @param logLevel - the log level
|
|
32
|
+
* @param vscLogger - the vscode logger
|
|
33
|
+
* @param vscode - the vscode instance
|
|
34
|
+
*/
|
|
35
|
+
static configureLogging(loggerName, yoLogger, logWrapper, logLevel, vscLogger, vscode) {
|
|
36
|
+
const logger = logWrapper ?? new fiori_generator_shared_1.LogWrapper(loggerName, yoLogger, logLevel, vscLogger, vscode);
|
|
37
|
+
RepoAppDownloadLogger.logger = logger;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.default = RepoAppDownloadLogger;
|
|
41
|
+
//# sourceMappingURL=logger.js.map
|