@ui5/builder 3.0.0-alpha.6 → 3.0.0-alpha.9

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 (49) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/index.js +0 -43
  3. package/lib/lbt/bundle/Builder.js +19 -49
  4. package/lib/lbt/resources/LocatorResource.js +1 -1
  5. package/lib/lbt/utils/escapePropertiesFile.js +3 -6
  6. package/lib/processors/bundlers/moduleBundler.js +2 -3
  7. package/lib/processors/jsdoc/lib/createIndexFiles.js +1 -1
  8. package/lib/processors/jsdoc/lib/transformApiJson.js +20 -20
  9. package/lib/processors/jsdoc/lib/ui5/plugin.js +111 -6
  10. package/lib/processors/jsdoc/lib/ui5/template/publish.js +112 -91
  11. package/lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js +1 -1
  12. package/lib/processors/manifestCreator.js +8 -45
  13. package/lib/tasks/bundlers/generateBundle.js +1 -1
  14. package/lib/tasks/bundlers/generateComponentPreload.js +15 -15
  15. package/lib/tasks/bundlers/generateFlexChangesBundle.js +7 -3
  16. package/lib/tasks/bundlers/generateLibraryPreload.js +84 -91
  17. package/lib/tasks/bundlers/generateManifestBundle.js +8 -10
  18. package/lib/tasks/bundlers/generateStandaloneAppBundle.js +8 -3
  19. package/lib/tasks/bundlers/utils/createModuleNameMapping.js +4 -3
  20. package/lib/tasks/generateCachebusterInfo.js +7 -3
  21. package/lib/tasks/generateLibraryManifest.js +5 -1
  22. package/lib/tasks/generateResourcesJson.js +2 -2
  23. package/lib/tasks/generateThemeDesignerResources.js +8 -2
  24. package/lib/tasks/generateVersionInfo.js +5 -5
  25. package/lib/tasks/jsdoc/generateJsdoc.js +1 -1
  26. package/lib/tasks/minify.js +3 -3
  27. package/lib/tasks/taskRepository.js +1 -13
  28. package/lib/tasks/transformBootstrapHtml.js +6 -1
  29. package/package.json +6 -7
  30. package/lib/builder/BuildContext.js +0 -60
  31. package/lib/builder/ProjectBuildContext.js +0 -61
  32. package/lib/builder/builder.js +0 -425
  33. package/lib/tasks/TaskUtil.js +0 -172
  34. package/lib/types/AbstractBuilder.js +0 -270
  35. package/lib/types/AbstractFormatter.js +0 -66
  36. package/lib/types/AbstractUi5Formatter.js +0 -95
  37. package/lib/types/application/ApplicationBuilder.js +0 -211
  38. package/lib/types/application/ApplicationFormatter.js +0 -227
  39. package/lib/types/application/applicationType.js +0 -15
  40. package/lib/types/library/LibraryBuilder.js +0 -231
  41. package/lib/types/library/LibraryFormatter.js +0 -519
  42. package/lib/types/library/libraryType.js +0 -15
  43. package/lib/types/module/ModuleBuilder.js +0 -7
  44. package/lib/types/module/ModuleFormatter.js +0 -54
  45. package/lib/types/module/moduleType.js +0 -15
  46. package/lib/types/themeLibrary/ThemeLibraryBuilder.js +0 -64
  47. package/lib/types/themeLibrary/ThemeLibraryFormatter.js +0 -90
  48. package/lib/types/themeLibrary/themeLibraryType.js +0 -15
  49. package/lib/types/typeRepository.js +0 -46
