@sap-ux/fiori-app-sub-generator 0.0.2

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 (61) hide show
  1. package/LICENSE +201 -0
  2. package/generators/app/index.d.ts +3 -0
  3. package/generators/app/index.js +5 -0
  4. package/generators/app-headless/index.d.ts +34 -0
  5. package/generators/app-headless/index.js +75 -0
  6. package/generators/app-headless/transforms.d.ts +9 -0
  7. package/generators/app-headless/transforms.js +208 -0
  8. package/generators/fiori-app-generator/end.d.ts +49 -0
  9. package/generators/fiori-app-generator/end.js +105 -0
  10. package/generators/fiori-app-generator/fioriAppGenerator.d.ts +45 -0
  11. package/generators/fiori-app-generator/fioriAppGenerator.js +319 -0
  12. package/generators/fiori-app-generator/fioriAppGeneratorOptions.d.ts +94 -0
  13. package/generators/fiori-app-generator/fioriAppGeneratorOptions.js +3 -0
  14. package/generators/fiori-app-generator/index.d.ts +3 -0
  15. package/generators/fiori-app-generator/index.js +19 -0
  16. package/generators/fiori-app-generator/install.d.ts +34 -0
  17. package/generators/fiori-app-generator/install.js +80 -0
  18. package/generators/fiori-app-generator/prompting.d.ts +84 -0
  19. package/generators/fiori-app-generator/prompting.js +303 -0
  20. package/generators/fiori-app-generator/subgenHelpers.d.ts +43 -0
  21. package/generators/fiori-app-generator/subgenHelpers.js +71 -0
  22. package/generators/fiori-app-generator/transforms.d.ts +38 -0
  23. package/generators/fiori-app-generator/transforms.js +278 -0
  24. package/generators/fiori-app-generator/writing.d.ts +27 -0
  25. package/generators/fiori-app-generator/writing.js +94 -0
  26. package/generators/index.d.ts +6 -0
  27. package/generators/index.js +22 -0
  28. package/generators/translations/fioriAppSubGenerator.i18n.json +119 -0
  29. package/generators/types/common.d.ts +46 -0
  30. package/generators/types/common.js +3 -0
  31. package/generators/types/constants.d.ts +60 -0
  32. package/generators/types/constants.js +98 -0
  33. package/generators/types/external.d.ts +261 -0
  34. package/generators/types/external.js +88 -0
  35. package/generators/types/index.d.ts +7 -0
  36. package/generators/types/index.js +23 -0
  37. package/generators/types/state.d.ts +149 -0
  38. package/generators/types/state.js +35 -0
  39. package/generators/types/telemetryEvents.d.ts +61 -0
  40. package/generators/types/telemetryEvents.js +3 -0
  41. package/generators/types/yeomanUiStepConfig.d.ts +13 -0
  42. package/generators/types/yeomanUiStepConfig.js +3 -0
  43. package/generators/utils/appWizardCache.d.ts +40 -0
  44. package/generators/utils/appWizardCache.js +72 -0
  45. package/generators/utils/command-runner.d.ts +30 -0
  46. package/generators/utils/command-runner.js +88 -0
  47. package/generators/utils/common.d.ts +147 -0
  48. package/generators/utils/common.js +286 -0
  49. package/generators/utils/eventHooks.d.ts +29 -0
  50. package/generators/utils/eventHooks.js +48 -0
  51. package/generators/utils/i18n.d.ts +16 -0
  52. package/generators/utils/i18n.js +54 -0
  53. package/generators/utils/index.d.ts +9 -0
  54. package/generators/utils/index.js +25 -0
  55. package/generators/utils/sapuxLayer.d.ts +15 -0
  56. package/generators/utils/sapuxLayer.js +24 -0
  57. package/generators/utils/stepsHelper.d.ts +47 -0
  58. package/generators/utils/stepsHelper.js +161 -0
  59. package/generators/utils/telemetry.d.ts +16 -0
  60. package/generators/utils/telemetry.js +41 -0
  61. package/package.json +84 -0
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPostGenerationTasks = runPostGenerationTasks;
4
+ const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
5
+ const btp_utils_1 = require("@sap-ux/btp-utils");
6
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
7
+ const store_1 = require("@sap-ux/store");
8
+ const path_1 = require("path");
9
+ const utils_1 = require("../utils");
10
+ /**
11
+ * Save API Hub key to the store.
12
+ *
13
+ * @param apiKey - API key to save
14
+ * @param logger - optional logger
15
+ * @returns - true if the API key was saved successfully, false otherwise
16
+ */
17
+ async function saveApiHubApiKey(apiKey, logger) {
18
+ let result;
19
+ if (!(0, btp_utils_1.isAppStudio)()) {
20
+ const apiHubStore = (await (0, store_1.getService)({
21
+ logger,
22
+ entityName: 'api-hub'
23
+ }));
24
+ const apiHubSettings = new store_1.ApiHubSettings({ apiKey });
25
+ result = await apiHubStore.write(apiHubSettings);
26
+ }
27
+ return Boolean(result);
28
+ }
29
+ /**
30
+ * Run post generation hooks: delegates to `runHooks` with `'app-generated'` as the event name.
31
+ *
32
+ * @param projectPath
33
+ * @param logger
34
+ * @param vscode
35
+ * @param followUpCommand
36
+ */
37
+ async function runPostGenHooks(projectPath, logger, vscode, followUpCommand) {
38
+ await (0, utils_1.runHooks)('app-generated', {
39
+ hookParameters: { fsPath: projectPath },
40
+ vscodeInstance: vscode,
41
+ options: { followUpCommand }
42
+ }, logger);
43
+ }
44
+ /**
45
+ * FioriBaseGeneratror end phase related functionality.
46
+ *
47
+ * @param state
48
+ * @param state.service
49
+ * @param state.service.backendSystem
50
+ * @param state.service.capService
51
+ * @param state.service.sapClient
52
+ * @param state.service.odataVersion
53
+ * @param state.service.datasourceType
54
+ * @param state.service.apiHubConfig
55
+ * @param state.project
56
+ * @param state.project.targetFolder
57
+ * @param state.project.name
58
+ * @param state.project.flpAppId
59
+ * @param fs - the file system editor
60
+ * @param logger - the logger
61
+ * @param vscode - the vscode instance
62
+ * @param appWizard - the app wizard instance
63
+ * @param followUpCommand - the follow up command
64
+ * @returns {Promise<void>}
65
+ */
66
+ async function runPostGenerationTasks({ service, project }, fs, logger, vscode, appWizard, followUpCommand) {
67
+ // Add launch config for non-cap projects
68
+ if (!service.capService) {
69
+ await (0, utils_1.generateLaunchConfig)({
70
+ targetFolder: project.targetFolder,
71
+ projectName: project.name,
72
+ flpAppId: project.flpAppId,
73
+ sapClientParam: service.sapClient ? (0, utils_1.buildSapClientParam)(service.sapClient) : undefined,
74
+ odataVersion: service.odataVersion,
75
+ datasourceType: service.datasourceType
76
+ }, fs, vscode, logger);
77
+ }
78
+ // Persist backend system connection information
79
+ const hostEnv = (0, fiori_generator_shared_1.getHostEnvironment)();
80
+ if (service.backendSystem && hostEnv !== fiori_generator_shared_1.hostEnvironment.bas && service.backendSystem.newOrUpdated) {
81
+ const storeService = await (0, store_1.getService)({
82
+ logger: logger,
83
+ entityName: 'system'
84
+ });
85
+ // No need to await, we cannot recover anyway
86
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
87
+ storeService.write(service.backendSystem);
88
+ }
89
+ // Display info message if using a cap service as it is not otherwise shown when a top level dir is not created
90
+ if (service.capService && appWizard) {
91
+ // this info message needs to be shown for cap projects as it is not shown when a top level dir is not created
92
+ appWizard.showInformation((0, utils_1.t)('wizardMessages.filesGenerated'), yeoman_ui_types_1.MessageType.notification);
93
+ }
94
+ if (hostEnv !== fiori_generator_shared_1.hostEnvironment.bas && service.apiHubConfig?.apiHubType === "API_HUB" /* ApiHubType.apiHub */) {
95
+ await saveApiHubApiKey(service.apiHubConfig.apiHubKey, logger);
96
+ }
97
+ // If we got here, the generation was successful and so targetFolder and name must be defined
98
+ const projectPath = (0, path_1.join)(project.targetFolder, project.name);
99
+ logger.info((0, utils_1.t)('logMessages.applicationGenerationSuccess', {
100
+ targetFolder: projectPath
101
+ }));
102
+ await (0, fiori_generator_shared_1.sendTelemetry)('GENERATION_SUCCESS', fiori_generator_shared_1.TelemetryHelper.telemetryData, projectPath);
103
+ await runPostGenHooks(projectPath, logger, vscode, followUpCommand);
104
+ }
105
+ //# sourceMappingURL=end.js.map
@@ -0,0 +1,45 @@
1
+ import { type ILogWrapper } from '@sap-ux/fiori-generator-shared';
2
+ import type { Logger } from '@sap-ux/logger';
3
+ import Generator from 'yeoman-generator';
4
+ import type { FioriStep, State } from '../types';
5
+ import type { FioriAppGeneratorOptions } from './fioriAppGeneratorOptions';
6
+ export declare const APP_GENERATOR_MODULE = "@sap/generator-fiori";
7
+ /**
8
+ * The root generator for Fiori Elements and Fiori Freestyle generators.
9
+ * All common functionality is implemented here.
10
+ */
11
+ export declare class FioriAppGenerator extends Generator {
12
+ private readonly vscode;
13
+ private generationTime0;
14
+ private appWizard;
15
+ protected state: State;
16
+ private static _logger;
17
+ protected generatorVersion: string;
18
+ private yeomanUiStepConfig;
19
+ private readonly setPromptsCallback;
20
+ private prompts;
21
+ protected fioriSteps: FioriStep[];
22
+ /**
23
+ *
24
+ * @param args
25
+ * @param opts
26
+ */
27
+ constructor(args: string | string[], opts: FioriAppGeneratorOptions);
28
+ /**
29
+ * Static getter for the logger.
30
+ *
31
+ * @returns {ILogWrapper & Logger}
32
+ */
33
+ static get logger(): ILogWrapper & Logger;
34
+ initializing(): Promise<void>;
35
+ prompting(): Promise<void>;
36
+ writing(): Promise<void>;
37
+ install(): Promise<void>;
38
+ end(): Promise<void>;
39
+ /**
40
+ *
41
+ * @param error
42
+ */
43
+ private _exitOnError;
44
+ }
45
+ //# sourceMappingURL=fioriAppGenerator.d.ts.map
@@ -0,0 +1,319 @@
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.FioriAppGenerator = exports.APP_GENERATOR_MODULE = void 0;
7
+ const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
8
+ const btp_utils_1 = require("@sap-ux/btp-utils");
9
+ const feature_toggle_1 = require("@sap-ux/feature-toggle");
10
+ const fiori_elements_writer_1 = require("@sap-ux/fiori-elements-writer");
11
+ const fiori_freestyle_writer_1 = require("@sap-ux/fiori-freestyle-writer");
12
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
13
+ const odata_service_inquirer_1 = require("@sap-ux/odata-service-inquirer");
14
+ const telemetry_1 = require("@sap-ux/telemetry");
15
+ const ui5_info_1 = require("@sap-ux/ui5-info");
16
+ const path_1 = require("path");
17
+ const yeoman_generator_1 = __importDefault(require("yeoman-generator"));
18
+ const types_1 = require("../types");
19
+ const utils_1 = require("../utils");
20
+ const end_1 = require("./end");
21
+ const install_1 = require("./install");
22
+ const prompting_1 = require("./prompting");
23
+ const subgenHelpers_1 = require("./subgenHelpers");
24
+ const transforms_1 = require("./transforms");
25
+ const writing_1 = require("./writing");
26
+ exports.APP_GENERATOR_MODULE = '@sap/generator-fiori';
27
+ /**
28
+ * The root generator for Fiori Elements and Fiori Freestyle generators.
29
+ * All common functionality is implemented here.
30
+ */
31
+ class FioriAppGenerator extends yeoman_generator_1.default {
32
+ vscode;
33
+ // Performance measurement
34
+ generationTime0; // start of writing phase millisecond timestamp
35
+ appWizard;
36
+ state;
37
+ // The logger is static to allow convenient access from everywhere, cross-cutting concern
38
+ static _logger = fiori_generator_shared_1.DefaultLogger;
39
+ // Generator name for use in telemetry, readmes etc.
40
+ generatorVersion = this.rootGeneratorVersion();
41
+ // The configuration of steps in YUI and their interdependence
42
+ yeomanUiStepConfig;
43
+ setPromptsCallback;
44
+ prompts;
45
+ fioriSteps;
46
+ /**
47
+ *
48
+ * @param args
49
+ * @param opts
50
+ */
51
+ constructor(args, opts) {
52
+ super(args, opts, {
53
+ unique: 'namespace'
54
+ });
55
+ this.vscode = opts['vscode'];
56
+ FioriAppGenerator._logger = this.options.logWrapper ?? fiori_generator_shared_1.DefaultLogger;
57
+ // Init the generator state
58
+ this.state = opts.state ?? { project: {}, service: {} };
59
+ }
60
+ /**
61
+ * Static getter for the logger.
62
+ *
63
+ * @returns {ILogWrapper & Logger}
64
+ */
65
+ static get logger() {
66
+ return FioriAppGenerator._logger;
67
+ }
68
+ async initializing() {
69
+ // Ensure i18n bundles are loaded, default loading is unreliable
70
+ await (0, utils_1.initI18nFioriAppSubGenerator)();
71
+ // When running in YUI context back navigation is supported and state may be cached.
72
+ if (this.options.appWizard) {
73
+ this.appWizard = this.options.appWizard;
74
+ (0, utils_1.initAppWizardCache)(FioriAppGenerator._logger, this.options.appWizard);
75
+ }
76
+ await (0, telemetry_1.initTelemetrySettings)({
77
+ consumerModule: { name: exports.APP_GENERATOR_MODULE, version: this.rootGeneratorVersion() },
78
+ internalFeature: (0, feature_toggle_1.isInternalFeaturesSettingEnabled)(),
79
+ watchTelemetrySettingStore: false
80
+ });
81
+ fiori_generator_shared_1.TelemetryHelper.createTelemetryData({
82
+ ...this.options.telemetryData
83
+ });
84
+ /**
85
+ * Preloading UI5 versions to be retreived from cache later in generation flow
86
+ * Not required when version is already in project state e.g S4
87
+ */
88
+ if (!this.state.project?.ui5Version) {
89
+ const filterOptions = {
90
+ useCache: true
91
+ };
92
+ // do not await as this is pre-loading the cache
93
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
94
+ (0, ui5_info_1.getUI5Versions)(filterOptions);
95
+ }
96
+ // Floorplans, externally configured either via adapters or headless config
97
+ if (this.options.floorplan) {
98
+ this.state.floorplan = this.options.floorplan;
99
+ }
100
+ // Configuration of steps in YUI and their interdependance
101
+ this.fioriSteps = this.options.fioriSteps ?? types_1.FIORI_STEPS;
102
+ this.yeomanUiStepConfig = this.options.yeomanUiStepConfig;
103
+ this.prompts = this.yeomanUiStepConfig?.activeSteps;
104
+ }
105
+ async prompting() {
106
+ try {
107
+ const generatorOptions = this.options;
108
+ const isFioriFreestyleTemplate = this.state.floorplan === types_1.FloorplanFF.FF_SIMPLE;
109
+ if ((0, utils_1.hasStep)(this.fioriSteps, types_1.STEP_DATASOURCE_AND_SERVICE)) {
110
+ const cachedService = (0, utils_1.getFromCache)(this.appWizard, 'service', FioriAppGenerator.logger);
111
+ const options = {
112
+ capService: cachedService?.capService ?? this.state.service?.capService,
113
+ requiredOdataVersion: (0, utils_1.getRequiredOdataVersion)(this.state.floorplan),
114
+ allowNoDatasource: isFioriFreestyleTemplate,
115
+ promptOptions: generatorOptions.promptSettings,
116
+ showCollabDraftWarning: generatorOptions.showCollabDraftWarning,
117
+ workspaceFolders: generatorOptions.workspaceFolders
118
+ };
119
+ let serviceAnswers = await (0, prompting_1.promptOdataServiceAnswers)(options, FioriAppGenerator.logger, this.env.adapter);
120
+ /** Back button issue temp fix */
121
+ // Persist derived state to facilitate backwards navigation
122
+ if ((0, fiori_generator_shared_1.getHostEnvironment)() !== fiori_generator_shared_1.hostEnvironment.cli) {
123
+ if (serviceAnswers.source === odata_service_inquirer_1.DatasourceType.none || serviceAnswers.edmx) {
124
+ (0, utils_1.addToCache)(this.appWizard, { service: serviceAnswers }, FioriAppGenerator.logger);
125
+ }
126
+ else {
127
+ serviceAnswers =
128
+ (0, utils_1.getFromCache)(this.appWizard, 'service', FioriAppGenerator.logger) ?? serviceAnswers;
129
+ }
130
+ if (!(serviceAnswers.source === odata_service_inquirer_1.DatasourceType.none || serviceAnswers.edmx)) {
131
+ FioriAppGenerator.logger?.error((0, utils_1.t)('error.fatalError'));
132
+ }
133
+ }
134
+ /** END: Back button temp fix */
135
+ this.state.service = { ...this.state?.service, ...serviceAnswers };
136
+ }
137
+ // Freestyle templates require a view name
138
+ if (isFioriFreestyleTemplate) {
139
+ const viewNameAnswer = await this.prompt([(0, prompting_1.getViewQuestion)()]);
140
+ this.state.viewName = viewNameAnswer.viewName;
141
+ }
142
+ else if (this.state.service.edmx) {
143
+ // Fiori Elements templates require entity and related settings
144
+ const entityQuestions = (0, odata_service_inquirer_1.getEntityRelatedPrompts)(this.state.service.edmx, (0, transforms_1.getTemplateType)(this.state.floorplan), !!this.state.service.capService, {
145
+ defaultMainEntityName: generatorOptions.preselectedEntityName,
146
+ useAutoComplete: (0, fiori_generator_shared_1.getHostEnvironment)() === fiori_generator_shared_1.hostEnvironment.cli,
147
+ hideTableLayoutPrompts: generatorOptions.showLayoutPrompts === false // Defaults to show layout prompts
148
+ }, this.state.service.annotations?.[0], FioriAppGenerator.logger, (0, fiori_generator_shared_1.getHostEnvironment)() !== fiori_generator_shared_1.hostEnvironment.cli);
149
+ const entityRelatedAnswers = await this.prompt(entityQuestions);
150
+ // Some state may have been assigned by adaptors, and then certain prompts hidden, so we must merge the answers
151
+ this.state.entityRelatedConfig = Object.assign(this.state.entityRelatedConfig ?? {}, entityRelatedAnswers);
152
+ }
153
+ else {
154
+ // Not Freestyle and no entity related config is an error and we cannot proceed
155
+ FioriAppGenerator.logger.error((0, utils_1.t)('error.edmxNotFound'));
156
+ this._exitOnError((0, utils_1.t)('error.edmxNotFound'));
157
+ }
158
+ // Pre-load the CAP project and get all relevant info in one call,
159
+ // this prevents re-reading from disc and parsing multiple times later
160
+ if (this.state.service.capService && !this.state.service.capService.cdsUi5PluginInfo) {
161
+ this.state.service.capService.cdsUi5PluginInfo = await (0, utils_1.getCdsUi5PluginInfo)(this.state.service.capService.projectPath, this.fs, this.state.service.capService.cdsVersionInfo);
162
+ }
163
+ // get project information
164
+ if ((0, utils_1.hasStep)(this.fioriSteps, types_1.STEP_PROJECT_ATTRIBUTES)) {
165
+ const { ui5AppAnswers, localUI5Version } = await (0, prompting_1.promptUI5ApplicationAnswers)({
166
+ projectName: this.state.project?.name,
167
+ targetFolder: this.state.project?.targetFolder,
168
+ service: this.state.service,
169
+ floorplan: this.state.floorplan,
170
+ hideUI5VersionPrompt: generatorOptions.hideUI5VersionPrompt,
171
+ promptSettings: generatorOptions.promptSettings,
172
+ promptExtension: generatorOptions.extensions
173
+ }, [this.yeomanUiStepConfig], this.env.adapter);
174
+ this.state.project = Object.assign(this.state.project ?? {}, ui5AppAnswers, {
175
+ ui5Version: ui5AppAnswers?.ui5Version || localUI5Version,
176
+ localUI5Version,
177
+ flpAppId: (0, utils_1.getFlpId)((0, utils_1.getAppId)(ui5AppAnswers.namespace ?? '', ui5AppAnswers?.name), this.state.floorplan === types_1.FloorplanFF.FF_SIMPLE ? types_1.defaultNavActionDisplay : types_1.defaultNavActionTile)
178
+ });
179
+ }
180
+ if (this.state.project?.addDeployConfig) {
181
+ // Allows back nav where we have iinterdependent steps
182
+ // Re-add dependant steps on back nav
183
+ if ((0, utils_1.hasStep)(this.fioriSteps, types_1.STEP_DEPLOY_CONFIG) &&
184
+ !(0, utils_1.hasActiveStep)((0, utils_1.t)('steps.deployConfig.title'), this.yeomanUiStepConfig.activeSteps)) {
185
+ (0, utils_1.updateDependentStep)((0, utils_1.t)('steps.projectAttributesConfig.title'), [this.yeomanUiStepConfig], true, (0, utils_1.t)('steps.deployConfig.title'));
186
+ }
187
+ (0, subgenHelpers_1.addDeployGen)({
188
+ service: this.state.service,
189
+ projectName: this.state.project.name,
190
+ targetFolder: this.state.project.targetFolder,
191
+ applicationType: 'FF' // Telemetry data
192
+ }, this.composeWith.bind(this), FioriAppGenerator.logger, this.appWizard);
193
+ }
194
+ if (this.state.project?.addFlpConfig) {
195
+ // Allows back nav where we have interdependent steps
196
+ // Re-add dependant steps on back nav
197
+ if ((0, utils_1.hasStep)(this.fioriSteps, types_1.STEP_FLP_CONFIG) &&
198
+ !(0, utils_1.hasActiveStep)((0, utils_1.t)('steps.flpConfig.title'), this.yeomanUiStepConfig.activeSteps)) {
199
+ (0, utils_1.updateDependentStep)((0, utils_1.t)('steps.projectAttributesConfig.title'), [this.yeomanUiStepConfig], true, (0, utils_1.t)('steps.flpConfig.title'));
200
+ }
201
+ (0, subgenHelpers_1.addFlpGen)({
202
+ projectName: this.state.project.name,
203
+ targetFolder: this.state.project.targetFolder,
204
+ title: this.state.project.title,
205
+ skipPrompt: !(0, utils_1.hasStep)(this.fioriSteps, types_1.STEP_FLP_CONFIG)
206
+ }, this.composeWith.bind(this), FioriAppGenerator.logger, generatorOptions.vscode, this.appWizard);
207
+ }
208
+ }
209
+ catch (error) {
210
+ // Fatal prompting error
211
+ FioriAppGenerator.logger.error(`${(0, utils_1.t)('error.fatalError')} : ${error}`);
212
+ this._exitOnError(error);
213
+ }
214
+ }
215
+ async writing() {
216
+ try {
217
+ this.generationTime0 = performance.now();
218
+ fiori_generator_shared_1.TelemetryHelper.markAppGenStartTime();
219
+ const { service, project, floorplan } = this.state;
220
+ FioriAppGenerator.logger.info((0, utils_1.t)('logMessages.copyingTemplateFiles', { templateName: this.state.floorplan }));
221
+ // Set the template folder
222
+ // this.sourceRoot(join(__dirname, '..', '..', 'templates')); // Path must match webpacked template paths
223
+ const destRoot = this.destinationRoot((0, path_1.join)(project.targetFolder, project.name));
224
+ const t1 = performance.now();
225
+ let appConfig;
226
+ // Determine which type of app to generate based on the selected floorplan (template type)
227
+ if (this.state.floorplan === types_1.FloorplanFF.FF_SIMPLE) {
228
+ const ffApp = await (0, transforms_1.transformState)(this.state, !!service.capService || this.options.generateIndexHtml);
229
+ await (0, fiori_freestyle_writer_1.generate)(destRoot, ffApp, this.fs);
230
+ appConfig = ffApp;
231
+ }
232
+ else {
233
+ const feApp = await (0, transforms_1.transformState)(this.state, !!service.capService || this.options.generateIndexHtml);
234
+ await (0, fiori_elements_writer_1.generate)(destRoot, feApp, this.fs);
235
+ appConfig = feApp;
236
+ }
237
+ const t2 = performance.now();
238
+ FioriAppGenerator.logger.debug(`Writing Fiori application files from template took ${Math.round(t2 - t1)} milliseconds.`);
239
+ fiori_generator_shared_1.TelemetryHelper.createTelemetryData({
240
+ Template: (0, utils_1.t)(`floorplans.label.${floorplan}`, {
241
+ odataVersion: service.version
242
+ }),
243
+ DataSource: service.source,
244
+ UI5Version: project.ui5Version || ui5_info_1.latestVersionString,
245
+ Theme: project.ui5Theme,
246
+ AppGenVersion: this.generatorVersion,
247
+ AppGenSourceType: service.source,
248
+ AppGenSapSystemType: service.source === odata_service_inquirer_1.DatasourceType.sapSystem && service.connectedSystem
249
+ ? (0, utils_1.getTelemetrySapSystemType)(service.connectedSystem)
250
+ : 'n/a',
251
+ AppGenBusinessHubType: (0, utils_1.getTelemetryBusinessHubType)(service.apiHubConfig?.apiHubType),
252
+ EnableEslint: project.enableEslint,
253
+ EnableTypeScript: project.enableTypeScript,
254
+ EnableCodeAssist: project.enableCodeAssist,
255
+ ToolsId: appConfig.app.sourceTemplate?.toolsId
256
+ });
257
+ if (service.apiHubConfig && (0, btp_utils_1.isAppStudio)()) {
258
+ (0, writing_1.writeAPIHubKeyFiles)(this.fs, destRoot, service.apiHubConfig);
259
+ }
260
+ // Write after app, using values from the transformed state so defaults have been applied
261
+ const readMeUpdated = { ui5Version: appConfig.ui5?.minUI5Version };
262
+ await (0, writing_1.writeReadMe)(this.state, types_1.generatorName, this.generatorVersion, destRoot, this.fs, readMeUpdated);
263
+ }
264
+ catch (error) {
265
+ FioriAppGenerator.logger.fatal(`${(0, utils_1.t)('error.errorWritingApplicationFiles')} : ${error}`);
266
+ this._exitOnError(error);
267
+ }
268
+ }
269
+ async install() {
270
+ if (!this.options.skipInstall) {
271
+ await (0, install_1.installDependencies)({
272
+ appPackagePath: this.destinationPath(),
273
+ capService: this.state.service.capService,
274
+ enableCodeAssist: this.state.project?.enableCodeAssist ?? false,
275
+ // Assumption that npm workspaces will be enabled if cds ui5 plugin is a depenedency
276
+ useNpmWorkspaces: !!(this.state.service.capService?.cdsUi5PluginInfo?.isCdsUi5PluginEnabled ||
277
+ this.state.service.capService?.cdsUi5PluginInfo?.hasCdsUi5Plugin ||
278
+ this.state.service.capService?.cdsUi5PluginInfo?.isWorkspaceEnabled),
279
+ ui5Version: this.state.project?.ui5Version
280
+ }, FioriAppGenerator.logger);
281
+ }
282
+ else {
283
+ FioriAppGenerator.logger.info((0, utils_1.t)('logMessages.installSkippedOptionSpecified'));
284
+ }
285
+ }
286
+ async end() {
287
+ (0, utils_1.deleteCache)(this.appWizard, FioriAppGenerator.logger);
288
+ await (0, end_1.runPostGenerationTasks)({
289
+ service: {
290
+ backendSystem: this.state.service.connectedSystem?.backendSystem,
291
+ capService: this.state.service.capService,
292
+ sapClient: this.state.service.client,
293
+ odataVersion: this.state.service.version,
294
+ datasourceType: this.state.service.source
295
+ },
296
+ project: {
297
+ targetFolder: this.state.project.targetFolder,
298
+ name: this.state.project.name,
299
+ flpAppId: this.state.project.flpAppId
300
+ }
301
+ }, this.fs, FioriAppGenerator.logger, this.vscode, this.appWizard, this.options.followUpCommand);
302
+ const generationTime02 = performance.now();
303
+ FioriAppGenerator.logger.info(`Total time taken: ${Math.round((generationTime02 - this.generationTime0) / 1000)} seconds.`);
304
+ }
305
+ /**
306
+ *
307
+ * @param error
308
+ */
309
+ _exitOnError(error) {
310
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
311
+ (0, fiori_generator_shared_1.sendTelemetry)('GENERATION_WRITING_FAIL', fiori_generator_shared_1.TelemetryHelper.telemetryData);
312
+ if ((0, fiori_generator_shared_1.getHostEnvironment)() !== fiori_generator_shared_1.hostEnvironment.cli) {
313
+ this.appWizard?.showError(`${(0, utils_1.t)('error.fatalError')} : ${error}`, yeoman_ui_types_1.MessageType.notification);
314
+ }
315
+ throw new Error(`${(0, utils_1.t)('error.fatalError')} : ${error}`);
316
+ }
317
+ }
318
+ exports.FioriAppGenerator = FioriAppGenerator;
319
+ //# sourceMappingURL=fioriAppGenerator.js.map
@@ -0,0 +1,94 @@
1
+ import type { AppWizard, Severity } from '@sap-devx/yeoman-ui-types';
2
+ import type Generator from 'yeoman-generator';
3
+ import type { FioriGeneratorSettings, FioriStep, Floorplan, PromptExtension, FioriAppGeneratorPromptSettings, State, YeomanUiStepConfig } from '../types';
4
+ /**
5
+ * Fiori generator specific options, for internal use only.
6
+ * todo: Split this into FioriGenerator options (e.g. disableS4, disableGeneratorExtensions, data) that are explicitly root generator options
7
+ * and FioriAppGenerator options which should be considered internal (passed from Fiori generator to FioriAppGenerator)
8
+ */
9
+ export interface FioriAppGeneratorOptions extends Generator.GeneratorOptions, FioriGeneratorSettings {
10
+ /**
11
+ * Disables loading of S4 generator steps even if its found.
12
+ * todo: External -> FioriGeneratorOptions
13
+ */
14
+ disableS4?: boolean;
15
+ /**
16
+ * Disables loading of generator extensions even if they are found
17
+ * todo: External -> FioriGeneratorOptions
18
+ */
19
+ disableGeneratorExtensions?: boolean;
20
+ /**
21
+ * Additional (non-specified option) data may be passed using this property. e.g. Adaptor data
22
+ * todo: External -> FioriGeneratorOptions
23
+ */
24
+ data?: Object;
25
+ /**
26
+ * Customer provided extensions used to customize existing questions
27
+ */
28
+ extensions?: PromptExtension;
29
+ /**
30
+ * The floorplan (app type) that will be created
31
+ */
32
+ floorplan?: Floorplan;
33
+ /**
34
+ * Prompt settings to control visibility and default values of prompts
35
+ */
36
+ promptSettings?: FioriAppGeneratorPromptSettings;
37
+ /**
38
+ * Changes the launch config writing behaviour from detecting and creating/updating workspace files to only creating with the app target folder
39
+ *
40
+ * @default false
41
+ */
42
+ writeLaunchConfigstoAppOnly?: boolean;
43
+ /**
44
+ * Show template selection step even if only one template. In some cases callers of the generator may want users to be able to confirm the selected floorplan even if theres only one.
45
+ *
46
+ * @default false
47
+ */
48
+ showTemplateSelectionStepIfOnlyOne?: boolean;
49
+ /**
50
+ * Wizard messages may be shown on the first step adjacent to the navigation buttons using this option.
51
+ * This enables callers of App Gen to set end-user messages specific to the context of the caller, for example BAS Storyboard flows.
52
+ */
53
+ wizardMessage?: {
54
+ /**
55
+ * The text of the message to show
56
+ */
57
+ text: string;
58
+ /**
59
+ * The severity of the notification. Default is `Severity.information`.
60
+ */
61
+ severity?: Severity;
62
+ /**
63
+ * A link may be included. Currently not supported by YUI.
64
+ */
65
+ link?: string;
66
+ };
67
+ /**
68
+ * State set by composing generator i.e `@sap/fiori-generator`
69
+ */
70
+ state?: State;
71
+ /**
72
+ * App Wizard reference
73
+ */
74
+ appWizard?: AppWizard;
75
+ /**
76
+ * The telemetry data to be sent along with any telemetry events
77
+ */
78
+ telemetryData?: Record<string, unknown>;
79
+ /**
80
+ * Defined the steps configuration to be used in the Fiori generator. Skip steps by omitting them from the array.
81
+ * Note that these should be aligned with `yeomanUiStepConfig`.
82
+ */
83
+ fioriSteps?: FioriStep[];
84
+ /**
85
+ * Defines the steps configuration to be used in the YUI generator.
86
+ * Not applicable to CLI usage.
87
+ */
88
+ yeomanUiStepConfig?: YeomanUiStepConfig;
89
+ /**
90
+ * VSCode Workspace folders
91
+ */
92
+ workspaceFolders?: string[];
93
+ }
94
+ //# sourceMappingURL=fioriAppGeneratorOptions.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=fioriAppGeneratorOptions.js.map
@@ -0,0 +1,3 @@
1
+ export * from './fioriAppGenerator';
2
+ export * from './fioriAppGeneratorOptions';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./fioriAppGenerator"), exports);
18
+ __exportStar(require("./fioriAppGeneratorOptions"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,34 @@
1
+ import type { CapService } from '@sap-ux/cap-config-writer';
2
+ import { type ILogWrapper } from '@sap-ux/fiori-generator-shared';
3
+ /**
4
+ * Defines the options used to install deps to a CAP project.
5
+ */
6
+ export type CapInstallOptions = {
7
+ ui5Version?: string;
8
+ codeAssist?: boolean;
9
+ rootPath?: string;
10
+ depsInstallPath?: string;
11
+ useWorkspaces?: boolean;
12
+ };
13
+ /**
14
+ * Perform the installation of dependencies for the specified project.
15
+ * If a CAP service is provided AND `useNpmWorkspaces` is false, the dependencies will be installed to the CAP root project,
16
+ * otherwise they will be installed to the specified app `packagePath`.
17
+ *
18
+ * @param param0
19
+ * @param param0.appPackagePath
20
+ * @param param0.capService
21
+ * @param param0.enableCodeAssist
22
+ * @param param0.useNpmWorkspaces
23
+ * @param param0.ui5Version
24
+ * @param logger The logger to use for output
25
+ * @returns Promise<void>
26
+ */
27
+ export declare function installDependencies({ appPackagePath, capService, enableCodeAssist, useNpmWorkspaces, ui5Version }: {
28
+ appPackagePath: string;
29
+ capService?: CapService;
30
+ enableCodeAssist: boolean;
31
+ useNpmWorkspaces: boolean;
32
+ ui5Version: string;
33
+ }, logger: ILogWrapper): Promise<void>;
34
+ //# sourceMappingURL=install.d.ts.map