@sap-ux/repo-app-import-sub-generator 0.4.17 → 1.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/generators/app/app-config.d.ts +1 -1
- package/generators/app/app-config.js +36 -44
- package/generators/app/index.d.ts +2 -2
- package/generators/app/index.js +79 -86
- package/generators/app/types.js +2 -5
- package/generators/prompts/prompt-helpers.d.ts +1 -1
- package/generators/prompts/prompt-helpers.js +19 -29
- package/generators/prompts/prompt-state.js +5 -12
- package/generators/prompts/prompts.d.ts +1 -1
- package/generators/prompts/prompts.js +27 -33
- package/generators/telemetryEvents/index.js +2 -5
- package/generators/utils/constants.d.ts +1 -1
- package/generators/utils/constants.js +16 -19
- package/generators/utils/download-utils.js +19 -27
- package/generators/utils/event-hook.js +6 -12
- package/generators/utils/file-helpers.d.ts +1 -1
- package/generators/utils/file-helpers.js +11 -18
- package/generators/utils/i18n.js +9 -19
- package/generators/utils/logger.js +4 -7
- package/generators/utils/updates.js +23 -30
- package/generators/utils/validators.d.ts +1 -1
- package/generators/utils/validators.js +24 -33
- package/package.json +25 -23
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type FioriElementsApp, type LROPSettings } from '@sap-ux/fiori-elements-writer';
|
|
2
2
|
import type { AbapServiceProvider } from '@sap-ux/axios-extension';
|
|
3
3
|
import type { Editor } from 'mem-fs-editor';
|
|
4
|
-
import type { AppInfo, QfaJsonConfig } from '../app/types';
|
|
4
|
+
import type { AppInfo, QfaJsonConfig } from '../app/types.js';
|
|
5
5
|
import type { AbapDeployConfig } from '@sap-ux/ui5-config';
|
|
6
6
|
import { type OdataServiceAnswers } from '@sap-ux/odata-service-inquirer';
|
|
7
7
|
/**
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const file_helpers_1 = require("../utils/file-helpers");
|
|
13
|
-
const constants_1 = require("../utils/constants");
|
|
14
|
-
const prompt_state_1 = require("../prompts/prompt-state");
|
|
15
|
-
const logger_1 = __importDefault(require("../utils/logger"));
|
|
16
|
-
const project_access_1 = require("@sap-ux/project-access");
|
|
17
|
-
const node_path_1 = require("node:path");
|
|
18
|
-
const ui5_info_1 = require("@sap-ux/ui5-info");
|
|
1
|
+
import { TemplateType } from '@sap-ux/fiori-elements-writer';
|
|
2
|
+
import { OdataVersion } from '@sap-ux/odata-service-inquirer';
|
|
3
|
+
import { TransportChecksService } from '@sap-ux/axios-extension';
|
|
4
|
+
import { t } from '../utils/i18n.js';
|
|
5
|
+
import { readManifest } from '../utils/file-helpers.js';
|
|
6
|
+
import { fioriAppSourcetemplateId } from '../utils/constants.js';
|
|
7
|
+
import { PromptState } from '../prompts/prompt-state.js';
|
|
8
|
+
import RepoAppDownloadLogger from '../utils/logger.js';
|
|
9
|
+
import { FileName } from '@sap-ux/project-access';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { getUI5Versions } from '@sap-ux/ui5-info';
|
|
19
12
|
/**
|
|
20
13
|
* Resolve a transport request for the given app/package context.
|
|
21
14
|
* This function performs defensive checks and logs clear, actionable messages.
|
|
@@ -35,7 +28,7 @@ async function resolveTransportRequest(context) {
|
|
|
35
28
|
return '';
|
|
36
29
|
}
|
|
37
30
|
try {
|
|
38
|
-
const transportService = await serviceProvider?.getAdtService(
|
|
31
|
+
const transportService = await serviceProvider?.getAdtService(TransportChecksService);
|
|
39
32
|
const transportRequests = await transportService?.getTransportRequests(packageName, appName);
|
|
40
33
|
if (transportRequests?.length === 1) {
|
|
41
34
|
return transportRequests[0].transportNumber;
|
|
@@ -43,11 +36,11 @@ async function resolveTransportRequest(context) {
|
|
|
43
36
|
return 'REPLACE_WITH_TRANSPORT';
|
|
44
37
|
}
|
|
45
38
|
catch (error) {
|
|
46
|
-
if (error.message ===
|
|
39
|
+
if (error.message === TransportChecksService.LocalPackageError) {
|
|
47
40
|
return '';
|
|
48
41
|
}
|
|
49
|
-
const msg =
|
|
50
|
-
|
|
42
|
+
const msg = t('error.transportCheckFailed', { error: error?.message });
|
|
43
|
+
RepoAppDownloadLogger.logger?.error(msg);
|
|
51
44
|
throw new Error(msg);
|
|
52
45
|
}
|
|
53
46
|
}
|
|
@@ -57,14 +50,14 @@ async function resolveTransportRequest(context) {
|
|
|
57
50
|
* @param {AppDownloadContext} context - The download context with service provider and qfa info.
|
|
58
51
|
* @returns {AbapDeployConfig} The deployment configuration containing `target` and `app` info.
|
|
59
52
|
*/
|
|
60
|
-
const getAbapDeployConfig = async (context) => {
|
|
53
|
+
export const getAbapDeployConfig = async (context) => {
|
|
61
54
|
const { qfaJson } = context;
|
|
62
55
|
const transportRequest = await resolveTransportRequest(context);
|
|
63
56
|
return {
|
|
64
57
|
target: {
|
|
65
|
-
url:
|
|
66
|
-
client:
|
|
67
|
-
destination:
|
|
58
|
+
url: PromptState.baseURL,
|
|
59
|
+
client: PromptState.sapClient,
|
|
60
|
+
destination: PromptState.destinationName
|
|
68
61
|
},
|
|
69
62
|
app: {
|
|
70
63
|
name: qfaJson.deploymentDetails.repositoryName,
|
|
@@ -74,7 +67,6 @@ const getAbapDeployConfig = async (context) => {
|
|
|
74
67
|
}
|
|
75
68
|
}; // NOSONAR
|
|
76
69
|
};
|
|
77
|
-
exports.getAbapDeployConfig = getAbapDeployConfig;
|
|
78
70
|
/**
|
|
79
71
|
* Fetches the metadata of a given service from the provided ABAP service provider.
|
|
80
72
|
*
|
|
@@ -85,11 +77,11 @@ exports.getAbapDeployConfig = getAbapDeployConfig;
|
|
|
85
77
|
const fetchServiceMetadata = async (provider, serviceUrl) => {
|
|
86
78
|
try {
|
|
87
79
|
const metadata = await provider.service(serviceUrl).metadata();
|
|
88
|
-
|
|
80
|
+
RepoAppDownloadLogger.logger?.debug('Metadata fetched successfully');
|
|
89
81
|
return metadata;
|
|
90
82
|
}
|
|
91
83
|
catch (err) {
|
|
92
|
-
|
|
84
|
+
RepoAppDownloadLogger.logger?.error(t('error.metadataFetchError', { error: err.message }));
|
|
93
85
|
}
|
|
94
86
|
};
|
|
95
87
|
/**
|
|
@@ -104,21 +96,21 @@ const fetchServiceMetadata = async (provider, serviceUrl) => {
|
|
|
104
96
|
* @returns {Promise<FioriElementsApp<LROPSettings>>} - A promise resolving to the generated app configuration.
|
|
105
97
|
* @throws {Error} - Throws an error if there are issues generating the configuration.
|
|
106
98
|
*/
|
|
107
|
-
async function getAppConfig(app, extractedProjectPath, context, systemSelection, fs) {
|
|
99
|
+
export async function getAppConfig(app, extractedProjectPath, context, systemSelection, fs) {
|
|
108
100
|
try {
|
|
109
|
-
const manifest =
|
|
110
|
-
const serviceProvider =
|
|
101
|
+
const manifest = readManifest(join(extractedProjectPath, FileName.Manifest), fs);
|
|
102
|
+
const serviceProvider = PromptState.systemSelection?.connectedSystem?.serviceProvider;
|
|
111
103
|
context.serviceProvider = serviceProvider;
|
|
112
104
|
if (!manifest?.['sap.app']?.dataSources) {
|
|
113
|
-
|
|
105
|
+
RepoAppDownloadLogger.logger?.error(t('error.dataSourcesNotFound'));
|
|
114
106
|
}
|
|
115
107
|
const odataVersion = manifest?.['sap.app']?.dataSources?.mainService?.settings?.odataVersion?.startsWith('4')
|
|
116
|
-
?
|
|
117
|
-
:
|
|
108
|
+
? OdataVersion.v4
|
|
109
|
+
: OdataVersion.v2;
|
|
118
110
|
// Fetch metadata for the service
|
|
119
111
|
const metadata = await fetchServiceMetadata(serviceProvider, manifest?.['sap.app']?.dataSources?.mainService.uri ?? '');
|
|
120
112
|
// Fetch latest UI5 versions from npm
|
|
121
|
-
const ui5Versions = await
|
|
113
|
+
const ui5Versions = await getUI5Versions({ onlyNpmVersion: true });
|
|
122
114
|
const localVersion = ui5Versions[0]?.version;
|
|
123
115
|
const appConfig = {
|
|
124
116
|
app: {
|
|
@@ -126,7 +118,7 @@ async function getAppConfig(app, extractedProjectPath, context, systemSelection,
|
|
|
126
118
|
title: app.title,
|
|
127
119
|
description: app.description,
|
|
128
120
|
sourceTemplate: {
|
|
129
|
-
id:
|
|
121
|
+
id: fioriAppSourcetemplateId
|
|
130
122
|
},
|
|
131
123
|
projectType: 'EDMXBackend',
|
|
132
124
|
flpAppId: `${app.appId.replace(/[-_.#]/g, '')}-tile`
|
|
@@ -139,7 +131,7 @@ async function getAppConfig(app, extractedProjectPath, context, systemSelection,
|
|
|
139
131
|
version: manifest?.['sap.app']?.applicationVersion?.version ?? '0.0.1'
|
|
140
132
|
},
|
|
141
133
|
template: {
|
|
142
|
-
type:
|
|
134
|
+
type: TemplateType.ListReportObjectPage,
|
|
143
135
|
settings: {
|
|
144
136
|
entityConfig: {
|
|
145
137
|
mainEntityName: context.qfaJson.serviceBindingDetails.mainEntityName
|
|
@@ -150,11 +142,11 @@ async function getAppConfig(app, extractedProjectPath, context, systemSelection,
|
|
|
150
142
|
path: manifest?.['sap.app']?.dataSources?.mainService.uri,
|
|
151
143
|
version: odataVersion,
|
|
152
144
|
metadata: metadata,
|
|
153
|
-
url:
|
|
154
|
-
client:
|
|
145
|
+
url: PromptState.baseURL,
|
|
146
|
+
client: PromptState.sapClient
|
|
155
147
|
},
|
|
156
148
|
appOptions: {
|
|
157
|
-
addAnnotations: odataVersion ===
|
|
149
|
+
addAnnotations: odataVersion === OdataVersion.v4,
|
|
158
150
|
addTests: true,
|
|
159
151
|
useVirtualPreviewEndpoints: true
|
|
160
152
|
},
|
|
@@ -162,13 +154,13 @@ async function getAppConfig(app, extractedProjectPath, context, systemSelection,
|
|
|
162
154
|
localVersion
|
|
163
155
|
}
|
|
164
156
|
};
|
|
165
|
-
if (
|
|
166
|
-
appConfig.service.destination = { name:
|
|
157
|
+
if (PromptState.destinationName) {
|
|
158
|
+
appConfig.service.destination = { name: PromptState.destinationName };
|
|
167
159
|
}
|
|
168
160
|
return appConfig;
|
|
169
161
|
}
|
|
170
162
|
catch (error) {
|
|
171
|
-
|
|
163
|
+
RepoAppDownloadLogger.logger?.error(t('error.appConfigGenError', { error: error.message }));
|
|
172
164
|
throw error;
|
|
173
165
|
}
|
|
174
166
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Generator from 'yeoman-generator';
|
|
2
|
-
import type { RepoAppDownloadOptions } from './types';
|
|
3
|
-
import { PromptNames } from './types';
|
|
2
|
+
import type { RepoAppDownloadOptions } from './types.js';
|
|
3
|
+
import { PromptNames } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Generator class for downloading a basic app from a repository.
|
|
6
6
|
* This class handles the process of app selection, downloading the app and generating a fiori app from the downloaded app
|
package/generators/app/index.js
CHANGED
|
@@ -1,48 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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");
|
|
1
|
+
import Generator from 'yeoman-generator';
|
|
2
|
+
import RepoAppDownloadLogger from '../utils/logger.js';
|
|
3
|
+
import { AppWizard, Prompts, MessageType } from '@sap-devx/yeoman-ui-types';
|
|
4
|
+
import { isInternalFeaturesSettingEnabled } from '@sap-ux/feature-toggle';
|
|
5
|
+
import { generatorTitle, extractedFilePath, generatorName, defaultAnswers, qfaJsonFileName } from '../utils/constants.js';
|
|
6
|
+
import { t } from '../utils/i18n.js';
|
|
7
|
+
import { extractZip } from '../utils/download-utils.js';
|
|
8
|
+
import { EventName } from '../telemetryEvents/index.js';
|
|
9
|
+
import { getDefaultTargetFolder, generateAppGenInfo, sendTelemetry, TelemetryHelper, isCli, setYeomanEnvConflicterForce } from '@sap-ux/fiori-generator-shared';
|
|
10
|
+
import { getPrompts } from '../prompts/prompts.js';
|
|
11
|
+
import { generate, TemplateType } from '@sap-ux/fiori-elements-writer';
|
|
12
|
+
import { join, basename } from 'node:path';
|
|
13
|
+
import { platform } from 'node:os';
|
|
14
|
+
import { runPostAppGenHook } from '../utils/event-hook.js';
|
|
15
|
+
import { getDefaultUI5Theme } from '@sap-ux/ui5-info';
|
|
16
|
+
import { createLaunchConfig, updateWorkspaceFoldersIfNeeded, handleWorkspaceConfig } from '@sap-ux/launch-config';
|
|
17
|
+
import { isAppStudio } from '@sap-ux/btp-utils';
|
|
18
|
+
import { OdataVersion } from '@sap-ux/odata-service-inquirer';
|
|
19
|
+
import { writeApplicationInfoSettings } from '@sap-ux/fiori-tools-settings';
|
|
20
|
+
import { generate as generateDeployConfig } from '@sap-ux/abap-deploy-config-writer';
|
|
21
|
+
import { PromptState } from '../prompts/prompt-state.js';
|
|
22
|
+
import { PromptNames } from './types.js';
|
|
23
|
+
import { getAbapDeployConfig, getAppConfig } from './app-config.js';
|
|
24
|
+
import { makeValidJson } from '../utils/file-helpers.js';
|
|
25
|
+
import { replaceWebappFiles, validateAndUpdateManifestUI5Version } from '../utils/updates.js';
|
|
26
|
+
import { getYUIDetails } from '../prompts/prompt-helpers.js';
|
|
27
|
+
import { isValidPromptState, validateQfaJsonFile } from '../utils/validators.js';
|
|
28
|
+
import { FileName, DirName } from '@sap-ux/project-access';
|
|
36
29
|
/**
|
|
37
30
|
* Generator class for downloading a basic app from a repository.
|
|
38
31
|
* This class handles the process of app selection, downloading the app and generating a fiori app from the downloaded app
|
|
39
32
|
*/
|
|
40
|
-
class
|
|
33
|
+
export default class extends Generator {
|
|
41
34
|
appWizard;
|
|
42
35
|
vscode;
|
|
43
36
|
appRootPath;
|
|
44
37
|
prompts;
|
|
45
|
-
answers =
|
|
38
|
+
answers = defaultAnswers;
|
|
46
39
|
options;
|
|
47
40
|
projectPath;
|
|
48
41
|
extractedProjectPath;
|
|
@@ -57,15 +50,15 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
57
50
|
constructor(args, opts) {
|
|
58
51
|
super(args, opts);
|
|
59
52
|
// Initialise properties from options
|
|
60
|
-
this.appWizard = opts.appWizard ??
|
|
53
|
+
this.appWizard = opts.appWizard ?? AppWizard.create(opts);
|
|
61
54
|
this.vscode = opts.vscode;
|
|
62
|
-
this.appRootPath = opts?.appRootPath ??
|
|
55
|
+
this.appRootPath = opts?.appRootPath ?? getDefaultTargetFolder(this.vscode) ?? this.destinationRoot();
|
|
63
56
|
this.options = opts;
|
|
64
57
|
// Configure logging
|
|
65
|
-
|
|
58
|
+
RepoAppDownloadLogger.configureLogging(this.rootGeneratorName(), this.log, this.options.logWrapper, this.options.logLevel, this.options.logger, this.vscode);
|
|
66
59
|
// Initialise prompts and callbacks if not launched as a subgenerator
|
|
67
|
-
this.appWizard.setHeaderTitle(
|
|
68
|
-
this.prompts = new
|
|
60
|
+
this.appWizard.setHeaderTitle(generatorTitle);
|
|
61
|
+
this.prompts = new Prompts(getYUIDetails());
|
|
69
62
|
this.setPromptsCallback = (fn) => {
|
|
70
63
|
if (this.prompts) {
|
|
71
64
|
this.prompts.setCallback(fn);
|
|
@@ -76,14 +69,14 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
76
69
|
* Initialises necessary settings and telemetry for the generator.
|
|
77
70
|
*/
|
|
78
71
|
async initializing() {
|
|
79
|
-
|
|
72
|
+
setYeomanEnvConflicterForce(this.env, this.options.force);
|
|
80
73
|
// Initialise telemetry settings
|
|
81
|
-
await
|
|
74
|
+
await TelemetryHelper.initTelemetrySettings({
|
|
82
75
|
consumerModule: {
|
|
83
|
-
name:
|
|
76
|
+
name: generatorName,
|
|
84
77
|
version: this.rootGeneratorVersion()
|
|
85
78
|
},
|
|
86
|
-
internalFeature:
|
|
79
|
+
internalFeature: isInternalFeaturesSettingEnabled(),
|
|
87
80
|
watchTelemetrySettingStore: false
|
|
88
81
|
});
|
|
89
82
|
}
|
|
@@ -92,57 +85,57 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
92
85
|
*/
|
|
93
86
|
async prompting() {
|
|
94
87
|
const quickDeployedAppConfig = this.options?.data?.quickDeployedAppConfig;
|
|
95
|
-
const questions = await
|
|
88
|
+
const questions = await getPrompts(this.appRootPath, quickDeployedAppConfig, this.appWizard, isCli());
|
|
96
89
|
const answers = await this.prompt(questions);
|
|
97
90
|
const { targetFolder } = answers;
|
|
98
91
|
if (quickDeployedAppConfig?.appId) {
|
|
99
92
|
// Handle quick deployed app download where prompts for system selection and app selection are not displayed
|
|
100
93
|
// Only target folder prompt is shown
|
|
101
94
|
this.answers.targetFolder = targetFolder;
|
|
102
|
-
this.answers.systemSelection =
|
|
95
|
+
this.answers.systemSelection = PromptState.systemSelection;
|
|
103
96
|
this.answers.selectedApp = answers.selectedApp;
|
|
104
97
|
}
|
|
105
98
|
else {
|
|
106
99
|
// Handle app download where prompts for system selection and app selection are shown
|
|
107
100
|
Object.assign(this.answers, answers);
|
|
108
101
|
}
|
|
109
|
-
if (
|
|
110
|
-
this.projectPath =
|
|
111
|
-
this.extractedProjectPath =
|
|
102
|
+
if (isValidPromptState(this.answers.targetFolder, this.answers.selectedApp.appId)) {
|
|
103
|
+
this.projectPath = join(this.answers.targetFolder, this.answers.selectedApp.appId);
|
|
104
|
+
this.extractedProjectPath = join(this.projectPath, extractedFilePath);
|
|
112
105
|
}
|
|
113
106
|
}
|
|
114
107
|
/**
|
|
115
108
|
* Writes the configuration files for the project, including deployment config, and README.
|
|
116
109
|
*/
|
|
117
110
|
async writing() {
|
|
118
|
-
await
|
|
111
|
+
await extractZip(this.extractedProjectPath, this.fs);
|
|
119
112
|
// Check if the qfa.json file
|
|
120
|
-
const qfaJsonFilePath =
|
|
121
|
-
const qfaJson =
|
|
113
|
+
const qfaJsonFilePath = join(this.extractedProjectPath, qfaJsonFileName);
|
|
114
|
+
const qfaJson = makeValidJson(qfaJsonFilePath, this.fs);
|
|
122
115
|
// Generate project files
|
|
123
|
-
|
|
116
|
+
validateQfaJsonFile(qfaJson);
|
|
124
117
|
const context = {
|
|
125
118
|
qfaJson
|
|
126
119
|
};
|
|
127
120
|
// Generate app config
|
|
128
|
-
const config = await
|
|
129
|
-
await
|
|
121
|
+
const config = await getAppConfig(this.answers.selectedApp, this.extractedProjectPath, context, this.answers.systemSelection, this.fs);
|
|
122
|
+
await generate(this.projectPath, config, this.fs);
|
|
130
123
|
// Generate deploy config
|
|
131
|
-
const deployConfig = await
|
|
132
|
-
await (
|
|
124
|
+
const deployConfig = await getAbapDeployConfig(context);
|
|
125
|
+
await generateDeployConfig(this.projectPath, deployConfig, undefined, this.fs);
|
|
133
126
|
if (this.vscode) {
|
|
134
127
|
// Generate Fiori launch config
|
|
135
128
|
const fioriOptions = this._getLaunchConfig(config);
|
|
136
129
|
// Create launch configuration
|
|
137
|
-
await
|
|
138
|
-
|
|
130
|
+
await createLaunchConfig(this.projectPath, fioriOptions, this.fs, RepoAppDownloadLogger.logger);
|
|
131
|
+
writeApplicationInfoSettings(this.projectPath);
|
|
139
132
|
}
|
|
140
133
|
// Generate README
|
|
141
134
|
const readMeConfig = this._getReadMeConfig(config);
|
|
142
|
-
|
|
135
|
+
generateAppGenInfo(this.projectPath, readMeConfig, this.fs);
|
|
143
136
|
// Replace webapp files with downloaded app files
|
|
144
|
-
await
|
|
145
|
-
await
|
|
137
|
+
await replaceWebappFiles(this.projectPath, this.extractedProjectPath, this.fs);
|
|
138
|
+
await validateAndUpdateManifestUI5Version(join(this.projectPath, DirName.Webapp, FileName.Manifest), this.fs);
|
|
146
139
|
// Clean up extracted project files
|
|
147
140
|
this.fs.delete(this.extractedProjectPath);
|
|
148
141
|
}
|
|
@@ -157,14 +150,14 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
157
150
|
appName: config.app.id,
|
|
158
151
|
appTitle: config.app.title ?? '',
|
|
159
152
|
appNamespace: config.app.id.substring(0, config.app.id.lastIndexOf('.')),
|
|
160
|
-
appDescription:
|
|
161
|
-
ui5Theme:
|
|
162
|
-
generatorName:
|
|
153
|
+
appDescription: t('readMe.appDescription'),
|
|
154
|
+
ui5Theme: getDefaultUI5Theme(config.ui5?.version),
|
|
155
|
+
generatorName: generatorName,
|
|
163
156
|
generatorVersion: this.rootGeneratorVersion(),
|
|
164
157
|
ui5Version: config.ui5?.version ?? '',
|
|
165
|
-
template:
|
|
158
|
+
template: TemplateType.ListReportObjectPage,
|
|
166
159
|
serviceUrl: config.service.url,
|
|
167
|
-
launchText:
|
|
160
|
+
launchText: t('readMe.launchText')
|
|
168
161
|
};
|
|
169
162
|
return readMeConfig;
|
|
170
163
|
}
|
|
@@ -178,11 +171,11 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
178
171
|
const debugOptions = {
|
|
179
172
|
vscode: this.vscode,
|
|
180
173
|
addStartCmd: true,
|
|
181
|
-
sapClientParam:
|
|
174
|
+
sapClientParam: PromptState.sapClient,
|
|
182
175
|
flpAppId: config.app.flpAppId ?? config.app.id,
|
|
183
176
|
flpSandboxAvailable: true,
|
|
184
|
-
isAppStudio:
|
|
185
|
-
odataVersion: config.service.version ===
|
|
177
|
+
isAppStudio: isAppStudio(),
|
|
178
|
+
odataVersion: config.service.version === OdataVersion.v2 ? '2.0' : '4.0'
|
|
186
179
|
};
|
|
187
180
|
this.debugOptions = debugOptions;
|
|
188
181
|
const fioriOptions = {
|
|
@@ -204,16 +197,16 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
204
197
|
async install() {
|
|
205
198
|
if (!this.options.skipInstall) {
|
|
206
199
|
try {
|
|
207
|
-
|
|
200
|
+
RepoAppDownloadLogger.logger?.debug('Running npm install...');
|
|
208
201
|
await this._runNpmInstall(this.projectPath);
|
|
209
|
-
|
|
202
|
+
RepoAppDownloadLogger.logger?.debug('npm install completed successfully.');
|
|
210
203
|
}
|
|
211
204
|
catch (error) {
|
|
212
|
-
|
|
205
|
+
RepoAppDownloadLogger.logger?.error(t('error.installationErrors.npmInstall', { error }));
|
|
213
206
|
}
|
|
214
207
|
}
|
|
215
208
|
else {
|
|
216
|
-
|
|
209
|
+
RepoAppDownloadLogger.logger?.info(t('info.installationErrors.skippedInstallation'));
|
|
217
210
|
}
|
|
218
211
|
}
|
|
219
212
|
/**
|
|
@@ -222,7 +215,7 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
222
215
|
* @param path - The path to run npm install.
|
|
223
216
|
*/
|
|
224
217
|
async _runNpmInstall(path) {
|
|
225
|
-
const npm =
|
|
218
|
+
const npm = platform() === 'win32' ? 'npm.cmd' : 'npm';
|
|
226
219
|
// install dependencies
|
|
227
220
|
await this.spawnCommand(npm, ['install', '--no-audit', '--no-fund', '--silent', '--prefer-offline', '--no-progress'], {
|
|
228
221
|
cwd: path
|
|
@@ -253,18 +246,18 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
253
246
|
if (this.vscode) {
|
|
254
247
|
const rootFolder = this.projectPath;
|
|
255
248
|
// Create workspace folder URI
|
|
256
|
-
const { workspaceFolderUri } =
|
|
249
|
+
const { workspaceFolderUri } = handleWorkspaceConfig(rootFolder, this.debugOptions);
|
|
257
250
|
const updateWorkspaceFolders = workspaceFolderUri
|
|
258
251
|
? {
|
|
259
252
|
uri: workspaceFolderUri,
|
|
260
|
-
projectName:
|
|
253
|
+
projectName: basename(rootFolder),
|
|
261
254
|
vscode: this.debugOptions.vscode
|
|
262
255
|
}
|
|
263
256
|
: undefined;
|
|
264
|
-
|
|
257
|
+
updateWorkspaceFoldersIfNeeded(updateWorkspaceFolders);
|
|
265
258
|
}
|
|
266
259
|
if (this.options.data?.postGenCommand) {
|
|
267
|
-
await
|
|
260
|
+
await runPostAppGenHook({
|
|
268
261
|
path: this.projectPath,
|
|
269
262
|
vscodeInstance: this.vscode,
|
|
270
263
|
postGenCommand: this.options.data?.postGenCommand
|
|
@@ -276,19 +269,19 @@ class default_1 extends yeoman_generator_1.default {
|
|
|
276
269
|
*/
|
|
277
270
|
async end() {
|
|
278
271
|
try {
|
|
279
|
-
this.appWizard.showInformation(
|
|
272
|
+
this.appWizard.showInformation(t('info.repoAppDownloadCompleteMsg'), MessageType.notification);
|
|
280
273
|
await this._handlePostAppGeneration();
|
|
281
|
-
await
|
|
274
|
+
await sendTelemetry(EventName.GENERATION_SUCCESS, TelemetryHelper.createTelemetryData({
|
|
282
275
|
appType: 'repo-app-import-sub-generator',
|
|
283
276
|
...this.options.telemetryData
|
|
284
277
|
}) ?? {}).catch((error) => {
|
|
285
|
-
|
|
278
|
+
RepoAppDownloadLogger.logger?.error(t('error.telemetry', { error: error.message }));
|
|
286
279
|
});
|
|
287
280
|
}
|
|
288
281
|
catch (error) {
|
|
289
|
-
|
|
282
|
+
RepoAppDownloadLogger.logger?.error(t('error.endPhase', { error: error.message }));
|
|
290
283
|
}
|
|
291
284
|
}
|
|
292
285
|
}
|
|
293
|
-
|
|
286
|
+
export { PromptNames };
|
|
294
287
|
//# sourceMappingURL=index.js.map
|
package/generators/app/types.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PromptNames = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* Enum representing the names of prompts used in the application download process.
|
|
6
3
|
*/
|
|
7
|
-
var PromptNames;
|
|
4
|
+
export var PromptNames;
|
|
8
5
|
(function (PromptNames) {
|
|
9
6
|
PromptNames["selectedApp"] = "selectedApp";
|
|
10
7
|
PromptNames["systemSelection"] = "systemSelection";
|
|
11
8
|
PromptNames["targetFolder"] = "targetFolder";
|
|
12
|
-
})(PromptNames || (
|
|
9
|
+
})(PromptNames || (PromptNames = {}));
|
|
13
10
|
//# sourceMappingURL=types.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AppIndex } from '@sap-ux/axios-extension';
|
|
2
|
-
import type { AppInfo, AppItem } from '../app/types';
|
|
2
|
+
import type { AppInfo, AppItem } from '../app/types.js';
|
|
3
3
|
import { type ConnectedSystem } from '@sap-ux/odata-service-inquirer';
|
|
4
4
|
/**
|
|
5
5
|
* Returns the details for the YUI prompt.
|
|
@@ -1,25 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.formatAppChoices = exports.extractAppData = void 0;
|
|
7
|
-
exports.getYUIDetails = getYUIDetails;
|
|
8
|
-
exports.fetchAppListForSelectedSystem = fetchAppListForSelectedSystem;
|
|
9
|
-
const constants_1 = require("../utils/constants");
|
|
10
|
-
const prompt_state_1 = require("./prompt-state");
|
|
11
|
-
const i18n_1 = require("../utils/i18n");
|
|
12
|
-
const logger_1 = __importDefault(require("../utils/logger"));
|
|
1
|
+
import { appListSearchParams, appListResultFields, generatorTitle, generatorDescription } from '../utils/constants.js';
|
|
2
|
+
import { PromptState } from './prompt-state.js';
|
|
3
|
+
import { t } from '../utils/i18n.js';
|
|
4
|
+
import RepoAppDownloadLogger from '../utils/logger.js';
|
|
13
5
|
/**
|
|
14
6
|
* Returns the details for the YUI prompt.
|
|
15
7
|
*
|
|
16
8
|
* @returns step details
|
|
17
9
|
*/
|
|
18
|
-
function getYUIDetails() {
|
|
10
|
+
export function getYUIDetails() {
|
|
19
11
|
return [
|
|
20
12
|
{
|
|
21
|
-
name:
|
|
22
|
-
description:
|
|
13
|
+
name: generatorTitle,
|
|
14
|
+
description: generatorDescription
|
|
23
15
|
}
|
|
24
16
|
];
|
|
25
17
|
}
|
|
@@ -29,7 +21,7 @@ function getYUIDetails() {
|
|
|
29
21
|
* @param {AppItem} app - The application item to extract details from.
|
|
30
22
|
* @returns {{ name: string; value: AppInfo }} The extracted details including name and value.
|
|
31
23
|
*/
|
|
32
|
-
const extractAppData = (app) => {
|
|
24
|
+
export const extractAppData = (app) => {
|
|
33
25
|
// cast to string because TypeScript doesn't automatically know at the point that these fields are defined
|
|
34
26
|
// after filtering out invalid apps.
|
|
35
27
|
const id = app['sap.app/id'];
|
|
@@ -48,29 +40,27 @@ const extractAppData = (app) => {
|
|
|
48
40
|
}
|
|
49
41
|
};
|
|
50
42
|
};
|
|
51
|
-
exports.extractAppData = extractAppData;
|
|
52
43
|
/**
|
|
53
44
|
* Formats the application list into selectable choices.
|
|
54
45
|
*
|
|
55
46
|
* @param {AppIndex} appList - List of applications retrieved from the system.
|
|
56
47
|
* @returns {Array<{ name: string; value: AppInfo }>} The formatted choices for selection.
|
|
57
48
|
*/
|
|
58
|
-
const formatAppChoices = (appList) => {
|
|
49
|
+
export const formatAppChoices = (appList) => {
|
|
59
50
|
return appList
|
|
60
51
|
.filter((app) => {
|
|
61
|
-
|
|
52
|
+
RepoAppDownloadLogger.logger?.debug(`formatAppChoices: ${JSON.stringify(app)}`);
|
|
62
53
|
const hasRequiredFields = app['sap.app/id'] &&
|
|
63
54
|
app['repoName'] &&
|
|
64
55
|
app['url'] &&
|
|
65
56
|
Object.prototype.hasOwnProperty.call(app, 'sap.app/title'); // allow for empty title
|
|
66
57
|
if (!hasRequiredFields) {
|
|
67
|
-
|
|
58
|
+
RepoAppDownloadLogger.logger?.warn(t('warn.requiredFieldsMissing', { app: app['sap.app/id'] }));
|
|
68
59
|
}
|
|
69
60
|
return hasRequiredFields;
|
|
70
61
|
})
|
|
71
|
-
.map((app) =>
|
|
62
|
+
.map((app) => extractAppData(app));
|
|
72
63
|
};
|
|
73
|
-
exports.formatAppChoices = formatAppChoices;
|
|
74
64
|
/**
|
|
75
65
|
* Fetches a list of deployed applications from the ABAP repository.
|
|
76
66
|
*
|
|
@@ -82,15 +72,15 @@ async function getAppList(provider, appId) {
|
|
|
82
72
|
try {
|
|
83
73
|
const searchParams = appId
|
|
84
74
|
? {
|
|
85
|
-
...
|
|
75
|
+
...appListSearchParams,
|
|
86
76
|
'sap.app/id': appId
|
|
87
77
|
}
|
|
88
|
-
:
|
|
89
|
-
return await provider.getAppIndex().search(searchParams,
|
|
78
|
+
: appListSearchParams;
|
|
79
|
+
return await provider.getAppIndex().search(searchParams, appListResultFields);
|
|
90
80
|
}
|
|
91
81
|
catch (error) {
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
RepoAppDownloadLogger.logger?.error(t('error.applicationListFetchError', { error: error.message }));
|
|
83
|
+
RepoAppDownloadLogger.logger?.debug(t('error.applicationListFetchError', { error: JSON.stringify(error) }));
|
|
94
84
|
return [];
|
|
95
85
|
}
|
|
96
86
|
}
|
|
@@ -101,9 +91,9 @@ async function getAppList(provider, appId) {
|
|
|
101
91
|
* @param {string} appId - Application ID to be downloaded.
|
|
102
92
|
* @returns {Promise<AppIndex>} A list of applications filtered by source template.
|
|
103
93
|
*/
|
|
104
|
-
async function fetchAppListForSelectedSystem(connectedSystem, appId) {
|
|
94
|
+
export async function fetchAppListForSelectedSystem(connectedSystem, appId) {
|
|
105
95
|
if (connectedSystem?.serviceProvider) {
|
|
106
|
-
|
|
96
|
+
PromptState.systemSelection = {
|
|
107
97
|
connectedSystem: connectedSystem
|
|
108
98
|
};
|
|
109
99
|
return await getAppList(connectedSystem.serviceProvider, appId);
|