@@ -1,172 +0,0 @@
1
- /**
2
- * Convenience functions for UI5 Builder tasks.
3
- * An instance of this class is passed to every standard UI5 Builder task that requires it.
4
- *
5
- * Custom tasks that define a specification version >= 2.2 will receive an interface
6
- * to an instance of this class when called.
7
- * The set of available functions on that interface depends on the specification
8
- * version defined for the extension.
9
- *
10
- * @public
11
- * @memberof module:@ui5/builder.tasks
12
- */
13
- class TaskUtil {
14
- /**
15
- * Standard Build Tags. See UI5 Tooling
16
- * [RFC 0008]{@link https://github.com/SAP/ui5-tooling/blob/master/rfcs/0008-resource-tagging-during-build.md}
17
- * for details.
18
- *
19
- * @public
20
- * @typedef {object} module:@ui5/builder.tasks.TaskUtil~StandardBuildTags
21
- * @property {string} OmitFromBuildResult
22
- * Setting this tag to true for a resource will prevent it from being written to the build target
23
- * @property {string} IsBundle
24
- * This tag identifies resources that contain (i.e. bundle) multiple other resources
25
- */
26
-
27
- /**
28
- * Since <code>@ui5/builder.builder.ProjectBuildContext</code> is a private class, TaskUtil must not be
29
- * instantiated by modules other than @ui5/builder itself.
30
- *
31
- * @param {object} parameters
32
- * @param {module:@ui5/builder.builder.ProjectBuildContext} parameters.projectBuildContext ProjectBuildContext
33
- * @public
34
- */
35
- constructor({projectBuildContext}) {
36
- this._projectBuildContext = projectBuildContext;
37
-
38
- /**
39
- * @member {module:@ui5/builder.tasks.TaskUtil~StandardBuildTags}
40
- * @public
41
- */
42
- this.STANDARD_TAGS = this._projectBuildContext.STANDARD_TAGS;
43
- }
44
-
45
- /**
46
- * Stores a tag with value for a given resource's path. Note that the tag is independent of the supplied
47
- * resource instance. For two resource instances with the same path, the same tag value is returned.
48
- * If the path of a resource is changed, any tag information previously stored for that resource is lost.
49
- *
50
- * </br></br>
51
- * This method is only available to custom task extensions defining
52
- * <b>Specification Version 2.2 and above</b>.
53
- *
54
- * @param {string|module:@ui5/fs.Resource} resourcePath Path or resource-instance the tag should be stored for
55
- * @param {string} tag Name of the tag.
56
- * Currently only the [STANDARD_TAGS]{@link module:@ui5/builder.tasks.TaskUtil#STANDARD_TAGS} are allowed
57
- * @param {string|boolean|integer} [value=true] Tag value. Must be primitive
58
- * @public
59
- */
60
- setTag(resourcePath, tag, value) {
61
- return this._projectBuildContext.getResourceTagCollection().setTag(resourcePath, tag, value);
62
- }
63
-
64
- /**
65
- * Retrieves the value for a stored tag. If no value is stored, <code>undefined</code> is returned.
66
- *
67
- * </br></br>
68
- * This method is only available to custom task extensions defining
69
- * <b>Specification Version 2.2 and above</b>.
70
- *
71
- * @param {string|module:@ui5/fs.Resource} resourcePath Path or resource-instance the tag should be retrieved for
72
- * @param {string} tag Name of the tag
73
- * @returns {string|boolean|integer|undefined} Tag value for the given resource.
74
- * <code>undefined</code> if no value is available
75
- * @public
76
- */
77
- getTag(resourcePath, tag) {
78
- return this._projectBuildContext.getResourceTagCollection().getTag(resourcePath, tag);
79
- }
80
-
81
- /**
82
- * Clears the value of a tag stored for the given resource's path.
83
- * It's like the tag was never set for that resource.
84
- *
85
- * </br></br>
86
- * This method is only available to custom task extensions defining
87
- * <b>Specification Version 2.2 and above</b>.
88
- *
89
- * @param {string|module:@ui5/fs.Resource} resourcePath Path or resource-instance the tag should be cleared for
90
- * @param {string} tag Tag
91
- * @public
92
- */
93
- clearTag(resourcePath, tag) {
94
- return this._projectBuildContext.getResourceTagCollection().clearTag(resourcePath, tag);
95
- }
96
-
97
- /**
98
- * Check whether the project currently being built is the root project.
99
- *
100
- * </br></br>
101
- * This method is only available to custom task extensions defining
102
- * <b>Specification Version 2.2 and above</b>.
103
- *
104
- * @returns {boolean} <code>true</code> if the currently built project is the root project
105
- * @public
106
- */
107
- isRootProject() {
108
- return this._projectBuildContext.isRootProject();
109
- }
110
-
111
- /**
112
- * Retrieves a build option defined by its <code>key</code.
113
- * If no option with the given <code>key</code> is stored, <code>undefined</code> is returned.
114
- *
115
- * @param {string} key The option key
116
- * @returns {any|undefined} The build option (or undefined)
117
- * @private
118
- */
119
- getBuildOption(key) {
120
- return this._projectBuildContext.getOption(key);
121
- }
122
-
123
- /**
124
- * Register a function that must be executed once the build is finished. This can be used to, for example,
125
- * clean up files temporarily created on the file system. If the callback returns a Promise, it will be waited for.
126
- * It will also be executed in cases where the build has failed or has been aborted.
127
- *
128
- * </br></br>
129
- * This method is only available to custom task extensions defining
130
- * <b>Specification Version 2.2 and above</b>.
131
- *
132
- * @param {Function} callback Callback to register. If it returns a Promise, it will be waited for
133
- * @public
134
- */
135
- registerCleanupTask(callback) {
136
- return this._projectBuildContext.registerCleanupTask(callback);
137
- }
138
-
139
- /**
140
- * Get an interface to an instance of this class that only provides those functions
141
- * that are supported by the given custom task extension specification version.
142
- *
143
- * @param {string} specVersion Specification version of custom task extension
144
- * @returns {object} An object with bound instance methods supported by the given specification version
145
- */
146
- getInterface(specVersion) {
147
- if (["0.1", "1.0", "1.1", "2.0", "2.1"].includes(specVersion)) {
148
- return undefined;
149
- }
150
-
151
- const baseInterface = {
152
- STANDARD_TAGS: this.STANDARD_TAGS,
153
- setTag: this.setTag.bind(this),
154
- clearTag: this.clearTag.bind(this),
155
- getTag: this.getTag.bind(this),
156
- isRootProject: this.isRootProject.bind(this),
157
- registerCleanupTask: this.registerCleanupTask.bind(this)
158
- };
159
- switch (specVersion) {
160
- case "2.2":
161
- case "2.3":
162
- case "2.4":
163
- case "2.5":
164
- case "2.6":
165
- return baseInterface;
166
- default:
167
- throw new Error(`TaskUtil: Unknown or unsupported Specification Version ${specVersion}`);
168
- }
169
- }
170
- }
171
-
172
- module.exports = TaskUtil;
@@ -1,270 +0,0 @@
1
-
2
- /**
3
- * Resource collections
4
- *
5
- * @public
6
- * @typedef module:@ui5/builder.BuilderResourceCollections
7
- * @property {module:@ui5/fs.DuplexCollection} workspace Workspace Resource
8
- * @property {module:@ui5/fs.ReaderCollection} dependencies Workspace Resource
9
- */
10
-
11
- /**
12
- * Base class for the builder implementation of a project type
13
- *
14
- * @abstract
15
- */
16
- class AbstractBuilder {
17
- /**
18
- * Constructor
19
- *
20
- * @param {object} parameters
21
- * @param {BuilderResourceCollections} parameters.resourceCollections Resource collections
22
- * @param {object} parameters.project Project configuration
23
- * @param {GroupLogger} parameters.parentLogger Logger to use
24
- * @param {object} parameters.taskUtil
25
- */
26
- constructor({resourceCollections, project, parentLogger, taskUtil}) {
27
- if (new.target === AbstractBuilder) {
28
- throw new TypeError("Class 'AbstractBuilder' is abstract");
29
- }
30
-
31
- this.project = project;
32
-
33
- this.log = parentLogger.createSubLogger(project.type + " " + project.metadata.name, 0.2);
34
- this.taskLog = this.log.createTaskLogger("🔨");
35
-
36
- this.tasks = {};
37
- this.taskExecutionOrder = [];
38
- this.addStandardTasks({
39
- resourceCollections,
40
- project,
41
- log: this.log,
42
- taskUtil
43
- });
44
- this.addCustomTasks({
45
- resourceCollections,
46
- project,
47
- taskUtil
48
- });
49
- }
50
-
51
- /**
52
- * Adds all standard tasks to execute
53
- *
54
- * @abstract
55
- * @protected
56
- * @param {object} parameters
57
- * @param {BuilderResourceCollections} parameters.resourceCollections Resource collections
58
- * @param {object} parameters.taskUtil
59
- * @param {object} parameters.project Project configuration
60
- * @param {object} parameters.log <code>@ui5/logger</code> logger instance
61
- */
62
- addStandardTasks({resourceCollections, project, log, taskUtil}) {
63
- throw new Error("Function 'addStandardTasks' is not implemented");
64
- }
65
-
66
- /**
67
- * Adds custom tasks to execute
68
- *
69
- * @private
70
- * @param {object} parameters
71
- * @param {BuilderResourceCollections} parameters.resourceCollections Resource collections
72
- * @param {object} parameters.taskUtil
73
- * @param {object} parameters.project Project configuration
74
- */
75
- addCustomTasks({resourceCollections, project, taskUtil}) {
76
- const projectCustomTasks = project.builder && project.builder.customTasks;
77
- if (!projectCustomTasks || projectCustomTasks.length === 0) {
78
- return; // No custom tasks defined
79
- }
80
- const taskRepository = require("../tasks/taskRepository");
81
- for (let i = 0; i < projectCustomTasks.length; i++) {
82
- const taskDef = projectCustomTasks[i];
83
- if (!taskDef.name) {
84
- throw new Error(`Missing name for custom task definition of project ${project.metadata.name} ` +
85
- `at index ${i}`);
86
- }
87
- if (taskDef.beforeTask && taskDef.afterTask) {
88
- throw new Error(`Custom task definition ${taskDef.name} of project ${project.metadata.name} ` +
89
- `defines both "beforeTask" and "afterTask" parameters. Only one must be defined.`);
90
- }
91
- if (this.taskExecutionOrder.length && !taskDef.beforeTask && !taskDef.afterTask) {
92
- // Iff there are tasks configured, beforeTask or afterTask must be given
93
- throw new Error(`Custom task definition ${taskDef.name} of project ${project.metadata.name} ` +
94
- `defines neither a "beforeTask" nor an "afterTask" parameter. One must be defined.`);
95
- }
96
-
97
- let newTaskName = taskDef.name;
98
- if (this.tasks[newTaskName]) {
99
- // Task is already known
100
- // => add a suffix to allow for multiple configurations of the same task
101
- let suffixCounter = 0;
102
- while (this.tasks[newTaskName]) {
103
- suffixCounter++; // Start at 1
104
- newTaskName = `${taskDef.name}--${suffixCounter}`;
105
- }
106
- }
107
- // Create custom task if not already done (task might be referenced multiple times, first one wins)
108
- const {specVersion, task} = taskRepository.getTask(taskDef.name);
109
- const execTask = function() {
110
- /* Custom Task Interface
111
- Parameters:
112
- {Object} parameters Parameters
113
- {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
114
- {module:@ui5/fs.AbstractReader} parameters.dependencies
115
- Reader or Collection to read dependency files
116
- {Object} parameters.taskUtil Specification Version dependent interface to a
117
- [TaskUtil]{@link module:@ui5/builder.tasks.TaskUtil} instance
118
- {Object} parameters.options Options
119
- {string} parameters.options.projectName Project name
120
- {string} [parameters.options.projectNamespace] Project namespace if available
121
- {string} [parameters.options.configuration] Task configuration if given in ui5.yaml
122
- Returns:
123
- {Promise<undefined>} Promise resolving with undefined once data has been written
124
- */
125
- const params = {
126
- workspace: resourceCollections.workspace,
127
- dependencies: resourceCollections.dependencies,
128
- options: {
129
- projectName: project.metadata.name,
130
- projectNamespace: project.metadata.namespace,
131
- configuration: taskDef.configuration
132
- }
133
- };
134
-
135
- const taskUtilInterface = taskUtil.getInterface(specVersion);
136
- // Interface is undefined if specVersion does not support taskUtil
137
- if (taskUtilInterface) {
138
- params.taskUtil = taskUtilInterface;
139
- }
140
- return task(params);
141
- };
142
-
143
- this.tasks[newTaskName] = execTask;
144
-
145
- if (this.taskExecutionOrder.length) {
146
- // There is at least one task configured. Use before- and afterTask to add the custom task
147
- const refTaskName = taskDef.beforeTask || taskDef.afterTask;
148
- let refTaskIdx = this.taskExecutionOrder.indexOf(refTaskName);
149
- if (refTaskIdx === -1) {
150
- throw new Error(`Could not find task ${refTaskName}, referenced by custom task ${newTaskName}, ` +
151
- `to be scheduled for project ${project.metadata.name}`);
152
- }
153
- if (taskDef.afterTask) {
154
- // Insert after index of referenced task
155
- refTaskIdx++;
156
- }
157
- this.taskExecutionOrder.splice(refTaskIdx, 0, newTaskName);
158
- } else {
159
- // There is no task configured so far. Just add the custom task
160
- this.taskExecutionOrder.push(newTaskName);
161
- }
162
- }
163
- }
164
-
165
- /**
166
- * Adds a executable task to the builder
167
- *
168
- * The order this function is being called defines the build order. FIFO.
169
- *
170
- * @param {string} taskName Name of the task which should be in the list availableTasks.
171
- * @param {Function} taskFunction
172
- */
173
- addTask(taskName, taskFunction) {
174
- if (this.tasks[taskName]) {
175
- throw new Error(`Failed to add duplicate task ${taskName} for project ${this.project.metadata.name}`);
176
- }
177
- if (this.taskExecutionOrder.includes(taskName)) {
178
- throw new Error(`Builder: Failed to add task ${taskName} for project ${this.project.metadata.name}. ` +
179
- `It has already been scheduled for execution.`);
180
- }
181
- this.tasks[taskName] = taskFunction;
182
- this.taskExecutionOrder.push(taskName);
183
- }
184
-
185
- /**
186
- * Check whether a task is defined
187
- *
188
- * @private
189
- * @param {string} taskName
190
- * @returns {boolean}
191
- */
192
- hasTask(taskName) {
193
- // TODO 3.0: Check whether this method is still required.
194
- // Only usage within #build seems to be unnecessary as all tasks are also added to the taskExecutionOrder
195
- return Object.prototype.hasOwnProperty.call(this.tasks, taskName);
196
- }
197
-
198
- /**
199
- * Takes a list of tasks which should be executed from the available task list of the current builder
200
- *
201
- * @param {Array} tasksToRun List of tasks which should be executed
202
- * @returns {Promise} Returns promise chain with tasks
203
- */
204
- build(tasksToRun) {
205
- const allTasks = this.taskExecutionOrder.filter((taskName) => {
206
- // There might be a numeric suffix in case a custom task is configured multiple times.
207
- // The suffix needs to be removed in order to check against the list of tasks to run.
208
- //
209
- // Note: The 'tasksToRun' parameter only allows to specify the custom task name
210
- // (without suffix), so it executes either all or nothing.
211
- // It's currently not possible to just execute some occurrences of a custom task.
212
- // This would require a more robust contract to identify task executions
213
- // (e.g. via an 'id' that can be assigned to a specific execution in the configuration).
214
- const taskWithoutSuffixCounter = taskName.replace(/--\d+$/, "");
215
- return this.hasTask(taskName) && tasksToRun.includes(taskWithoutSuffixCounter);
216
- });
217
-
218
- this.taskLog.addWork(allTasks.length);
219
-
220
- return allTasks.reduce((taskChain, taskName) => {
221
- const taskFunction = this.tasks[taskName];
222
-
223
- if (typeof taskFunction === "function") {
224
- taskChain = taskChain.then(this.wrapTask(taskName, taskFunction));
225
- }
226
-
227
- return taskChain;
228
- }, Promise.resolve());
229
- }
230
-
231
- /**
232
- * Adds progress related functionality to task function.
233
- *
234
- * @private
235
- * @param {string} taskName Name of the task
236
- * @param {Function} taskFunction Function which executed the task
237
- * @returns {Function} Wrapped task function
238
- */
239
- wrapTask(taskName, taskFunction) {
240
- return () => {
241
- this.taskLog.startWork(`Running task ${taskName}...`);
242
- return taskFunction().then(() => this.taskLog.completeWork(1));
243
- };
244
- }
245
-
246
- /**
247
- * Appends the list of 'excludes' to the list of 'patterns'. To harmonize both lists, the 'excludes'
248
- * are negated and the 'patternPrefix' is added to make them absolute.
249
- *
250
- * @private
251
- * @param {string[]} patterns
252
- * List of absolute default patterns.
253
- * @param {string[]} excludes
254
- * List of relative patterns to be excluded. Excludes with a leading "!" are meant to be re-included.
255
- * @param {string} patternPrefix
256
- * Prefix to be added to the excludes to make them absolute. The prefix must have a leading and a
257
- * trailing "/".
258
- */
259
- enhancePatternWithExcludes(patterns, excludes, patternPrefix) {
260
- excludes.forEach((exclude) => {
261
- if (exclude.startsWith("!")) {
262
- patterns.push(`${patternPrefix}${exclude.slice(1)}`);
263
- } else {
264
- patterns.push(`!${patternPrefix}${exclude}`);
265
- }
266
- });
267
- }
268
- }
269
-
270
- module.exports = AbstractBuilder;
@@ -1,66 +0,0 @@
1
- const fs = require("graceful-fs");
2
-
3
- /**
4
- * Base class for the formatter implementation of a project type.
5
- *
6
- * @abstract
7
- */
8
- class AbstractFormatter {
9
- /**
10
- * Constructor
11
- *
12
- * @param {object} parameters
13
- * @param {object} parameters.project Project
14
- */
15
- constructor({project}) {
16
- if (new.target === AbstractFormatter) {
17
- throw new TypeError("Class 'AbstractFormatter' is abstract");
18
- }
19
- this._project = project;
20
- }
21
-
22
- /**
23
- * Formats and validates the project
24
- *
25
- * @returns {Promise}
26
- */
27
- format() {
28
- throw new Error("AbstractFormatter: Function format Not implemented");
29
- }
30
-
31
- /**
32
- * Validates the project
33
- *
34
- * @returns {Promise} resolves if successfully validated
35
- * @throws {Error} if validation fails
36
- */
37
- validate() {
38
- throw new Error("AbstractFormatter: Function validate Not implemented");
39
- }
40
-
41
- /**
42
- * Checks whether or not the given input is a directory on the file system.
43
- *
44
- * @param {string} dirPath directory
45
- * @returns {Promise<boolean>} whether or not the given directory exists.
46
- * <code>true</code> directory exists
47
- * <code>false</code> directory does not exist
48
- */
49
- dirExists(dirPath) {
50
- return new Promise((resolve, reject) => {
51
- fs.stat(dirPath, (err, stats) => {
52
- if (err) {
53
- if (err.code === "ENOENT") { // "File or directory does not exist"
54
- resolve(false);
55
- } else {
56
- reject(err);
57
- }
58
- } else {
59
- resolve(stats.isDirectory());
60
- }
61
- });
62
- });
63
- }
64
- }
65
-
66
- module.exports = AbstractFormatter;
@@ -1,95 +0,0 @@
1
- const log = require("@ui5/logger").getLogger("types:AbstractUi5Formatter");
2
- const path = require("path");
3
- const fs = require("graceful-fs");
4
- const AbstractFormatter = require("./AbstractFormatter");
5
- const {promisify} = require("util");
6
- const readFile = promisify(fs.readFile);
7
-
8
- /**
9
- * Base class for formatters that require access to some UI5 specific resources
10
- * like pom.xml
11
- *
12
- * @abstract
13
- */
14
- class AbstractUi5Formatter extends AbstractFormatter {
15
- /**
16
- * Constructor
17
- *
18
- * @param {object} parameters
19
- * @param {object} parameters.project Project
20
- */
21
- constructor(parameters) {
22
- super(parameters);
23
- if (new.target === AbstractUi5Formatter) {
24
- throw new TypeError("Class 'AbstractUi5Formatter' is abstract");
25
- }
26
- }
27
-
28
- /**
29
- * Checks whether a given string contains a maven placeholder.
30
- * E.g. <code>${appId}</code>.
31
- *
32
- * @param {string} value String to check
33
- * @returns {boolean} True if given string contains a maven placeholder
34
- */
35
- hasMavenPlaceholder(value) {
36
- return !!value.match(/^\$\{(.*)\}$/);
37
- }
38
-
39
- /**
40
- * Resolves a maven placeholder in a given string using the projects pom.xml
41
- *
42
- * @param {string} value String containing a maven placeholder
43
- * @returns {Promise<string>} Resolved string
44
- */
45
- async resolveMavenPlaceholder(value) {
46
- const parts = value && value.match(/^\$\{(.*)\}$/);
47
- if (parts) {
48
- log.verbose(`"${value} contains a maven placeholder "${parts[1]}". Resolving from projects pom.xml...`);
49
- const pom = await this.getPom();
50
- let mvnValue;
51
- if (pom.project && pom.project.properties && pom.project.properties[parts[1]]) {
52
- mvnValue = pom.project.properties[parts[1]];
53
- } else {
54
- let obj = pom;
55
- parts[1].split(".").forEach((part) => {
56
- obj = obj && obj[part];
57
- });
58
- mvnValue = obj;
59
- }
60
- if (!mvnValue) {
61
- throw new Error(`"${value}" couldn't be resolved from maven property ` +
62
- `"${parts[1]}" of pom.xml of project ${this._project.metadata.name}`);
63
- }
64
- return mvnValue;
65
- } else {
66
- throw new Error(`"${value}" is not a maven placeholder`);
67
- }
68
- }
69
-
70
- /**
71
- * Reads the projects pom.xml file
72
- *
73
- * @returns {Promise<object>} Resolves with a JSON representation of the content
74
- */
75
- async getPom() {
76
- if (this._pPom) {
77
- return this._pPom;
78
- }
79
- const fsPath = path.join(this._project.path, "pom.xml");
80
- return this._pPom = readFile(fsPath).then(async (content) => {
81
- const xml2js = require("xml2js");
82
- const parser = new xml2js.Parser({
83
- explicitArray: false,
84
- ignoreAttrs: true
85
- });
86
- const readXML = promisify(parser.parseString);
87
- return readXML(content);
88
- }).catch((err) => {
89
- throw new Error(
90
- `Failed to read pom.xml for project ${this._project.metadata.name}: ${err.message}`);
91
- });
92
- }
93
- }
94
-
95
- module.exports = AbstractUi5Formatter;