@sap-ux/generator-adp 0.1.20 → 0.2.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.
@@ -42,6 +42,23 @@ export default class extends Generator {
42
42
  * Instance of the configuration prompter class.
43
43
  */
44
44
  private prompter;
45
+ /**
46
+ * JSON object representing the complete adaptation project configuration,
47
+ * passed as a CLI argument.
48
+ */
49
+ private readonly jsonInput?;
50
+ /**
51
+ * Instance of AbapServiceProvider.
52
+ */
53
+ private abapProvider;
54
+ /**
55
+ * Publicly available UI5 versions.
56
+ */
57
+ private publicVersions;
58
+ /**
59
+ * Indicates if the current layer is based on a customer base.
60
+ */
61
+ private isCustomerBase;
45
62
  /**
46
63
  * Creates an instance of the generator.
47
64
  *
@@ -68,6 +85,10 @@ export default class extends Generator {
68
85
  * Configures logging for the generator.
69
86
  */
70
87
  private _setupLogging;
88
+ /**
89
+ * Initialize the project generator from a json.
90
+ */
91
+ private _initFromJson;
71
92
  }
72
93
  export type { AdpGeneratorOptions };
73
94
  //# sourceMappingURL=index.d.ts.map
@@ -6,17 +6,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const path_1 = require("path");
7
7
  const yeoman_generator_1 = __importDefault(require("yeoman-generator"));
8
8
  const yeoman_ui_types_1 = require("@sap-devx/yeoman-ui-types");
9
- const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
10
- const logger_1 = require("@sap-ux/logger");
11
9
  const adp_tooling_1 = require("@sap-ux/adp-tooling");
12
10
  const feature_toggle_1 = require("@sap-ux/feature-toggle");
13
- const layer_1 = require("./layer");
14
- const i18n_1 = require("../utils/i18n");
11
+ const fiori_generator_shared_1 = require("@sap-ux/fiori-generator-shared");
12
+ const logger_1 = require("@sap-ux/logger");
15
13
  const telemetryEvents_1 = require("../telemetryEvents");
14
+ const deps_1 = require("../utils/deps");
15
+ const i18n_1 = require("../utils/i18n");
16
16
  const logger_2 = __importDefault(require("../utils/logger"));
17
+ const parse_json_input_1 = require("../utils/parse-json-input");
18
+ const layer_1 = require("./layer");
17
19
  const attributes_1 = require("./questions/attributes");
18
20
  const configuration_1 = require("./questions/configuration");
19
- const deps_1 = require("../utils/deps");
21
+ const default_values_1 = require("./questions/helper/default-values");
22
+ const validators_1 = require("./questions/helper/validators");
20
23
  /**
21
24
  * Generator for creating an Adaptation Project.
22
25
  *
@@ -59,6 +62,23 @@ class default_1 extends yeoman_generator_1.default {
59
62
  * Instance of the configuration prompter class.
60
63
  */
61
64
  prompter;
65
+ /**
66
+ * JSON object representing the complete adaptation project configuration,
67
+ * passed as a CLI argument.
68
+ */
69
+ jsonInput;
70
+ /**
71
+ * Instance of AbapServiceProvider.
72
+ */
73
+ abapProvider;
74
+ /**
75
+ * Publicly available UI5 versions.
76
+ */
77
+ publicVersions;
78
+ /**
79
+ * Indicates if the current layer is based on a customer base.
80
+ */
81
+ isCustomerBase;
62
82
  /**
63
83
  * Creates an instance of the generator.
64
84
  *
@@ -72,19 +92,26 @@ class default_1 extends yeoman_generator_1.default {
72
92
  this.toolsLogger = new logger_1.ToolsLogger();
73
93
  this.vscode = opts.vscode;
74
94
  this.options = opts;
75
- this._setupPrompts();
76
95
  this._setupLogging();
96
+ const jsonInputString = (0, parse_json_input_1.getFirstArgAsString)(args);
97
+ this.jsonInput = (0, parse_json_input_1.parseJsonInput)(jsonInputString, this.toolsLogger);
98
+ if (!this.jsonInput) {
99
+ this._setupPrompts();
100
+ }
77
101
  }
78
102
  async initializing() {
79
103
  await (0, i18n_1.initI18n)();
80
- const pages = [
81
- { name: (0, i18n_1.t)('yuiNavSteps.configurationName'), description: (0, i18n_1.t)('yuiNavSteps.configurationDescr') },
82
- { name: (0, i18n_1.t)('yuiNavSteps.projectAttributesName'), description: (0, i18n_1.t)('yuiNavSteps.projectAttributesDescr') }
83
- ];
84
- this.prompts.splice(0, 0, pages);
85
104
  this.layer = await (0, layer_1.getFlexLayer)();
105
+ this.isCustomerBase = this.layer === "CUSTOMER_BASE" /* FlexLayer.CUSTOMER_BASE */;
86
106
  this.systemLookup = new adp_tooling_1.SystemLookup(this.toolsLogger);
87
- this.prompter = new configuration_1.ConfigPrompter(this.systemLookup, this.layer, this.toolsLogger);
107
+ if (!this.jsonInput) {
108
+ const pages = [
109
+ { name: (0, i18n_1.t)('yuiNavSteps.configurationName'), description: (0, i18n_1.t)('yuiNavSteps.configurationDescr') },
110
+ { name: (0, i18n_1.t)('yuiNavSteps.projectAttributesName'), description: (0, i18n_1.t)('yuiNavSteps.projectAttributesDescr') }
111
+ ];
112
+ this.prompts.splice(0, 0, pages);
113
+ this.prompter = new configuration_1.ConfigPrompter(this.systemLookup, this.layer, this.toolsLogger);
114
+ }
88
115
  await fiori_generator_shared_1.TelemetryHelper.initTelemetrySettings({
89
116
  consumerModule: {
90
117
  name: '@sap/generator-fiori:generator-adp',
@@ -95,6 +122,9 @@ class default_1 extends yeoman_generator_1.default {
95
122
  });
96
123
  }
97
124
  async prompting() {
125
+ if (this.jsonInput) {
126
+ return;
127
+ }
98
128
  const isCLI = (0, fiori_generator_shared_1.getHostEnvironment)() === fiori_generator_shared_1.hostEnvironment.cli;
99
129
  const configQuestions = this.prompter.getPrompts({
100
130
  appValidationCli: { hide: !isCLI },
@@ -120,13 +150,18 @@ class default_1 extends yeoman_generator_1.default {
120
150
  this.logger.info(`Project Attributes: ${JSON.stringify(this.attributeAnswers, null, 2)}`);
121
151
  }
122
152
  async writing() {
153
+ if (this.jsonInput) {
154
+ await this._initFromJson();
155
+ }
123
156
  try {
157
+ const provider = this.jsonInput ? this.abapProvider : this.prompter.provider;
158
+ const publicVersions = this.jsonInput ? this.publicVersions : this.prompter.ui5.publicVersions;
124
159
  const packageJson = (0, deps_1.getPackageInfo)();
125
160
  const config = await (0, adp_tooling_1.getConfig)({
126
- provider: this.prompter.provider,
161
+ provider,
127
162
  configAnswers: this.configAnswers,
128
163
  attributeAnswers: this.attributeAnswers,
129
- publicVersions: this.prompter?.ui5?.publicVersions,
164
+ publicVersions,
130
165
  layer: this.layer,
131
166
  packageJson,
132
167
  logger: this.toolsLogger
@@ -185,6 +220,49 @@ class default_1 extends yeoman_generator_1.default {
185
220
  logger_2.default.configureLogging(this.options.logger, this.rootGeneratorName(), this.log, this.options.vscode, this.options.logLevel, this.options.logWrapper);
186
221
  this.logger = logger_2.default.logger;
187
222
  }
223
+ /**
224
+ * Initialize the project generator from a json.
225
+ */
226
+ async _initFromJson() {
227
+ if (!this.jsonInput) {
228
+ return;
229
+ }
230
+ const { system, client, username = '', password = '', application: baseApplicationName, applicationTitle, targetFolder = '/home/user/projects', projectName = (0, default_values_1.getDefaultProjectName)(targetFolder, `${baseApplicationName}.variant`), namespace = (0, default_values_1.getDefaultNamespace)(projectName, this.isCustomerBase) } = this.jsonInput;
231
+ await (0, validators_1.validateJsonInput)(this.systemLookup, this.isCustomerBase, {
232
+ projectName,
233
+ targetFolder,
234
+ namespace,
235
+ system
236
+ });
237
+ this.publicVersions = await (0, adp_tooling_1.fetchPublicVersions)();
238
+ const providerOptions = {
239
+ system,
240
+ client,
241
+ username,
242
+ password
243
+ };
244
+ this.abapProvider = await (0, adp_tooling_1.getConfiguredProvider)(providerOptions, this.toolsLogger);
245
+ const applications = await (0, adp_tooling_1.loadApps)(this.abapProvider, this.isCustomerBase);
246
+ const application = applications.find((application) => application.id === baseApplicationName);
247
+ if (!application) {
248
+ throw new Error((0, i18n_1.t)('error.applicationNotFound', { appName: baseApplicationName }));
249
+ }
250
+ this.configAnswers = {
251
+ system,
252
+ username,
253
+ password,
254
+ application
255
+ };
256
+ this.attributeAnswers = {
257
+ projectName,
258
+ title: applicationTitle ?? `${application.title} (variant)`,
259
+ namespace,
260
+ targetFolder,
261
+ // If not provided, latest ui5 version will be used. See getConfig() for a reference.
262
+ ui5Version: '',
263
+ enableTypeScript: false
264
+ };
265
+ }
188
266
  }
189
267
  exports.default = default_1;
190
268
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,26 @@
1
+ import type { SystemLookup } from '@sap-ux/adp-tooling';
2
+ interface JsonInputParams {
3
+ projectName: string;
4
+ targetFolder: string;
5
+ namespace: string;
6
+ system: string;
7
+ }
8
+ /**
9
+ * Validates the input parameters for an adaptation project configuration.
10
+ *
11
+ * @param {SystemLookup} systemLookup - The system lookup utility to resolve system names.
12
+ * @param {boolean} isCustomerBase - Indicates if the project is for the customer base layer.
13
+ * @param {JsonInputParams} params - The input parameters to validate.
14
+ * @param {string} params.projectName - The name of the project to validate.
15
+ * @param {string} params.targetFolder - The target folder where the project will be created.
16
+ * @param {string} params.namespace - The namespace of the project to validate.
17
+ * @param {string} params.system - The name of the system to validate.
18
+ * @throws {Error} Throws an error if any of the validations fail:
19
+ * - If the project name is invalid.
20
+ * - If the namespace is invalid.
21
+ * - If the system cannot be resolved.
22
+ * @returns {Promise<void>} Resolves if all validations pass, otherwise throws an error.
23
+ */
24
+ export declare function validateJsonInput(systemLookup: SystemLookup, isCustomerBase: boolean, { projectName, targetFolder, namespace, system }: JsonInputParams): Promise<void>;
25
+ export {};
26
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateJsonInput = void 0;
4
+ const project_input_validator_1 = require("@sap-ux/project-input-validator");
5
+ const i18n_1 = require("../../../utils/i18n");
6
+ const type_guards_1 = require("../../../utils/type-guards");
7
+ /**
8
+ * Validates the input parameters for an adaptation project configuration.
9
+ *
10
+ * @param {SystemLookup} systemLookup - The system lookup utility to resolve system names.
11
+ * @param {boolean} isCustomerBase - Indicates if the project is for the customer base layer.
12
+ * @param {JsonInputParams} params - The input parameters to validate.
13
+ * @param {string} params.projectName - The name of the project to validate.
14
+ * @param {string} params.targetFolder - The target folder where the project will be created.
15
+ * @param {string} params.namespace - The namespace of the project to validate.
16
+ * @param {string} params.system - The name of the system to validate.
17
+ * @throws {Error} Throws an error if any of the validations fail:
18
+ * - If the project name is invalid.
19
+ * - If the namespace is invalid.
20
+ * - If the system cannot be resolved.
21
+ * @returns {Promise<void>} Resolves if all validations pass, otherwise throws an error.
22
+ */
23
+ async function validateJsonInput(systemLookup, isCustomerBase, { projectName, targetFolder, namespace, system }) {
24
+ let validationResult = (0, project_input_validator_1.validateProjectName)(projectName, targetFolder, isCustomerBase);
25
+ if ((0, type_guards_1.isString)(validationResult)) {
26
+ throw new Error(validationResult);
27
+ }
28
+ validationResult = (0, project_input_validator_1.validateNamespaceAdp)(namespace, projectName, isCustomerBase);
29
+ if ((0, type_guards_1.isString)(validationResult)) {
30
+ throw new Error(validationResult);
31
+ }
32
+ const systemEndpoint = await systemLookup.getSystemByName(system);
33
+ if (!systemEndpoint) {
34
+ throw new Error((0, i18n_1.t)('error.systemNotFound', { system }));
35
+ }
36
+ }
37
+ exports.validateJsonInput = validateJsonInput;
38
+ //# sourceMappingURL=validators.js.map
@@ -110,4 +110,19 @@ export type AttributePromptOptions = Partial<{
110
110
  [attributePromptNames.ui5ValidationCli]: CliValidationPromptOptions;
111
111
  [attributePromptNames.enableTypeScript]: EnableTypeScriptPromptOptions;
112
112
  }>;
113
+ /**
114
+ * An interface representing the json input used to store the complete adaptation project
115
+ * generator configurations. The json is passed as an CLI argument.
116
+ */
117
+ export interface JsonInput {
118
+ system: string;
119
+ client?: string;
120
+ username?: string;
121
+ password?: string;
122
+ application: string;
123
+ applicationTitle?: string;
124
+ targetFolder?: string;
125
+ projectName?: string;
126
+ namespace?: string;
127
+ }
113
128
  //# sourceMappingURL=types.d.ts.map
@@ -44,6 +44,8 @@
44
44
  "notDeployableSystemError": "The system that you have selected is not an ABAP On-Premise system which supports DTA_FOLDER deployment. Adaptation projects are only supported on those systems. Please choose an ABAP On-Premise system which supports DTA_FOLDER deployment.",
45
45
  "notFlexEnabledError": "The system that you have selected is not an ABAP On-Premise system which supports flexibility. Adaptation projects are only supported on those systems. Please choose an ABAP On-Premise system which supports flexibility. If you continue, you will only be able to create an extension project.",
46
46
  "manifestCouldNotBeValidated": "The manifest.json file of the selected application could not be validated. Please select a different application.",
47
- "appDoesNotSupportAdaptation": "The application that you have selected does not support flexibility. Adaptation projects are only supported with those applications. Please choose an application which supports flexibility."
47
+ "appDoesNotSupportAdaptation": "The application that you have selected does not support flexibility. Adaptation projects are only supported with those applications. Please choose an application which supports flexibility.",
48
+ "systemNotFound": "System not found or not supported: {{system}}. Please check the system exists.",
49
+ "applicationNotFound": "Application not found or not supported: {{appName}}. Please check the application exists."
48
50
  }
49
51
  }
@@ -0,0 +1,20 @@
1
+ import type { ToolsLogger } from '@sap-ux/logger';
2
+ import type { JsonInput } from '../app/types';
3
+ /**
4
+ * Returns the first argument from a list of CLI arguments. If the first argument
5
+ * is not a string returns empty string.
6
+ *
7
+ * @param {string | string[]} args - The list of CLI command arguments.
8
+ * @returns {string} The first parameter in the argument's list as string.
9
+ */
10
+ export declare function getFirstArgAsString(args: string | string[]): string;
11
+ /**
12
+ * Parse a json string as an object conforming to the {@link JsonInput} interface.
13
+ *
14
+ * @param {string} jsonString - The json string representation.
15
+ * @param {ToolsLogger} logger - The logger instance.
16
+ * @returns {JsonInput | undefined} The parsed json object, in case of an error or
17
+ * if the object does not match the above interface - returns undefined.
18
+ */
19
+ export declare function parseJsonInput(jsonString: string, logger: ToolsLogger): JsonInput | undefined;
20
+ //# sourceMappingURL=parse-json-input.d.ts.map
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseJsonInput = exports.getFirstArgAsString = void 0;
4
+ const type_guards_1 = require("./type-guards");
5
+ /**
6
+ * Returns the first argument from a list of CLI arguments. If the first argument
7
+ * is not a string returns empty string.
8
+ *
9
+ * @param {string | string[]} args - The list of CLI command arguments.
10
+ * @returns {string} The first parameter in the argument's list as string.
11
+ */
12
+ function getFirstArgAsString(args) {
13
+ if ((0, type_guards_1.isString)(args)) {
14
+ return args;
15
+ }
16
+ if (Array.isArray(args) && args.length) {
17
+ return args[0];
18
+ }
19
+ return '';
20
+ }
21
+ exports.getFirstArgAsString = getFirstArgAsString;
22
+ /**
23
+ * Parse a json string as an object conforming to the {@link JsonInput} interface.
24
+ *
25
+ * @param {string} jsonString - The json string representation.
26
+ * @param {ToolsLogger} logger - The logger instance.
27
+ * @returns {JsonInput | undefined} The parsed json object, in case of an error or
28
+ * if the object does not match the above interface - returns undefined.
29
+ */
30
+ function parseJsonInput(jsonString, logger) {
31
+ try {
32
+ const parsed = JSON.parse(jsonString);
33
+ if (!(0, type_guards_1.isJsonInput)(parsed)) {
34
+ return undefined;
35
+ }
36
+ return parsed;
37
+ }
38
+ catch (error) {
39
+ logger.debug(`Failed to parse adp JSON input: ${error.message}`);
40
+ return undefined;
41
+ }
42
+ }
43
+ exports.parseJsonInput = parseJsonInput;
44
+ //# sourceMappingURL=parse-json-input.js.map
@@ -0,0 +1,16 @@
1
+ import type { JsonInput } from '../app/types';
2
+ /**
3
+ * Type guard for a string values.
4
+ *
5
+ * @param {unknown} value - The value being checked.
6
+ * @returns {boolean} True if the value is of type string.
7
+ */
8
+ export declare function isString(value: unknown): value is string;
9
+ /**
10
+ * Type guard for an adaptation project configuration json.
11
+ *
12
+ * @param {unknown} value - The value being checked.
13
+ * @returns {boolean} True if the value conforms to the AdpJsonInput interface.
14
+ */
15
+ export declare function isJsonInput(value: unknown): value is JsonInput;
16
+ //# sourceMappingURL=type-guards.d.ts.map
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isJsonInput = exports.isString = void 0;
4
+ /**
5
+ * Type guard for a string values.
6
+ *
7
+ * @param {unknown} value - The value being checked.
8
+ * @returns {boolean} True if the value is of type string.
9
+ */
10
+ function isString(value) {
11
+ return typeof value === 'string';
12
+ }
13
+ exports.isString = isString;
14
+ /**
15
+ * Type guard for an adaptation project configuration json.
16
+ *
17
+ * @param {unknown} value - The value being checked.
18
+ * @returns {boolean} True if the value conforms to the AdpJsonInput interface.
19
+ */
20
+ function isJsonInput(value) {
21
+ if (!isPlainObject(value)) {
22
+ return false;
23
+ }
24
+ return (isString(value.system) &&
25
+ isString(value.application) &&
26
+ isOptionalString(value.applicationTitle) &&
27
+ isOptionalString(value.client) &&
28
+ isOptionalString(value.username) &&
29
+ isOptionalString(value.password) &&
30
+ isOptionalString(value.targetFolder) &&
31
+ isOptionalString(value.projectName) &&
32
+ isOptionalString(value.namespace));
33
+ }
34
+ exports.isJsonInput = isJsonInput;
35
+ /**
36
+ * Type guard for a plain javascript object.
37
+ *
38
+ * @param {unknown} value - The value being checked.
39
+ * @returns {boolean} True if the value is a plain javascripot object.
40
+ */
41
+ function isPlainObject(value) {
42
+ return typeof value === 'object' && value !== null && Object.getPrototypeOf(value) === Object.prototype;
43
+ }
44
+ /**
45
+ * Type guard for an optional strings.
46
+ *
47
+ * @param {unknown} value - The value being checked.
48
+ * @returns {boolean} True if the value is string or undefined.
49
+ */
50
+ function isOptionalString(value) {
51
+ return typeof value === 'undefined' || isString(value);
52
+ }
53
+ //# sourceMappingURL=type-guards.js.map
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@sap-ux/generator-adp",
3
3
  "displayName": "SAPUI5 Adaptation Project",
4
4
  "description": "Adaptation project allows you to create an app variant for an existing SAP Fiori elements-based or SAPUI5 freestyle application, without changing the original application.",
5
- "version": "0.1.20",
5
+ "version": "0.2.0",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -29,17 +29,17 @@
29
29
  "i18next": "23.5.1",
30
30
  "yeoman-generator": "5.10.0",
31
31
  "uuid": "10.0.0",
32
- "@sap-ux/adp-tooling": "0.13.41",
33
- "@sap-ux/axios-extension": "1.20.2",
32
+ "@sap-ux/adp-tooling": "0.13.42",
34
33
  "@sap-ux/btp-utils": "1.0.3",
34
+ "@sap-ux/axios-extension": "1.20.2",
35
+ "@sap-ux/inquirer-common": "0.6.42",
35
36
  "@sap-ux/feature-toggle": "0.2.3",
36
- "@sap-ux/inquirer-common": "0.6.41",
37
37
  "@sap-ux/logger": "0.6.0",
38
- "@sap-ux/project-access": "1.29.21",
38
+ "@sap-ux/project-access": "1.29.22",
39
39
  "@sap-ux/store": "1.0.0",
40
40
  "@sap-ux/system-access": "0.5.38",
41
- "@sap-ux/project-input-validator": "0.5.4",
42
- "@sap-ux/fiori-generator-shared": "0.11.2"
41
+ "@sap-ux/project-input-validator": "0.5.5",
42
+ "@sap-ux/fiori-generator-shared": "0.11.3"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@jest/types": "29.6.3",